Centralize class loading and implement fallback bundle scanning
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/f3154764 Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/f3154764 Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/f3154764 Branch: refs/heads/master Commit: f31547645060e69bcdc1b96882d0040e9a266333 Parents: 1ecd7fe Author: Svetoslav Neykov <[email protected]> Authored: Tue Jul 5 21:00:53 2016 +0300 Committer: Svetoslav Neykov <[email protected]> Committed: Wed Jul 6 15:28:57 2016 +0300 ---------------------------------------------------------------------- .../spi/dsl/methods/BrooklynDslCommon.java | 10 +- .../brooklyn/core/effector/AddSensor.java | 15 +- .../drivers/ReflectiveEntityDriverFactory.java | 5 +- .../brooklyn/core/location/geo/HostGeoInfo.java | 3 +- .../JavaBrooklynClassLoadingContext.java | 18 +- .../core/mgmt/entitlement/Entitlements.java | 8 +- .../internal/AbstractManagementContext.java | 3 +- .../transformer/CompoundTransformerLoader.java | 3 +- .../brooklyn/core/objs/BrooklynTypes.java | 5 +- .../core/sensor/DurationSinceSensor.java | 7 +- .../core/sensor/ssh/SshCommandSensor.java | 2 +- .../location/byon/ByonLocationResolver.java | 4 +- .../location/ssh/SshMachineLocation.java | 3 +- .../brooklyn/util/core/ClassLoaderUtils.java | 249 +++++++++++++++++++ .../brooklyn/util/core/flags/TypeCoercions.java | 9 +- .../objs/BasicSpecParameterFromClassTest.java | 5 +- .../brooklyn/rest/resources/PolicyResource.java | 7 +- .../provider/DelegatingSecurityProvider.java | 10 +- .../HardcodedCatalogEntitySpecResolver.java | 59 +++-- .../location/winrm/WinRmMachineLocation.java | 11 +- 20 files changed, 366 insertions(+), 70 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f3154764/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 b1db078..a67d89e 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 @@ -45,6 +45,7 @@ import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal; import org.apache.brooklyn.core.mgmt.persist.DeserializingClassRenamesProvider; import org.apache.brooklyn.core.sensor.DependentConfiguration; import org.apache.brooklyn.util.collections.MutableMap; +import org.apache.brooklyn.util.core.ClassLoaderUtils; import org.apache.brooklyn.util.core.config.ConfigBag; import org.apache.brooklyn.util.core.flags.ClassCoercionException; import org.apache.brooklyn.util.core.flags.FlagUtils; @@ -129,9 +130,10 @@ public class BrooklynDslCommon { @SuppressWarnings({ "unchecked", "rawtypes" }) public static Sensor<?> sensor(String clazzName, String sensorName) { try { - // TODO Should use catalog's classloader, rather than Class.forName; how to get that? Should we return a future?! + // TODO Should use catalog's classloader, rather than ClassLoaderUtils; how to get that? Should we return a future?! + // Should have the catalog's loader at this point in a thread local String mappedClazzName = DeserializingClassRenamesProvider.findMappedName(clazzName); - Class<?> clazz = Class.forName(mappedClazzName); + Class<?> clazz = new ClassLoaderUtils(BrooklynDslCommon.class).loadClass(mappedClazzName); Sensor<?> sensor; if (Entity.class.isAssignableFrom(clazz)) { @@ -170,9 +172,9 @@ public class BrooklynDslCommon { Map<String,Object> objectFields = (Map<String, Object>) config.getStringKeyMaybe("object.fields").or(MutableMap.of()); Map<String,Object> brooklynConfig = (Map<String, Object>) config.getStringKeyMaybe(BrooklynCampReservedKeys.BROOKLYN_CONFIG).or(MutableMap.of()); try { - // TODO Should use catalog's classloader, rather than Class.forName; how to get that? Should we return a future?! + // TODO Should use catalog's classloader, rather than ClassLoaderUtils; how to get that? Should we return a future?! String mappedTypeName = DeserializingClassRenamesProvider.findMappedName(typeName); - Class<?> type = Class.forName(mappedTypeName); + Class<?> type = new ClassLoaderUtils(BrooklynDslCommon.class).loadClass(mappedTypeName); if (!Reflections.hasNoArgConstructor(type)) { throw new IllegalStateException(String.format("Cannot construct %s bean: No public no-arg constructor available", type)); http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f3154764/core/src/main/java/org/apache/brooklyn/core/effector/AddSensor.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/effector/AddSensor.java b/core/src/main/java/org/apache/brooklyn/core/effector/AddSensor.java index d35068f..ba8d679 100644 --- a/core/src/main/java/org/apache/brooklyn/core/effector/AddSensor.java +++ b/core/src/main/java/org/apache/brooklyn/core/effector/AddSensor.java @@ -20,6 +20,7 @@ package org.apache.brooklyn.core.effector; import java.util.Map; +import org.apache.brooklyn.api.entity.Entity; import org.apache.brooklyn.api.entity.EntityInitializer; import org.apache.brooklyn.api.entity.EntityLocal; import org.apache.brooklyn.api.sensor.AttributeSensor; @@ -27,6 +28,7 @@ import org.apache.brooklyn.config.ConfigKey; import org.apache.brooklyn.core.config.ConfigKeys; import org.apache.brooklyn.core.entity.EntityInternal; import org.apache.brooklyn.core.sensor.Sensors; +import org.apache.brooklyn.util.core.ClassLoaderUtils; import org.apache.brooklyn.util.core.config.ConfigBag; import org.apache.brooklyn.util.guava.Maybe; import org.apache.brooklyn.util.javalang.Boxing; @@ -54,7 +56,7 @@ public class AddSensor<T> implements EntityInitializer { protected final String name; protected final Duration period; protected final String type; - protected final AttributeSensor<T> sensor; + protected AttributeSensor<T> sensor; public AddSensor(Map<String, String> params) { this(ConfigBag.newInstance(params)); @@ -64,27 +66,28 @@ public class AddSensor<T> implements EntityInitializer { this.name = Preconditions.checkNotNull(params.get(SENSOR_NAME), "Name must be supplied when defining a sensor"); this.period = params.get(SENSOR_PERIOD); this.type = params.get(SENSOR_TYPE); - this.sensor = newSensor(); } @Override public void apply(EntityLocal entity) { + sensor = newSensor(entity); ((EntityInternal) entity).getMutableEntityType().addSensor(sensor); } - private AttributeSensor<T> newSensor() { + private AttributeSensor<T> newSensor(Entity entity) { String className = getFullClassName(type); - Class<T> clazz = getType(className); + Class<T> clazz = getType(entity, className); return Sensors.newSensor(clazz, name); } @SuppressWarnings("unchecked") - protected Class<T> getType(String className) { + protected Class<T> getType(Entity entity, String className) { try { // TODO use OSGi loader (low priority however); also ensure that allows primitives Maybe<Class<?>> primitive = Boxing.getPrimitiveType(className); if (primitive.isPresent()) return (Class<T>) primitive.get(); - return (Class<T>) Class.forName(className); + + return (Class<T>) new ClassLoaderUtils(this, entity).loadClass(className); } catch (ClassNotFoundException e) { if (!className.contains(".")) { // could be assuming "java.lang" package; try again with that http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f3154764/core/src/main/java/org/apache/brooklyn/core/entity/drivers/ReflectiveEntityDriverFactory.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/drivers/ReflectiveEntityDriverFactory.java b/core/src/main/java/org/apache/brooklyn/core/entity/drivers/ReflectiveEntityDriverFactory.java index f9cf5a7..a2d6722 100644 --- a/core/src/main/java/org/apache/brooklyn/core/entity/drivers/ReflectiveEntityDriverFactory.java +++ b/core/src/main/java/org/apache/brooklyn/core/entity/drivers/ReflectiveEntityDriverFactory.java @@ -26,12 +26,14 @@ import java.util.Map; import org.apache.brooklyn.api.entity.drivers.DriverDependentEntity; import org.apache.brooklyn.api.entity.drivers.EntityDriver; import org.apache.brooklyn.api.location.Location; +import org.apache.brooklyn.core.BrooklynVersion; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.brooklyn.location.paas.PaasLocation; import org.apache.brooklyn.location.ssh.SshMachineLocation; import org.apache.brooklyn.util.collections.MutableList; import org.apache.brooklyn.util.collections.MutableMap; +import org.apache.brooklyn.util.core.ClassLoaderUtils; import org.apache.brooklyn.util.exceptions.Exceptions; import org.apache.brooklyn.util.exceptions.ReferenceWithError; import org.apache.brooklyn.util.text.Strings; @@ -193,7 +195,8 @@ public class ReflectiveEntityDriverFactory { String driverInterfaceName = driverInterface.getName(); // TODO: use a proper registry later on try { - if (!Class.forName("org.apache.brooklyn.location.winrm.WinRmMachineLocation").isInstance(location)) return null; + Class<?> winRmLocationClass = new ClassLoaderUtils(this, entity).loadClass("org.apache.brooklyn.software-winrm", BrooklynVersion.get(), "org.apache.brooklyn.location.winrm.WinRmMachineLocation"); + if (!winRmLocationClass.isInstance(location)) return null; } catch (ClassNotFoundException ex) { return null; } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f3154764/core/src/main/java/org/apache/brooklyn/core/location/geo/HostGeoInfo.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/location/geo/HostGeoInfo.java b/core/src/main/java/org/apache/brooklyn/core/location/geo/HostGeoInfo.java index f99b41d..ced6b7c 100644 --- a/core/src/main/java/org/apache/brooklyn/core/location/geo/HostGeoInfo.java +++ b/core/src/main/java/org/apache/brooklyn/core/location/geo/HostGeoInfo.java @@ -28,6 +28,7 @@ import org.apache.brooklyn.api.location.AddressableLocation; import org.apache.brooklyn.api.location.Location; import org.apache.brooklyn.core.location.AbstractLocation; import org.apache.brooklyn.core.location.LocationConfigKeys; +import org.apache.brooklyn.util.core.ClassLoaderUtils; import org.apache.brooklyn.util.core.flags.TypeCoercions; import org.apache.brooklyn.util.exceptions.Exceptions; import org.apache.brooklyn.util.guava.Maybe; @@ -164,7 +165,7 @@ public class HostGeoInfo implements Serializable { return new UtraceHostGeoLookup(); } if (type.isEmpty()) return null; - return (HostGeoLookup) Class.forName(type).newInstance(); + return (HostGeoLookup) new ClassLoaderUtils(HostGeoInfo.class).loadClass(type).newInstance(); } public static HostGeoInfo fromEntity(Entity e) { http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f3154764/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/JavaBrooklynClassLoadingContext.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/JavaBrooklynClassLoadingContext.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/JavaBrooklynClassLoadingContext.java index 064ba03..e89501e 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/JavaBrooklynClassLoadingContext.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/JavaBrooklynClassLoadingContext.java @@ -29,6 +29,7 @@ import java.util.Enumeration; import org.apache.brooklyn.api.mgmt.ManagementContext; import org.apache.brooklyn.core.entity.AbstractEntity; import org.apache.brooklyn.core.mgmt.persist.DeserializingClassRenamesProvider; +import org.apache.brooklyn.util.core.ClassLoaderUtils; import org.apache.brooklyn.util.exceptions.Exceptions; import org.apache.brooklyn.util.guava.Maybe; import org.slf4j.Logger; @@ -81,9 +82,24 @@ public class JavaBrooklynClassLoadingContext extends AbstractBrooklynClassLoadin if (mgmt!=null) return mgmt.getCatalogClassLoader(); return JavaBrooklynClassLoadingContext.class.getClassLoader(); } - + @SuppressWarnings({ "rawtypes", "unchecked" }) public Maybe<Class<?>> tryLoadClass(String className) { + Maybe<Class<?>> cls = tryLoadClass0(className); + if (cls.isPresent()) { + return cls; + } + try { + return (Maybe) Maybe.of(new ClassLoaderUtils(this, mgmt).loadClass(className)); + } catch (Exception e) { + Exceptions.propagateIfFatal(e); + // return original error + return cls; + } + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + private Maybe<Class<?>> tryLoadClass0(String className) { try { className = DeserializingClassRenamesProvider.findMappedName(className); return (Maybe) Maybe.of(getClassLoader().loadClass(className)); http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f3154764/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..e867c76 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,8 +34,8 @@ 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.ClassLoaderUtils; import org.apache.brooklyn.util.core.task.Tasks; import org.apache.brooklyn.util.exceptions.Exceptions; import org.apache.brooklyn.util.javalang.Reflections; @@ -455,10 +454,7 @@ public class Entitlements { } if (Strings.isNonBlank(type)) { try { - ClassLoader cl = mgmt != null - ? mgmt.getCatalogClassLoader() - : Entitlements.class.getClassLoader(); - Class<?> clazz = cl.loadClass(DeserializingClassRenamesProvider.findMappedName(type)); + Class<?> clazz = new ClassLoaderUtils(Entitlements.class, mgmt).loadClass(DeserializingClassRenamesProvider.findMappedName(type)); return (EntitlementManager) instantiate(clazz, ImmutableList.of( new Object[] {mgmt, brooklynProperties}, new Object[] {mgmt}, http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f3154764/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java index da2f30c..67bcd11 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java @@ -73,6 +73,7 @@ import org.apache.brooklyn.core.mgmt.rebind.RebindManagerImpl; import org.apache.brooklyn.core.typereg.BasicBrooklynTypeRegistry; import org.apache.brooklyn.util.collections.MutableList; import org.apache.brooklyn.util.collections.MutableMap; +import org.apache.brooklyn.util.core.ClassLoaderUtils; import org.apache.brooklyn.util.core.ResourceUtils; import org.apache.brooklyn.util.core.config.ConfigBag; import org.apache.brooklyn.util.core.task.BasicExecutionContext; @@ -99,7 +100,7 @@ public abstract class AbstractManagementContext implements ManagementContextInte Class<?> clazz; try{ //todo: which classloader should we use? - clazz = LocalManagementContext.class.getClassLoader().loadClass(clazzName); + clazz = new ClassLoaderUtils(AbstractManagementContext.class).loadClass(clazzName); }catch(ClassNotFoundException e){ throw new IllegalStateException(format("Could not load class [%s]",clazzName),e); } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f3154764/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/transformer/CompoundTransformerLoader.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/transformer/CompoundTransformerLoader.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/transformer/CompoundTransformerLoader.java index 7965327..37f2cae 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/transformer/CompoundTransformerLoader.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/transformer/CompoundTransformerLoader.java @@ -23,6 +23,7 @@ import java.util.Map; import java.util.Map.Entry; import org.apache.brooklyn.core.mgmt.rebind.transformer.CompoundTransformer.Builder; +import org.apache.brooklyn.util.core.ClassLoaderUtils; import org.apache.brooklyn.util.core.ResourceUtils; import org.apache.brooklyn.util.core.text.TemplateProcessor; import org.apache.brooklyn.util.exceptions.Exceptions; @@ -89,7 +90,7 @@ public class CompoundTransformerLoader { } else if (name.equals("rawDataTransformer")) { String type = (String) args.get("type"); try { - Class<?> clazz = CompoundTransformerLoader.class.getClassLoader().loadClass(type); + Class<?> clazz = new ClassLoaderUtils(CompoundTransformer.class).loadClass(type); builder.rawDataTransformer((RawDataTransformer) clazz.newInstance()); } catch (Exception e) { throw Exceptions.propagate(e); http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f3154764/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynTypes.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynTypes.java b/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynTypes.java index 4170613..fa8d607 100644 --- a/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynTypes.java +++ b/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynTypes.java @@ -30,6 +30,7 @@ import org.apache.brooklyn.config.ConfigKey; import org.apache.brooklyn.core.enricher.EnricherDynamicType; import org.apache.brooklyn.core.entity.EntityDynamicType; import org.apache.brooklyn.core.policy.PolicyDynamicType; +import org.apache.brooklyn.util.core.ClassLoaderUtils; import org.apache.brooklyn.util.exceptions.Exceptions; import com.google.common.collect.Maps; @@ -110,7 +111,7 @@ public class BrooklynTypes { @SuppressWarnings("unchecked") public static Map<String, ConfigKey<?>> getDefinedConfigKeys(String brooklynTypeName) { try { - return getDefinedConfigKeys((Class<? extends BrooklynObject>) Class.forName(brooklynTypeName)); + return getDefinedConfigKeys((Class<? extends BrooklynObject>) new ClassLoaderUtils(BrooklynTypes.class).loadClass(brooklynTypeName)); } catch (ClassNotFoundException e) { throw Exceptions.propagate(e); } @@ -123,7 +124,7 @@ public class BrooklynTypes { @SuppressWarnings("unchecked") public static Map<String, Sensor<?>> getDefinedSensors(String entityTypeName) { try { - return getDefinedSensors((Class<? extends Entity>) Class.forName(entityTypeName)); + return getDefinedSensors((Class<? extends Entity>) new ClassLoaderUtils(BrooklynTypes.class).loadClass(entityTypeName)); } catch (ClassNotFoundException e) { throw Exceptions.propagate(e); } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f3154764/core/src/main/java/org/apache/brooklyn/core/sensor/DurationSinceSensor.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/sensor/DurationSinceSensor.java b/core/src/main/java/org/apache/brooklyn/core/sensor/DurationSinceSensor.java index 4be57d8..b26af56 100644 --- a/core/src/main/java/org/apache/brooklyn/core/sensor/DurationSinceSensor.java +++ b/core/src/main/java/org/apache/brooklyn/core/sensor/DurationSinceSensor.java @@ -39,6 +39,7 @@ public class DurationSinceSensor extends AddSensor<Duration> { private static final Supplier<Long> CURRENT_TIME_SUPPLIER = new CurrentTimeSupplier(); + @SuppressWarnings("serial") public static final ConfigKey<Supplier<Long>> EPOCH_SUPPLIER = ConfigKeys.builder(new TypeToken<Supplier<Long>>() {}) .name("duration.since.epochsupplier") .description("The source of time from which durations are measured. Defaults to System.currentTimeMillis when " + @@ -46,6 +47,7 @@ public class DurationSinceSensor extends AddSensor<Duration> { .defaultValue(CURRENT_TIME_SUPPLIER) .build(); + @SuppressWarnings("serial") public static final ConfigKey<Supplier<Long>> TIME_SUPPLIER = ConfigKeys.builder(new TypeToken<Supplier<Long>>() {}) .name("duration.since.timesupplier") .description("The source of the current time. Defaults to System.currentTimeMillis if unconfigured or the " + @@ -55,19 +57,20 @@ public class DurationSinceSensor extends AddSensor<Duration> { private final Supplier<Long> epochSupplier; private final Supplier<Long> timeSupplier; - private final AttributeSensor<Long> epochSensor; + private AttributeSensor<Long> epochSensor; public DurationSinceSensor(ConfigBag params) { super(params); epochSupplier = params.get(EPOCH_SUPPLIER); timeSupplier = params.get(TIME_SUPPLIER); - epochSensor = Sensors.newLongSensor(sensor.getName() + ".epoch"); } @Override public void apply(final EntityLocal entity) { super.apply(entity); + epochSensor = Sensors.newLongSensor(sensor.getName() + ".epoch"); + if (entity.sensors().get(epochSensor) == null) { Long epoch = epochSupplier.get(); if (epoch == null) { http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f3154764/core/src/main/java/org/apache/brooklyn/core/sensor/ssh/SshCommandSensor.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/sensor/ssh/SshCommandSensor.java b/core/src/main/java/org/apache/brooklyn/core/sensor/ssh/SshCommandSensor.java index 839448e..25ae2b5 100644 --- a/core/src/main/java/org/apache/brooklyn/core/sensor/ssh/SshCommandSensor.java +++ b/core/src/main/java/org/apache/brooklyn/core/sensor/ssh/SshCommandSensor.java @@ -105,7 +105,7 @@ public final class SshCommandSensor<T> extends AddSensor<T> { .onSuccess(Functions.compose(new Function<String, T>() { @Override public T apply(String input) { - return TypeCoercions.coerce(Strings.trimEnd(input), getType(type)); + return TypeCoercions.coerce(Strings.trimEnd(input), getType(entity, type)); }}, SshValueFunctions.stdout())); SshFeed.builder() http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f3154764/core/src/main/java/org/apache/brooklyn/location/byon/ByonLocationResolver.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/location/byon/ByonLocationResolver.java b/core/src/main/java/org/apache/brooklyn/location/byon/ByonLocationResolver.java index 58b4989..ca478fd 100644 --- a/core/src/main/java/org/apache/brooklyn/location/byon/ByonLocationResolver.java +++ b/core/src/main/java/org/apache/brooklyn/location/byon/ByonLocationResolver.java @@ -35,6 +35,7 @@ import org.apache.brooklyn.core.config.Sanitizer; import org.apache.brooklyn.core.location.AbstractLocationResolver; import org.apache.brooklyn.core.mgmt.internal.LocalLocationManager; import org.apache.brooklyn.util.collections.MutableMap; +import org.apache.brooklyn.util.core.ClassLoaderUtils; import org.apache.brooklyn.util.core.config.ConfigBag; import org.apache.brooklyn.util.core.flags.TypeCoercions; import org.apache.brooklyn.util.net.UserAndHostAndPort; @@ -212,7 +213,8 @@ public class ByonLocationResolver extends AbstractLocationResolver { private Class<? extends MachineLocation> getLocationClass(String osFamily) { try { if (osFamily != null) { - return Class.forName(OS_TO_MACHINE_LOCATION_TYPE.get(osFamily.toLowerCase(Locale.ENGLISH))).asSubclass(MachineLocation.class); + String className = OS_TO_MACHINE_LOCATION_TYPE.get(osFamily.toLowerCase(Locale.ENGLISH)); + return new ClassLoaderUtils(this, managementContext).loadClass(className).asSubclass(MachineLocation.class); } } catch (ClassNotFoundException ex) {} return null; http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f3154764/core/src/main/java/org/apache/brooklyn/location/ssh/SshMachineLocation.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/location/ssh/SshMachineLocation.java b/core/src/main/java/org/apache/brooklyn/location/ssh/SshMachineLocation.java index b66c94c..de7b7a8 100644 --- a/core/src/main/java/org/apache/brooklyn/location/ssh/SshMachineLocation.java +++ b/core/src/main/java/org/apache/brooklyn/location/ssh/SshMachineLocation.java @@ -72,6 +72,7 @@ import org.apache.brooklyn.core.location.access.PortForwardManagerLocationResolv import org.apache.brooklyn.core.mgmt.BrooklynTaskTags; import org.apache.brooklyn.core.mgmt.internal.LocalLocationManager; import org.apache.brooklyn.util.collections.MutableMap; +import org.apache.brooklyn.util.core.ClassLoaderUtils; import org.apache.brooklyn.util.core.ResourceUtils; import org.apache.brooklyn.util.core.config.ConfigBag; import org.apache.brooklyn.util.core.crypto.SecureKeys; @@ -688,7 +689,7 @@ public class SshMachineLocation extends AbstractLocation implements MachineLocat } } if (sshToolClass==null) sshToolClass = SshjTool.class.getName(); - SshTool ssh = (SshTool) Class.forName(sshToolClass).getConstructor(Map.class).newInstance(args.getAllConfig()); + SshTool ssh = (SshTool) new ClassLoaderUtils(this, getManagementContext()).loadClass(sshToolClass).getConstructor(Map.class).newInstance(args.getAllConfig()); if (LOG.isTraceEnabled()) LOG.trace("using ssh-tool {} (of type {}); props ", ssh, sshToolClass); http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f3154764/core/src/main/java/org/apache/brooklyn/util/core/ClassLoaderUtils.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/util/core/ClassLoaderUtils.java b/core/src/main/java/org/apache/brooklyn/util/core/ClassLoaderUtils.java new file mode 100644 index 0000000..5bbce8d --- /dev/null +++ b/core/src/main/java/org/apache/brooklyn/util/core/ClassLoaderUtils.java @@ -0,0 +1,249 @@ +/* + * Copyright 2016 The Apache Software Foundation. + * + * Licensed 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.core; + +import java.util.List; +import java.util.regex.Pattern; + +import javax.annotation.Nullable; + +import org.apache.brooklyn.api.catalog.CatalogItem; +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.mgmt.ManagementContext; +import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext; +import org.apache.brooklyn.core.BrooklynVersion; +import org.apache.brooklyn.core.catalog.internal.CatalogUtils; +import org.apache.brooklyn.core.entity.EntityInternal; +import org.apache.brooklyn.core.mgmt.ha.OsgiManager; +import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal; +import org.apache.brooklyn.util.core.osgi.Osgis; +import org.apache.brooklyn.util.core.osgi.SystemFrameworkLoader; +import org.apache.brooklyn.util.exceptions.Exceptions; +import org.apache.brooklyn.util.guava.Maybe; +import org.apache.brooklyn.util.osgi.SystemFramework; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.launch.Framework; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Predicate; + +public class ClassLoaderUtils { + /** + * White list format should be + * <bundle symbolic name regex>[:<bundle version regex in dotted format (X.X.X.SNAPSHOT, instead of X.X.X-SNAPSHOT)>] + */ + private static final String WHITE_LIST_DEFAULT = "org\\.apache\\.brooklyn\\..*:" + BrooklynVersion.get().replaceFirst("-", "."); + private static final String WHITE_LIST_KEY = "org.apache.brooklyn.classloader.fallback.bundles"; + private static final String CLASS_NAME_DELIMITER = ":"; + private static final Logger log = LoggerFactory.getLogger(ClassLoaderUtils.class); + + // Class.forName gets the class loader from the calling class. + // We don't have access to the same reflection API so need to pass it explicitly. + private final Class<?> callingClass; + private final Entity entity; + private final ManagementContext mgmt; + + public ClassLoaderUtils(Object callingObj, Entity entity) { + this(callingObj.getClass(), entity); + } + public ClassLoaderUtils(Object callingObj, @Nullable ManagementContext mgmt) { + this(callingObj.getClass(), mgmt); + } + + public ClassLoaderUtils(Class<?> callingClass) { + this.callingClass = callingClass; + this.entity = null; + this.mgmt = null; + } + + public ClassLoaderUtils(Class<?> callingClass, Entity entity) { + this.callingClass = callingClass; + this.entity = entity; + this.mgmt = ((EntityInternal)entity).getManagementContext(); + } + + public ClassLoaderUtils(Class<?> callingClass, @Nullable ManagementContext mgmt) { + this.callingClass = callingClass; + this.entity = null; + this.mgmt = mgmt; + } + + public Class<?> loadClass(String name) throws ClassNotFoundException { + if (looksLikeBundledClassName(name)) { + String[] arr = name.split(CLASS_NAME_DELIMITER); + String symbolicName; + String version; + String className; + if (arr.length > 3) { + throw new IllegalStateException("'" + name + "' doesn't look like a class name and contains too many colons to be parsed as bundle:version:class triple."); + } else if (arr.length == 3) { + symbolicName = arr[0]; + version = arr[1]; + className = arr[2]; + } else if (arr.length == 2) { + symbolicName = arr[0]; + version = null; + className = arr[1]; + } else { + throw new IllegalStateException("'" + name + "' contains a bundle:version:class delimiter, but only one of those specified"); + } + return loadClass(symbolicName, version, className); + } + + if (entity != null && mgmt != null) { + String catalogItemId = entity.getCatalogItemId(); + if (catalogItemId != null) { + CatalogItem<?, ?> item = CatalogUtils.getCatalogItemOptionalVersion(mgmt, catalogItemId); + if (item != null) { + BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(mgmt, item); + try { + return loader.loadClass(name); + } catch (IllegalStateException e) { + ClassNotFoundException cnfe = Exceptions.getFirstThrowableOfType(e, ClassNotFoundException.class); + NoClassDefFoundError ncdfe = Exceptions.getFirstThrowableOfType(e, NoClassDefFoundError.class); + if (cnfe == null && ncdfe == null) { + throw e; + } else { + // ignore, fall back to Class.forName(...) + } + } + } else { + log.warn("Entity " + entity + " refers to non-existent catalog item " + catalogItemId + ". Trying to load class " + name); + } + } + } + + try { + // Used instead of callingClass.getClassLoader() as it could be null (only for bootstrap classes) + return Class.forName(name, true, callingClass.getClassLoader()); + } catch (ClassNotFoundException e) { + } + + if (mgmt != null) { + try { + return mgmt.getCatalogClassLoader().loadClass(name); + } catch (ClassNotFoundException e) { + } + } + + Class<?> cls = tryLoadFromBundleWhiteList(name); + if (cls != null) { + return cls; + } else { + throw new ClassNotFoundException("Class " + name + " not found on the application class path, nor in the bundle white list."); + } + } + + public Class<?> loadClass(String symbolicName, @Nullable String version, String className) throws ClassNotFoundException { + Framework framework = getFramework(); + if (framework != null) { + Maybe<Bundle> bundle = Osgis.bundleFinder(framework) + .symbolicName(symbolicName) + .version(version) + .find(); + if (bundle.isAbsent() && version != null) { + bundle = Osgis.bundleFinder(framework) + .symbolicName(symbolicName) + // Convert X.X.X-SNAPSHOT to X.X.X.SNAPSHOT. Any better way to do it? + .version(version.replace("-", ".")) + .find(); + } + if (bundle.isAbsent()) { + throw new IllegalStateException("Bundle " + symbolicName + ":" + (version != null ? version : "any") + " not found to load class " + className); + } + return SystemFrameworkLoader.get().loadClassFromBundle(className, bundle.get()); + } else { + return Class.forName(className); + } + } + + protected Framework getFramework() { + if (mgmt != null) { + Maybe<OsgiManager> osgiManager = ((ManagementContextInternal)mgmt).getOsgiManager(); + if (osgiManager.isPresent()) { + OsgiManager osgi = osgiManager.get(); + return osgi.getFramework(); + } + } + + // Requires that caller code is executed AFTER loading bundle brooklyn-core + Bundle bundle = FrameworkUtil.getBundle(ClassLoaderUtils.class); + if (bundle != null) { + BundleContext bundleContext = bundle.getBundleContext(); + return (Framework) bundleContext.getBundle(0); + } else { + return null; + } + } + + private boolean looksLikeBundledClassName(String name) { + return name.indexOf(CLASS_NAME_DELIMITER) != -1; + } + + + private static class WhiteListBundlePredicate implements Predicate<Bundle> { + private Pattern symbolicName; + private Pattern version; + + private WhiteListBundlePredicate(String symbolicName, String version) { + this.symbolicName = Pattern.compile(symbolicName); + this.version = version != null ? Pattern.compile(version) : null; + } + + @Override + public boolean apply(Bundle input) { + return symbolicName.matcher(input.getSymbolicName()).matches() && + (version == null || version.matcher(input.getVersion().toString()).matches()); + } + + } + + private Class<?> tryLoadFromBundleWhiteList(String name) { + Framework framework = getFramework(); + if (framework == null) { + return null; + } + List<Bundle> bundles = Osgis.bundleFinder(framework) + .satisfying(createBundleMatchingPredicate()) + .findAll(); + SystemFramework bundleLoader = SystemFrameworkLoader.get(); + for (Bundle b : bundles) { + try { + return bundleLoader.loadClassFromBundle(name, b); + } catch (Exception e) { + Exceptions.propagateIfFatal(e); + } + } + return null; + } + + protected WhiteListBundlePredicate createBundleMatchingPredicate() { + String whiteList = System.getProperty(WHITE_LIST_KEY, WHITE_LIST_DEFAULT); + String[] arr = whiteList.split(":"); + String symbolicName = arr[0]; + String version = null; + if (arr.length > 2) { + throw new IllegalStateException("Class loading fallback bundle white list '" + whiteList + "' not in the expected format <symbolic name regex>[:<version regex>]."); + } else if (arr.length == 2) { + version = arr[1]; + } + return new WhiteListBundlePredicate(symbolicName, version); + } + +} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f3154764/core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java b/core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java index 65f85d6..94a0991 100644 --- a/core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java +++ b/core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java @@ -18,9 +18,6 @@ */ package org.apache.brooklyn.util.core.flags; -import groovy.lang.Closure; -import groovy.time.TimeDuration; - import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -56,6 +53,7 @@ import org.apache.brooklyn.util.JavaGroovyEquivalents; import org.apache.brooklyn.util.collections.MutableSet; import org.apache.brooklyn.util.collections.QuorumCheck; import org.apache.brooklyn.util.collections.QuorumCheck.QuorumChecks; +import org.apache.brooklyn.util.core.ClassLoaderUtils; import org.apache.brooklyn.util.core.task.Tasks; import org.apache.brooklyn.util.exceptions.Exceptions; import org.apache.brooklyn.util.guava.Maybe; @@ -89,6 +87,9 @@ import com.google.common.net.HostAndPort; import com.google.common.primitives.Primitives; import com.google.common.reflect.TypeToken; +import groovy.lang.Closure; +import groovy.time.TimeDuration; + @SuppressWarnings("rawtypes") public class TypeCoercions { @@ -773,7 +774,7 @@ public class TypeCoercions { @Override public Class apply(final String input) { try { - return Class.forName(input); + return new ClassLoaderUtils(this.getClass()).loadClass(input); } catch (ClassNotFoundException e) { throw Exceptions.propagate(e); } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f3154764/core/src/test/java/org/apache/brooklyn/core/objs/BasicSpecParameterFromClassTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/core/objs/BasicSpecParameterFromClassTest.java b/core/src/test/java/org/apache/brooklyn/core/objs/BasicSpecParameterFromClassTest.java index be91c27..13c3977 100644 --- a/core/src/test/java/org/apache/brooklyn/core/objs/BasicSpecParameterFromClassTest.java +++ b/core/src/test/java/org/apache/brooklyn/core/objs/BasicSpecParameterFromClassTest.java @@ -23,7 +23,6 @@ import static org.testng.Assert.assertNotNull; import java.util.List; import java.util.Map; -import java.util.Set; import org.apache.brooklyn.api.catalog.CatalogConfig; import org.apache.brooklyn.api.entity.Entity; @@ -35,9 +34,9 @@ import org.apache.brooklyn.core.config.ConfigKeys; import org.apache.brooklyn.core.entity.AbstractEntity; import org.apache.brooklyn.core.entity.BrooklynConfigKeys; import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests; +import org.apache.brooklyn.util.core.ClassLoaderUtils; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; -import org.testng.collections.Sets; import com.google.common.base.Predicate; import com.google.common.collect.ImmutableMap; @@ -94,7 +93,7 @@ public class BasicSpecParameterFromClassTest { @Test public void testDebug() throws ClassNotFoundException { - System.out.println(BasicSpecParameter.fromClass(mgmt, Class.forName("org.apache.brooklyn.entity.stock.BasicApplication"))); + System.out.println(BasicSpecParameter.fromClass(mgmt, new ClassLoaderUtils(this.getClass()).loadClass("org.apache.brooklyn.entity.stock.BasicApplication"))); } @Test http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f3154764/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/PolicyResource.java ---------------------------------------------------------------------- diff --git a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/PolicyResource.java b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/PolicyResource.java index 2696440..0b8d2c2 100644 --- a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/PolicyResource.java +++ b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/PolicyResource.java @@ -21,7 +21,9 @@ package org.apache.brooklyn.rest.resources; import java.util.List; import java.util.Map; +import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; import org.apache.brooklyn.api.entity.Entity; import org.apache.brooklyn.api.policy.Policy; @@ -35,6 +37,7 @@ import org.apache.brooklyn.rest.filter.HaHotStateRequired; import org.apache.brooklyn.rest.transform.ApplicationTransformer; import org.apache.brooklyn.rest.transform.PolicyTransformer; import org.apache.brooklyn.rest.util.WebResourceUtils; +import org.apache.brooklyn.util.core.ClassLoaderUtils; import org.apache.brooklyn.util.exceptions.Exceptions; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -42,8 +45,6 @@ import org.slf4j.LoggerFactory; import com.google.common.base.Function; import com.google.common.collect.FluentIterable; import com.google.common.collect.Maps; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.UriInfo; @HaHotStateRequired public class PolicyResource extends AbstractBrooklynRestResource implements PolicyApi { @@ -86,7 +87,7 @@ public class PolicyResource extends AbstractBrooklynRestResource implements Poli Entity entity = brooklyn().getEntity(application, entityToken); Class<? extends Policy> policyType; try { - policyType = (Class<? extends Policy>) Class.forName(policyTypeName); + policyType = (Class<? extends Policy>) new ClassLoaderUtils(this, mgmt()).loadClass(policyTypeName); } catch (ClassNotFoundException e) { throw WebResourceUtils.badRequest("No policy with type %s found", policyTypeName); } catch (ClassCastException e) { http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f3154764/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/security/provider/DelegatingSecurityProvider.java ---------------------------------------------------------------------- diff --git a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/security/provider/DelegatingSecurityProvider.java b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/security/provider/DelegatingSecurityProvider.java index ca7fdf1..b374189 100644 --- a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/security/provider/DelegatingSecurityProvider.java +++ b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/security/provider/DelegatingSecurityProvider.java @@ -24,13 +24,14 @@ import java.util.concurrent.atomic.AtomicLong; import javax.servlet.http.HttpSession; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.apache.brooklyn.api.mgmt.ManagementContext; import org.apache.brooklyn.config.StringConfigMap; import org.apache.brooklyn.core.internal.BrooklynProperties; import org.apache.brooklyn.rest.BrooklynWebConfig; +import org.apache.brooklyn.util.core.ClassLoaderUtils; import org.apache.brooklyn.util.text.Strings; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class DelegatingSecurityProvider implements SecurityProvider { @@ -85,15 +86,16 @@ public class DelegatingSecurityProvider implements SecurityProvider { log.info("REST using security provider " + className); try { + ClassLoaderUtils clu = new ClassLoaderUtils(this, mgmt); Class<? extends SecurityProvider> clazz; try { - clazz = (Class<? extends SecurityProvider>) Class.forName(className); + clazz = (Class<? extends SecurityProvider>) clu.loadClass(className); } catch (Exception e) { String oldPackage = "brooklyn.web.console.security."; if (className.startsWith(oldPackage)) { className = Strings.removeFromStart(className, oldPackage); className = DelegatingSecurityProvider.class.getPackage().getName() + "." + className; - clazz = (Class<? extends SecurityProvider>) Class.forName(className); + clazz = (Class<? extends SecurityProvider>) clu.loadClass(className); log.warn("Deprecated package " + oldPackage + " detected; please update security provider to point to " + className); } else throw e; } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f3154764/software/base/src/main/java/org/apache/brooklyn/entity/resolve/HardcodedCatalogEntitySpecResolver.java ---------------------------------------------------------------------- diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/resolve/HardcodedCatalogEntitySpecResolver.java b/software/base/src/main/java/org/apache/brooklyn/entity/resolve/HardcodedCatalogEntitySpecResolver.java index 7d48643..e5a8b92 100644 --- a/software/base/src/main/java/org/apache/brooklyn/entity/resolve/HardcodedCatalogEntitySpecResolver.java +++ b/software/base/src/main/java/org/apache/brooklyn/entity/resolve/HardcodedCatalogEntitySpecResolver.java @@ -24,12 +24,14 @@ import java.util.Set; import org.apache.brooklyn.api.entity.Entity; import org.apache.brooklyn.api.entity.EntitySpec; import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext; +import org.apache.brooklyn.core.BrooklynVersion; import org.apache.brooklyn.core.resolve.entity.AbstractEntitySpecResolver; import org.apache.brooklyn.entity.brooklynnode.BrooklynNode; import org.apache.brooklyn.entity.group.DynamicCluster; import org.apache.brooklyn.entity.group.DynamicRegionsFabric; import org.apache.brooklyn.entity.java.VanillaJavaApp; import org.apache.brooklyn.entity.software.base.VanillaSoftwareProcess; +import org.apache.brooklyn.util.core.ClassLoaderUtils; import com.google.common.base.CaseFormat; import com.google.common.base.Converter; @@ -38,14 +40,17 @@ import com.google.common.collect.ImmutableMap; public class HardcodedCatalogEntitySpecResolver extends AbstractEntitySpecResolver { private static final String RESOLVER_NAME = "catalog"; - private static final Map<String, String> CATALOG_TYPES = ImmutableMap.<String, String>builder() - .put("cluster", DynamicCluster.class.getName()) - .put("fabric", DynamicRegionsFabric.class.getName()) - .put("vanilla", VanillaSoftwareProcess.class.getName()) - .put("software-process", VanillaSoftwareProcess.class.getName()) - .put("java-app", VanillaJavaApp.class.getName()) - .put("brooklyn-node", BrooklynNode.class.getName()) - .put("web-app-cluster","org.apache.brooklyn.entity.webapp.ControlledDynamicWebAppCluster") + private static final Map<String, Class<? extends Entity>> CATALOG_CLASS_TYPES = ImmutableMap.<String, Class<? extends Entity>>builder() + .put("cluster", DynamicCluster.class) + .put("fabric", DynamicRegionsFabric.class) + .put("vanilla", VanillaSoftwareProcess.class) + .put("software-process", VanillaSoftwareProcess.class) + .put("java-app", VanillaJavaApp.class) + .put("brooklyn-node", BrooklynNode.class) + .build(); + + private static final Map<String, String> CATALOG_STRING_TYPES = ImmutableMap.<String, String>builder() + .put("web-app-cluster","org.apache.brooklyn.software-webapp:" + BrooklynVersion.get() + ":org.apache.brooklyn.entity.webapp.ControlledDynamicWebAppCluster") .build(); // Allow catalog-type or CatalogType as service type string @@ -58,39 +63,47 @@ public class HardcodedCatalogEntitySpecResolver extends AbstractEntitySpecResolv @Override protected boolean canResolve(String type, BrooklynClassLoadingContext loader) { String localType = getLocalType(type); - String specType = getImplementation(localType); - return specType != null; + return getImplementation(CATALOG_CLASS_TYPES, localType) != null || + getImplementation(CATALOG_STRING_TYPES, localType) != null; } @Override public EntitySpec<?> resolve(String type, BrooklynClassLoadingContext loader, Set<String> encounteredTypes) { String localType = getLocalType(type); - String specType = getImplementation(localType); - if (specType != null) { - return buildSpec(specType); - } else { - return null; + Class<? extends Entity> specClassType = getImplementation(CATALOG_CLASS_TYPES, localType); + if (specClassType != null) { + return buildSpec(specClassType); } + String specStringType = getImplementation(CATALOG_STRING_TYPES, localType); + if (specStringType != null) { + return buildSpec(specStringType); + } + return null; } - private String getImplementation(String type) { - String specType = CATALOG_TYPES.get(type); + private <T> T getImplementation(Map<String, T> types, String type) { + T specType = types.get(type); if (specType != null) { return specType; } else { - return CATALOG_TYPES.get(FMT.convert(type)); + return types.get(FMT.convert(type)); } } - private EntitySpec<?> buildSpec(String specType) { + private EntitySpec<?> buildSpec(String specTypName) { // TODO is this hardcoded list deprecated? If so log a warning. try { - @SuppressWarnings("unchecked") - Class<Entity> specClass = (Class<Entity>)mgmt.getCatalogClassLoader().loadClass(specType); - return EntitySpec.create(specClass); + Class<?> specType = new ClassLoaderUtils(this.getClass()).loadClass(specTypName); + return buildSpec(specType); } catch (ClassNotFoundException e) { - throw new IllegalStateException("Unable to load hardcoded catalog type " + specType, e); + throw new IllegalStateException("Unable to load hardcoded catalog type " + specTypName, e); } } + protected EntitySpec<?> buildSpec(Class<?> specType) { + @SuppressWarnings("unchecked") + Class<Entity> specClass = (Class<Entity>)specType; + return EntitySpec.create(specClass); + } + } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f3154764/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRmMachineLocation.java ---------------------------------------------------------------------- diff --git a/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRmMachineLocation.java b/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRmMachineLocation.java index 7a5b638..8d537ac 100644 --- a/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRmMachineLocation.java +++ b/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRmMachineLocation.java @@ -18,6 +18,9 @@ */ package org.apache.brooklyn.location.winrm; +import static org.apache.brooklyn.core.config.ConfigKeys.newConfigKeyWithPrefix; +import static org.apache.brooklyn.core.config.ConfigKeys.newStringConfigKey; + import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -29,7 +32,6 @@ import java.util.Set; import javax.annotation.Nullable; -import com.google.common.annotations.Beta; import org.apache.brooklyn.api.location.MachineDetails; import org.apache.brooklyn.api.location.MachineLocation; import org.apache.brooklyn.api.location.OsDetails; @@ -42,6 +44,7 @@ import org.apache.brooklyn.core.entity.BrooklynConfigKeys; import org.apache.brooklyn.core.location.AbstractLocation; import org.apache.brooklyn.core.location.access.PortForwardManager; import org.apache.brooklyn.core.location.access.PortForwardManagerLocationResolver; +import org.apache.brooklyn.util.core.ClassLoaderUtils; import org.apache.brooklyn.util.core.config.ConfigBag; import org.apache.brooklyn.util.core.internal.ssh.SshTool; import org.apache.brooklyn.util.core.internal.winrm.WinRmTool; @@ -55,6 +58,7 @@ import org.apache.commons.codec.binary.Base64; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.annotations.Beta; import com.google.common.base.Charsets; import com.google.common.base.Function; import com.google.common.base.Joiner; @@ -66,9 +70,6 @@ import com.google.common.collect.Iterables; import com.google.common.net.HostAndPort; import com.google.common.reflect.TypeToken; -import static org.apache.brooklyn.core.config.ConfigKeys.newConfigKeyWithPrefix; -import static org.apache.brooklyn.core.config.ConfigKeys.newStringConfigKey; - public class WinRmMachineLocation extends AbstractLocation implements MachineLocation { private static final Logger LOG = LoggerFactory.getLogger(WinRmMachineLocation.class); @@ -353,7 +354,7 @@ public class WinRmMachineLocation extends AbstractLocation implements MachineLoc // look up tool class String toolClass = args.get(WINRM_TOOL_CLASS); if (toolClass == null) toolClass = Winrm4jTool.class.getName(); - WinRmTool tool = (WinRmTool) Class.forName(toolClass).getConstructor(Map.class).newInstance(args.getAllConfig()); + WinRmTool tool = (WinRmTool) new ClassLoaderUtils(this, getManagementContext()).loadClass(toolClass).getConstructor(Map.class).newInstance(args.getAllConfig()); if (LOG.isTraceEnabled()) LOG.trace("using ssh-tool {} (of type {}); props ", tool, toolClass);
