http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a2da61d1/software/webapp/src/test/java/brooklyn/entity/webapp/jboss/DynamicWebAppClusterRebindIntegrationTest.java ---------------------------------------------------------------------- diff --git a/software/webapp/src/test/java/brooklyn/entity/webapp/jboss/DynamicWebAppClusterRebindIntegrationTest.java b/software/webapp/src/test/java/brooklyn/entity/webapp/jboss/DynamicWebAppClusterRebindIntegrationTest.java index a1d8d35..0005f49 100644 --- a/software/webapp/src/test/java/brooklyn/entity/webapp/jboss/DynamicWebAppClusterRebindIntegrationTest.java +++ b/software/webapp/src/test/java/brooklyn/entity/webapp/jboss/DynamicWebAppClusterRebindIntegrationTest.java @@ -61,7 +61,7 @@ public class DynamicWebAppClusterRebindIntegrationTest { private TestApplication origApp; private TestApplication newApp; private List<WebAppMonitor> webAppMonitors = new CopyOnWriteArrayList<WebAppMonitor>(); - private ExecutorService executor; + private ExecutorService executor; private ClassLoader classLoader = getClass().getClassLoader(); private LocalManagementContext origManagementContext; @@ -69,7 +69,7 @@ public class DynamicWebAppClusterRebindIntegrationTest { @BeforeMethod(groups = "Integration") public void setUp() { - String warPath = "hello-world.war"; + String warPath = "hello-world.war"; warUrl = getClass().getClassLoader().getResource(warPath); executor = Executors.newCachedThreadPool(); @@ -77,14 +77,14 @@ public class DynamicWebAppClusterRebindIntegrationTest { mementoDir = Files.createTempDir(); origManagementContext = RebindTestUtils.newPersistingManagementContext(mementoDir, classLoader); - localhostProvisioningLocation = new LocalhostMachineProvisioningLocation(); - origApp = ApplicationBuilder.newManagedApp(TestApplication.class, origManagementContext); + localhostProvisioningLocation = new LocalhostMachineProvisioningLocation(); + origApp = ApplicationBuilder.newManagedApp(TestApplication.class, origManagementContext); } @AfterMethod(groups = "Integration", alwaysRun=true) public void tearDown() throws Exception { for (WebAppMonitor monitor : webAppMonitors) { - monitor.terminate(); + monitor.terminate(); } if (executor != null) executor.shutdownNow(); if (newApp != null) Entities.destroyAll(newApp.getManagementContext()); @@ -102,20 +102,20 @@ public class DynamicWebAppClusterRebindIntegrationTest { } private WebAppMonitor newWebAppMonitor(String url) { - WebAppMonitor monitor = new WebAppMonitor(url) -// .delayMillis(0) - .logFailures(LOG); - webAppMonitors.add(monitor); - executor.execute(monitor); - return monitor; + WebAppMonitor monitor = new WebAppMonitor(url) +// .delayMillis(0) + .logFailures(LOG); + webAppMonitors.add(monitor); + executor.execute(monitor); + return monitor; } @Test(groups = "Integration") public void testRebindsToRunningCluster() throws Exception { DynamicWebAppCluster origCluster = origApp.createAndManageChild(EntitySpec.create(DynamicWebAppCluster.class) .configure("memberSpec", EntitySpec.create(JBoss7Server.class).configure("war", warUrl.toString())) - .configure("initialSize", 1)); - + .configure("initialSize", 1)); + origApp.start(ImmutableList.of(localhostProvisioningLocation)); JBoss7Server origJboss = (JBoss7Server) Iterables.find(origCluster.getChildren(), Predicates.instanceOf(JBoss7Server.class)); String jbossUrl = origJboss.getAttribute(JBoss7Server.ROOT_URL);
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a2da61d1/software/webapp/src/test/java/brooklyn/entity/webapp/jboss/Jboss7ServerIntegrationTest.java ---------------------------------------------------------------------- diff --git a/software/webapp/src/test/java/brooklyn/entity/webapp/jboss/Jboss7ServerIntegrationTest.java b/software/webapp/src/test/java/brooklyn/entity/webapp/jboss/Jboss7ServerIntegrationTest.java index 5bae403..a6cf0b8 100644 --- a/software/webapp/src/test/java/brooklyn/entity/webapp/jboss/Jboss7ServerIntegrationTest.java +++ b/software/webapp/src/test/java/brooklyn/entity/webapp/jboss/Jboss7ServerIntegrationTest.java @@ -61,10 +61,10 @@ public class Jboss7ServerIntegrationTest { @BeforeMethod(alwaysRun=true) public void setUp() throws Exception { - String warPath = "hello-world.war"; + String warPath = "hello-world.war"; warUrl = getClass().getClassLoader().getResource(warPath); - localhostProvisioningLocation = new LocalhostMachineProvisioningLocation(); + localhostProvisioningLocation = new LocalhostMachineProvisioningLocation(); app = ApplicationBuilder.newManagedApp(TestApplication.class); keystoreFile = createTemporaryKeyStore("myname", "mypass"); } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a2da61d1/software/webapp/src/test/java/brooklyn/entity/webapp/jboss/Jboss7ServerRebindIntegrationTest.java ---------------------------------------------------------------------- diff --git a/software/webapp/src/test/java/brooklyn/entity/webapp/jboss/Jboss7ServerRebindIntegrationTest.java b/software/webapp/src/test/java/brooklyn/entity/webapp/jboss/Jboss7ServerRebindIntegrationTest.java index f116bff..9a1bd5e 100644 --- a/software/webapp/src/test/java/brooklyn/entity/webapp/jboss/Jboss7ServerRebindIntegrationTest.java +++ b/software/webapp/src/test/java/brooklyn/entity/webapp/jboss/Jboss7ServerRebindIntegrationTest.java @@ -56,13 +56,13 @@ public class Jboss7ServerRebindIntegrationTest extends RebindTestFixtureWithApp private LocalhostMachineProvisioningLocation localhostProvisioningLocation; private TestApplication newApp; private List<WebAppMonitor> webAppMonitors = new CopyOnWriteArrayList<WebAppMonitor>(); - private ExecutorService executor; + private ExecutorService executor; @BeforeMethod(groups = "Integration") @Override public void setUp() throws Exception { super.setUp(); - String warPath = "hello-world.war"; + String warPath = "hello-world.war"; warUrl = getClass().getClassLoader().getResource(warPath); executor = Executors.newCachedThreadPool(); localhostProvisioningLocation = (LocalhostMachineProvisioningLocation) origManagementContext.getLocationRegistry().resolve("localhost"); @@ -72,24 +72,24 @@ public class Jboss7ServerRebindIntegrationTest extends RebindTestFixtureWithApp @AfterMethod(alwaysRun=true) public void tearDown() throws Exception { for (WebAppMonitor monitor : webAppMonitors) { - monitor.terminate(); + monitor.terminate(); } if (executor != null) executor.shutdownNow(); super.tearDown(); } private WebAppMonitor newWebAppMonitor(String url) { - WebAppMonitor monitor = new WebAppMonitor(url) -// .delayMillis(0) - .logFailures(LOG); - webAppMonitors.add(monitor); - executor.execute(monitor); - return monitor; + WebAppMonitor monitor = new WebAppMonitor(url) +// .delayMillis(0) + .logFailures(LOG); + webAppMonitors.add(monitor); + executor.execute(monitor); + return monitor; } @Test(groups = "Integration") public void testRebindsToRunningServer() throws Exception { - // Start an app-server, and wait for it to be fully up + // Start an app-server, and wait for it to be fully up JBoss7Server origServer = origApp.createAndManageChild(EntitySpec.create(JBoss7Server.class) .configure("war", warUrl.toString())); http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a2da61d1/software/webapp/src/test/java/brooklyn/test/entity/TestJavaWebAppEntity.java ---------------------------------------------------------------------- diff --git a/software/webapp/src/test/java/brooklyn/test/entity/TestJavaWebAppEntity.java b/software/webapp/src/test/java/brooklyn/test/entity/TestJavaWebAppEntity.java index 9a3e08a..62dce29 100644 --- a/software/webapp/src/test/java/brooklyn/test/entity/TestJavaWebAppEntity.java +++ b/software/webapp/src/test/java/brooklyn/test/entity/TestJavaWebAppEntity.java @@ -41,7 +41,7 @@ import brooklyn.util.flags.SetFromFlag; * Mock web application server entity for testing. */ public class TestJavaWebAppEntity extends VanillaJavaAppImpl { - private static final Logger LOG = LoggerFactory.getLogger(TestJavaWebAppEntity.class); + private static final Logger LOG = LoggerFactory.getLogger(TestJavaWebAppEntity.class); public static final Effector<Void> START = new EffectorAndBody<Void>(SoftwareProcessImpl.START, new MethodEffector<Void>(TestJavaWebAppEntity.class, "customStart").getBody()); @SetFromFlag public int a; @@ -51,18 +51,18 @@ public class TestJavaWebAppEntity extends VanillaJavaAppImpl { public TestJavaWebAppEntity() {} public TestJavaWebAppEntity(@SuppressWarnings("rawtypes") Map flags, Entity parent) { super(flags, parent); } - public void waitForHttpPort() { } + public void waitForHttpPort() { } - public void customStart(Collection<? extends Location> loc) { - ServiceStateLogic.setExpectedState(this, Lifecycle.STARTING); + public void customStart(Collection<? extends Location> loc) { + ServiceStateLogic.setExpectedState(this, Lifecycle.STARTING); LOG.trace("Starting {}", this); ServiceStateLogic.setExpectedState(this, Lifecycle.RUNNING); setAttribute(Attributes.SERVICE_UP, true); } @Override - protected void doStop() { + protected void doStop() { LOG.trace("Stopping {}", this); } @@ -71,9 +71,9 @@ public class TestJavaWebAppEntity extends VanillaJavaAppImpl { throw new UnsupportedOperationException(); } - public synchronized void spoofRequest() { - Integer rc = getAttribute(WebAppServiceConstants.REQUEST_COUNT); - if (rc==null) rc = 0; - setAttribute(WebAppServiceConstants.REQUEST_COUNT, rc+1); - } + public synchronized void spoofRequest() { + Integer rc = getAttribute(WebAppServiceConstants.REQUEST_COUNT); + if (rc==null) rc = 0; + setAttribute(WebAppServiceConstants.REQUEST_COUNT, rc+1); + } } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a2da61d1/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java ---------------------------------------------------------------------- diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java index e339f1e..21e8afc 100644 --- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java +++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java @@ -50,26 +50,26 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity> { private static final long serialVersionUID = -7715984495268724954L; private final String componentId; - private final DslComponent scopeComponent; - private final Scope scope; + private final DslComponent scopeComponent; + private final Scope scope; - public DslComponent(String componentId) { - this(Scope.GLOBAL, componentId); - } - - public DslComponent(Scope scope, String componentId) { - this(null, scope, componentId); - } - - public DslComponent(DslComponent scopeComponent, Scope scope, String componentId) { - Preconditions.checkNotNull(scope, "scope"); - this.scopeComponent = scopeComponent; - this.componentId = componentId; - this.scope = scope; - } + public DslComponent(String componentId) { + this(Scope.GLOBAL, componentId); + } + + public DslComponent(Scope scope, String componentId) { + this(null, scope, componentId); + } + + public DslComponent(DslComponent scopeComponent, Scope scope, String componentId) { + Preconditions.checkNotNull(scope, "scope"); + this.scopeComponent = scopeComponent; + this.componentId = componentId; + this.scope = scope; + } - // --------------------------- - + // --------------------------- + @Override public Task<Entity> newTask() { return TaskBuilder.<Entity>builder().name("component("+componentId+")").body( @@ -173,11 +173,11 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity> { // DSL words which return things - public BrooklynDslDeferredSupplier<?> attributeWhenReady(final String sensorName) { - return new AttributeWhenReady(this, sensorName); - } - // class simply makes the memento XML files nicer - protected static class AttributeWhenReady extends BrooklynDslDeferredSupplier<Object> { + public BrooklynDslDeferredSupplier<?> attributeWhenReady(final String sensorName) { + return new AttributeWhenReady(this, sensorName); + } + // class simply makes the memento XML files nicer + protected static class AttributeWhenReady extends BrooklynDslDeferredSupplier<Object> { private static final long serialVersionUID = 1740899524088902383L; private final DslComponent component; private final String sensorName; @@ -199,9 +199,9 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity> { public String toString() { return component.toString()+"."+"attributeWhenReady("+sensorName+")"; } - } + } - public BrooklynDslDeferredSupplier<?> config(final String keyName) { + public BrooklynDslDeferredSupplier<?> config(final String keyName) { return new DslConfigSupplier(this, keyName); } protected final static class DslConfigSupplier extends BrooklynDslDeferredSupplier<Object> { @@ -231,41 +231,41 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity> { } } - public static enum Scope { - GLOBAL ("global"), - CHILD ("child"), - PARENT ("parent"), - SIBLING ("sibling"), - DESCENDANT ("descendant"), - ANCESTOR("ancestor"), - THIS ("this"); - - public static final Set<Scope> VALUES = ImmutableSet.of(GLOBAL, CHILD, PARENT, SIBLING, DESCENDANT, ANCESTOR, THIS); - - private final String name; - - private Scope(String name) { - this.name = name; - } - - public static Scope fromString(String name) { - return tryFromString(name).get(); - } - - public static Maybe<Scope> tryFromString(String name) { - for (Scope scope : VALUES) - if (scope.name.toLowerCase().equals(name.toLowerCase())) - return Maybe.of(scope); - return Maybe.absent(new IllegalArgumentException(name + " is not a valid scope")); - } - - public static boolean isValid(String name) { - for (Scope scope : VALUES) - if (scope.name.toLowerCase().equals(name.toLowerCase())) - return true; - return false; - } - } + public static enum Scope { + GLOBAL ("global"), + CHILD ("child"), + PARENT ("parent"), + SIBLING ("sibling"), + DESCENDANT ("descendant"), + ANCESTOR("ancestor"), + THIS ("this"); + + public static final Set<Scope> VALUES = ImmutableSet.of(GLOBAL, CHILD, PARENT, SIBLING, DESCENDANT, ANCESTOR, THIS); + + private final String name; + + private Scope(String name) { + this.name = name; + } + + public static Scope fromString(String name) { + return tryFromString(name).get(); + } + + public static Maybe<Scope> tryFromString(String name) { + for (Scope scope : VALUES) + if (scope.name.toLowerCase().equals(name.toLowerCase())) + return Maybe.of(scope); + return Maybe.absent(new IllegalArgumentException(name + " is not a valid scope")); + } + + public static boolean isValid(String name) { + for (Scope scope : VALUES) + if (scope.name.toLowerCase().equals(name.toLowerCase())) + return true; + return false; + } + } @Override http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a2da61d1/usage/qa/src/main/java/brooklyn/qa/longevity/Monitor.java ---------------------------------------------------------------------- diff --git a/usage/qa/src/main/java/brooklyn/qa/longevity/Monitor.java b/usage/qa/src/main/java/brooklyn/qa/longevity/Monitor.java index fc89c85..36e9f55 100644 --- a/usage/qa/src/main/java/brooklyn/qa/longevity/Monitor.java +++ b/usage/qa/src/main/java/brooklyn/qa/longevity/Monitor.java @@ -212,8 +212,8 @@ public class Monitor { if (min > prefs.numWebProcesses.lowerEndpoint() || max < prefs.numWebProcesses.upperEndpoint()) { failureMsg.append("num web processes not increasing/decreasing correctly: " + - "pids="+pids+"; size="+pids.size()+"; cyclePeriod="+prefs.webProcessesCyclingPeriod+ - "; expectedRange="+prefs.numWebProcesses+"; min="+min+"; max="+max+"; history="+values); + "pids="+pids+"; size="+pids.size()+"; cyclePeriod="+prefs.webProcessesCyclingPeriod+ + "; expectedRange="+prefs.numWebProcesses+"; min="+min+"; max="+max+"; history="+values); } } else { int numVals = values.size(); http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a2da61d1/usage/rest-api/src/main/java/brooklyn/rest/api/EffectorApi.java ---------------------------------------------------------------------- diff --git a/usage/rest-api/src/main/java/brooklyn/rest/api/EffectorApi.java b/usage/rest-api/src/main/java/brooklyn/rest/api/EffectorApi.java index 812ae2f..59726fd 100644 --- a/usage/rest-api/src/main/java/brooklyn/rest/api/EffectorApi.java +++ b/usage/rest-api/src/main/java/brooklyn/rest/api/EffectorApi.java @@ -72,10 +72,10 @@ public interface EffectorApi { // TODO test timeout; and should it be header, form, or what? @ApiParam(name = "timeout", value = "Delay before server should respond with activity task ID rather than result (in millis if no unit specified): " + - "'never' (blocking) is default; " + - "'0' means 'always' return task activity ID; " + - "and e.g. '1000' or '1s' will return a result if available within one second otherwise status 202 and the activity task ID", - required = false, defaultValue = "never") + "'never' (blocking) is default; " + + "'0' means 'always' return task activity ID; " + + "and e.g. '1000' or '1s' will return a result if available within one second otherwise status 202 and the activity task ID", + required = false, defaultValue = "never") @QueryParam("timeout") String timeout, http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a2da61d1/usage/rest-api/src/main/java/brooklyn/rest/domain/CatalogEntitySummary.java ---------------------------------------------------------------------- diff --git a/usage/rest-api/src/main/java/brooklyn/rest/domain/CatalogEntitySummary.java b/usage/rest-api/src/main/java/brooklyn/rest/domain/CatalogEntitySummary.java index 65f8f4d..928530c 100644 --- a/usage/rest-api/src/main/java/brooklyn/rest/domain/CatalogEntitySummary.java +++ b/usage/rest-api/src/main/java/brooklyn/rest/domain/CatalogEntitySummary.java @@ -66,7 +66,7 @@ public class CatalogEntitySummary extends CatalogItemSummary { public String toString() { return super.toString()+"["+ "config="+getConfig()+"; " + - "sensors="+getSensors()+"; "+ - "effectors="+getEffectors()+"]"; + "sensors="+getSensors()+"; "+ + "effectors="+getEffectors()+"]"; } } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a2da61d1/usage/test-support/src/main/java/brooklyn/test/EntityTestUtils.java ---------------------------------------------------------------------- diff --git a/usage/test-support/src/main/java/brooklyn/test/EntityTestUtils.java b/usage/test-support/src/main/java/brooklyn/test/EntityTestUtils.java index 693c807..5332818 100644 --- a/usage/test-support/src/main/java/brooklyn/test/EntityTestUtils.java +++ b/usage/test-support/src/main/java/brooklyn/test/EntityTestUtils.java @@ -47,9 +47,9 @@ public class EntityTestUtils { // TODO would be nice to have this... perhaps moving this class, or perhaps this whole project, to core/src/test ? // public static LocalManagementContext newManagementContext() { return new LocalManagementContextForTests(); } - // TODO Delete methods from TestUtils, to just have them here (or switch so TestUtils delegates here, - // and deprecate methods in TestUtils until deleted). - + // TODO Delete methods from TestUtils, to just have them here (or switch so TestUtils delegates here, + // and deprecate methods in TestUtils until deleted). + public static <T> void assertAttributeEquals(Entity entity, AttributeSensor<T> attribute, T expected) { assertEquals(entity.getAttribute(attribute), expected); } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a2da61d1/usage/test-support/src/main/java/brooklyn/test/HttpTestUtils.java ---------------------------------------------------------------------- diff --git a/usage/test-support/src/main/java/brooklyn/test/HttpTestUtils.java b/usage/test-support/src/main/java/brooklyn/test/HttpTestUtils.java index 8f96dcf..6142f78 100644 --- a/usage/test-support/src/main/java/brooklyn/test/HttpTestUtils.java +++ b/usage/test-support/src/main/java/brooklyn/test/HttpTestUtils.java @@ -62,8 +62,8 @@ import com.google.common.util.concurrent.ListeningExecutorService; */ public class HttpTestUtils { - // TODO Delete methods from TestUtils, to just have them here (or switch so TestUtils delegates here, - // and deprecate methods in TestUtils until deleted). + // TODO Delete methods from TestUtils, to just have them here (or switch so TestUtils delegates here, + // and deprecate methods in TestUtils until deleted). private static final Logger LOG = LoggerFactory.getLogger(HttpTestUtils.class); http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a2da61d1/usage/test-support/src/main/java/brooklyn/test/WebAppMonitor.java ---------------------------------------------------------------------- diff --git a/usage/test-support/src/main/java/brooklyn/test/WebAppMonitor.java b/usage/test-support/src/main/java/brooklyn/test/WebAppMonitor.java index a784367..2d0a457 100644 --- a/usage/test-support/src/main/java/brooklyn/test/WebAppMonitor.java +++ b/usage/test-support/src/main/java/brooklyn/test/WebAppMonitor.java @@ -198,9 +198,9 @@ public class WebAppMonitor implements Runnable { int attempts = getAttempts(); if ((failures > (1-fraction) * attempts + 0.0001) || attempts <= 0) { Assert.fail(message+" -- webapp access failures! " + - "("+failures+" failed of "+attempts+" monitoring attempts) against "+getUrl()+"; " + - "last was "+getLastStatus()+" taking "+getLastTime()+"ms" + - (getLastFailure() != null ? "; last failure was "+getLastFailure() : "")); + "("+failures+" failed of "+attempts+" monitoring attempts) against "+getUrl()+"; " + + "last was "+getLastStatus()+" taking "+getLastTime()+"ms" + + (getLastFailure() != null ? "; last failure was "+getLastFailure() : "")); } return this; } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a2da61d1/utils/common/src/main/java/brooklyn/util/collections/Jsonya.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/brooklyn/util/collections/Jsonya.java b/utils/common/src/main/java/brooklyn/util/collections/Jsonya.java index 383b926..c917bd0 100644 --- a/utils/common/src/main/java/brooklyn/util/collections/Jsonya.java +++ b/utils/common/src/main/java/brooklyn/util/collections/Jsonya.java @@ -415,7 +415,7 @@ public class Jsonya { // build a source map from the arguments as key-value pairs if ((others.length % 2)==0) throw new IllegalArgumentException("cannot add an odd number of arguments to a map" + - " ("+o1+" then "+Arrays.toString(others)+" in "+currentFocus+" in "+initialFocus+")"); + " ("+o1+" then "+Arrays.toString(others)+" in "+currentFocus+" in "+initialFocus+")"); source = MutableMap.of(translateKey(o1), translate(others[0])); for (int i=1; i<others.length; ) source.put(translateKey(others[i++]), translate(others[i++])); http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a2da61d1/utils/common/src/main/java/brooklyn/util/collections/MutableMap.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/brooklyn/util/collections/MutableMap.java b/utils/common/src/main/java/brooklyn/util/collections/MutableMap.java index f8b2f6c..5c6a9fe 100644 --- a/utils/common/src/main/java/brooklyn/util/collections/MutableMap.java +++ b/utils/common/src/main/java/brooklyn/util/collections/MutableMap.java @@ -216,9 +216,9 @@ public class MutableMap<K,V> extends LinkedHashMap<K,V> { } public Builder<K, V> removeAll(Iterable<? extends K> keys) { - for (K key : keys) { - result.remove(key); - } + for (K key : keys) { + result.remove(key); + } return this; } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a2da61d1/utils/common/src/main/java/brooklyn/util/javalang/Reflections.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/brooklyn/util/javalang/Reflections.java b/utils/common/src/main/java/brooklyn/util/javalang/Reflections.java index 115feff..7db91d4 100644 --- a/utils/common/src/main/java/brooklyn/util/javalang/Reflections.java +++ b/utils/common/src/main/java/brooklyn/util/javalang/Reflections.java @@ -65,31 +65,31 @@ public class Reflections { private static final Logger LOG = LoggerFactory.getLogger(Reflections.class); - public static class ReflectionNotFoundException extends RuntimeException { - private static final long serialVersionUID = 9032835250796708037L; - public ReflectionNotFoundException(String message, Throwable cause) { - super(message, cause); - } - public ReflectionNotFoundException(String message) { - super(message); - } - } - - public static class ReflectionAccessException extends RuntimeException { - private static final long serialVersionUID = 6569605861192432009L; - - public ReflectionAccessException(String message, Throwable cause) { - super(message, cause); - } - } - - private final ClassLoader classLoader; - - public Reflections(ClassLoader classLoader) { - this.classLoader = checkNotNull(classLoader); - } - - public Object loadInstance(String classname, Object...argValues) throws ReflectionNotFoundException, ReflectionAccessException { + public static class ReflectionNotFoundException extends RuntimeException { + private static final long serialVersionUID = 9032835250796708037L; + public ReflectionNotFoundException(String message, Throwable cause) { + super(message, cause); + } + public ReflectionNotFoundException(String message) { + super(message); + } + } + + public static class ReflectionAccessException extends RuntimeException { + private static final long serialVersionUID = 6569605861192432009L; + + public ReflectionAccessException(String message, Throwable cause) { + super(message, cause); + } + } + + private final ClassLoader classLoader; + + public Reflections(ClassLoader classLoader) { + this.classLoader = checkNotNull(classLoader); + } + + public Object loadInstance(String classname, Object...argValues) throws ReflectionNotFoundException, ReflectionAccessException { Class<?> clazz = loadClass(classname); Optional<?> v = null; try { @@ -99,118 +99,118 @@ public class Reflections { throw new IllegalStateException("Error invoking constructor for "+clazz+Arrays.toString(argValues) + ": " + Exceptions.collapseText(e)); } throw new IllegalStateException("No suitable constructor for "+clazz+Arrays.toString(argValues)); - } - public Object loadInstance(String classname, Class<?>[] argTypes, Object[] argValues) throws ReflectionNotFoundException, ReflectionAccessException { - Class<?> clazz = loadClass(classname); - Constructor<?> constructor = loadConstructor(clazz, argTypes); - return loadInstance(constructor, argValues); - } - - public Object loadInstance(String classname) throws ReflectionNotFoundException, ReflectionAccessException { - Class<?> clazz = loadClass(classname); - try { - return clazz.newInstance(); - } catch (InstantiationException e) { - throw new ReflectionAccessException("Failed to create instance of class '" + classname + "' using class loader " + classLoader + ": " + Exceptions.collapseText(e), e); - } catch (IllegalAccessException e) { - throw new ReflectionAccessException("Failed to create instance of class '" + classname + "' using class loader " + classLoader + ": " + Exceptions.collapseText(e), e); - } - } - - /** instantiates the given class from its binary name */ - public Class<?> loadClass(String classname) throws ReflectionNotFoundException { - try { - return classLoader.loadClass(classname); - } catch (ClassNotFoundException e) { - throw new ReflectionNotFoundException("Failed to load class '" + classname + "' using class loader " + classLoader + ": " + Exceptions.collapseText(e), e); - } catch (NoClassDefFoundError e) { - throw new ReflectionNotFoundException("Failed to load class '" + classname + "' using class loader " + classLoader + ": " + Exceptions.collapseText(e), e); - } catch (UnsupportedClassVersionError e) { - throw new ReflectionNotFoundException("Failed to load class '" + classname + "' using class loader " + classLoader + ": " + Exceptions.collapseText(e), e); - } - } - - @SuppressWarnings("unchecked") + } + public Object loadInstance(String classname, Class<?>[] argTypes, Object[] argValues) throws ReflectionNotFoundException, ReflectionAccessException { + Class<?> clazz = loadClass(classname); + Constructor<?> constructor = loadConstructor(clazz, argTypes); + return loadInstance(constructor, argValues); + } + + public Object loadInstance(String classname) throws ReflectionNotFoundException, ReflectionAccessException { + Class<?> clazz = loadClass(classname); + try { + return clazz.newInstance(); + } catch (InstantiationException e) { + throw new ReflectionAccessException("Failed to create instance of class '" + classname + "' using class loader " + classLoader + ": " + Exceptions.collapseText(e), e); + } catch (IllegalAccessException e) { + throw new ReflectionAccessException("Failed to create instance of class '" + classname + "' using class loader " + classLoader + ": " + Exceptions.collapseText(e), e); + } + } + + /** instantiates the given class from its binary name */ + public Class<?> loadClass(String classname) throws ReflectionNotFoundException { + try { + return classLoader.loadClass(classname); + } catch (ClassNotFoundException e) { + throw new ReflectionNotFoundException("Failed to load class '" + classname + "' using class loader " + classLoader + ": " + Exceptions.collapseText(e), e); + } catch (NoClassDefFoundError e) { + throw new ReflectionNotFoundException("Failed to load class '" + classname + "' using class loader " + classLoader + ": " + Exceptions.collapseText(e), e); + } catch (UnsupportedClassVersionError e) { + throw new ReflectionNotFoundException("Failed to load class '" + classname + "' using class loader " + classLoader + ": " + Exceptions.collapseText(e), e); + } + } + + @SuppressWarnings("unchecked") public <T> Class<? extends T> loadClass(String classname, Class<T> superType) throws ReflectionNotFoundException { - return (Class<? extends T>) loadClass(classname); - } - - /** given a nested part, e.g. Inner$VeryInner, this will recurse through clazz.Inner, looking for VeryInner, - * then looking in each supertype (interface) of clazz for Inner.VeryInner; - * <p> - * so it will find Clazz.Inner.VeryInner wherever in the hierarchy it is defined - * <p> - * (as opposed to ClassLoader which requires Inner.VeryInner to be _declared_ in clazz, not in any supertype - * <p> - * returns null if not found - */ - public static Class<?> loadInnerClassPossiblyInheritted(Class<?> clazz, String nestedPart) throws ReflectionNotFoundException { - Set<String> visited = new HashSet<String>(); - Class<?> result = loadInnerClassPossiblyInheritted(visited, clazz, nestedPart); - if (result!=null) return result; - throw new ReflectionNotFoundException("Inner class " + nestedPart + " could not be found in " + clazz + " or any of its super-types"); - } - - /** as 2-arg, but maintains set of visited elements, and returns null if not found */ - private static Class<?> loadInnerClassPossiblyInheritted(Set<String> visited, Class<?> clazz, String nestedPart) throws ReflectionNotFoundException { - if (clazz==null) return null; - if (nestedPart==null || nestedPart.length()==0) return clazz; - - int i1 = nestedPart.indexOf('$'); - int i2 = nestedPart.indexOf('.'); - int idx = (i2 > -1 && (i2 < i1 || i1==-1) ? i2 : i1); - String thisClassToFind = nestedPart; - String nextClassesToFind = ""; - if (idx>=0) { - thisClassToFind = nestedPart.substring(0, idx); - nextClassesToFind = nestedPart.substring(idx+1); - } - - if (!visited.add(clazz.getCanonicalName()+"!"+nestedPart)) { - //already visited - return null; - } - - Class<?>[] members = clazz.getClasses(); - for (int i = 0; i < members.length; i++) { - if (members[i].getSimpleName().equals(thisClassToFind)) { - Class<?> clazzI = loadInnerClassPossiblyInheritted(visited, members[i], nextClassesToFind); - if (clazzI!=null) return clazzI; - } - } - - //look in supertype first (not sure if necessary) - Class<?> result = loadInnerClassPossiblyInheritted(visited, clazz.getSuperclass(), nestedPart); - if (result!=null) return result; - - for (Class<?> iface : clazz.getInterfaces()) { - result = loadInnerClassPossiblyInheritted(visited, iface, nestedPart); - if (result!=null) return result; - } - return null; - } - - /** does not look through ancestors of outer class */ - public Class<?> loadInnerClassNotInheritted(String outerClassname, String innerClassname) throws ReflectionNotFoundException { - return loadClass(outerClassname + "$" + innerClassname); - } - - /** does not look through ancestors of outer class - * <p> - * uses the classloader set in this class, not in the clazz supplied */ - public Class<?> loadInnerClassNotInheritted(Class<?> outerClazz, String innerClassname) throws ReflectionNotFoundException { - return loadClass(outerClazz.getName() + "$" + innerClassname); - } - - public Constructor<?> loadConstructor(Class<?> clazz, Class<?>[] argTypes) throws ReflectionAccessException { - try { - return clazz.getConstructor(argTypes); - } catch (SecurityException e) { - throw new ReflectionAccessException("Failed to load constructor of class '" + clazz + " with argument types " + Arrays.asList(argTypes) + ": " + Exceptions.collapseText(e), e); - } catch (NoSuchMethodException e) { - throw new ReflectionAccessException("Failed to load constructor of class '" + clazz + " with argument types " + Arrays.asList(argTypes) + ": " + Exceptions.collapseText(e), e); - } - } + return (Class<? extends T>) loadClass(classname); + } + + /** given a nested part, e.g. Inner$VeryInner, this will recurse through clazz.Inner, looking for VeryInner, + * then looking in each supertype (interface) of clazz for Inner.VeryInner; + * <p> + * so it will find Clazz.Inner.VeryInner wherever in the hierarchy it is defined + * <p> + * (as opposed to ClassLoader which requires Inner.VeryInner to be _declared_ in clazz, not in any supertype + * <p> + * returns null if not found + */ + public static Class<?> loadInnerClassPossiblyInheritted(Class<?> clazz, String nestedPart) throws ReflectionNotFoundException { + Set<String> visited = new HashSet<String>(); + Class<?> result = loadInnerClassPossiblyInheritted(visited, clazz, nestedPart); + if (result!=null) return result; + throw new ReflectionNotFoundException("Inner class " + nestedPart + " could not be found in " + clazz + " or any of its super-types"); + } + + /** as 2-arg, but maintains set of visited elements, and returns null if not found */ + private static Class<?> loadInnerClassPossiblyInheritted(Set<String> visited, Class<?> clazz, String nestedPart) throws ReflectionNotFoundException { + if (clazz==null) return null; + if (nestedPart==null || nestedPart.length()==0) return clazz; + + int i1 = nestedPart.indexOf('$'); + int i2 = nestedPart.indexOf('.'); + int idx = (i2 > -1 && (i2 < i1 || i1==-1) ? i2 : i1); + String thisClassToFind = nestedPart; + String nextClassesToFind = ""; + if (idx>=0) { + thisClassToFind = nestedPart.substring(0, idx); + nextClassesToFind = nestedPart.substring(idx+1); + } + + if (!visited.add(clazz.getCanonicalName()+"!"+nestedPart)) { + //already visited + return null; + } + + Class<?>[] members = clazz.getClasses(); + for (int i = 0; i < members.length; i++) { + if (members[i].getSimpleName().equals(thisClassToFind)) { + Class<?> clazzI = loadInnerClassPossiblyInheritted(visited, members[i], nextClassesToFind); + if (clazzI!=null) return clazzI; + } + } + + //look in supertype first (not sure if necessary) + Class<?> result = loadInnerClassPossiblyInheritted(visited, clazz.getSuperclass(), nestedPart); + if (result!=null) return result; + + for (Class<?> iface : clazz.getInterfaces()) { + result = loadInnerClassPossiblyInheritted(visited, iface, nestedPart); + if (result!=null) return result; + } + return null; + } + + /** does not look through ancestors of outer class */ + public Class<?> loadInnerClassNotInheritted(String outerClassname, String innerClassname) throws ReflectionNotFoundException { + return loadClass(outerClassname + "$" + innerClassname); + } + + /** does not look through ancestors of outer class + * <p> + * uses the classloader set in this class, not in the clazz supplied */ + public Class<?> loadInnerClassNotInheritted(Class<?> outerClazz, String innerClassname) throws ReflectionNotFoundException { + return loadClass(outerClazz.getName() + "$" + innerClassname); + } + + public Constructor<?> loadConstructor(Class<?> clazz, Class<?>[] argTypes) throws ReflectionAccessException { + try { + return clazz.getConstructor(argTypes); + } catch (SecurityException e) { + throw new ReflectionAccessException("Failed to load constructor of class '" + clazz + " with argument types " + Arrays.asList(argTypes) + ": " + Exceptions.collapseText(e), e); + } catch (NoSuchMethodException e) { + throw new ReflectionAccessException("Failed to load constructor of class '" + clazz + " with argument types " + Arrays.asList(argTypes) + ": " + Exceptions.collapseText(e), e); + } + } /** Invokes a suitable constructor, supporting varargs and primitives */ public static <T> Optional<T> invokeConstructorWithArgs(ClassLoader classLoader, String className, Object...argsArray) { @@ -276,256 +276,256 @@ public class Reflections { /** returns a single constructor in a given class, or throws an exception */ - public Constructor<?> loadSingleConstructor(Class<?> clazz) { - Constructor<?>[] constructors = clazz.getConstructors(); - if (constructors.length == 1) { - return constructors[0]; - } - throw new IllegalArgumentException("Class " + clazz + " has more than one constructor"); - } - - public <T> T loadInstance(Constructor<T> constructor, Object...argValues) throws IllegalArgumentException, ReflectionAccessException { - try { - try { - return constructor.newInstance(argValues); - } catch (IllegalArgumentException e) { - try { - LOG.warn("Failure passing provided arguments ("+getIllegalArgumentsErrorMessage(constructor, argValues)+"; "+e+"); attempting to reconstitute"); - argValues = (Object[]) updateFromNewClassLoader(argValues); - return constructor.newInstance(argValues); - } catch (Throwable e2) { - LOG.warn("Reconstitution attempt failed (will rethrow original excaption): "+e2, e2); - throw e; - } - } - } catch (IllegalArgumentException e) { - throw new IllegalArgumentException(getIllegalArgumentsErrorMessage(constructor, argValues)+": " + Exceptions.collapseText(e), e); - } catch (InstantiationException e) { - throw new ReflectionAccessException("Failed to create instance of " + constructor.getDeclaringClass() + ": " + Exceptions.collapseText(e), e); - } catch (IllegalAccessException e) { - throw new ReflectionAccessException("Failed to create instance of " + constructor.getDeclaringClass() + ": " + Exceptions.collapseText(e), e); - } catch (InvocationTargetException e) { - throw new ReflectionAccessException("Failed to create instance of " + constructor.getDeclaringClass() + ": " + Exceptions.collapseText(e), e); - } - } - - public Method loadMethod(Class<?> clazz, String methodName, Class<?>[] argTypes) throws ReflectionNotFoundException, ReflectionAccessException { - try { - return clazz.getMethod(methodName, argTypes); - } catch (NoClassDefFoundError e) { - throw new ReflectionNotFoundException("Failed to invoke method " + methodName + " on class " + clazz + " with argument types " + Arrays.asList(argTypes) + ", using class loader " + clazz.getClassLoader() + ": " + Exceptions.collapseText(e), e); - } catch (NoSuchMethodException e) { - throw new ReflectionNotFoundException("Failed to invoke method " + methodName + " on class " + clazz + " with argument types " + Arrays.asList(argTypes) + ": " + Exceptions.collapseText(e), e); - } catch (SecurityException e) { - throw new ReflectionAccessException("Failed to invoke method " + methodName + " on class " + clazz + " with argument types " + Arrays.asList(argTypes) + ": " + Exceptions.collapseText(e), e); - } - } - - /** returns the first method matching the given name */ - public Method loadMethod(Class<?> clazz, String methodName) throws ReflectionNotFoundException, ReflectionAccessException { - try { - Method[] allmethods = clazz.getMethods(); - for (int i = 0; i < allmethods.length; i++) { - if (allmethods[i].getName().equals(methodName)) { - return allmethods[i]; - } - } - throw new ReflectionNotFoundException("Cannot find method " + methodName + " on class " + clazz); - - } catch (SecurityException e) { - throw new ReflectionAccessException("Failed to invoke method '" + methodName + " on class " + clazz + ": " + Exceptions.collapseText(e), e); - } - } - - /** - * - * @throws ReflectionAccessException If invocation failed due to illegal access or the invoked method failed - * @throws IllegalArgumentException If the arguments were invalid - */ - public Object invokeMethod(Method method, Object obj, Object... argValues) throws ReflectionAccessException { - try { - return method.invoke(obj, argValues); - } catch (IllegalArgumentException e) { - throw new IllegalArgumentException(getIllegalArgumentsErrorMessage(method, argValues), e); - } catch (IllegalAccessException e) { - throw new ReflectionAccessException("Failed to invoke method '" + method.toGenericString() + " on class " + method.getDeclaringClass() + " with argument values " + Arrays.asList(argValues) + ": " + Exceptions.collapseText(e), e); - } catch (InvocationTargetException e) { - throw new ReflectionAccessException("Failed to invoke method '" + method.toGenericString() + " on class " + method.getDeclaringClass() + " with argument values " + Arrays.asList(argValues) + ": " + Exceptions.collapseText(e), e); - } - } - - public Object invokeStaticMethod(Method method, Object... argValues) throws IllegalArgumentException, ReflectionAccessException { - try { - return method.invoke(null, argValues); - } catch (IllegalArgumentException e) { - throw new IllegalArgumentException(getIllegalArgumentsErrorMessage(method, argValues), e); - } catch (IllegalAccessException e) { - throw new ReflectionAccessException("Failed to invoke method '" + method.toGenericString() + " on class " + method.getDeclaringClass() + " with argument values " + Arrays.asList(argValues) + ": " + Exceptions.collapseText(e), e); - } catch (InvocationTargetException e) { - throw new ReflectionAccessException("Failed to invoke method '" + method.toGenericString() + " on class " + method.getDeclaringClass() + " with argument values " + Arrays.asList(argValues) + ": " + Exceptions.collapseText(e), e); - } - } - - public Object loadStaticField(Class<?> clazz, String fieldname) throws ReflectionAccessException { - return loadStaticFields(clazz, new String[] {fieldname}, null)[0]; - } - - public Object[] loadStaticFields(Class<?> clazz, String[] fieldnamesArray, Object[] defaults) throws ReflectionAccessException { - Object[] result = new Object[fieldnamesArray.length]; - if (defaults!=null) { - for (int i = 0; i < defaults.length; i++) { - result[i] = defaults[i]; - } - } - - List<String> fieldnames = Arrays.asList(fieldnamesArray); - Field[] classFields = clazz.getDeclaredFields(); - - for (int i = 0; i < classFields.length; i++) { - Field field = classFields[i]; - int index = fieldnames.indexOf(field.getName()); - if (index >= 0) { - try { - result[index] = field.get(null); - } catch (IllegalArgumentException e) { - throw new ReflectionAccessException("Failed to load field '" + field.getName() + " from class " + clazz + ": " + Exceptions.collapseText(e), e); - } catch (IllegalAccessException e) { - throw new ReflectionAccessException("Failed to load field '" + field.getName() + " from class " + clazz + ": " + Exceptions.collapseText(e), e); - } - } - } - return result; - } - - private static String getIllegalArgumentsErrorMessage(Method method, Object[] argValues) { - return method.toGenericString() + " not applicable for the parameters of type " + argumentTypesToString(argValues); - } - - private static String getIllegalArgumentsErrorMessage(Constructor<?> constructor, Object[] argValues) { - return constructor.toGenericString() + " not applicable for the parameters of type " + argumentTypesToString(argValues); - } - - private static String argumentTypesToString(Object[] argValues) { - StringBuffer msg = new StringBuffer("("); - for (int i = 0; i < argValues.length; i++) { - if (i != 0) msg.append(", "); - msg.append(argValues[i] != null ? argValues[i].getClass().getName() : "null"); - } - msg.append(")"); - return msg.toString(); - } - - /** copies all fields from the source to target; very little compile-time safety checking, so use with care - * @throws IllegalAccessException - * @throws IllegalArgumentException */ - public static <T> void copyFields(T source, T target) throws IllegalArgumentException, IllegalAccessException { - Class<? extends Object> clazz = source.getClass(); - while (clazz!=null) { - Field[] fields = clazz.getDeclaredFields(); - for (Field f : fields) { - f.setAccessible(true); - Object vs = f.get(source); - Object vt = f.get(target); - if ((vs==null && vt!=null) || (vs!=null && !vs.equals(vt))) { - f.set(target, vs); - } - } - clazz = clazz.getSuperclass(); - } - } - - /** - * Loads class given its canonical name format (e.g. com.acme.Foo.Inner), - * using iterative strategy (trying com.acme.Foo$Inner, then com.acme$Foo$Inner, etc). - * @throws ReflectionNotFoundException - */ - public Class<?> loadClassFromCanonicalName(String canonicalName) throws ClassNotFoundException, ReflectionNotFoundException { - ClassNotFoundException err = null; - String name = canonicalName; - do { - try { - return classLoader.loadClass(name); - } catch (ClassNotFoundException e) { - if (err == null) err = e; - int lastIndexOf = name.lastIndexOf("."); - if (lastIndexOf >= 0) { - name = name.substring(0, lastIndexOf) + "$" + name.substring(lastIndexOf+1); - } - } - } while (name.contains(".")); - throw err; - } - - /** finds the resource in the classloader, if it exists; inserts or replaces leading slash as necessary - * (i believe it should _not_ have one, but there is some inconsistency) - * - * Will return null if no resource is found. - */ - @Nullable - public URL getResource(String r) { - URL u = null; - u = classLoader.getResource(r); - if (u!=null) return u; - - if (r.startsWith("/")) r = r.substring(1); - else r = "/"+r; - return classLoader.getResource(r); - } - - /** - * Serialize the given object, then reload using the current class loader; - * this removes linkages to instances with classes loaded by an older class loader. - * <p> - * (like a poor man's clone) - * <p> - * aka "reconstitute(Object)" - */ - public final Object updateFromNewClassLoader(Object data) throws IOException, ClassNotFoundException { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - new ObjectOutputStream(bytes).writeObject(data); - Object reconstituted = new ObjectInputStream(new ByteArrayInputStream(bytes.toByteArray())).readObject(); - if (LOG.isDebugEnabled()) LOG.debug("Reconstituted data: " + reconstituted + ", class loader: " + classLoader); - return reconstituted; - } - - public ClassLoader getClassLoader() { - return classLoader; - } - - @SuppressWarnings("unchecked") - public static <T> Class<? super T> findSuperType(T impl, String typeName) { + public Constructor<?> loadSingleConstructor(Class<?> clazz) { + Constructor<?>[] constructors = clazz.getConstructors(); + if (constructors.length == 1) { + return constructors[0]; + } + throw new IllegalArgumentException("Class " + clazz + " has more than one constructor"); + } + + public <T> T loadInstance(Constructor<T> constructor, Object...argValues) throws IllegalArgumentException, ReflectionAccessException { + try { + try { + return constructor.newInstance(argValues); + } catch (IllegalArgumentException e) { + try { + LOG.warn("Failure passing provided arguments ("+getIllegalArgumentsErrorMessage(constructor, argValues)+"; "+e+"); attempting to reconstitute"); + argValues = (Object[]) updateFromNewClassLoader(argValues); + return constructor.newInstance(argValues); + } catch (Throwable e2) { + LOG.warn("Reconstitution attempt failed (will rethrow original excaption): "+e2, e2); + throw e; + } + } + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException(getIllegalArgumentsErrorMessage(constructor, argValues)+": " + Exceptions.collapseText(e), e); + } catch (InstantiationException e) { + throw new ReflectionAccessException("Failed to create instance of " + constructor.getDeclaringClass() + ": " + Exceptions.collapseText(e), e); + } catch (IllegalAccessException e) { + throw new ReflectionAccessException("Failed to create instance of " + constructor.getDeclaringClass() + ": " + Exceptions.collapseText(e), e); + } catch (InvocationTargetException e) { + throw new ReflectionAccessException("Failed to create instance of " + constructor.getDeclaringClass() + ": " + Exceptions.collapseText(e), e); + } + } + + public Method loadMethod(Class<?> clazz, String methodName, Class<?>[] argTypes) throws ReflectionNotFoundException, ReflectionAccessException { + try { + return clazz.getMethod(methodName, argTypes); + } catch (NoClassDefFoundError e) { + throw new ReflectionNotFoundException("Failed to invoke method " + methodName + " on class " + clazz + " with argument types " + Arrays.asList(argTypes) + ", using class loader " + clazz.getClassLoader() + ": " + Exceptions.collapseText(e), e); + } catch (NoSuchMethodException e) { + throw new ReflectionNotFoundException("Failed to invoke method " + methodName + " on class " + clazz + " with argument types " + Arrays.asList(argTypes) + ": " + Exceptions.collapseText(e), e); + } catch (SecurityException e) { + throw new ReflectionAccessException("Failed to invoke method " + methodName + " on class " + clazz + " with argument types " + Arrays.asList(argTypes) + ": " + Exceptions.collapseText(e), e); + } + } + + /** returns the first method matching the given name */ + public Method loadMethod(Class<?> clazz, String methodName) throws ReflectionNotFoundException, ReflectionAccessException { + try { + Method[] allmethods = clazz.getMethods(); + for (int i = 0; i < allmethods.length; i++) { + if (allmethods[i].getName().equals(methodName)) { + return allmethods[i]; + } + } + throw new ReflectionNotFoundException("Cannot find method " + methodName + " on class " + clazz); + + } catch (SecurityException e) { + throw new ReflectionAccessException("Failed to invoke method '" + methodName + " on class " + clazz + ": " + Exceptions.collapseText(e), e); + } + } + + /** + * + * @throws ReflectionAccessException If invocation failed due to illegal access or the invoked method failed + * @throws IllegalArgumentException If the arguments were invalid + */ + public Object invokeMethod(Method method, Object obj, Object... argValues) throws ReflectionAccessException { + try { + return method.invoke(obj, argValues); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException(getIllegalArgumentsErrorMessage(method, argValues), e); + } catch (IllegalAccessException e) { + throw new ReflectionAccessException("Failed to invoke method '" + method.toGenericString() + " on class " + method.getDeclaringClass() + " with argument values " + Arrays.asList(argValues) + ": " + Exceptions.collapseText(e), e); + } catch (InvocationTargetException e) { + throw new ReflectionAccessException("Failed to invoke method '" + method.toGenericString() + " on class " + method.getDeclaringClass() + " with argument values " + Arrays.asList(argValues) + ": " + Exceptions.collapseText(e), e); + } + } + + public Object invokeStaticMethod(Method method, Object... argValues) throws IllegalArgumentException, ReflectionAccessException { + try { + return method.invoke(null, argValues); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException(getIllegalArgumentsErrorMessage(method, argValues), e); + } catch (IllegalAccessException e) { + throw new ReflectionAccessException("Failed to invoke method '" + method.toGenericString() + " on class " + method.getDeclaringClass() + " with argument values " + Arrays.asList(argValues) + ": " + Exceptions.collapseText(e), e); + } catch (InvocationTargetException e) { + throw new ReflectionAccessException("Failed to invoke method '" + method.toGenericString() + " on class " + method.getDeclaringClass() + " with argument values " + Arrays.asList(argValues) + ": " + Exceptions.collapseText(e), e); + } + } + + public Object loadStaticField(Class<?> clazz, String fieldname) throws ReflectionAccessException { + return loadStaticFields(clazz, new String[] {fieldname}, null)[0]; + } + + public Object[] loadStaticFields(Class<?> clazz, String[] fieldnamesArray, Object[] defaults) throws ReflectionAccessException { + Object[] result = new Object[fieldnamesArray.length]; + if (defaults!=null) { + for (int i = 0; i < defaults.length; i++) { + result[i] = defaults[i]; + } + } + + List<String> fieldnames = Arrays.asList(fieldnamesArray); + Field[] classFields = clazz.getDeclaredFields(); + + for (int i = 0; i < classFields.length; i++) { + Field field = classFields[i]; + int index = fieldnames.indexOf(field.getName()); + if (index >= 0) { + try { + result[index] = field.get(null); + } catch (IllegalArgumentException e) { + throw new ReflectionAccessException("Failed to load field '" + field.getName() + " from class " + clazz + ": " + Exceptions.collapseText(e), e); + } catch (IllegalAccessException e) { + throw new ReflectionAccessException("Failed to load field '" + field.getName() + " from class " + clazz + ": " + Exceptions.collapseText(e), e); + } + } + } + return result; + } + + private static String getIllegalArgumentsErrorMessage(Method method, Object[] argValues) { + return method.toGenericString() + " not applicable for the parameters of type " + argumentTypesToString(argValues); + } + + private static String getIllegalArgumentsErrorMessage(Constructor<?> constructor, Object[] argValues) { + return constructor.toGenericString() + " not applicable for the parameters of type " + argumentTypesToString(argValues); + } + + private static String argumentTypesToString(Object[] argValues) { + StringBuffer msg = new StringBuffer("("); + for (int i = 0; i < argValues.length; i++) { + if (i != 0) msg.append(", "); + msg.append(argValues[i] != null ? argValues[i].getClass().getName() : "null"); + } + msg.append(")"); + return msg.toString(); + } + + /** copies all fields from the source to target; very little compile-time safety checking, so use with care + * @throws IllegalAccessException + * @throws IllegalArgumentException */ + public static <T> void copyFields(T source, T target) throws IllegalArgumentException, IllegalAccessException { + Class<? extends Object> clazz = source.getClass(); + while (clazz!=null) { + Field[] fields = clazz.getDeclaredFields(); + for (Field f : fields) { + f.setAccessible(true); + Object vs = f.get(source); + Object vt = f.get(target); + if ((vs==null && vt!=null) || (vs!=null && !vs.equals(vt))) { + f.set(target, vs); + } + } + clazz = clazz.getSuperclass(); + } + } + + /** + * Loads class given its canonical name format (e.g. com.acme.Foo.Inner), + * using iterative strategy (trying com.acme.Foo$Inner, then com.acme$Foo$Inner, etc). + * @throws ReflectionNotFoundException + */ + public Class<?> loadClassFromCanonicalName(String canonicalName) throws ClassNotFoundException, ReflectionNotFoundException { + ClassNotFoundException err = null; + String name = canonicalName; + do { + try { + return classLoader.loadClass(name); + } catch (ClassNotFoundException e) { + if (err == null) err = e; + int lastIndexOf = name.lastIndexOf("."); + if (lastIndexOf >= 0) { + name = name.substring(0, lastIndexOf) + "$" + name.substring(lastIndexOf+1); + } + } + } while (name.contains(".")); + throw err; + } + + /** finds the resource in the classloader, if it exists; inserts or replaces leading slash as necessary + * (i believe it should _not_ have one, but there is some inconsistency) + * + * Will return null if no resource is found. + */ + @Nullable + public URL getResource(String r) { + URL u = null; + u = classLoader.getResource(r); + if (u!=null) return u; + + if (r.startsWith("/")) r = r.substring(1); + else r = "/"+r; + return classLoader.getResource(r); + } + + /** + * Serialize the given object, then reload using the current class loader; + * this removes linkages to instances with classes loaded by an older class loader. + * <p> + * (like a poor man's clone) + * <p> + * aka "reconstitute(Object)" + */ + public final Object updateFromNewClassLoader(Object data) throws IOException, ClassNotFoundException { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + new ObjectOutputStream(bytes).writeObject(data); + Object reconstituted = new ObjectInputStream(new ByteArrayInputStream(bytes.toByteArray())).readObject(); + if (LOG.isDebugEnabled()) LOG.debug("Reconstituted data: " + reconstituted + ", class loader: " + classLoader); + return reconstituted; + } + + public ClassLoader getClassLoader() { + return classLoader; + } + + @SuppressWarnings("unchecked") + public static <T> Class<? super T> findSuperType(T impl, String typeName) { Set<Class<?>> toinspect = new LinkedHashSet<Class<?>>(); - Set<Class<?>> inspected = new HashSet<Class<?>>(); - toinspect.add(impl.getClass()); - - while (toinspect.size() > 0) { - Class<?> clazz = toinspect.iterator().next(); // get and remove the first element - if (clazz.getName().equals(typeName)) { - return (Class<? super T>) clazz; - } - inspected.add(clazz); - List<Class<?>> toAdd = Arrays.asList(clazz.getInterfaces()); - toinspect.addAll( toAdd ); - if (clazz.getSuperclass() != null) toinspect.add(clazz.getSuperclass()); - toinspect.removeAll(inspected); - } - - return null; - } - - /** whereas Class.getInterfaces() only returns interfaces directly implemented by a class, - * this walks the inheritance hierarchy to include interfaces implemented by superclass/ancestors; - * (note it does not include superinterfaces) - */ - public static Set<Class<?>> getInterfacesIncludingClassAncestors(Class<?> clazz) { - Set<Class<?>> result = new LinkedHashSet<Class<?>>(); - while (clazz!=null) { - for (Class<?> iface: clazz.getInterfaces()) - result.add(iface); - clazz = clazz.getSuperclass(); - } - return result; - } + Set<Class<?>> inspected = new HashSet<Class<?>>(); + toinspect.add(impl.getClass()); + + while (toinspect.size() > 0) { + Class<?> clazz = toinspect.iterator().next(); // get and remove the first element + if (clazz.getName().equals(typeName)) { + return (Class<? super T>) clazz; + } + inspected.add(clazz); + List<Class<?>> toAdd = Arrays.asList(clazz.getInterfaces()); + toinspect.addAll( toAdd ); + if (clazz.getSuperclass() != null) toinspect.add(clazz.getSuperclass()); + toinspect.removeAll(inspected); + } + + return null; + } + + /** whereas Class.getInterfaces() only returns interfaces directly implemented by a class, + * this walks the inheritance hierarchy to include interfaces implemented by superclass/ancestors; + * (note it does not include superinterfaces) + */ + public static Set<Class<?>> getInterfacesIncludingClassAncestors(Class<?> clazz) { + Set<Class<?>> result = new LinkedHashSet<Class<?>>(); + while (clazz!=null) { + for (Class<?> iface: clazz.getInterfaces()) + result.add(iface); + clazz = clazz.getSuperclass(); + } + return result; + } public static Method findMethod(Class<?> clazz, String name, Class<?>... parameterTypes) throws NoSuchMethodException { if (clazz == null || name == null) { http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a2da61d1/utils/common/src/main/java/brooklyn/util/logging/SimpleOneLineLogFormatter.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/brooklyn/util/logging/SimpleOneLineLogFormatter.java b/utils/common/src/main/java/brooklyn/util/logging/SimpleOneLineLogFormatter.java index fd24fb7..19ca7e6 100644 --- a/utils/common/src/main/java/brooklyn/util/logging/SimpleOneLineLogFormatter.java +++ b/utils/common/src/main/java/brooklyn/util/logging/SimpleOneLineLogFormatter.java @@ -33,108 +33,108 @@ import com.google.common.base.Throwables; //however we don't typically use java.util.logger... public class SimpleOneLineLogFormatter extends Formatter { - public SimpleOneLineLogFormatter() { - this(true, false, false); - } - - public SimpleOneLineLogFormatter(boolean showLevel, boolean showThread, boolean showCaller) { - this.showLevel = showLevel; - this.showThread = showThread; - this.showCaller = showCaller; - } - - - public final boolean showLevel; - public final boolean showThread; - public final boolean showCaller; - - // use shared date and formatter to minimize memory/time overhead - protected final Date date = new Date(); - protected DateFormat dateFormat = new SimpleDateFormat(getDateFormat()); - - public String getDateFormat() { - return "yyyy-MM-dd HH:mm:ss.SSSZ"; - } - - /** uses "YYYY-DD-MM hh:mm:ss.SSS message" format */ - public String format(LogRecord record) { - StringBuffer sb = new StringBuffer(); - appendDate(record, sb); - appendLevel(record, sb); - sb.append(" "); - sb.append(formatMessage(record)); - appendThreadAndCaller(record, sb); - appendDetailsWithNewLine(sb, record); - return sb.toString(); - } - - protected void appendLevel(LogRecord record, StringBuffer sb) { - if (showLevel) { - sb.append(" [").append(record.getLevel()).append("]"); - } - } - - protected void appendDate(LogRecord record, StringBuffer sb) { - synchronized (date) { - date.setTime(record.getMillis()); - sb.append(dateFormat.format(date)); - } - } - - protected void appendThreadAndCaller(LogRecord record, StringBuffer sb) { - if (showThread || showCaller) { - sb.append(" ["); - if (showThread) - sb.append(getThreadName(record)); - if (showThread && showCaller) sb.append(", "); - if (showCaller) { - if (record.getSourceClassName() != null) { - sb.append(record.getSourceClassName()); - } else { - sb.append(record.getLoggerName()); - } - if (record.getSourceMethodName() != null) { - sb.append(" "); - sb.append(record.getSourceMethodName()); - } - } - sb.append("]"); - } - } - - protected void appendDetailsWithNewLine(StringBuffer sb, LogRecord record) { - if (record.getThrown() != null) { - try { - sb.append('\n'); - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - record.getThrown().printStackTrace(pw); - pw.close(); - sb.append(sw.toString()); - } catch (Exception ex) { - //shouldn't happen with printwriter - throw Throwables.propagate(ex); - } - } else { - sb.append('\n'); - } - } - - protected String getThreadName(LogRecord record) { - //try to get the thread's name - //only possible if we are the thread (unless do something messy like cache or access private fields) - //fortunately we typically are the thread - LogRecord lr = new LogRecord(Level.INFO, ""); - if (lr.getThreadID()==record.getThreadID()) - return Thread.currentThread().getName() + " ("+record.getThreadID()+")"; - //otherwise just say the number - return "thread ("+record.getThreadID()+")"; - } - - public static class LogFormatterWithThreadAndCaller extends SimpleOneLineLogFormatter { - public LogFormatterWithThreadAndCaller() { - super(true, true, true); - } - } - + public SimpleOneLineLogFormatter() { + this(true, false, false); + } + + public SimpleOneLineLogFormatter(boolean showLevel, boolean showThread, boolean showCaller) { + this.showLevel = showLevel; + this.showThread = showThread; + this.showCaller = showCaller; + } + + + public final boolean showLevel; + public final boolean showThread; + public final boolean showCaller; + + // use shared date and formatter to minimize memory/time overhead + protected final Date date = new Date(); + protected DateFormat dateFormat = new SimpleDateFormat(getDateFormat()); + + public String getDateFormat() { + return "yyyy-MM-dd HH:mm:ss.SSSZ"; + } + + /** uses "YYYY-DD-MM hh:mm:ss.SSS message" format */ + public String format(LogRecord record) { + StringBuffer sb = new StringBuffer(); + appendDate(record, sb); + appendLevel(record, sb); + sb.append(" "); + sb.append(formatMessage(record)); + appendThreadAndCaller(record, sb); + appendDetailsWithNewLine(sb, record); + return sb.toString(); + } + + protected void appendLevel(LogRecord record, StringBuffer sb) { + if (showLevel) { + sb.append(" [").append(record.getLevel()).append("]"); + } + } + + protected void appendDate(LogRecord record, StringBuffer sb) { + synchronized (date) { + date.setTime(record.getMillis()); + sb.append(dateFormat.format(date)); + } + } + + protected void appendThreadAndCaller(LogRecord record, StringBuffer sb) { + if (showThread || showCaller) { + sb.append(" ["); + if (showThread) + sb.append(getThreadName(record)); + if (showThread && showCaller) sb.append(", "); + if (showCaller) { + if (record.getSourceClassName() != null) { + sb.append(record.getSourceClassName()); + } else { + sb.append(record.getLoggerName()); + } + if (record.getSourceMethodName() != null) { + sb.append(" "); + sb.append(record.getSourceMethodName()); + } + } + sb.append("]"); + } + } + + protected void appendDetailsWithNewLine(StringBuffer sb, LogRecord record) { + if (record.getThrown() != null) { + try { + sb.append('\n'); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + record.getThrown().printStackTrace(pw); + pw.close(); + sb.append(sw.toString()); + } catch (Exception ex) { + //shouldn't happen with printwriter + throw Throwables.propagate(ex); + } + } else { + sb.append('\n'); + } + } + + protected String getThreadName(LogRecord record) { + //try to get the thread's name + //only possible if we are the thread (unless do something messy like cache or access private fields) + //fortunately we typically are the thread + LogRecord lr = new LogRecord(Level.INFO, ""); + if (lr.getThreadID()==record.getThreadID()) + return Thread.currentThread().getName() + " ("+record.getThreadID()+")"; + //otherwise just say the number + return "thread ("+record.getThreadID()+")"; + } + + public static class LogFormatterWithThreadAndCaller extends SimpleOneLineLogFormatter { + public LogFormatterWithThreadAndCaller() { + super(true, true, true); + } + } + } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a2da61d1/utils/common/src/main/java/brooklyn/util/net/HasNetworkAddresses.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/brooklyn/util/net/HasNetworkAddresses.java b/utils/common/src/main/java/brooklyn/util/net/HasNetworkAddresses.java index 2b784a6..18d1019 100644 --- a/utils/common/src/main/java/brooklyn/util/net/HasNetworkAddresses.java +++ b/utils/common/src/main/java/brooklyn/util/net/HasNetworkAddresses.java @@ -27,22 +27,22 @@ import com.google.common.annotations.Beta; @Beta public interface HasNetworkAddresses { - /** - * <h4>note</h4> hostname is something that is set in the operating system. - * This value may or may not be set in DNS. - * - * @return hostname of the node, or null if unknown - */ - @Nullable - String getHostname(); - - /** - * All public IP addresses, potentially including shared ips. - */ - Set<String> getPublicAddresses(); + /** + * <h4>note</h4> hostname is something that is set in the operating system. + * This value may or may not be set in DNS. + * + * @return hostname of the node, or null if unknown + */ + @Nullable + String getHostname(); + + /** + * All public IP addresses, potentially including shared ips. + */ + Set<String> getPublicAddresses(); - /** - * All private IP addresses. - */ - Set<String> getPrivateAddresses(); + /** + * All private IP addresses. + */ + Set<String> getPrivateAddresses(); } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a2da61d1/utils/common/src/main/java/brooklyn/util/stream/StreamGobbler.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/brooklyn/util/stream/StreamGobbler.java b/utils/common/src/main/java/brooklyn/util/stream/StreamGobbler.java index 68c3056..7d5f9fe 100644 --- a/utils/common/src/main/java/brooklyn/util/stream/StreamGobbler.java +++ b/utils/common/src/main/java/brooklyn/util/stream/StreamGobbler.java @@ -28,7 +28,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import org.slf4j.Logger; public class StreamGobbler extends Thread implements Closeable { - + protected final InputStream stream; protected final PrintStream out; protected final Logger log; @@ -63,8 +63,8 @@ public class StreamGobbler extends Thread implements Closeable { public StreamGobbler setPrefix(String prefix) { setLogPrefix(prefix); setPrintPrefix(prefix); - return this; - } + return this; + } public StreamGobbler setPrintPrefix(String prefix) { printPrefix = prefix; return this; @@ -83,36 +83,36 @@ public class StreamGobbler extends Thread implements Closeable { } onClose(); } catch (IOException e) { - onClose(); - //TODO parametrise log level, for this error, and for normal messages - if (log!=null && log.isTraceEnabled()) log.trace(logPrefix+"exception reading from stream ("+e+")"); + onClose(); + //TODO parametrise log level, for this error, and for normal messages + if (log!=null && log.isTraceEnabled()) log.trace(logPrefix+"exception reading from stream ("+e+")"); } } private final StringBuilder lineSoFar = new StringBuilder(16); public void onChar(int c) { - if (c=='\n' || c=='\r') { - if (lineSoFar.length()>0) - //suppress blank lines, so that we can treat either newline char as a line separator - //(eg to show curl updates frequently) - onLine(lineSoFar.toString()); - lineSoFar.setLength(0); - } else { - lineSoFar.append((char)c); - } + if (c=='\n' || c=='\r') { + if (lineSoFar.length()>0) + //suppress blank lines, so that we can treat either newline char as a line separator + //(eg to show curl updates frequently) + onLine(lineSoFar.toString()); + lineSoFar.setLength(0); + } else { + lineSoFar.append((char)c); + } } public void onLine(String line) { - //right trim, in case there is \r or other funnies - while (line.length()>0 && Character.isWhitespace(line.charAt(line.length()-1))) - line = line.substring(0, line.length()-1); - //right trim, in case there is \r or other funnies - while (line.length()>0 && (line.charAt(0)=='\n' || line.charAt(0)=='\r')) - line = line.substring(1); - if (!line.isEmpty()) { - if (out!=null) out.println(printPrefix+line); - if (log!=null && log.isDebugEnabled()) log.debug(logPrefix+line); - } + //right trim, in case there is \r or other funnies + while (line.length()>0 && Character.isWhitespace(line.charAt(line.length()-1))) + line = line.substring(0, line.length()-1); + //right trim, in case there is \r or other funnies + while (line.length()>0 && (line.charAt(0)=='\n' || line.charAt(0)=='\r')) + line = line.substring(1); + if (!line.isEmpty()) { + if (out!=null) out.println(printPrefix+line); + if (log!=null && log.isDebugEnabled()) log.debug(logPrefix+line); + } } public void onClose() { http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a2da61d1/utils/common/src/main/java/brooklyn/util/text/NaturalOrderComparator.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/brooklyn/util/text/NaturalOrderComparator.java b/utils/common/src/main/java/brooklyn/util/text/NaturalOrderComparator.java index 34d96e3..84ea567 100644 --- a/utils/common/src/main/java/brooklyn/util/text/NaturalOrderComparator.java +++ b/utils/common/src/main/java/brooklyn/util/text/NaturalOrderComparator.java @@ -61,105 +61,105 @@ public class NaturalOrderComparator implements Comparator<String> { public static final NaturalOrderComparator INSTANCE = new NaturalOrderComparator(); - int compareRight(String a, String b) - { - int bias = 0; - int ia = 0; - int ib = 0; - - // The longest run of digits wins. That aside, the greatest - // value wins, but we can't know that it will until we've scanned - // both numbers to know that they have the same magnitude, so we - // remember it in BIAS. - for (;; ia++, ib++) { - char ca = charAt(a, ia); - char cb = charAt(b, ib); - - if (!Character.isDigit(ca) - && !Character.isDigit(cb)) { - return bias; - } else if (!Character.isDigit(ca)) { - return -1; - } else if (!Character.isDigit(cb)) { - return +1; - } else if (ca < cb) { - if (bias == 0) { - bias = -1; - } - } else if (ca > cb) { - if (bias == 0) - bias = +1; - } else if (ca == 0 && cb == 0) { - return bias; - } - } - } - - public int compare(String a, String b) { - - int ia = 0, ib = 0; - int nza = 0, nzb = 0; - char ca, cb; - int result; - - while (true) { - // only count the number of zeroes leading the last number compared - nza = nzb = 0; - - ca = charAt(a, ia); cb = charAt(b, ib); - - // skip over leading spaces or zeros - while (Character.isSpaceChar(ca) || ca == '0') { - if (ca == '0') { - nza++; - } else { - // only count consecutive zeroes - nza = 0; - } - - ca = charAt(a, ++ia); - } - - while (Character.isSpaceChar(cb) || cb == '0') { - if (cb == '0') { - nzb++; - } else { - // only count consecutive zeroes - nzb = 0; - } - - cb = charAt(b, ++ib); - } - - // process run of digits - if (Character.isDigit(ca) && Character.isDigit(cb)) { - if ((result = compareRight(a.substring(ia), b.substring(ib))) != 0) { - return result; - } - } - - if (ca == 0 && cb == 0) { - // The strings compare the same. Perhaps the caller - // will want to call strcmp to break the tie. - return nza - nzb; - } - - if (ca < cb) { - return -1; - } else if (ca > cb) { - return +1; - } - - ++ia; ++ib; - } - } - - static char charAt(String s, int i) { - if (i >= s.length()) { - return 0; - } else { - return s.charAt(i); - } - } + int compareRight(String a, String b) + { + int bias = 0; + int ia = 0; + int ib = 0; + + // The longest run of digits wins. That aside, the greatest + // value wins, but we can't know that it will until we've scanned + // both numbers to know that they have the same magnitude, so we + // remember it in BIAS. + for (;; ia++, ib++) { + char ca = charAt(a, ia); + char cb = charAt(b, ib); + + if (!Character.isDigit(ca) + && !Character.isDigit(cb)) { + return bias; + } else if (!Character.isDigit(ca)) { + return -1; + } else if (!Character.isDigit(cb)) { + return +1; + } else if (ca < cb) { + if (bias == 0) { + bias = -1; + } + } else if (ca > cb) { + if (bias == 0) + bias = +1; + } else if (ca == 0 && cb == 0) { + return bias; + } + } + } + + public int compare(String a, String b) { + + int ia = 0, ib = 0; + int nza = 0, nzb = 0; + char ca, cb; + int result; + + while (true) { + // only count the number of zeroes leading the last number compared + nza = nzb = 0; + + ca = charAt(a, ia); cb = charAt(b, ib); + + // skip over leading spaces or zeros + while (Character.isSpaceChar(ca) || ca == '0') { + if (ca == '0') { + nza++; + } else { + // only count consecutive zeroes + nza = 0; + } + + ca = charAt(a, ++ia); + } + + while (Character.isSpaceChar(cb) || cb == '0') { + if (cb == '0') { + nzb++; + } else { + // only count consecutive zeroes + nzb = 0; + } + + cb = charAt(b, ++ib); + } + + // process run of digits + if (Character.isDigit(ca) && Character.isDigit(cb)) { + if ((result = compareRight(a.substring(ia), b.substring(ib))) != 0) { + return result; + } + } + + if (ca == 0 && cb == 0) { + // The strings compare the same. Perhaps the caller + // will want to call strcmp to break the tie. + return nza - nzb; + } + + if (ca < cb) { + return -1; + } else if (ca > cb) { + return +1; + } + + ++ia; ++ib; + } + } + + static char charAt(String s, int i) { + if (i >= s.length()) { + return 0; + } else { + return s.charAt(i); + } + } } \ No newline at end of file