diff --git a/.github/workflows/build-and-test-pr.yml b/.github/workflows/build-and-test-pr.yml index 2d76db5fc8..28c669e39d 100644 --- a/.github/workflows/build-and-test-pr.yml +++ b/.github/workflows/build-and-test-pr.yml @@ -26,6 +26,22 @@ jobs: uses: apache/skywalking-eyes@main env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: "Set up JDK 17" + uses: actions/setup-java@v3 + with: + distribution: 'zulu' + java-version: 17 + - name: "Compile Dubbo (Linux)" + run: | + ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast -T 2C clean install -DskipTests=true -DskipIntegrationTests=true -Dcheckstyle.skip=true -Dcheckstyle_unix.skip=true -Drat.skip=true -Dmaven.javadoc.skip=true + - name: Check Dependencies' License + uses: apache/skywalking-eyes/dependency@main + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + config: .licenserc.yaml + mode: check + build-source: runs-on: ubuntu-latest outputs: diff --git a/.licenserc.yaml b/.licenserc.yaml index 00b7286672..fcbf54b12b 100644 --- a/.licenserc.yaml +++ b/.licenserc.yaml @@ -80,3 +80,118 @@ header: comment: on-failure license-location-threshold: 130 + +dependency: + files: + - pom.xml + - dubbo-dependencies-bom/pom.xml + licenses: + - name: com.alibaba.spring:spring-context-support + license: Apache-2.0 + - name: com.fasterxml.jackson.core:jackson-annotations + license: Apache-2.0 + - name: com.fasterxml.jackson.core:jackson-core + license: Apache-2.0 + - name: com.fasterxml.jackson.core:jackson-databind + license: Apache-2.0 + - name: com.fasterxml.jackson.dataformat:jackson-dataformat-yaml + license: Apache-2.0 + - name: com.fasterxml.jackson.datatype:jackson-datatype-jsr310 + license: Apache-2.0 + - name: com.google.code.gson:gson + license: Apache-2.0 + - name: com.google.guava:listenablefuture + license: Apache-2.0 + - name: com.salesforce.servicelibs:grpc-contrib + license: BSD 3-clause + - name: com.squareup.okhttp3:logging-interceptor + license: Apache-2.0 + - name: com.squareup.okhttp3:okhttp + license: Apache-2.0 + - name: com.squareup.okio:okio + license: Apache-2.0 + - name: com.sun.xml.fastinfoset:FastInfoset + license: Apache-2.0 + - name: io.envoyproxy.controlplane:api + license: Apache-2.0 + - name: io.swagger:swagger-annotations + license: Apache-2.0 + - name: io.swagger:swagger-models + license: Apache-2.0 + - name: org.springframework.boot:spring-boot + license: Apache-2.0 + - name: org.springframework.boot:spring-boot-actuator + license: Apache-2.0 + - name: org.springframework.boot:spring-boot-autoconfigure + license: Apache-2.0 + - name: org.springframework.boot:spring-boot-configuration-processor + license: Apache-2.0 + - name: org.springframework.boot:spring-boot-starter + license: Apache-2.0 + - name: org.springframework.boot:spring-boot-starter-actuator + license: Apache-2.0 + - name: org.springframework.boot:spring-boot-starter-logging + license: Apache-2.0 + - name: org.springframework.boot:spring-boot-starter-tomcat + license: Apache-2.0 + - name: org.springframework.boot:spring-boot-starter-web + license: Apache-2.0 + - name: org.slf4j:slf4j-api + license: MIT + - name: org.slf4j:slf4j-log4j12 + license: MIT + - name: org.jboss.resteasy:resteasy-jaxrs + license: Apache-2.0 + - name: org.jboss.resteasy:resteasy-client + license: Apache-2.0 + - name: org.jboss.resteasy:resteasy-netty4 + license: Apache-2.0 + - name: org.jboss.resteasy:resteasy-jdk-http + license: Apache-2.0 + - name: org.jboss.resteasy:resteasy-jackson-provider + license: Apache-2.0 + - name: org.jboss.resteasy:resteasy-jaxb-provider + license: Apache-2.0 + - name: net.jcip:jcip-annotations + license: Apache-2.0 + - name: org.apache.zookeeper:zookeeper + license: Apache-2.0 + - name: org.apache.zookeeper:zookeeper-jute + license: Apache-2.0 + - name: net.bytebuddy:byte-buddy + license: Apache-2.0 + - name: javax.enterprise:cdi-api + license: Apache-2.0 + - name: org.codehaus.plexus:plexus-component-annotations + license: Apache-2.0 + - name: org.slf4j:jcl-over-slf4j + license: Apache-2.0 + - name: org.slf4j:jul-to-slf4j + license: Apache-2.0 + # multi license + - name: org.javassist:javassist + license: Apache-2.0 + - name: javax.annotation:javax.annotation-api + license: CDDL-1.0 + - name: com.salesforce.servicelibs:jprotoc + license: CDDL-1.0 + - name: org.checkerframework:checker-compat-qual + license: MIT + - name: ch.qos.logback:logback-classic + license: EPL-1.0 + - name: ch.qos.logback:logback-core + license: EPL-1.0 + - name: javax.servlet:javax.servlet-api + license: CDDL-1.1 + - name: com.sun.activation:javax.activation + license: CDDL-1.1 + - name: javax.activation:activation + license: CDDL-1.1 + - name: jakarta.annotation:jakarta.annotation-api + license: EPL-2.0 + - name: org.glassfish:jakarta.el + license: EPL-2.0 + - name: org.jboss.spec.javax.annotation:jboss-annotations-api_1.2_spec + license: CDDL-1.1 + excludes: + - name: javax.xml.bind:jsr173_api diff --git a/Jenkinsfile.sonar b/Jenkinsfile.sonar new file mode 100644 index 0000000000..b16366afb0 --- /dev/null +++ b/Jenkinsfile.sonar @@ -0,0 +1,49 @@ +/* + * + * 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. + * + */ +pipeline { + agent any + + tools { + maven 'maven_3_latest' + jdk 'jdk_11_latest' + } + + stages { + stage('Code Quality') { + steps { + echo 'Checking Code Quality on SonarCloud' + script { + // Main parameters + def sonarcloudParams="" + if ( env.BRANCH_NAME.startsWith("PR-") ) { + // this is a pull request + withCredentials([string(credentialsId: 'sonarcloud-token', variable: 'SONAR_TOKEN')]) { + sh 'mvn --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean verify sonar:sonar -Pjacoco -Dsonar.host.url=https://sonarcloud.io -Dsonar.organization=apache -Dsonar.projectKey=apache_dubbo -Dsonar.pullrequest.branch=${CHANGE_BRANCH} -Dsonar.pullrequest.base=${CHANGE_TARGET} -Dsonar.pullrequest.key=${CHANGE_ID} -Dsonar.login=${SONAR_TOKEN}' + } + } else { + // this is just a branch + withCredentials([string(credentialsId: 'sonarcloud-token', variable: 'SONAR_TOKEN')]) { + sh 'mvn --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean verify sonar:sonar -Pjacoco -Dsonar.host.url=https://sonarcloud.io -Dsonar.organization=apache -Dsonar.projectKey=apache_dubbo -Dsonar.branch.name=${BRANCH_NAME} -Dsonar.login=${SONAR_TOKEN}' + } + } + } + } + } + } +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/metadata/definition/ServiceDefinitionBuilderTest.java b/dubbo-common/src/test/java/org/apache/dubbo/metadata/definition/ServiceDefinitionBuilderTest.java index 6d59887d18..cc9c6f9c8b 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/metadata/definition/ServiceDefinitionBuilderTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/metadata/definition/ServiceDefinitionBuilderTest.java @@ -21,6 +21,7 @@ import org.apache.dubbo.metadata.definition.model.MethodDefinition; import org.apache.dubbo.metadata.definition.model.TypeDefinition; import org.apache.dubbo.metadata.definition.service.ComplexObject; import org.apache.dubbo.metadata.definition.service.DemoService; +import org.apache.dubbo.rpc.model.FrameworkModel; import org.apache.dubbo.rpc.model.FrameworkModel; import org.junit.jupiter.api.AfterAll; @@ -52,6 +53,7 @@ public class ServiceDefinitionBuilderTest { @Test public void testBuilderComplexObject() { + TypeDefinitionBuilder.initBuilders(FrameworkModel.defaultModel()); FullServiceDefinition fullServiceDefinition = ServiceDefinitionBuilder.buildFullDefinition(DemoService.class); checkComplexObjectAsParam(fullServiceDefinition); } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java index 42073fec71..b1ec2c7274 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java @@ -72,6 +72,7 @@ import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY; import static org.apache.dubbo.common.constants.CommonConstants.CLUSTER_KEY; import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN; import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER; +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_SERVER_SHUTDOWN_TIMEOUT; import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_VERSION_KEY; import static org.apache.dubbo.common.constants.CommonConstants.ENABLED_KEY; import static org.apache.dubbo.common.constants.CommonConstants.EXTRA_KEYS_KEY; @@ -920,7 +921,10 @@ public class RegistryProtocol implements Protocol, ScopeModelAware { } //TODO wait for shutdown timeout is a bit strange - int timeout = ConfigurationUtils.getServerShutdownTimeout(subscribeUrl.getScopeModel()); + int timeout = DEFAULT_SERVER_SHUTDOWN_TIMEOUT; + if (subscribeUrl != null) { + timeout = ConfigurationUtils.getServerShutdownTimeout(subscribeUrl.getScopeModel()); + } executor.schedule(() -> { try { exporter.unexport(); diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/AccessLogFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/AccessLogFilter.java index ec74ff6d77..3433fb4dc6 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/AccessLogFilter.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/AccessLogFilter.java @@ -212,7 +212,7 @@ public class AccessLogFilter implements Filter { String now = fileNameFormatter.format(new Date()); String last = fileNameFormatter.format(new Date(file.lastModified())); if (!now.equals(last)) { - File archive = new File(file.getAbsolutePath() + "." + last); + File archive = new File(file.getAbsolutePath() + "." + now); file.renameTo(archive); } } diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/RpcUtils.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/RpcUtils.java index 8f864efb46..816350eaa8 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/RpcUtils.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/RpcUtils.java @@ -78,10 +78,22 @@ public class RpcUtils { && invocation.getInvoker().getUrl() != null && invocation.getInvoker().getInterface() != GenericService.class && !invocation.getMethodName().startsWith("$")) { + Type[] returnTypes = null; + if (invocation instanceof RpcInvocation) { + returnTypes = ((RpcInvocation) invocation).getReturnTypes(); + if (returnTypes != null) { + return returnTypes; + } + } String service = invocation.getInvoker().getUrl().getServiceInterface(); if (StringUtils.isNotEmpty(service)) { Method method = getMethodByService(invocation, service); - return ReflectUtils.getReturnTypes(method); + if (method != null) { + returnTypes = ReflectUtils.getReturnTypes(method); + } + } + if (returnTypes != null) { + return returnTypes; } } } catch (Throwable t) { @@ -150,7 +162,7 @@ public class RpcUtils { } Class[] parameterTypes = new Class[types.length]; for (int i = 0; i < types.length; i++) { - parameterTypes[i] = ReflectUtils.forName(types[0]); + parameterTypes[i] = ReflectUtils.forName(types[i]); } return parameterTypes; } diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/RpcUtilsTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/RpcUtilsTest.java index ed5271191f..f93d896c22 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/RpcUtilsTest.java +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/RpcUtilsTest.java @@ -35,6 +35,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import static org.apache.dubbo.common.constants.CommonConstants.$INVOKE; import static org.apache.dubbo.rpc.Constants.AUTO_ATTACH_INVOCATIONID_KEY; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -153,7 +154,7 @@ public class RpcUtilsTest { } @Test - public void testGetReturnTypes() throws Exception { + public void testGetReturnTypesUseCache() throws Exception { Class demoServiceClass = DemoService.class; String serviceName = demoServiceClass.getName(); Invoker invoker = mock(Invoker.class); @@ -216,6 +217,114 @@ public class RpcUtilsTest { Assertions.assertArrayEquals(types5, inv5.getReturnTypes()); } + @Test + public void testGetReturnTypesWithoutCache() throws Exception { + Class demoServiceClass = DemoService.class; + String serviceName = demoServiceClass.getName(); + Invoker invoker = mock(Invoker.class); + given(invoker.getUrl()).willReturn(URL.valueOf( + "test://127.0.0.1:1/org.apache.dubbo.rpc.support.DemoService?interface=org.apache.dubbo.rpc.support.DemoService")); + + RpcInvocation inv = new RpcInvocation("testReturnType", serviceName, "", new Class[] {String.class}, null, null, invoker, null); + inv.setReturnTypes(null); + Type[] types = RpcUtils.getReturnTypes(inv); + Assertions.assertNotNull(types); + Assertions.assertEquals(2, types.length); + Assertions.assertEquals(String.class, types[0]); + Assertions.assertEquals(String.class, types[1]); + + RpcInvocation inv1 = + new RpcInvocation("testReturnType1", serviceName, "", new Class[] {String.class}, null, null, invoker, null); + inv1.setReturnTypes(null); + java.lang.reflect.Type[] types1 = RpcUtils.getReturnTypes(inv1); + Assertions.assertNotNull(types1); + Assertions.assertEquals(2, types1.length); + Assertions.assertEquals(List.class, types1[0]); + Assertions.assertEquals(demoServiceClass.getMethod("testReturnType1", String.class).getGenericReturnType(), types1[1]); + + RpcInvocation inv2 = + new RpcInvocation("testReturnType2", serviceName, "", new Class[] {String.class}, null, null, invoker, null); + inv2.setReturnTypes(null); + java.lang.reflect.Type[] types2 = RpcUtils.getReturnTypes(inv2); + Assertions.assertNotNull(types2); + Assertions.assertEquals(2, types2.length); + Assertions.assertEquals(String.class, types2[0]); + Assertions.assertEquals(String.class, types2[1]); + + RpcInvocation inv3 = + new RpcInvocation("testReturnType3", serviceName, "", new Class[] {String.class}, null, null, invoker, null); + inv3.setReturnTypes(null); + java.lang.reflect.Type[] types3 = RpcUtils.getReturnTypes(inv3); + Assertions.assertNotNull(types3); + Assertions.assertEquals(2, types3.length); + Assertions.assertEquals(List.class, types3[0]); + java.lang.reflect.Type genericReturnType3 = demoServiceClass.getMethod("testReturnType3", String.class).getGenericReturnType(); + Assertions.assertEquals(((ParameterizedType) genericReturnType3).getActualTypeArguments()[0], types3[1]); + + RpcInvocation inv4 = + new RpcInvocation("testReturnType4", serviceName, "", new Class[] {String.class}, null, null, invoker, null); + inv4.setReturnTypes(null); + java.lang.reflect.Type[] types4 = RpcUtils.getReturnTypes(inv4); + Assertions.assertNotNull(types4); + Assertions.assertEquals(2, types4.length); + Assertions.assertNull(types4[0]); + Assertions.assertNull(types4[1]); + + RpcInvocation inv5 = + new RpcInvocation("testReturnType5", serviceName, "", new Class[] {String.class}, null, null, invoker, null); + inv5.setReturnTypes(null); + java.lang.reflect.Type[] types5 = RpcUtils.getReturnTypes(inv5); + Assertions.assertNotNull(types5); + Assertions.assertEquals(2, types5.length); + Assertions.assertEquals(Map.class, types5[0]); + java.lang.reflect.Type genericReturnType5 = demoServiceClass.getMethod("testReturnType5", String.class).getGenericReturnType(); + Assertions.assertEquals(((ParameterizedType) genericReturnType5).getActualTypeArguments()[0], types5[1]); + } + + + @Test + public void testGetReturnTypesWhenGeneric() throws Exception { + Class demoServiceClass = DemoService.class; + String serviceName = demoServiceClass.getName(); + Invoker invoker = mock(Invoker.class); + given(invoker.getUrl()).willReturn(URL.valueOf( + "test://127.0.0.1:1/org.apache.dubbo.rpc.support.DemoService?interface=org.apache.dubbo.rpc.support.DemoService")); + + RpcInvocation inv = new RpcInvocation("testReturnType", serviceName, "", new Class[] {String.class}, null, null, invoker, null); + inv.setMethodName($INVOKE); + Type[] types = RpcUtils.getReturnTypes(inv); + Assertions.assertNull(types); + + RpcInvocation inv1 = + new RpcInvocation("testReturnType1", serviceName, "", new Class[] {String.class}, null, null, invoker, null); + inv1.setMethodName($INVOKE); + java.lang.reflect.Type[] types1 = RpcUtils.getReturnTypes(inv1); + Assertions.assertNull(types1); + + RpcInvocation inv2 = + new RpcInvocation("testReturnType2", serviceName, "", new Class[] {String.class}, null, null, invoker, null); + inv2.setMethodName($INVOKE); + java.lang.reflect.Type[] types2 = RpcUtils.getReturnTypes(inv2); + Assertions.assertNull(types2); + + RpcInvocation inv3 = + new RpcInvocation("testReturnType3", serviceName, "", new Class[] {String.class}, null, null, invoker, null); + inv3.setMethodName($INVOKE); + java.lang.reflect.Type[] types3 = RpcUtils.getReturnTypes(inv3); + Assertions.assertNull(types3); + + RpcInvocation inv4 = + new RpcInvocation("testReturnType4", serviceName, "", new Class[] {String.class}, null, null, invoker, null); + inv4.setMethodName($INVOKE); + java.lang.reflect.Type[] types4 = RpcUtils.getReturnTypes(inv4); + Assertions.assertNull(types4); + + RpcInvocation inv5 = + new RpcInvocation("testReturnType5", serviceName, "", new Class[] {String.class}, null, null, invoker, null); + inv5.setMethodName($INVOKE); + java.lang.reflect.Type[] types5 = RpcUtils.getReturnTypes(inv5); + Assertions.assertNull(types5); + } @Test public void testGetParameterTypes() { Class demoServiceClass = DemoService.class; @@ -261,8 +370,8 @@ public class RpcUtilsTest { Assertions.assertNotNull(parameterTypes5); Assertions.assertEquals(3, parameterTypes5.length); Assertions.assertEquals(String.class, parameterTypes5[0]); - Assertions.assertEquals(String.class, parameterTypes5[1]); - Assertions.assertEquals(String.class, parameterTypes5[2]); + Assertions.assertEquals(void.class, parameterTypes5[1]); + Assertions.assertEquals(Object.class, parameterTypes5[2]); } @ParameterizedTest diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java index 1b0e748fe3..b70e9c1a4e 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java @@ -32,7 +32,6 @@ import org.apache.dubbo.remoting.exchange.Response; import org.apache.dubbo.remoting.transport.CodecSupport; import org.apache.dubbo.rpc.AppResponse; import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.RpcInvocation; import org.apache.dubbo.rpc.support.RpcUtils; import java.io.IOException; @@ -151,15 +150,10 @@ public class DecodeableRpcResult extends AppResponse implements Codec, Decodeabl private void handleValue(ObjectInput in) throws IOException { try { - Type[] returnTypes; - if (invocation instanceof RpcInvocation) { - returnTypes = ((RpcInvocation) invocation).getReturnTypes(); - } else { - returnTypes = RpcUtils.getReturnTypes(invocation); - } + Type[] returnTypes = RpcUtils.getReturnTypes(invocation); Object value; if (ArrayUtils.isEmpty(returnTypes)) { - // This almost never happens? + // happens when generic invoke or void return value = in.readObject(); } else if (returnTypes.length == 1) { value = in.readObject((Class) returnTypes[0]); diff --git a/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/ObjectInput.java b/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/ObjectInput.java index 0c68993523..4c3ce7c736 100644 --- a/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/ObjectInput.java +++ b/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/ObjectInput.java @@ -32,7 +32,6 @@ public interface ObjectInput extends DataInput { * @throws IOException if an I/O error occurs * @throws ClassNotFoundException if an ClassNotFoundException occurs */ - @Deprecated Object readObject() throws IOException, ClassNotFoundException; /**