This is an automated email from the ASF dual-hosted git repository.

iluo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/dubbo.git


The following commit(s) were added to refs/heads/master by this push:
     new d727461  fix bug about the generateReturnAndInvocation method of the 
class AdaptiveClassCodeGenerator (#4339)
d727461 is described below

commit d727461bf004cdaeb9f645cf5b071c7cf666e9c7
Author: MarsMuse <[email protected]>
AuthorDate: Wed Jul 17 14:29:58 2019 +0800

    fix bug about the generateReturnAndInvocation method of the class 
AdaptiveClassCodeGenerator (#4339)
    
    * fix bug about the proxy method is called with the old parameter name
    
    * fix bug about the proxy method is called with the old parameter name
---
 .../extension/AdaptiveClassCodeGenerator.java      | 765 +++++++++++----------
 1 file changed, 384 insertions(+), 381 deletions(-)

diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/AdaptiveClassCodeGenerator.java
 
b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/AdaptiveClassCodeGenerator.java
index 50bf950..239f862 100644
--- 
a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/AdaptiveClassCodeGenerator.java
+++ 
b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/AdaptiveClassCodeGenerator.java
@@ -1,381 +1,384 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.common.extension;
-
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.Parameter;
-import java.util.Arrays;
-import java.util.stream.Collectors;
-import java.util.stream.IntStream;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.logger.Logger;
-import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.common.utils.StringUtils;
-
-/**
- * Code generator for Adaptive class
- */
-public class AdaptiveClassCodeGenerator {
-    
-    private static final Logger logger = 
LoggerFactory.getLogger(AdaptiveClassCodeGenerator.class);
-
-    private static final String CLASSNAME_INVOCATION = 
"org.apache.dubbo.rpc.Invocation";
-    
-    private static final String CODE_PACKAGE = "package %s;\n";
-    
-    private static final String CODE_IMPORTS = "import %s;\n";
-    
-    private static final String CODE_CLASS_DECLARATION = "public class 
%s$Adaptive implements %s {\n";
-    
-    private static final String CODE_METHOD_DECLARATION = "public %s %s(%s) %s 
{\n%s}\n";
-    
-    private static final String CODE_METHOD_ARGUMENT = "%s arg%d";
-    
-    private static final String CODE_METHOD_THROWS = "throws %s";
-    
-    private static final String CODE_UNSUPPORTED = "throw new 
UnsupportedOperationException(\"The method %s of interface %s is not adaptive 
method!\");\n";
-    
-    private static final String CODE_URL_NULL_CHECK = "if (arg%d == null) 
throw new IllegalArgumentException(\"url == null\");\n%s url = arg%d;\n";
-    
-    private static final String CODE_EXT_NAME_ASSIGNMENT = "String extName = 
%s;\n";
-    
-    private static final String CODE_EXT_NAME_NULL_CHECK = "if(extName == 
null) "
-                    + "throw new IllegalStateException(\"Failed to get 
extension (%s) name from url (\" + url.toString() + \") use keys(%s)\");\n";
-    
-    private static final String CODE_INVOCATION_ARGUMENT_NULL_CHECK = "if 
(arg%d == null) throw new IllegalArgumentException(\"invocation == null\"); "
-                    + "String methodName = arg%d.getMethodName();\n";
-    
-    
-    private static final String CODE_EXTENSION_ASSIGNMENT = "%s extension = 
(%<s)%s.getExtensionLoader(%s.class).getExtension(extName);\n";
-    
-    private final Class<?> type;
-    
-    private String defaultExtName;
-    
-    public AdaptiveClassCodeGenerator(Class<?> type, String defaultExtName) {
-        this.type = type;
-        this.defaultExtName = defaultExtName;
-    }
-    
-    /**
-     * test if given type has at least one method annotated with 
<code>SPI</code>
-     */
-    private boolean hasAdaptiveMethod() {
-        return Arrays.stream(type.getMethods()).anyMatch(m -> 
m.isAnnotationPresent(Adaptive.class));
-    }
-    
-    /**
-     * generate and return class code
-     */
-    public String generate() {
-        // no need to generate adaptive class since there's no adaptive method 
found.
-        if (!hasAdaptiveMethod()) {
-            throw new IllegalStateException("No adaptive method exist on 
extension " + type.getName() + ", refuse to create the adaptive class!");
-        }
-
-        StringBuilder code = new StringBuilder();
-        code.append(generatePackageInfo());
-        code.append(generateImports());
-        code.append(generateClassDeclaration());
-        
-        Method[] methods = type.getMethods();
-        for (Method method : methods) {
-            code.append(generateMethod(method));
-        }
-        code.append("}");
-        
-        if (logger.isDebugEnabled()) {
-            logger.debug(code.toString());
-        }
-        return code.toString();
-    }
-
-    /**
-     * generate package info
-     */
-    private String generatePackageInfo() {
-        return String.format(CODE_PACKAGE, type.getPackage().getName());
-    }
-
-    /**
-     * generate imports
-     */
-    private String generateImports() {
-        return String.format(CODE_IMPORTS, ExtensionLoader.class.getName());
-    }
-
-    /**
-     * generate class declaration
-     */
-    private String generateClassDeclaration() {
-        return String.format(CODE_CLASS_DECLARATION, type.getSimpleName(), 
type.getCanonicalName());
-    }
-    
-    /**
-     * generate method not annotated with Adaptive with throwing unsupported 
exception 
-     */
-    private String generateUnsupported(Method method) {
-        return String.format(CODE_UNSUPPORTED, method, type.getName());
-    }
-    
-    /**
-     * get index of parameter with type URL
-     */
-    private int getUrlTypeIndex(Method method) {            
-        int urlTypeIndex = -1;
-        Class<?>[] pts = method.getParameterTypes();
-        for (int i = 0; i < pts.length; ++i) {
-            if (pts[i].equals(URL.class)) {
-                urlTypeIndex = i;
-                break;
-            }
-        }
-        return urlTypeIndex;
-    }
-    
-    /**
-     * generate method declaration
-     */
-    private String generateMethod(Method method) {
-        String methodReturnType = method.getReturnType().getCanonicalName();
-        String methodName = method.getName();
-        String methodContent = generateMethodContent(method);
-        String methodArgs = generateMethodArguments(method);
-        String methodThrows = generateMethodThrows(method);
-        return String.format(CODE_METHOD_DECLARATION, methodReturnType, 
methodName, methodArgs, methodThrows, methodContent);
-    }
-
-    /**
-     * generate method arguments
-     */
-    private String generateMethodArguments(Method method) {
-        Class<?>[] pts = method.getParameterTypes();
-        return IntStream.range(0, pts.length)
-                        .mapToObj(i -> String.format(CODE_METHOD_ARGUMENT, 
pts[i].getCanonicalName(), i))
-                        .collect(Collectors.joining(", "));
-    }
-    
-    /**
-     * generate method throws 
-     */
-    private String generateMethodThrows(Method method) {
-        Class<?>[] ets = method.getExceptionTypes();
-        if (ets.length > 0) {
-            String list = 
Arrays.stream(ets).map(Class::getCanonicalName).collect(Collectors.joining(", 
"));
-            return String.format(CODE_METHOD_THROWS, list);
-        } else {
-            return "";
-        }
-    }
-    
-    /**
-     * generate method URL argument null check 
-     */
-    private String generateUrlNullCheck(int index) {
-        return String.format(CODE_URL_NULL_CHECK, index, URL.class.getName(), 
index);
-    }
-    
-    /**
-     * generate method content
-     */
-    private String generateMethodContent(Method method) {
-        Adaptive adaptiveAnnotation = method.getAnnotation(Adaptive.class);
-        StringBuilder code = new StringBuilder(512);
-        if (adaptiveAnnotation == null) {
-            return generateUnsupported(method);
-        } else {
-            int urlTypeIndex = getUrlTypeIndex(method);
-            
-            // found parameter in URL type
-            if (urlTypeIndex != -1) {
-                // Null Point check
-                code.append(generateUrlNullCheck(urlTypeIndex));
-            } else {
-                // did not find parameter in URL type
-                code.append(generateUrlAssignmentIndirectly(method));
-            }
-
-            String[] value = getMethodAdaptiveValue(adaptiveAnnotation);
-
-            boolean hasInvocation = hasInvocationArgument(method);
-            
-            code.append(generateInvocationArgumentNullCheck(method));
-            
-            code.append(generateExtNameAssignment(value, hasInvocation));
-            // check extName == null?
-            code.append(generateExtNameNullCheck(value));
-            
-            code.append(generateExtensionAssignment());
-
-            // return statement
-            code.append(generateReturnAndInvocation(method));
-        }
-        
-        return code.toString();
-    }
-
-    /**
-     * generate code for variable extName null check
-     */
-    private String generateExtNameNullCheck(String[] value) {
-        return String.format(CODE_EXT_NAME_NULL_CHECK, type.getName(), 
Arrays.toString(value));
-    }
-
-    /**
-     * generate extName assigment code
-     */
-    private String generateExtNameAssignment(String[] value, boolean 
hasInvocation) {
-        // TODO: refactor it
-        String getNameCode = null;
-        for (int i = value.length - 1; i >= 0; --i) {
-            if (i == value.length - 1) {
-                if (null != defaultExtName) {
-                    if (!"protocol".equals(value[i])) {
-                        if (hasInvocation) {
-                            getNameCode = 
String.format("url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], 
defaultExtName);
-                        } else {
-                            getNameCode = 
String.format("url.getParameter(\"%s\", \"%s\")", value[i], defaultExtName);
-                        }
-                    } else {
-                        getNameCode = String.format("( url.getProtocol() == 
null ? \"%s\" : url.getProtocol() )", defaultExtName);
-                    }
-                } else {
-                    if (!"protocol".equals(value[i])) {
-                        if (hasInvocation) {
-                            getNameCode = 
String.format("url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], 
defaultExtName);
-                        } else {
-                            getNameCode = 
String.format("url.getParameter(\"%s\")", value[i]);
-                        }
-                    } else {
-                        getNameCode = "url.getProtocol()";
-                    }
-                }
-            } else {
-                if (!"protocol".equals(value[i])) {
-                    if (hasInvocation) {
-                        getNameCode = 
String.format("url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], 
defaultExtName);
-                    } else {
-                        getNameCode = String.format("url.getParameter(\"%s\", 
%s)", value[i], getNameCode);
-                    }
-                } else {
-                    getNameCode = String.format("url.getProtocol() == null ? 
(%s) : url.getProtocol()", getNameCode);
-                }
-            }
-        }
-        
-        return String.format(CODE_EXT_NAME_ASSIGNMENT, getNameCode);
-    }
-
-    /**
-     * @return
-     */
-    private String generateExtensionAssignment() {
-        return String.format(CODE_EXTENSION_ASSIGNMENT, type.getName(), 
ExtensionLoader.class.getSimpleName(), type.getName());
-    }
-
-    /**
-     * generate method invocation statement and return it if necessary
-     */
-    private String generateReturnAndInvocation(Method method) {
-        String returnStatement = method.getReturnType().equals(void.class) ? 
"" : "return ";
-        
-        String args = 
Arrays.stream(method.getParameters()).map(Parameter::getName).collect(Collectors.joining(",
 "));
-
-        return returnStatement + String.format("extension.%s(%s);\n", 
method.getName(), args);
-    }
-    
-    /**
-     * test if method has argument of type <code>Invocation</code>
-     */
-    private boolean hasInvocationArgument(Method method) {
-        Class<?>[] pts = method.getParameterTypes();
-        return Arrays.stream(pts).anyMatch(p -> 
CLASSNAME_INVOCATION.equals(p.getName()));
-    }
-    
-    /**
-     * generate code to test argument of type <code>Invocation</code> is null
-     */
-    private String generateInvocationArgumentNullCheck(Method method) {
-        Class<?>[] pts = method.getParameterTypes();
-        return IntStream.range(0, pts.length).filter(i -> 
CLASSNAME_INVOCATION.equals(pts[i].getName()))
-                        .mapToObj(i -> 
String.format(CODE_INVOCATION_ARGUMENT_NULL_CHECK, i, i))
-                        .findFirst().orElse("");
-    }
-
-    /**
-     * get value of adaptive annotation or if empty return splitted simple name
-     */
-    private String[] getMethodAdaptiveValue(Adaptive adaptiveAnnotation) {
-        String[] value = adaptiveAnnotation.value();
-        // value is not set, use the value generated from class name as the key
-        if (value.length == 0) {
-            String splitName = 
StringUtils.camelToSplitName(type.getSimpleName(), ".");
-            value = new String[]{splitName};
-        }
-        return value;
-    }
-
-    /**
-     * get parameter with type <code>URL</code> from method parameter:
-     * <p>
-     * test if parameter has method which returns type <code>URL</code>
-     * <p>
-     * if not found, throws IllegalStateException
-     */
-    private String generateUrlAssignmentIndirectly(Method method) {
-        Class<?>[] pts = method.getParameterTypes();
-        
-        // find URL getter method
-        for (int i = 0; i < pts.length; ++i) {
-            for (Method m : pts[i].getMethods()) {
-                String name = m.getName();
-                if ((name.startsWith("get") || name.length() > 3)
-                        && Modifier.isPublic(m.getModifiers())
-                        && !Modifier.isStatic(m.getModifiers())
-                        && m.getParameterTypes().length == 0
-                        && m.getReturnType() == URL.class) {
-                    return generateGetUrlNullCheck(i, pts[i], name);
-                }
-            }
-        }
-        
-        // getter method not found, throw
-        throw new IllegalStateException("Failed to create adaptive class for 
interface " + type.getName()
-                        + ": not found url parameter or url attribute in 
parameters of method " + method.getName());
-
-    }
-
-    /**
-     * 1, test if argi is null
-     * 2, test if argi.getXX() returns null
-     * 3, assign url with argi.getXX()
-     */
-    private String generateGetUrlNullCheck(int index, Class<?> type, String 
method) {
-        // Null point check
-        StringBuilder code = new StringBuilder();
-        code.append(String.format("if (arg%d == null) throw new 
IllegalArgumentException(\"%s argument == null\");\n",
-                index, type.getName()));
-        code.append(String.format("if (arg%d.%s() == null) throw new 
IllegalArgumentException(\"%s argument %s() == null\");\n",
-                index, method, type.getName(), method));
-
-        code.append(String.format("%s url = arg%d.%s();\n", 
URL.class.getName(), index, method));
-        return code.toString();
-    }
-    
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.extension;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.utils.StringUtils;
+
+/**
+ * Code generator for Adaptive class
+ */
+public class AdaptiveClassCodeGenerator {
+    
+    private static final Logger logger = 
LoggerFactory.getLogger(AdaptiveClassCodeGenerator.class);
+
+    private static final String CLASSNAME_INVOCATION = 
"org.apache.dubbo.rpc.Invocation";
+    
+    private static final String CODE_PACKAGE = "package %s;\n";
+    
+    private static final String CODE_IMPORTS = "import %s;\n";
+    
+    private static final String CODE_CLASS_DECLARATION = "public class 
%s$Adaptive implements %s {\n";
+    
+    private static final String CODE_METHOD_DECLARATION = "public %s %s(%s) %s 
{\n%s}\n";
+    
+    private static final String CODE_METHOD_ARGUMENT = "%s arg%d";
+    
+    private static final String CODE_METHOD_THROWS = "throws %s";
+    
+    private static final String CODE_UNSUPPORTED = "throw new 
UnsupportedOperationException(\"The method %s of interface %s is not adaptive 
method!\");\n";
+    
+    private static final String CODE_URL_NULL_CHECK = "if (arg%d == null) 
throw new IllegalArgumentException(\"url == null\");\n%s url = arg%d;\n";
+    
+    private static final String CODE_EXT_NAME_ASSIGNMENT = "String extName = 
%s;\n";
+    
+    private static final String CODE_EXT_NAME_NULL_CHECK = "if(extName == 
null) "
+                    + "throw new IllegalStateException(\"Failed to get 
extension (%s) name from url (\" + url.toString() + \") use keys(%s)\");\n";
+    
+    private static final String CODE_INVOCATION_ARGUMENT_NULL_CHECK = "if 
(arg%d == null) throw new IllegalArgumentException(\"invocation == null\"); "
+                    + "String methodName = arg%d.getMethodName();\n";
+    
+    
+    private static final String CODE_EXTENSION_ASSIGNMENT = "%s extension = 
(%<s)%s.getExtensionLoader(%s.class).getExtension(extName);\n";
+
+    private static final String CODE_EXTENSION_METHOD_INVOKE_ARGUMENT = "arg%d 
";
+
+    private final Class<?> type;
+    
+    private String defaultExtName;
+    
+    public AdaptiveClassCodeGenerator(Class<?> type, String defaultExtName) {
+        this.type = type;
+        this.defaultExtName = defaultExtName;
+    }
+    
+    /**
+     * test if given type has at least one method annotated with 
<code>SPI</code>
+     */
+    private boolean hasAdaptiveMethod() {
+        return Arrays.stream(type.getMethods()).anyMatch(m -> 
m.isAnnotationPresent(Adaptive.class));
+    }
+    
+    /**
+     * generate and return class code
+     */
+    public String generate() {
+        // no need to generate adaptive class since there's no adaptive method 
found.
+        if (!hasAdaptiveMethod()) {
+            throw new IllegalStateException("No adaptive method exist on 
extension " + type.getName() + ", refuse to create the adaptive class!");
+        }
+
+        StringBuilder code = new StringBuilder();
+        code.append(generatePackageInfo());
+        code.append(generateImports());
+        code.append(generateClassDeclaration());
+        
+        Method[] methods = type.getMethods();
+        for (Method method : methods) {
+            code.append(generateMethod(method));
+        }
+        code.append("}");
+        
+        if (logger.isDebugEnabled()) {
+            logger.debug(code.toString());
+        }
+        return code.toString();
+    }
+
+    /**
+     * generate package info
+     */
+    private String generatePackageInfo() {
+        return String.format(CODE_PACKAGE, type.getPackage().getName());
+    }
+
+    /**
+     * generate imports
+     */
+    private String generateImports() {
+        return String.format(CODE_IMPORTS, ExtensionLoader.class.getName());
+    }
+
+    /**
+     * generate class declaration
+     */
+    private String generateClassDeclaration() {
+        return String.format(CODE_CLASS_DECLARATION, type.getSimpleName(), 
type.getCanonicalName());
+    }
+    
+    /**
+     * generate method not annotated with Adaptive with throwing unsupported 
exception 
+     */
+    private String generateUnsupported(Method method) {
+        return String.format(CODE_UNSUPPORTED, method, type.getName());
+    }
+    
+    /**
+     * get index of parameter with type URL
+     */
+    private int getUrlTypeIndex(Method method) {            
+        int urlTypeIndex = -1;
+        Class<?>[] pts = method.getParameterTypes();
+        for (int i = 0; i < pts.length; ++i) {
+            if (pts[i].equals(URL.class)) {
+                urlTypeIndex = i;
+                break;
+            }
+        }
+        return urlTypeIndex;
+    }
+    
+    /**
+     * generate method declaration
+     */
+    private String generateMethod(Method method) {
+        String methodReturnType = method.getReturnType().getCanonicalName();
+        String methodName = method.getName();
+        String methodContent = generateMethodContent(method);
+        String methodArgs = generateMethodArguments(method);
+        String methodThrows = generateMethodThrows(method);
+        return String.format(CODE_METHOD_DECLARATION, methodReturnType, 
methodName, methodArgs, methodThrows, methodContent);
+    }
+
+    /**
+     * generate method arguments
+     */
+    private String generateMethodArguments(Method method) {
+        Class<?>[] pts = method.getParameterTypes();
+        return IntStream.range(0, pts.length)
+                        .mapToObj(i -> String.format(CODE_METHOD_ARGUMENT, 
pts[i].getCanonicalName(), i))
+                        .collect(Collectors.joining(", "));
+    }
+    
+    /**
+     * generate method throws 
+     */
+    private String generateMethodThrows(Method method) {
+        Class<?>[] ets = method.getExceptionTypes();
+        if (ets.length > 0) {
+            String list = 
Arrays.stream(ets).map(Class::getCanonicalName).collect(Collectors.joining(", 
"));
+            return String.format(CODE_METHOD_THROWS, list);
+        } else {
+            return "";
+        }
+    }
+    
+    /**
+     * generate method URL argument null check 
+     */
+    private String generateUrlNullCheck(int index) {
+        return String.format(CODE_URL_NULL_CHECK, index, URL.class.getName(), 
index);
+    }
+    
+    /**
+     * generate method content
+     */
+    private String generateMethodContent(Method method) {
+        Adaptive adaptiveAnnotation = method.getAnnotation(Adaptive.class);
+        StringBuilder code = new StringBuilder(512);
+        if (adaptiveAnnotation == null) {
+            return generateUnsupported(method);
+        } else {
+            int urlTypeIndex = getUrlTypeIndex(method);
+            
+            // found parameter in URL type
+            if (urlTypeIndex != -1) {
+                // Null Point check
+                code.append(generateUrlNullCheck(urlTypeIndex));
+            } else {
+                // did not find parameter in URL type
+                code.append(generateUrlAssignmentIndirectly(method));
+            }
+
+            String[] value = getMethodAdaptiveValue(adaptiveAnnotation);
+
+            boolean hasInvocation = hasInvocationArgument(method);
+            
+            code.append(generateInvocationArgumentNullCheck(method));
+            
+            code.append(generateExtNameAssignment(value, hasInvocation));
+            // check extName == null?
+            code.append(generateExtNameNullCheck(value));
+            
+            code.append(generateExtensionAssignment());
+
+            // return statement
+            code.append(generateReturnAndInvocation(method));
+        }
+        
+        return code.toString();
+    }
+
+    /**
+     * generate code for variable extName null check
+     */
+    private String generateExtNameNullCheck(String[] value) {
+        return String.format(CODE_EXT_NAME_NULL_CHECK, type.getName(), 
Arrays.toString(value));
+    }
+
+    /**
+     * generate extName assigment code
+     */
+    private String generateExtNameAssignment(String[] value, boolean 
hasInvocation) {
+        // TODO: refactor it
+        String getNameCode = null;
+        for (int i = value.length - 1; i >= 0; --i) {
+            if (i == value.length - 1) {
+                if (null != defaultExtName) {
+                    if (!"protocol".equals(value[i])) {
+                        if (hasInvocation) {
+                            getNameCode = 
String.format("url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], 
defaultExtName);
+                        } else {
+                            getNameCode = 
String.format("url.getParameter(\"%s\", \"%s\")", value[i], defaultExtName);
+                        }
+                    } else {
+                        getNameCode = String.format("( url.getProtocol() == 
null ? \"%s\" : url.getProtocol() )", defaultExtName);
+                    }
+                } else {
+                    if (!"protocol".equals(value[i])) {
+                        if (hasInvocation) {
+                            getNameCode = 
String.format("url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], 
defaultExtName);
+                        } else {
+                            getNameCode = 
String.format("url.getParameter(\"%s\")", value[i]);
+                        }
+                    } else {
+                        getNameCode = "url.getProtocol()";
+                    }
+                }
+            } else {
+                if (!"protocol".equals(value[i])) {
+                    if (hasInvocation) {
+                        getNameCode = 
String.format("url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], 
defaultExtName);
+                    } else {
+                        getNameCode = String.format("url.getParameter(\"%s\", 
%s)", value[i], getNameCode);
+                    }
+                } else {
+                    getNameCode = String.format("url.getProtocol() == null ? 
(%s) : url.getProtocol()", getNameCode);
+                }
+            }
+        }
+        
+        return String.format(CODE_EXT_NAME_ASSIGNMENT, getNameCode);
+    }
+
+    /**
+     * @return
+     */
+    private String generateExtensionAssignment() {
+        return String.format(CODE_EXTENSION_ASSIGNMENT, type.getName(), 
ExtensionLoader.class.getSimpleName(), type.getName());
+    }
+
+    /**
+     * generate method invocation statement and return it if necessary
+     */
+    private String generateReturnAndInvocation(Method method) {
+        String returnStatement = method.getReturnType().equals(void.class) ? 
"" : "return ";
+
+        String args = IntStream.range(0, method.getParameters().length)
+                .mapToObj(i -> 
String.format(CODE_EXTENSION_METHOD_INVOKE_ARGUMENT, i))
+                .collect(Collectors.joining(", "));
+
+        return returnStatement + String.format("extension.%s(%s);\n", 
method.getName(), args);
+    }
+    
+    /**
+     * test if method has argument of type <code>Invocation</code>
+     */
+    private boolean hasInvocationArgument(Method method) {
+        Class<?>[] pts = method.getParameterTypes();
+        return Arrays.stream(pts).anyMatch(p -> 
CLASSNAME_INVOCATION.equals(p.getName()));
+    }
+    
+    /**
+     * generate code to test argument of type <code>Invocation</code> is null
+     */
+    private String generateInvocationArgumentNullCheck(Method method) {
+        Class<?>[] pts = method.getParameterTypes();
+        return IntStream.range(0, pts.length).filter(i -> 
CLASSNAME_INVOCATION.equals(pts[i].getName()))
+                        .mapToObj(i -> 
String.format(CODE_INVOCATION_ARGUMENT_NULL_CHECK, i, i))
+                        .findFirst().orElse("");
+    }
+
+    /**
+     * get value of adaptive annotation or if empty return splitted simple name
+     */
+    private String[] getMethodAdaptiveValue(Adaptive adaptiveAnnotation) {
+        String[] value = adaptiveAnnotation.value();
+        // value is not set, use the value generated from class name as the key
+        if (value.length == 0) {
+            String splitName = 
StringUtils.camelToSplitName(type.getSimpleName(), ".");
+            value = new String[]{splitName};
+        }
+        return value;
+    }
+
+    /**
+     * get parameter with type <code>URL</code> from method parameter:
+     * <p>
+     * test if parameter has method which returns type <code>URL</code>
+     * <p>
+     * if not found, throws IllegalStateException
+     */
+    private String generateUrlAssignmentIndirectly(Method method) {
+        Class<?>[] pts = method.getParameterTypes();
+        
+        // find URL getter method
+        for (int i = 0; i < pts.length; ++i) {
+            for (Method m : pts[i].getMethods()) {
+                String name = m.getName();
+                if ((name.startsWith("get") || name.length() > 3)
+                        && Modifier.isPublic(m.getModifiers())
+                        && !Modifier.isStatic(m.getModifiers())
+                        && m.getParameterTypes().length == 0
+                        && m.getReturnType() == URL.class) {
+                    return generateGetUrlNullCheck(i, pts[i], name);
+                }
+            }
+        }
+        
+        // getter method not found, throw
+        throw new IllegalStateException("Failed to create adaptive class for 
interface " + type.getName()
+                        + ": not found url parameter or url attribute in 
parameters of method " + method.getName());
+
+    }
+
+    /**
+     * 1, test if argi is null
+     * 2, test if argi.getXX() returns null
+     * 3, assign url with argi.getXX()
+     */
+    private String generateGetUrlNullCheck(int index, Class<?> type, String 
method) {
+        // Null point check
+        StringBuilder code = new StringBuilder();
+        code.append(String.format("if (arg%d == null) throw new 
IllegalArgumentException(\"%s argument == null\");\n",
+                index, type.getName()));
+        code.append(String.format("if (arg%d.%s() == null) throw new 
IllegalArgumentException(\"%s argument %s() == null\");\n",
+                index, method, type.getName(), method));
+
+        code.append(String.format("%s url = arg%d.%s();\n", 
URL.class.getName(), index, method));
+        return code.toString();
+    }
+    
+}

Reply via email to