You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2016/07/07 09:18:40 UTC

[06/10] brooklyn-server git commit: tidy/enhancements to javalang utils

tidy/enhancements to javalang utils

a few more methods which were elsewhere or not present,
better methods using Maybe, and callers updated to use them


Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/23ab1c50
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/23ab1c50
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/23ab1c50

Branch: refs/heads/master
Commit: 23ab1c506bdda9a3ac79199146ea9750d18d9005
Parents: 8644003
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Fri Jun 24 11:13:18 2016 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Fri Jun 24 23:02:48 2016 +0100

----------------------------------------------------------------------
 .../creation/BrooklynYamlTypeInstantiator.java  |   6 +-
 .../spi/dsl/methods/BrooklynDslCommon.java      |   2 +-
 .../core/mgmt/entitlement/Entitlements.java     |   6 +-
 .../BasicExternalConfigSupplierRegistry.java    |   6 +-
 .../core/mgmt/internal/LocalUsageManager.java   |   4 +-
 .../core/mgmt/rebind/RebindIteration.java       |   3 +-
 .../core/objs/proxy/InternalFactory.java        |   7 +-
 .../entity/group/DynamicClusterImpl.java        |   4 +-
 .../location/jclouds/JcloudsLocation.java       |  15 +-
 .../java/org/apache/brooklyn/test/Asserts.java  |   8 +-
 .../util/guava/AnyExceptionSupplier.java        |   8 +-
 .../apache/brooklyn/util/javalang/Boxing.java   |  29 +++
 .../apache/brooklyn/util/javalang/Enums.java    |   4 +-
 .../brooklyn/util/javalang/FieldOrderings.java  |  82 +++++++
 .../brooklyn/util/javalang/JavaClassNames.java  |  18 +-
 .../util/javalang/ReflectionPredicates.java     |  71 ++++++
 .../brooklyn/util/javalang/Reflections.java     | 239 ++++++++++++++-----
 .../apache/brooklyn/util/javalang/Threads.java  |   1 -
 .../brooklyn/util/javalang/BoxingTest.java      |   5 +
 .../brooklyn/util/javalang/ReflectionsTest.java |  13 +-
 20 files changed, 422 insertions(+), 109 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/23ab1c50/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeInstantiator.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeInstantiator.java b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeInstantiator.java
