This is an automated email from the ASF dual-hosted git repository. liubao pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-java-chassis.git
commit 9147c70ac78f2dcd1d4e629da15eb51773234f73 Author: wujimin <wuji...@huawei.com> AuthorDate: Thu Jun 21 00:14:51 2018 +0800 [SCB-194] boot from BeanUtils.init will auto scan main class package --- .../main/resources/META-INF/spring/cse.bean.xml | 2 +- foundations/foundation-common/pom.xml | 19 +++-- .../foundation/common/utils/BeanUtils.java | 40 ++++++++++ .../foundation/common/utils/JvmUtils.java | 53 +++++++++++++ .../foundation/common/utils/TestBeanUtils.java | 90 ++++++++++++++++++++++ .../foundation/common/utils/TestJvmUtils.java | 71 +++++++++++++++++ 6 files changed, 269 insertions(+), 6 deletions(-) diff --git a/core/src/main/resources/META-INF/spring/cse.bean.xml b/core/src/main/resources/META-INF/spring/cse.bean.xml index 44817fb..8ae429a 100644 --- a/core/src/main/resources/META-INF/spring/cse.bean.xml +++ b/core/src/main/resources/META-INF/spring/cse.bean.xml @@ -23,7 +23,7 @@ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:annotation-config/> <!-- <context:spring-configured /> --> - <context:component-scan base-package="org.apache.servicecomb"/> + <context:component-scan base-package="${scb-scan-package:org.apache.servicecomb}"/> <bean class="org.apache.servicecomb.core.config.ConfigurationSpringInitializer"> <property name="configId" value="config"/> diff --git a/foundations/foundation-common/pom.xml b/foundations/foundation-common/pom.xml index d1a369f..dced02a 100644 --- a/foundations/foundation-common/pom.xml +++ b/foundations/foundation-common/pom.xml @@ -48,11 +48,6 @@ <artifactId>slf4j-api</artifactId> </dependency> <dependency> - <groupId>org.slf4j</groupId> - <artifactId>slf4j-log4j12</artifactId> - <scope>test</scope> - </dependency> - <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </dependency> @@ -76,5 +71,19 @@ <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + </dependency> + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.servicecomb</groupId> + <artifactId>foundation-test-scaffolding</artifactId> + </dependency> </dependencies> </project> diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/BeanUtils.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/BeanUtils.java index cb1536e..103ac79 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/BeanUtils.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/BeanUtils.java @@ -17,13 +17,22 @@ package org.apache.servicecomb.foundation.common.utils; +import java.util.LinkedHashSet; +import java.util.Set; + +import org.apache.commons.lang3.StringUtils; import org.springframework.aop.TargetClassAware; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; + public final class BeanUtils { public static final String DEFAULT_BEAN_RESOURCE = "classpath*:META-INF/spring/*.bean.xml"; + public static final String SCB_SCAN_PACKAGE = "scb-scan-package"; + + private static final String SCB_PACKAGE = "org.apache.servicecomb"; + private static ApplicationContext context; private BeanUtils() { @@ -33,10 +42,41 @@ public final class BeanUtils { init(DEFAULT_BEAN_RESOURCE); } + public static void init(String... configLocations) { + prepareServiceCombScanPackage(); + context = new ClassPathXmlApplicationContext(configLocations); } + public static void prepareServiceCombScanPackage() { + Set<String> scanPackags = new LinkedHashSet<>(); + // add exists settings + String exists = System.getProperty(SCB_SCAN_PACKAGE); + if (exists != null) { + for (String exist : exists.trim().split(",")) { + if (!exist.isEmpty()) { + scanPackags.add(exist.trim()); + } + } + } + + // ensure servicecomb package exist + scanPackags.add(SCB_PACKAGE); + + // add main class package + Class<?> mainClass = JvmUtils.findMainClass(); + if (mainClass != null) { + String pkg = mainClass.getPackage().getName(); + if (!pkg.startsWith(SCB_PACKAGE)) { + scanPackags.add(pkg); + } + } + + // finish + System.setProperty(SCB_SCAN_PACKAGE, StringUtils.join(scanPackags, ",")); + } + public static ApplicationContext getContext() { return context; } diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/JvmUtils.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/JvmUtils.java new file mode 100644 index 0000000..e2b2b86 --- /dev/null +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/JvmUtils.java @@ -0,0 +1,53 @@ +/* + * 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.servicecomb.foundation.common.utils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.annotations.VisibleForTesting; + +public final class JvmUtils { + private static final Logger LOGGER = LoggerFactory.getLogger(JvmUtils.class); + + // available for oracle jdk/ open jdk, and maybe others + @VisibleForTesting + static final String SUN_JAVA_COMMAND = "sun.java.command"; + + private JvmUtils() { + } + + /** + * + * @return main class or null, never throw exception + */ + public static Class<?> findMainClass() { + String command = System.getProperty(SUN_JAVA_COMMAND); + if (command == null || command.isEmpty()) { + return null; + } + + // command is main class and args + String mainClass = command.trim().split(" ")[0]; + try { + return Class.forName(mainClass); + } catch (Throwable e) { + LOGGER.warn("\"{}\" is not a valid class.", mainClass, e); + return null; + } + } +} \ No newline at end of file diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestBeanUtils.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestBeanUtils.java index fc7afcf..c9a28c1 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestBeanUtils.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestBeanUtils.java @@ -17,9 +17,15 @@ package org.apache.servicecomb.foundation.common.utils; import org.aspectj.lang.annotation.Aspect; +import org.junit.AfterClass; import org.junit.Assert; +import org.junit.BeforeClass; import org.junit.Test; import org.springframework.aop.aspectj.annotation.AspectJProxyFactory; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +import mockit.Expectations; +import mockit.Mocked; public class TestBeanUtils { static interface Intf { @@ -34,6 +40,16 @@ public class TestBeanUtils { static class MyAspect { } + @BeforeClass + public static void setup() { + System.clearProperty(BeanUtils.SCB_SCAN_PACKAGE); + } + + @AfterClass + public static void tearDown() { + System.clearProperty(BeanUtils.SCB_SCAN_PACKAGE); + } + @Test public void test() { Intf target = new Impl(); @@ -45,4 +61,78 @@ public class TestBeanUtils { Assert.assertEquals(Impl.class, BeanUtils.getImplClassFromBean(proxy)); Assert.assertEquals(Impl.class, BeanUtils.getImplClassFromBean(new Impl())); } + + @Test + public void prepareServiceCombScanPackage_noExist_noMain() { + System.clearProperty(BeanUtils.SCB_SCAN_PACKAGE); + new Expectations(JvmUtils.class) { + { + JvmUtils.findMainClass(); + result = null; + } + }; + + BeanUtils.prepareServiceCombScanPackage(); + + Assert.assertEquals("org.apache.servicecomb", System.getProperty(BeanUtils.SCB_SCAN_PACKAGE)); + } + + @Test + public void prepareServiceCombScanPackage_noExist_scbMain() { + System.clearProperty(BeanUtils.SCB_SCAN_PACKAGE); + new Expectations(JvmUtils.class) { + { + JvmUtils.findMainClass(); + result = TestBeanUtils.class; + } + }; + + BeanUtils.prepareServiceCombScanPackage(); + + Assert.assertEquals("org.apache.servicecomb", System.getProperty(BeanUtils.SCB_SCAN_PACKAGE)); + } + + @Test + public void prepareServiceCombScanPackage_noExist_otherMain() { + System.clearProperty(BeanUtils.SCB_SCAN_PACKAGE); + new Expectations(JvmUtils.class) { + { + JvmUtils.findMainClass(); + result = String.class; + } + }; + + BeanUtils.prepareServiceCombScanPackage(); + + Assert.assertEquals("org.apache.servicecomb,java.lang", System.getProperty(BeanUtils.SCB_SCAN_PACKAGE)); + } + + @Test + public void prepareServiceCombScanPackage_exist() { + System.setProperty(BeanUtils.SCB_SCAN_PACKAGE, "a.b,,c.d"); + new Expectations(JvmUtils.class) { + { + JvmUtils.findMainClass(); + result = null; + } + }; + + BeanUtils.prepareServiceCombScanPackage(); + + Assert.assertEquals("a.b,c.d,org.apache.servicecomb", System.getProperty(BeanUtils.SCB_SCAN_PACKAGE)); + } + + @Test + public void init(@Mocked ClassPathXmlApplicationContext context) { + System.clearProperty(BeanUtils.SCB_SCAN_PACKAGE); + new Expectations(JvmUtils.class) { + { + JvmUtils.findMainClass(); + result = TestBeanUtils.class; + } + }; + BeanUtils.init(); + + Assert.assertEquals("org.apache.servicecomb", System.getProperty(BeanUtils.SCB_SCAN_PACKAGE)); + } } diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestJvmUtils.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestJvmUtils.java new file mode 100644 index 0000000..d16792f --- /dev/null +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestJvmUtils.java @@ -0,0 +1,71 @@ +/* + * 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.servicecomb.foundation.common.utils; + +import org.apache.servicecomb.foundation.test.scaffolding.log.LogCollector; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class TestJvmUtils { + static String orgCmd = System.getProperty(JvmUtils.SUN_JAVA_COMMAND); + + @Before + public void setup() { + System.clearProperty(JvmUtils.SUN_JAVA_COMMAND); + } + + @AfterClass + public static void tearDown() { + if (orgCmd == null) { + System.clearProperty(JvmUtils.SUN_JAVA_COMMAND); + return; + } + + System.setProperty(JvmUtils.SUN_JAVA_COMMAND, orgCmd); + } + + @Test + public void findMainClass_notExist() { + Assert.assertNull(JvmUtils.findMainClass()); + } + + @Test + public void findMainClass_existButEmpty() { + System.setProperty(JvmUtils.SUN_JAVA_COMMAND, ""); + Assert.assertNull(JvmUtils.findMainClass()); + } + + @Test + public void findMainClass_invalid() { + LogCollector logCollector = new LogCollector(); + + System.setProperty(JvmUtils.SUN_JAVA_COMMAND, "invalidCls"); + + Assert.assertNull(JvmUtils.findMainClass()); + Assert.assertEquals("\"invalidCls\" is not a valid class.", logCollector.getEvents().get(0).getMessage()); + logCollector.teardown(); + } + + @Test + public void findMainClass_normal() { + System.setProperty(JvmUtils.SUN_JAVA_COMMAND, TestJvmUtils.class.getName() + " arg"); + + Assert.assertEquals(TestJvmUtils.class, JvmUtils.findMainClass()); + } +}