index 01bfaa2..a8f8c5a 100644
--- a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeInstantiator.java
+++ b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeInstantiator.java
@@ -129,17 +129,17 @@ public abstract class BrooklynYamlTypeInstantiator {
         public <T> T newInstance(@Nullable Class<T> supertype) {
             Class<? extends T> type = getType(supertype);
             Map<String, ?> cfg = getConfigMap();
-            Optional<? extends T> result = Reflections.invokeConstructorWithArgs(type, cfg);
+            Maybe<? extends T> result = Reflections.invokeConstructorFromArgs(type, cfg);
             if (result.isPresent()) 
                 return result.get();
             
             ConfigBag cfgBag = ConfigBag.newInstance(cfg);
-            result = Reflections.invokeConstructorWithArgs(type, cfgBag);
+            result = Reflections.invokeConstructorFromArgs(type, cfgBag);
             if (result.isPresent()) 
                 return result.get();
             
             if (cfg.isEmpty()) {
-                result = Reflections.invokeConstructorWithArgs(type);
+                result = Reflections.invokeConstructorFromArgs(type);
                 if (result.isPresent()) 
                     return result.get();
             }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/23ab1c50/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
index 48ea03f..b88829b 100644
--- a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
+++ b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
@@ -359,7 +359,7 @@ public class BrooklynDslCommon {
                 try {
                     bean = (T) TypeCoercions.coerce(fields, type);
                 } catch (ClassCoercionException ex) {
-                    bean = Reflections.invokeConstructorWithArgs(type).get();
+                    bean = Reflections.invokeConstructorFromArgs(type).get();
                     BeanUtils.populate(bean, fields);
                 }
                 if (bean instanceof Configurable && config.size() > 0) {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/23ab1c50/core/src/main/java/org/apache/brooklyn/core/mgmt/entitlement/Entitlements.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/entitlement/Entitlements.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/entitlement/Entitlements.java
index 7199267..df3f7a8 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/entitlement/Entitlements.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/entitlement/Entitlements.java
@@ -21,7 +21,6 @@ package org.apache.brooklyn.core.mgmt.entitlement;
 import java.util.Arrays;
 import java.util.List;
 
-import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
 import org.apache.brooklyn.api.entity.Entity;
@@ -35,10 +34,10 @@ import org.apache.brooklyn.core.config.ConfigKeys;
 import org.apache.brooklyn.core.config.Sanitizer;
 import org.apache.brooklyn.core.internal.BrooklynProperties;
 import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
-import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 import org.apache.brooklyn.core.mgmt.persist.DeserializingClassRenamesProvider;
 import org.apache.brooklyn.util.core.task.Tasks;
 import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.javalang.Reflections;
 import org.apache.brooklyn.util.text.Strings;
 import org.slf4j.Logger;
@@ -47,7 +46,6 @@ import org.slf4j.LoggerFactory;
 import com.google.common.annotations.Beta;
 import com.google.common.base.Joiner;
 import com.google.common.base.Objects;
-import com.google.common.base.Optional;
 import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 import com.google.common.collect.ImmutableList;
@@ -474,7 +472,7 @@ public class Entitlements {
     private static Object instantiate(Class<?> clazz, List<Object[]> constructorArgOptions) {
         try {
             for (Object[] constructorArgOption : constructorArgOptions) {
-                Optional<?> result = Reflections.invokeConstructorWithArgs(clazz, constructorArgOption);
+                Maybe<?> result = Reflections.invokeConstructorFromArgs(clazz, constructorArgOption);
                 if (result.isPresent()) return result.get();
             }
         } catch (Exception e) { 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/23ab1c50/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/BasicExternalConfigSupplierRegistry.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/BasicExternalConfigSupplierRegistry.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/BasicExternalConfigSupplierRegistry.java
index 6b261db..ac67f22 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/BasicExternalConfigSupplierRegistry.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/BasicExternalConfigSupplierRegistry.java
@@ -27,11 +27,11 @@ import org.apache.brooklyn.core.config.ConfigPredicates;
 import org.apache.brooklyn.core.config.ConfigUtils;
 import org.apache.brooklyn.core.config.external.ExternalConfigSupplier;
 import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.javalang.Reflections;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Optional;
 import com.google.common.collect.Maps;
 
 /**
@@ -102,9 +102,9 @@ public class BasicExternalConfigSupplierRegistry implements ExternalConfigSuppli
             Map<String, Object> config = ConfigUtils.filterForPrefixAndStrip(externalProviderProperties, key + ".");
 
             try {
-                Optional<ExternalConfigSupplier> configSupplier = Reflections.invokeConstructorWithArgs(classloader, providerClassname, mgmt, name, config);
+                Maybe<ExternalConfigSupplier> configSupplier = Reflections.invokeConstructorFromArgs(classloader, ExternalConfigSupplier.class, providerClassname, mgmt, name, config);
                 if (!configSupplier.isPresent()) {
-                    configSupplier = Reflections.invokeConstructorWithArgs(classloader, providerClassname, mgmt, name);
+                    configSupplier = Reflections.invokeConstructorFromArgs(classloader, ExternalConfigSupplier.class, providerClassname, mgmt, name);
                 }
                 if (!configSupplier.isPresent()) {
                     throw new IllegalStateException("No matching constructor found in "+providerClassname);

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/23ab1c50/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalUsageManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalUsageManager.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalUsageManager.java
index 7caf958..50df5c8 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalUsageManager.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalUsageManager.java
@@ -50,6 +50,7 @@ import org.apache.brooklyn.core.mgmt.usage.UsageListener;
 import org.apache.brooklyn.core.mgmt.usage.UsageManager;
 import org.apache.brooklyn.util.core.flags.TypeCoercions;
 import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.javalang.Reflections;
 import org.apache.brooklyn.util.time.Duration;
 import org.slf4j.Logger;
@@ -57,7 +58,6 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Function;
-import com.google.common.base.Optional;
 import com.google.common.base.Predicate;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
@@ -142,7 +142,7 @@ public class LocalUsageManager implements UsageManager {
             @Override public UsageListener apply(String input) {
                 // TODO Want to use classLoader = mgmt.getCatalog().getRootClassLoader();
                 ClassLoader classLoader = LocalUsageManager.class.getClassLoader();
-                Optional<Object> result = Reflections.invokeConstructorWithArgs(classLoader, input);
+                Maybe<Object> result = Reflections.invokeConstructorFromArgs(classLoader, input);
                 if (result.isPresent()) {
                     return (UsageListener) result.get();
                 } else {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/23ab1c50/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindIteration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindIteration.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindIteration.java
index 5c77753..6c0bd9d 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindIteration.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindIteration.java
@@ -101,7 +101,6 @@ import org.apache.brooklyn.util.time.Time;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Stopwatch;
 import com.google.common.collect.ImmutableMap;
@@ -1118,7 +1117,7 @@ public abstract class RebindIteration {
         protected <T> T invokeConstructor(Reflections reflections, Class<T> clazz, Object[]... possibleArgs) {
             for (Object[] args : possibleArgs) {
                 try {
-                    Optional<T> v = Reflections.invokeConstructorWithArgs(clazz, args, true);
+                    Maybe<T> v = Reflections.invokeConstructorFromArgs(clazz, args, true);
                     if (v.isPresent()) {
                         return v.get();
                     }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/23ab1c50/core/src/main/java/org/apache/brooklyn/core/objs/proxy/InternalFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/objs/proxy/InternalFactory.java b/core/src/main/java/org/apache/brooklyn/core/objs/proxy/InternalFactory.java
index f5454fe..0f7e79e 100644
--- a/core/src/main/java/org/apache/brooklyn/core/objs/proxy/InternalFactory.java
+++ b/core/src/main/java/org/apache/brooklyn/core/objs/proxy/InternalFactory.java
@@ -28,10 +28,9 @@ import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.core.config.ConfigBag;
 import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.javalang.Reflections;
 
-import com.google.common.base.Optional;
-
 /**
  */
 public class InternalFactory {
@@ -142,9 +141,9 @@ public class InternalFactory {
     
     protected <T> T constructOldStyle(Class<T> clazz, Map<String,?> flags) throws InstantiationException, IllegalAccessException, InvocationTargetException {
         FactoryConstructionTracker.setConstructing();
-        Optional<T> v;
+        Maybe<T> v;
         try {
-            v = Reflections.invokeConstructorWithArgs(clazz, new Object[] {MutableMap.copyOf(flags)}, true);
+            v = Reflections.invokeConstructorFromArgs(clazz, new Object[] {MutableMap.copyOf(flags)}, true);
         } finally {
             FactoryConstructionTracker.reset();
         }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/23ab1c50/core/src/main/java/org/apache/brooklyn/entity/group/DynamicClusterImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/entity/group/DynamicClusterImpl.java b/core/src/main/java/org/apache/brooklyn/entity/group/DynamicClusterImpl.java
index d4d5b1d..0271134 100644
--- a/core/src/main/java/org/apache/brooklyn/entity/group/DynamicClusterImpl.java
+++ b/core/src/main/java/org/apache/brooklyn/entity/group/DynamicClusterImpl.java
@@ -115,7 +115,7 @@ public class DynamicClusterImpl extends AbstractGroupImpl implements DynamicClus
             @Override
             public NodePlacementStrategy apply(final String input) {
                 ClassLoader classLoader = NodePlacementStrategy.class.getClassLoader();
-                Optional<NodePlacementStrategy> strategy = Reflections.<NodePlacementStrategy>invokeConstructorWithArgs(classLoader, input);
+                Maybe<NodePlacementStrategy> strategy = Reflections.invokeConstructorFromArgs(classLoader, NodePlacementStrategy.class, input);
                 if (strategy.isPresent()) {
                     return strategy.get();
                 } else {
@@ -127,7 +127,7 @@ public class DynamicClusterImpl extends AbstractGroupImpl implements DynamicClus
             @Override
             public ZoneFailureDetector apply(final String input) {
                 ClassLoader classLoader = ZoneFailureDetector.class.getClassLoader();
-                Optional<ZoneFailureDetector> detector = Reflections.<ZoneFailureDetector>invokeConstructorWithArgs(classLoader, input);
+                Maybe<ZoneFailureDetector> detector = Reflections.invokeConstructorFromArgs(classLoader, ZoneFailureDetector.class, input);
                 if (detector.isPresent()) {
                     return detector.get();
                 } else {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/23ab1c50/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java
index 51e9d6a..58895a8 100644
--- a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java
+++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java
@@ -58,7 +58,6 @@ import org.apache.brooklyn.api.location.NoMachinesAvailableException;
 import org.apache.brooklyn.api.location.PortRange;
 import org.apache.brooklyn.api.mgmt.AccessController;
 import org.apache.brooklyn.api.mgmt.Task;
-import org.apache.brooklyn.api.mgmt.TaskAdaptable;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.config.ConfigKey.HasConfigKey;
 import org.apache.brooklyn.core.BrooklynVersion;
@@ -107,8 +106,6 @@ import org.apache.brooklyn.util.core.task.TaskBuilder;
 import org.apache.brooklyn.util.core.task.TaskInternal;
 import org.apache.brooklyn.util.core.task.Tasks;
 import org.apache.brooklyn.util.core.task.ssh.SshTasks;
-import org.apache.brooklyn.util.core.task.system.ProcessTaskFactory;
-import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper;
 import org.apache.brooklyn.util.core.text.TemplateProcessor;
 import org.apache.brooklyn.util.exceptions.CompoundRuntimeException;
 import org.apache.brooklyn.util.exceptions.Exceptions;
@@ -400,7 +397,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im
     protected CloudMachineNamer getCloudMachineNamer(ConfigBag config) {
         String namerClass = config.get(LocationConfigKeys.CLOUD_MACHINE_NAMER_CLASS);
         if (Strings.isNonBlank(namerClass)) {
-            Optional<CloudMachineNamer> cloudNamer = Reflections.invokeConstructorWithArgs(getManagementContext().getCatalogClassLoader(), namerClass);
+            Maybe<CloudMachineNamer> cloudNamer = Reflections.invokeConstructorFromArgs(getManagementContext().getCatalogClassLoader(), CloudMachineNamer.class, namerClass);
             if (cloudNamer.isPresent()) {
                 return cloudNamer.get();
             } else {
@@ -425,11 +422,11 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im
         if (customizer != null) result.add(customizer);
         if (customizers != null) result.addAll(customizers);
         if (Strings.isNonBlank(customizerType)) {
-            Optional<JcloudsLocationCustomizer> customizerByType = Reflections.invokeConstructorWithArgs(catalogClassLoader, customizerType, setup);
+            Maybe<JcloudsLocationCustomizer> customizerByType = Reflections.invokeConstructorFromArgs(catalogClassLoader, JcloudsLocationCustomizer.class, customizerType, setup);
             if (customizerByType.isPresent()) {
                 result.add(customizerByType.get());
             } else {
-                customizerByType = Reflections.invokeConstructorWithArgs(catalogClassLoader, customizerType);
+                customizerByType = Reflections.invokeConstructorFromArgs(catalogClassLoader, JcloudsLocationCustomizer.class, customizerType);
                 if (customizerByType.isPresent()) {
                     result.add(customizerByType.get());
                 } else {
@@ -438,11 +435,11 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im
             }
         }
         if (Strings.isNonBlank(customizersSupplierType)) {
-            Optional<Supplier<Collection<JcloudsLocationCustomizer>>> supplier = Reflections.invokeConstructorWithArgs(catalogClassLoader, customizersSupplierType, setup);
+            Maybe<Supplier<Collection<JcloudsLocationCustomizer>>> supplier = Reflections.<Supplier<Collection<JcloudsLocationCustomizer>>>invokeConstructorFromArgsUntyped(catalogClassLoader, customizersSupplierType, setup);
             if (supplier.isPresent()) {
                 result.addAll(supplier.get().get());
             } else {
-                supplier = Reflections.invokeConstructorWithArgs(catalogClassLoader, customizersSupplierType);
+                supplier = Reflections.<Supplier<Collection<JcloudsLocationCustomizer>>>invokeConstructorFromArgsUntyped(catalogClassLoader, customizersSupplierType);
                 if (supplier.isPresent()) {
                     result.addAll(supplier.get().get());
                 } else {
@@ -1566,7 +1563,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im
         Object rawVal = config.getStringKey(JcloudsLocationConfig.IMAGE_CHOOSER.getName());
         if (rawVal instanceof String && Strings.isNonBlank((String)rawVal)) {
             // Configured with a string: it could be a class that we need to instantiate
-            Optional<?> instance = Reflections.invokeConstructorWithArgs(getManagementContext().getCatalogClassLoader(), (String)rawVal);
+            Maybe<?> instance = Reflections.invokeConstructorFromArgs(getManagementContext().getCatalogClassLoader(), (String)rawVal);
             if (!instance.isPresent()) {
                 throw new IllegalStateException("Failed to create ImageChooser "+rawVal+" for location "+this);
             } else if (!(instance.get() instanceof Function)) {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/23ab1c50/utils/common/src/main/java/org/apache/brooklyn/test/Asserts.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/test/Asserts.java b/utils/common/src/main/java/org/apache/brooklyn/test/Asserts.java
index aa74d1b..a544f01 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/test/Asserts.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/test/Asserts.java
@@ -1161,8 +1161,12 @@ public class Asserts {
     /** Throws a {@link ShouldHaveFailedPreviouslyAssertionError} exception, 
      * to more easily distinguish this failure from other fails.
      * In particular, use one of the <code>expectedFailure</code> methods
-     * in the surrounding <code>catch</code> block and this error will pass through it. */
-    public static void shouldHaveFailedPreviously() {
+     * in the surrounding <code>catch</code> block and this error will pass through it.
+     * <p>
+     * This method throws, never returning normally, but declares a return type 
+     * so you can pretend to throw the result,
+     * for instance if your calling code otherwise warns about needing to return something. */
+    public static RuntimeException shouldHaveFailedPreviously() {
         throw new ShouldHaveFailedPreviouslyAssertionError();
     }
     /** As {@link #shouldHaveFailedPreviously()} but allowing detail,

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/23ab1c50/utils/common/src/main/java/org/apache/brooklyn/util/guava/AnyExceptionSupplier.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/guava/AnyExceptionSupplier.java b/utils/common/src/main/java/org/apache/brooklyn/util/guava/AnyExceptionSupplier.java
index 7111c39..a194ac0 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/guava/AnyExceptionSupplier.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/guava/AnyExceptionSupplier.java
@@ -44,10 +44,10 @@ public class AnyExceptionSupplier<T extends Throwable> implements Supplier<T> {
     public T get() {
         String msg = message==null ? null : message.get();
         Maybe<T> result = Maybe.absent();
-        if (result.isAbsent() && msg==null && cause==null) result = Reflections.invokeConstructorWithArgs(type);
-        if (result.isAbsent() && cause==null) result = Reflections.invokeConstructorWithArgs(type, msg);
-        if (result.isAbsent() && msg==null) result = Reflections.invokeConstructorWithArgs(type, cause);
-        if (result.isAbsent()) result = Reflections.invokeConstructorWithArgs(type, msg, cause);
+        if (result.isAbsent() && msg==null && cause==null) result = Reflections.invokeConstructorFromArgs(type);
+        if (result.isAbsent() && cause==null) result = Reflections.invokeConstructorFromArgs(type, msg);
+        if (result.isAbsent() && msg==null) result = Reflections.invokeConstructorFromArgs(type, cause);
+        if (result.isAbsent()) result = Reflections.invokeConstructorFromArgs(type, msg, cause);
         if (result.isAbsent()) {
             throw new IllegalStateException("Cannot create desired "+type+" (missing constructor)",
                 new IllegalStateException(message==null ? null : message.get(), cause));

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/23ab1c50/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Boxing.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Boxing.java b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Boxing.java
index 79a1830..87529ad 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Boxing.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Boxing.java
@@ -23,7 +23,11 @@ import java.lang.reflect.Array;
 import org.apache.brooklyn.util.guava.Maybe;
 
 import com.google.common.collect.ImmutableBiMap;
+import com.google.common.primitives.Primitives;
 
+/** Conveniences for working with primitives and their boxed (wrapper) types.
+ * NB: there is redundancy with {@link Primitives}
+ */
 public class Boxing {
 
     public static boolean unboxSafely(Boolean ref, boolean valueIfNull) {
@@ -56,6 +60,17 @@ public class Boxing {
         }
         return Maybe.absent("Not a primitive: "+typeName);
     }
+
+    /** returns name of primitive corresponding to the given (boxed or unboxed) type */
+    public static Maybe<String> getPrimitiveName(Class<?> type) {
+        if (type!=null) {
+            if (PRIMITIVE_TO_BOXED.containsKey(type)) return Maybe.of(type.getName());
+            if (PRIMITIVE_TO_BOXED.containsValue(type)) {
+                return Maybe.of(PRIMITIVE_TO_BOXED.inverse().get(type).getName());
+            }
+        }
+        return Maybe.absent("Not a primitive or boxed primitive: "+type);
+    }
     
     public static Class<?> boxedType(Class<?> type) {
         if (PRIMITIVE_TO_BOXED.containsKey(type))
@@ -63,6 +78,20 @@ public class Boxing {
         return type;
     }
 
+    public static boolean isPrimitiveOrBoxedObject(Object o) {
+        if (o==null) return false;
+        return isPrimitiveOrBoxedClass(o.getClass());
+    }
+    public static boolean isPrimitiveOrBoxedClass(Class<?> t) {
+        // TODO maybe better to switch to using Primitives, eg:
+        // return Primitives.allPrimitiveTypes().contains(type) || Primitives.allWrapperTypes().contains(type);
+        
+        if (t==null) return false;
+        if (t.isPrimitive()) return true;
+        if (PRIMITIVE_TO_BOXED.containsValue(t)) return true;
+        return false;
+    }
+    
     /** sets the given element in an array to the indicated value;
      * if the type is a primitive type, the appropriate primitive method is used
      * <p>

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/23ab1c50/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Enums.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Enums.java b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Enums.java
index d3bfd83..a9305a8 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Enums.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Enums.java
@@ -71,8 +71,10 @@ public class Enums {
         return new EnumFromStringFunction<T>(type);
     }
 
+    /** returns array of values in the given enum, or null if it is not an enum */
     @SuppressWarnings("unchecked")
-    private static <T extends Enum<?>> T[] values(Class<T> type) {
+    public static <T extends Enum<?>> T[] values(Class<T> type) {
+        if (type==null || !type.isEnum()) return null;
         try {
             return (T[]) type.getMethod("values").invoke(null);
         } catch (Exception e) {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/23ab1c50/utils/common/src/main/java/org/apache/brooklyn/util/javalang/FieldOrderings.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/FieldOrderings.java b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/FieldOrderings.java
new file mode 100644
index 0000000..ceb33e8
--- /dev/null
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/FieldOrderings.java
@@ -0,0 +1,82 @@
+/*
+ * 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.brooklyn.util.javalang;
+
+import java.lang.reflect.Field;
+import java.util.Comparator;
+
+import org.apache.brooklyn.util.collections.MutableList;
+
+import com.google.common.collect.Ordering;
+
+public class FieldOrderings {
+    public static class FieldNameComparator implements Comparator<Field> {
+        private final Comparator<String> nameComparator;
+        public FieldNameComparator(Comparator<String> nameComparator) { this.nameComparator = nameComparator; }
+        @Override
+        public int compare(Field o1, Field o2) {
+            return nameComparator.compare(o1.getName(), o2.getName());
+        }
+    }
+    public static class FieldClassComparator implements Comparator<Field> {
+        private final Comparator<Class<?>> classComparator;
+        public FieldClassComparator(Comparator<Class<?>> classComparator) { this.classComparator = classComparator; }
+        @Override
+        public int compare(Field o1, Field o2) {
+            return classComparator.compare(o1.getDeclaringClass(), o2.getDeclaringClass());
+        }
+    }
+
+    public static Comparator<Class<?>> SUB_BEST_CLASS_COMPARATOR = new SubbestClassComparator();
+    private static class SubbestClassComparator implements Comparator<Class<?>> {
+        @Override
+        public int compare(Class<?> c1, Class<?> c2) {
+            Class<?> cS = Reflections.inferSubbest(c1, c2);
+            return (cS==c1 ? -1 : cS==c2 ? 1 : 0);
+        }
+    }
+
+    /** Puts fields lower in the hierarchy first, and otherwise leaves fields in order */
+    public static Comparator<Field> SUB_BEST_FIELD_FIST_THEN_DEFAULT = 
+        new FieldClassComparator(SUB_BEST_CLASS_COMPARATOR);
+    /** Puts fields higher in the hierarchy first, and otherwise leaves fields in order */
+    public static Comparator<Field> SUB_BEST_FIELD_LAST_THEN_DEFAULT = 
+        new FieldClassComparator(Ordering.from(SUB_BEST_CLASS_COMPARATOR).reverse());
+    /** Puts fields that are lower down the hierarchy first, and then sorts those alphabetically */
+    @SuppressWarnings("unchecked")
+    public static Comparator<Field> SUB_BEST_FIELD_FIRST_THEN_ALPHABETICAL = Ordering.compound(MutableList.of(
+        new FieldClassComparator(SUB_BEST_CLASS_COMPARATOR),
+        new FieldNameComparator(Ordering.<String>natural())));
+    /** Puts fields that are higher up in the hierarchy first, and then sorts those alphabetically */
+    @SuppressWarnings("unchecked")
+    public static Comparator<Field> SUB_BEST_FIELD_LAST_THEN_ALPHABETICAL = Ordering.compound(MutableList.of(
+        new FieldClassComparator(Ordering.from(SUB_BEST_CLASS_COMPARATOR).reverse()),
+        new FieldNameComparator(Ordering.<String>natural())));
+    /** Puts fields in alpha order, but in cases of duplicate those lower down the hierarchy are first */
+    @SuppressWarnings("unchecked")
+    public static Comparator<Field> ALPHABETICAL_FIELD_THEN_SUB_BEST_FIRST = Ordering.compound(MutableList.of(
+        new FieldNameComparator(Ordering.<String>natural()),
+        new FieldClassComparator(SUB_BEST_CLASS_COMPARATOR)));
+    /** Puts fields in alpha order, but in cases of duplicate those higher up in the hierarchy are first 
+     * (potentially confusing, as this will put masked fields first) */
+    @SuppressWarnings("unchecked")
+    public static Comparator<Field> ALPHABETICAL_FIELD_THEN_SUB_BEST_LAST = Ordering.compound(MutableList.of(
+        new FieldNameComparator(Ordering.<String>natural()),
+        new FieldClassComparator(Ordering.from(SUB_BEST_CLASS_COMPARATOR).reverse())));
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/23ab1c50/utils/common/src/main/java/org/apache/brooklyn/util/javalang/JavaClassNames.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/JavaClassNames.java b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/JavaClassNames.java
index e9918df..fe8dd0c 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/JavaClassNames.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/JavaClassNames.java
@@ -79,15 +79,23 @@ public class JavaClassNames {
         
         String result = ct.getSimpleName();
         if (Strings.isBlank(result) || result.length()<=4) {
-            if (ct.isPrimitive()) {
-                // TODO unbox
-            } else {
-                result = ct.getName();
-            }
+            result = ct.getName();
         }
         return result+Strings.repeat("[]", arrayCount);
     }
     
+    /** as {@link #simpleClassName(Class)} but if something is an inner class it drops everything before the $ */
+    public static String verySimpleClassName(Class<?> t) {
+        t = componentType(t);
+        String result = t.getSimpleName();
+        result = result.substring(result.lastIndexOf('.')+1);
+        result = result.substring(result.lastIndexOf('$')+1);
+        if (Strings.isBlank(result)) {
+            result = t.getName();
+        }
+        return result;
+    }
+    
     /** as {@link #simpleClassName(Class)} but taking the type of the object if it is not already a class
      * or a type-token; callers should usually do the getClass themselves, unless they aren't sure whether
      * it is already a Class-type object */

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/23ab1c50/utils/common/src/main/java/org/apache/brooklyn/util/javalang/ReflectionPredicates.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/ReflectionPredicates.java b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/ReflectionPredicates.java
new file mode 100644
index 0000000..3395296
--- /dev/null
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/ReflectionPredicates.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.brooklyn.util.javalang;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+
+public class ReflectionPredicates {
+    
+    public static Predicate<Integer> MODIFIERS_PRIVATE = new ModifiersPrivate();
+    private static class ModifiersPrivate implements Predicate<Integer> {
+        @Override public boolean apply(Integer modifiers) { return Modifier.isPrivate(modifiers); }
+    }
+    public static Predicate<Integer> MODIFIERS_PUBLIC = new ModifiersPublic();
+    private static class ModifiersPublic implements Predicate<Integer> {
+        @Override public boolean apply(Integer modifiers) { return Modifier.isPublic(modifiers); }
+    }
+    public static Predicate<Integer> MODIFIERS_PROTECTED = new ModifiersProtected();
+    private static class ModifiersProtected implements Predicate<Integer> {
+        @Override public boolean apply(Integer modifiers) { return Modifier.isProtected(modifiers); }
+    }
+    
+    public static Predicate<Integer> MODIFIERS_TRANSIENT = new ModifiersTransient();
+    private static class ModifiersTransient implements Predicate<Integer> {
+        @Override public boolean apply(Integer modifiers) { return Modifier.isTransient(modifiers); }
+    }
+    public static Predicate<Integer> MODIFIERS_STATIC = new ModifiersStatic();
+    private static class ModifiersStatic implements Predicate<Integer> {
+        @Override public boolean apply(Integer modifiers) { return Modifier.isStatic(modifiers); }
+    }
+    
+    public static Predicate<Field> fieldModifiers(Predicate<Integer> modifiersCheck) { return new FieldModifiers(modifiersCheck); }
+    private static class FieldModifiers implements Predicate<Field> {
+        private Predicate<Integer> modifiersCheck;
+        private FieldModifiers(Predicate<Integer> modifiersCheck) { this.modifiersCheck = modifiersCheck; }
+        @Override public boolean apply(Field f) { return modifiersCheck.apply(f.getModifiers()); }
+    }
+    public static Predicate<Field> IS_FIELD_PUBLIC = fieldModifiers(MODIFIERS_PUBLIC);
+    public static Predicate<Field> IS_FIELD_TRANSIENT = fieldModifiers(MODIFIERS_TRANSIENT);
+    public static Predicate<Field> IS_FIELD_NON_TRANSIENT = Predicates.not(IS_FIELD_TRANSIENT);
+    public static Predicate<Field> IS_FIELD_STATIC = fieldModifiers(MODIFIERS_STATIC);
+    public static Predicate<Field> IS_FIELD_NON_STATIC = Predicates.not(IS_FIELD_STATIC);
+
+    public static Predicate<Method> methodModifiers(Predicate<Integer> modifiersCheck) { return new MethodModifiers(modifiersCheck); }
+    private static class MethodModifiers implements Predicate<Method> {
+        private Predicate<Integer> modifiersCheck;
+        private MethodModifiers(Predicate<Integer> modifiersCheck) { this.modifiersCheck = modifiersCheck; }
+        @Override public boolean apply(Method m) { return modifiersCheck.apply(m.getModifiers()); }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/23ab1c50/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Reflections.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Reflections.java b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Reflections.java
index 0f31882..7b2cba4 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Reflections.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Reflections.java
@@ -47,18 +47,20 @@ import javax.annotation.Nullable;
 import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.guava.Maybe;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Sets;
 
 /**
- * Reflection utilities ("borrowed" from cloudsoft monterey).
+ * Reflection utilities
  * 
  * @author aled
  */
@@ -88,7 +90,7 @@ public class Reflections {
     private final Map<String, String> classRenameMap = MutableMap.of();
     
     public Reflections(ClassLoader classLoader) {
-        this.classLoader = checkNotNull(classLoader);
+        this.classLoader = classLoader!=null ? classLoader : getClass().getClassLoader();
     }
     
     /** supply a map of known renames, of the form "old-class -> new-class" */ 
@@ -99,9 +101,9 @@ public class Reflections {
 
     public Object loadInstance(String classname, Object...argValues) throws ReflectionNotFoundException, ReflectionAccessException {
         Class<?> clazz = loadClass(classname);
-        Optional<?> v = null;
+        Maybe<?> v = null;
         try {
-            v = invokeConstructorWithArgs(clazz, argValues);
+            v = invokeConstructorFromArgs(clazz, argValues);
             if (v.isPresent()) return v.get();
         } catch (Exception e) {
             throw new IllegalStateException("Error invoking constructor for "+clazz+Arrays.toString(argValues) + ": " + Exceptions.collapseText(e));
@@ -221,41 +223,80 @@ public class Reflections {
         }
     }
 
-    /** Invokes a suitable constructor, supporting varargs and primitives */
+    /** @deprecated since 0.10.0 use {@link #invokeConstructorFromArgs(Class, Object...)} or one of the variants;
+     * this allows null field values */ @Deprecated
     public static <T> Optional<T> invokeConstructorWithArgs(ClassLoader classLoader, String className, Object...argsArray) {
+        return Reflections.<T>invokeConstructorFromArgsUntyped(classLoader, className, argsArray).toOptional();
+    }
+    /** @deprecated since 0.10.0 use {@link #invokeConstructorFromArgs(Class, Object...)} or one of the variants */ @Deprecated
+    public static <T> Optional<T> invokeConstructorWithArgs(ClassLoader classLoader, Class<T> clazz, Object[] argsArray, boolean setAccessible) {
+        return invokeConstructorFromArgs(classLoader, clazz, argsArray, setAccessible).toOptional();
+    }
+    /** @deprecated since 0.10.0 use {@link #invokeConstructorFromArgs(Class, Object...)} or one of the variants */ @Deprecated
+    public static <T> Optional<T> invokeConstructorWithArgs(Class<? extends T> clazz, Object...argsArray) {
+        return invokeConstructorFromArgs(clazz, argsArray).toOptional();
+    }
+    /** @deprecated since 0.10.0 use {@link #invokeConstructorFromArgs(Class, Object...)} or one of the variants */ @Deprecated
+    public static <T> Optional<T> invokeConstructorWithArgs(Class<? extends T> clazz, Object[] argsArray, boolean setAccessible) {
+        return invokeConstructorFromArgs(clazz, argsArray, setAccessible).toOptional();
+    }
+    /** @deprecated since 0.10.0 use {@link #invokeConstructorFromArgs(Class, Object...)} or one of the variants */ @Deprecated
+    public static <T> Optional<T> invokeConstructorWithArgs(Reflections reflections, Class<? extends T> clazz, Object[] argsArray, boolean setAccessible) {
+        return invokeConstructorFromArgs(reflections, clazz, argsArray, setAccessible).toOptional();
+    }
+    
+    /** Finds and invokes a suitable constructor, supporting varargs and primitives, boxing and looking at compatible supertypes in the constructor's signature */
+    public static <T> Maybe<T> invokeConstructorFromArgs(Class<? extends T> clazz, Object...argsArray) {
+        return invokeConstructorFromArgs(clazz, argsArray, false);
+    }
+
+    /** As {@link #invokeConstructorFromArgs(Class, Object...)} but allowing more configurable input */
+    public static Maybe<Object> invokeConstructorFromArgs(ClassLoader classLoader, String className, Object...argsArray) {
+        return invokeConstructorFromArgs(classLoader, null, className, argsArray);
+    }
+    
+    /** As {@link #invokeConstructorFromArgs(Class, Object...)} but allowing more configurable input */
+    @SuppressWarnings("unchecked")
+    public static <T> Maybe<T> invokeConstructorFromArgs(ClassLoader classLoader, Class<T> optionalSupertype, String className, Object...argsArray) {
         Reflections reflections = new Reflections(classLoader);
-        @SuppressWarnings("unchecked")
-        Class<T> clazz = (Class<T>) reflections.loadClass(className);
-        return invokeConstructorWithArgs(reflections, clazz, argsArray, false);
+        Class<?> clazz = reflections.loadClass(className);
+        if (optionalSupertype!=null && !optionalSupertype.isAssignableFrom(clazz)) {
+            return Maybe.absent("The type requested '"+className+"' is not assignable to "+optionalSupertype);
+        }
+        return invokeConstructorFromArgs(reflections, (Class<T>)clazz, argsArray, false);
     }
 
-    /** Invokes a suitable constructor, supporting varargs and primitives */
-    public static <T> Optional<T> invokeConstructorWithArgs(ClassLoader classLoader, Class<T> clazz, Object[] argsArray, boolean setAccessible) {
+    /** As {@link #invokeConstructorFromArgs(Class, Object...)} but allowing more configurable input */
+    public static <T> Maybe<T> invokeConstructorFromArgsUntyped(ClassLoader classLoader, String className, Object...argsArray) {
         Reflections reflections = new Reflections(classLoader);
-        return invokeConstructorWithArgs(reflections, clazz, argsArray, setAccessible);
+        @SuppressWarnings("unchecked")
+        Class<T> clazz = (Class<T>)reflections.loadClass(className);
+        return invokeConstructorFromArgs(reflections, clazz, argsArray, false);
     }
 
-    /** Invokes a suitable constructor, supporting varargs and primitives */
-    public static <T> Optional<T> invokeConstructorWithArgs(Class<T> clazz, Object...argsArray) {
-        return invokeConstructorWithArgs(clazz, argsArray, false);
+    /** As {@link #invokeConstructorFromArgs(Class, Object...)} but allowing more configurable input; 
+     * in particular setAccessible allows private constructors to be used (not the default) */
+    public static <T> Maybe<T> invokeConstructorFromArgs(ClassLoader classLoader, Class<T> clazz, Object[] argsArray, boolean setAccessible) {
+        Reflections reflections = new Reflections(classLoader);
+        return invokeConstructorFromArgs(reflections, clazz, argsArray, setAccessible);
     }
 
-    /** Invokes a suitable constructor, supporting varargs and primitives */
-    public static <T> Optional<T> invokeConstructorWithArgs(Class<T> clazz, Object[] argsArray, boolean setAccessible) {
-        ClassLoader cl = clazz.getClassLoader();
-        // if bootstrap class loader
-        if (cl == null) {
-            // The classloader isn't actually used so anything non-null will work
-            cl = ClassLoader.getSystemClassLoader();
-        }
-        Reflections reflections = new Reflections(cl);
-        return invokeConstructorWithArgs(reflections, clazz, argsArray, setAccessible);
+    /** As {@link #invokeConstructorFromArgs(Class, Object...)} but allowing more configurable input;
+     * in particular setAccessible allows private constructors to be used (not the default) */
+    public static <T> Maybe<T> invokeConstructorFromArgs(Class<? extends T> clazz, Object[] argsArray, boolean setAccessible) {
+        Reflections reflections = new Reflections(clazz.getClassLoader());
+        return invokeConstructorFromArgs(reflections, clazz, argsArray, setAccessible);
     }
 
-    /** Invokes a suitable constructor, supporting varargs and primitives, additionally supporting setAccessible */
+    /** As {@link #invokeConstructorFromArgs(Class, Object...)} but will use private constructors (with setAccessible = true) */
+    public static <T> Maybe<T> invokeConstructorFromArgsIncludingPrivate(Class<? extends T> clazz, Object ...argsArray) {
+        return Reflections.invokeConstructorFromArgs(new Reflections(clazz.getClassLoader()), clazz, argsArray, true);
+    }
+    /** As {@link #invokeConstructorFromArgs(Class, Object...)} but allowing more configurable input;
+     * in particular setAccessible allows private constructors to be used (not the default) */
     @SuppressWarnings("unchecked")
-    public static <T> Optional<T> invokeConstructorWithArgs(Reflections reflections, Class<T> clazz, Object[] argsArray, boolean setAccessible) {
-        for (Constructor<?> constructor : clazz.getConstructors()) {
+    public static <T> Maybe<T> invokeConstructorFromArgs(Reflections reflections, Class<? extends T> clazz, Object[] argsArray, boolean setAccessible) {
+        for (Constructor<?> constructor : MutableList.<Constructor<?>>of().appendAll(Arrays.asList(clazz.getConstructors())).appendAll(Arrays.asList(clazz.getDeclaredConstructors()))) {
             Class<?>[] parameterTypes = constructor.getParameterTypes();
             if (constructor.isVarArgs()) {
                 if (typesMatchUpTo(argsArray, parameterTypes, parameterTypes.length-1)) {
@@ -277,16 +318,16 @@ public class Reflections {
                         System.arraycopy(argsArray, 0, newArgsArray, 0, parameterTypes.length-1);
                         newArgsArray[parameterTypes.length-1] = varargs;
                         if (setAccessible) constructor.setAccessible(true);
-                        return (Optional<T>) Optional.of(reflections.loadInstance(constructor, newArgsArray));
+                        return Maybe.of((T)reflections.loadInstance(constructor, newArgsArray));
                     }
                 }
             }
             if (typesMatch(argsArray, parameterTypes)) {
                 if (setAccessible) constructor.setAccessible(true);
-                return (Optional<T>) Optional.of(reflections.loadInstance(constructor, argsArray));
+                return Maybe.of((T) reflections.loadInstance(constructor, argsArray));
             }
         }
-        return Optional.absent();
+        return Maybe.absent("Constructor not found");
     }
     
     
@@ -560,25 +601,86 @@ public class Reflections {
         throw toThrowIfFails;
     }
     
+    /** Finds the field with the given name declared on the given class or any superclass,
+     * using {@link Class#getDeclaredField(String)}.
+     * <p> 
+     * If the field name contains a '.' the field is interpreted as having
+     * <code>DeclaringClassCanonicalName.FieldName</code> format,
+     * allowing a way to set a field unambiguously if some are masked.
+     * <p>
+     * @throws NoSuchFieldException if not found
+     */
     public static Field findField(Class<?> clazz, String name) throws NoSuchFieldException {
+        return findFieldMaybe(clazz, name).orThrowUnwrapped();
+    }
+    public static Maybe<Field> findFieldMaybe(Class<?> clazz, String originalName) {
+        String name = originalName;
         if (clazz == null || name == null) {
             throw new NullPointerException("Must not be null: clazz="+clazz+"; name="+name);
         }
         Class<?> clazzToInspect = clazz;
         NoSuchFieldException toThrowIfFails = null;
+
+        String clazzRequired = null;
+        if (name.indexOf('.')>=0) {
+            int lastDotIndex = name.lastIndexOf('.');
+            clazzRequired = name.substring(0, lastDotIndex);
+            name = name.substring(lastDotIndex+1);
+        }
         
         while (clazzToInspect != null) {
             try {
-                return clazzToInspect.getDeclaredField(name);
+                if (clazzRequired==null || clazzRequired.equals(clazzToInspect.getCanonicalName())) {
+                    return Maybe.of(clazzToInspect.getDeclaredField(name));
+                }
             } catch (NoSuchFieldException e) {
                 if (toThrowIfFails == null) toThrowIfFails = e;
-                clazzToInspect = clazzToInspect.getSuperclass();
             }
+            clazzToInspect = clazzToInspect.getSuperclass();
         }
-        throw toThrowIfFails;
+        if (toThrowIfFails==null) return Maybe.absent("Field '"+originalName+"' not found");
+        return Maybe.absent(toThrowIfFails);
     }
     
+    public static Maybe<Object> getFieldValueMaybe(Object instance, String fieldName) {
+        try {
+            if (instance==null) return null;
+            Field f = findField(instance.getClass(), fieldName);
+            return getFieldValueMaybe(instance, f);
+        } catch (Exception e) {
+            Exceptions.propagateIfFatal(e);
+            return Maybe.absent(e);
+        }
+    }
+
+    public static Maybe<Object> getFieldValueMaybe(Object instance, Field field) {
+        try {
+            if (instance==null) return null;
+            if (field==null) return null;
+            field.setAccessible(true);
+            return Maybe.of(field.get(instance));
+        } catch (Exception e) {
+            Exceptions.propagateIfFatal(e);
+            return Maybe.absent(e);
+        }
+    }
+
+    /** Lists all public fields declared on the class or any ancestor, with those HIGHEST in the hierarchy first */
     public static List<Field> findPublicFieldsOrderedBySuper(Class<?> clazz) {
+        return findFields(clazz, new Predicate<Field>() {
+            @Override public boolean apply(Field input) {
+                return Modifier.isPublic(input.getModifiers());
+            }}, FieldOrderings.SUB_BEST_FIELD_LAST_THEN_DEFAULT);
+    }
+
+    /** Lists all fields declared on the class, with those lowest in the hierarchy first,
+     *  filtered and ordered as requested. 
+     *  <p>
+     *  See {@link ReflectionPredicates} and {@link FieldOrderings} for conveniences.
+     *  <p>
+     *  Default is no filter and {@link FieldOrderings#SUB_BEST_FIELD_LAST_THEN_ALPHABETICAL}
+     *  */
+    public static List<Field> findFields(final Class<?> clazz, Predicate<Field> filter, Comparator<Field> fieldOrdering) {
         checkNotNull(clazz, "clazz");
         MutableList.Builder<Field> result = MutableList.<Field>builder();
         Stack<Class<?>> tovisit = new Stack<Class<?>>();
@@ -593,19 +695,12 @@ public class Reflections {
             if (nextclazz.getSuperclass() != null) tovisit.add(nextclazz.getSuperclass());
             tovisit.addAll(Arrays.asList(nextclazz.getInterfaces()));
             
-            result.addAll(Iterables.filter(Arrays.asList(nextclazz.getDeclaredFields()), new Predicate<Field>() {
-                @Override public boolean apply(Field input) {
-                    return Modifier.isPublic(input.getModifiers());
-                }}));
-            
+            result.addAll(Iterables.filter(Arrays.asList(nextclazz.getDeclaredFields()), 
+                filter!=null ? filter : Predicates.<Field>alwaysTrue()));
         }
         
         List<Field> resultList = result.build();
-        Collections.sort(resultList, new Comparator<Field>() {
-            @Override public int compare(Field f1, Field f2) {
-                Field fsubbest = inferSubbestField(f1, f2);
-                return (fsubbest == null) ? 0 : (fsubbest == f1 ? 1 : -1);
-            }});
+        Collections.sort(resultList, fieldOrdering != null ? fieldOrdering : FieldOrderings.SUB_BEST_FIELD_LAST_THEN_ALPHABETICAL);
         
         return resultList;
     }
@@ -645,18 +740,25 @@ public class Reflections {
     }
     
     /**
-     * Gets the field that is in the sub-class; or null if one field does not come from a sub-class of the other field's class
+     * If the classes of the fields satisfy {@link #inferSubbest(Class, Class)}
+     * return the field in the lower (sub-best) class, otherwise null.
      */
     public static Field inferSubbestField(Field f1, Field f2) {
         Class<?> c1 = f1.getDeclaringClass();
         Class<?> c2 = f2.getDeclaringClass();
         boolean isSuper1 = c1.isAssignableFrom(c2);
         boolean isSuper2 = c2.isAssignableFrom(c1);
-        return (isSuper1) ? (isSuper2 ? null : f2) : (isSuper2 ? f1 : null);
+        return (isSuper1) ? (isSuper2 ? 
+            /* same field */ null : 
+            /* f1 from super */ f2) : 
+            (isSuper2 ? 
+                /* f2 from super of f1 */ f1 : 
+                /* fields are from different hierarchies */ null);
     }
     
     /**
-     * Gets the method that is in the sub-class; or null if one method does not come from a sub-class of the other method's class
+     * If the classes of the methods satisfy {@link #inferSubbest(Class, Class)}
+     * return the field in the lower (sub-best) class, otherwise null.
      */
     public static Method inferSubbestMethod(Method m1, Method m2) {
         Class<?> c1 = m1.getDeclaringClass();
@@ -667,7 +769,8 @@ public class Reflections {
     }
     
     /**
-     * Gets the class that is in the sub-class; or null if neither is a sub-class of the other.
+     * If one class is a subclass of the other, return that (the lower in the type hierarchy);
+     * otherwise return null (if they are the same or neither is a subclass of the other).
      */
     public static Class<?> inferSubbest(Class<?> c1, Class<?> c2) {
         boolean isSuper1 = c1.isAssignableFrom(c2);
@@ -684,14 +787,25 @@ public class Reflections {
         return (T)candidate;
     }
 
+    /** @deprecated since 0.10.0 use {@link #invokeMethodFromArgs(Object, String, List)};
+     * this allows null return values */ @Deprecated
+    public static Optional<Object> invokeMethodWithArgs(Object clazzOrInstance, String method, List<Object> args) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
+        return invokeMethodWithArgs(clazzOrInstance, method, args, false);
+    }
+    /** @deprecated since 0.10.0 use {@link #invokeMethodFromArgs(Object, String, List)} */ @Deprecated
+    public static Optional<Object> invokeMethodWithArgs(Object clazzOrInstance, String method, List<Object> args, boolean setAccessible) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
+        return invokeMethodFromArgs(clazzOrInstance, method, args, setAccessible).toOptional();
+    }
+    
     /** invokes the given method on the given clazz or instance, doing reasonably good matching on args etc 
      * @throws InvocationTargetException 
      * @throws IllegalAccessException 
      * @throws IllegalArgumentException */
-    public static Optional<Object> invokeMethodWithArgs(Object clazzOrInstance, String method, List<Object> args) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
-        return invokeMethodWithArgs(clazzOrInstance, method, args, false);
+    public static Maybe<Object> invokeMethodFromArgs(Object clazzOrInstance, String method, List<Object> args) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
+        return invokeMethodFromArgs(clazzOrInstance, method, args, false);
     }
-    public static Optional<Object> invokeMethodWithArgs(Object clazzOrInstance, String method, List<Object> args, boolean setAccessible) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
+    /** as {@link #invokeMethodFromArgs(Object, String, List)} but giving control over whether to set it accessible */
+    public static Maybe<Object> invokeMethodFromArgs(Object clazzOrInstance, String method, List<Object> args, boolean setAccessible) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
         Preconditions.checkNotNull(clazzOrInstance, "clazz or instance");
         Preconditions.checkNotNull(method, "method");
         Preconditions.checkNotNull(args, "args to "+method);
@@ -731,18 +845,18 @@ public class Reflections {
                             System.arraycopy(argsArray, 0, newArgsArray, 0, parameterTypes.length-1);
                             newArgsArray[parameterTypes.length-1] = varargs;
                             if (setAccessible) m.setAccessible(true);
-                            return Optional.of(m.invoke(instance, newArgsArray));
+                            return Maybe.of(m.invoke(instance, newArgsArray));
                         }
                     }
                 }
                 if (typesMatch(argsArray, parameterTypes)) {
                     if (setAccessible) m.setAccessible(true);
-                    return Optional.of(m.invoke(instance, argsArray));
+                    return Maybe.of(m.invoke(instance, argsArray));
                 }
             }
         }
         
-        return Optional.absent();
+        return Maybe.absent("Method not found matching given args");
     }
 
     /** true iff all args match the corresponding types */
@@ -802,13 +916,18 @@ public class Reflections {
         return hasNoNonObjectFields(clazz.getSuperclass());
     }
 
-    /** Takes a map of old-class-names to renames classes, and returns the mapped name if matched, or absent */
+    /** @deprecated since 0.10.0 use {@link #findMappedNameMaybe(Map, String)} */ @Deprecated
     public static Optional<String> tryFindMappedName(Map<String, String> renames, String name) {
-        if (renames==null) return Optional.absent();
+        return findMappedNameMaybe(renames, name).toOptional();
+    }
+    
+    /** Takes a map of old-class-names to renames classes, and returns the mapped name if matched, or absent */
+    public static Maybe<String> findMappedNameMaybe(Map<String, String> renames, String name) {
+        if (renames==null) return Maybe.absent("no renames supplied");
         
         String mappedName = renames.get(name);
         if (mappedName != null) {
-            return Optional.of(mappedName);
+            return Maybe.of(mappedName);
         }
         
         // look for inner classes by mapping outer class
@@ -816,20 +935,20 @@ public class Reflections {
             String outerClassName = name.substring(0, name.indexOf('$'));
             mappedName = renames.get(outerClassName);
             if (mappedName != null) {
-                return Optional.of(mappedName + name.substring(name.indexOf('$')));
+                return Maybe.of(mappedName + name.substring(name.indexOf('$')));
             }
         }
         
-        return Optional.absent();
+        return Maybe.absent("mapped name not present");
     }
 
     public static String findMappedNameAndLog(Map<String, String> renames, String name) {
-        Optional<String> rename = Reflections.tryFindMappedName(renames, name);
+        Maybe<String> rename = Reflections.findMappedNameMaybe(renames, name);
         if (rename.isPresent()) {
             LOG.debug("Mapping class '"+name+"' to '"+rename.get()+"'");
             return rename.get();
         }
         return name;
     }
-    
+
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/23ab1c50/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Threads.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Threads.java b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Threads.java
index 8e1b3d2..9d4625a 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Threads.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Threads.java
@@ -23,7 +23,6 @@ import java.util.Collection;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.brooklyn.util.exceptions.Exceptions;
-import org.apache.brooklyn.util.exceptions.RuntimeInterruptedException;
 import org.osgi.framework.FrameworkUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/23ab1c50/utils/common/src/test/java/org/apache/brooklyn/util/javalang/BoxingTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/javalang/BoxingTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/javalang/BoxingTest.java
index 8b5a362..802fb22 100644
--- a/utils/common/src/test/java/org/apache/brooklyn/util/javalang/BoxingTest.java
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/javalang/BoxingTest.java
@@ -35,4 +35,9 @@ public class BoxingTest {
         Assert.assertEquals(bt, Integer.class);
     }
 
+    @Test
+    public static void getPrimitive() {
+        Assert.assertEquals(Boxing.getPrimitiveName(Integer.class).get(), "int");
+    }
+    
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/23ab1c50/utils/common/src/test/java/org/apache/brooklyn/util/javalang/ReflectionsTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/javalang/ReflectionsTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/javalang/ReflectionsTest.java
index 2f0537c..b6bb63c 100644
--- a/utils/common/src/test/java/org/apache/brooklyn/util/javalang/ReflectionsTest.java
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/javalang/ReflectionsTest.java
@@ -58,7 +58,8 @@ public class ReflectionsTest {
     
     @Test
     public void testConstructLangObject() {
-        Reflections.invokeConstructorWithArgs(java.util.Date.class);
+        // special test for this because the lang object might have classloader null
+        Assert.assertTrue(Reflections.invokeConstructorFromArgs(java.util.Date.class).get() instanceof java.util.Date);
     }
     
     public static interface MyInterface {
@@ -123,15 +124,15 @@ public class ReflectionsTest {
         Method m = CI1.class.getMethod("m1", String.class, int.class, int.class, int[].class);
         Assert.assertEquals(m.invoke(null, "hello", 1, 2, new int[] { 3, 4}), "hello10");
         
-        Assert.assertEquals(Reflections.invokeMethodWithArgs(CI1.class, "m1", Arrays.<Object>asList("hello", 3)).get(), "hello3");
-        Assert.assertEquals(Reflections.invokeMethodWithArgs(CI1.class, "m1", Arrays.<Object>asList("hello", 3, 4, 5)).get(), "hello12");
+        Assert.assertEquals(Reflections.invokeMethodFromArgs(CI1.class, "m1", Arrays.<Object>asList("hello", 3)).get(), "hello3");
+        Assert.assertEquals(Reflections.invokeMethodFromArgs(CI1.class, "m1", Arrays.<Object>asList("hello", 3, 4, 5)).get(), "hello12");
     }
     
     @Test
     public void testConstruction() throws Exception {
-        Assert.assertEquals(Reflections.invokeConstructorWithArgs(CI1.class, new Object[] {"hello", 3}).get().constructorArgs, ImmutableList.of("hello", 3));
-        Assert.assertEquals(Reflections.invokeConstructorWithArgs(CI1.class, new Object[] {"hello", 3, 4, 5}).get().constructorArgs, ImmutableList.of("hello", 3, 4, 5));
-        Assert.assertFalse(Reflections.invokeConstructorWithArgs(CI1.class, new Object[] {"wrong", "args"}).isPresent());
+        Assert.assertEquals(Reflections.invokeConstructorFromArgs(CI1.class, new Object[] {"hello", 3}).get().constructorArgs, ImmutableList.of("hello", 3));
+        Assert.assertEquals(Reflections.invokeConstructorFromArgs(CI1.class, new Object[] {"hello", 3, 4, 5}).get().constructorArgs, ImmutableList.of("hello", 3, 4, 5));
+        Assert.assertFalse(Reflections.invokeConstructorFromArgs(CI1.class, new Object[] {"wrong", "args"}).isPresent());
     }
 
     interface I { };