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 2015/09/01 17:16:37 UTC
[14/28] incubator-brooklyn git commit: Builds on #872 to add
renamed-class checks in a few other places classes are loaded.
Builds on #872 to add renamed-class checks in a few other places classes are loaded.
Also tidies some error messages and adds a cache for renamed classes.
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/9fca8a27
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/9fca8a27
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/9fca8a27
Branch: refs/heads/master
Commit: 9fca8a279c372088c99c5e120db35dd9c74c538c
Parents: be3e182
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Aug 31 15:38:56 2015 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Aug 31 17:04:24 2015 +0100
----------------------------------------------------------------------
.../catalog/internal/CatalogInitialization.java | 7 +--
.../factory/BasicConfigurableEntityFactory.java | 3 +-
.../JavaBrooklynClassLoadingContext.java | 2 +
.../OsgiBrooklynClassLoadingContext.java | 1 -
.../core/mgmt/entitlement/Entitlements.java | 7 +--
.../DeserializingClassRenamesProvider.java | 31 +++++++------
.../core/mgmt/persist/XmlMementoSerializer.java | 4 +-
.../core/mgmt/rebind/RebindIteration.java | 11 +++--
.../brooklyn/core/plan/PlanToSpecFactory.java | 3 +-
.../util/core/xstream/ClassRenamingMapper.java | 33 +++-----------
.../util/core/xstream/XmlSerializer.java | 38 ++++++++++++++--
.../mgmt/persist/XmlMementoSerializerTest.java | 5 ++-
.../service/BrooklynServiceTypeResolver.java | 24 +---------
.../brooklyn/util/exceptions/Exceptions.java | 47 +++++++++++++-------
.../brooklyn/util/javalang/Reflections.java | 41 +++++++++++++++++
15 files changed, 157 insertions(+), 100 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9fca8a27/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java
index 80d29ad..907cbb8 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java
@@ -434,14 +434,15 @@ public class CatalogInitialization implements ManagementContextInjectable {
if (throwable instanceof RuntimeInterruptedException)
throw (RuntimeInterruptedException) throwable;
- log.error("Error loading catalog item '"+details+"': "+throwable);
- log.debug("Trace for error loading catalog item '"+details+"': "+throwable, throwable);
+ String throwableText = Exceptions.collapseText(throwable);
+ log.error("Error loading catalog item '"+details+"': "+throwableText);
+ log.debug("Trace for error loading catalog item '"+details+"': "+throwableText, throwable);
// TODO give more detail when adding
((ManagementContextInternal)getManagementContext()).errors().add(throwable);
if (isStartingUp && failOnStartupErrors) {
- throw new FatalRuntimeException("Unable to load catalog item '"+details+"': "+throwable, throwable);
+ throw new FatalRuntimeException("Unable to load catalog item '"+details+"': "+throwableText, throwable);
}
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9fca8a27/core/src/main/java/org/apache/brooklyn/core/entity/factory/BasicConfigurableEntityFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/factory/BasicConfigurableEntityFactory.java b/core/src/main/java/org/apache/brooklyn/core/entity/factory/BasicConfigurableEntityFactory.java
index 3011c9a..8f6e3f6 100644
--- a/core/src/main/java/org/apache/brooklyn/core/entity/factory/BasicConfigurableEntityFactory.java
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/factory/BasicConfigurableEntityFactory.java
@@ -28,6 +28,7 @@ import java.util.HashMap;
import java.util.Map;
import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.core.mgmt.persist.DeserializingClassRenamesProvider;
import com.google.common.base.Objects;
import com.google.common.base.Throwables;
@@ -45,7 +46,7 @@ public class BasicConfigurableEntityFactory<T extends Entity> extends AbstractCo
public BasicConfigurableEntityFactory(Map flags, Class<? extends T> clazz) {
super(flags);
this.clazz = checkNotNull(clazz, "clazz");
- this.clazzName = clazz.getName();
+ this.clazzName = DeserializingClassRenamesProvider.findMappedName(clazz.getName());
}
public T newEntity2(Map flags, Entity parent) {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9fca8a27/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 18f328f..51007d7 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
@@ -27,6 +27,7 @@ import java.util.Collections;
import java.util.Enumeration;
import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.core.mgmt.persist.DeserializingClassRenamesProvider;
import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.guava.Maybe;
@@ -79,6 +80,7 @@ public class JavaBrooklynClassLoadingContext extends AbstractBrooklynClassLoadin
@SuppressWarnings({ "rawtypes", "unchecked" })
public Maybe<Class<?>> tryLoadClass(String className) {
try {
+ className = DeserializingClassRenamesProvider.findMappedName(className);
return (Maybe) Maybe.of(getClassLoader().loadClass(className));
} catch (Exception e) {
Exceptions.propagateIfFatal(e);
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9fca8a27/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/OsgiBrooklynClassLoadingContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/OsgiBrooklynClassLoadingContext.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/OsgiBrooklynClassLoadingContext.java
index fd1acb0..fa12aa2 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/OsgiBrooklynClassLoadingContext.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/OsgiBrooklynClassLoadingContext.java
@@ -25,7 +25,6 @@ import java.util.Collections;
import org.apache.brooklyn.api.catalog.CatalogItem;
import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
import org.apache.brooklyn.api.mgmt.ManagementContext;
-import org.apache.brooklyn.api.mgmt.entitlement.EntitlementClass;
import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.mgmt.entitlement.Entitlements;
import org.apache.brooklyn.core.mgmt.ha.OsgiManager;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9fca8a27/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 d916c5c..6c281fc 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
@@ -31,10 +31,11 @@ import org.apache.brooklyn.api.mgmt.entitlement.EntitlementContext;
import org.apache.brooklyn.api.mgmt.entitlement.EntitlementManager;
import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.core.entity.Entities;
+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.javalang.Reflections;
@@ -278,7 +279,7 @@ public class Entitlements {
@Override
public boolean apply(EntityAndItem<String> input) {
if (input == null) return false;
- return !Entities.isSecret(input.getItem());
+ return !Sanitizer.IS_SECRET_PREDICATE.apply(input.getItem());
}
@Override
public String toString() {
@@ -390,7 +391,7 @@ public class Entitlements {
try {
ClassLoader cl = mgmt==null ? null : ((ManagementContextInternal)mgmt).getCatalogClassLoader();
if (cl==null) cl = Entitlements.class.getClassLoader();
- Class<?> clazz = cl.loadClass(type);
+ Class<?> clazz = cl.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/incubator-brooklyn/blob/9fca8a27/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/DeserializingClassRenamesProvider.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/DeserializingClassRenamesProvider.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/DeserializingClassRenamesProvider.java
index e8ac5a4..9fbac01 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/DeserializingClassRenamesProvider.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/DeserializingClassRenamesProvider.java
@@ -24,22 +24,34 @@ import java.util.Enumeration;
import java.util.Map;
import java.util.Properties;
+import org.apache.brooklyn.util.core.ResourceUtils;
import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.javalang.Reflections;
import org.apache.brooklyn.util.stream.Streams;
import com.google.common.annotations.Beta;
-import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
@Beta
public class DeserializingClassRenamesProvider {
- public static final String DESERIALIZING_CLASS_RENAMES_PROPERTIES_PATH = "classpath://org/apache/brooklyn/deserializingClassRenames.properties";
+ public static final String DESERIALIZING_CLASS_RENAMES_PROPERTIES_PATH = "classpath://org/apache/brooklyn/core/mgmt/persist/deserializingClassRenames.properties";
+
+ private static Map<String, String> cache = null;
@Beta
public static Map<String, String> loadDeserializingClassRenames() {
- InputStream resource = XmlMementoSerializer.class.getClassLoader().getResourceAsStream(DESERIALIZING_CLASS_RENAMES_PROPERTIES_PATH);
+ if (cache!=null) return cache;
+ synchronized (DeserializingClassRenamesProvider.class) {
+ cache = loadDeserializingClassRenamesCache();
+ return cache;
+ }
+ }
+
+ private synchronized static Map<String, String> loadDeserializingClassRenamesCache() {
+ if (cache!=null) return cache;
+ InputStream resource = new ResourceUtils(DeserializingClassRenamesProvider.class).getResourceFromUrl(DESERIALIZING_CLASS_RENAMES_PROPERTIES_PATH);
if (resource != null) {
try {
Properties props = new Properties();
@@ -63,16 +75,7 @@ public class DeserializingClassRenamesProvider {
}
@Beta
- public static Optional<String> tryFindMappedName(Map<String, String> renames, String name) {
- String mappedName = (String) renames.get(name);
- if (mappedName != null) {
- return Optional.of(mappedName);
- }
- for (Map.Entry<String, String> entry : renames.entrySet()) {
- if (name.startsWith(entry.getKey())) {
- return Optional.of(entry.getValue()+ name.substring(entry.getKey().length()));
- }
- }
- return Optional.<String>absent();
+ public static String findMappedName(String name) {
+ return Reflections.findMappedNameAndLog(loadDeserializingClassRenames(), name);
}
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9fca8a27/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java
index a8a20b7..ec7fb6f 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java
@@ -139,8 +139,8 @@ public class XmlMementoSerializer<T> extends XmlSerializer<T> implements Memento
// Warning: this is called in the super-class constuctor, so before this constructor!
@Override
- protected MapperWrapper wrapMapper(MapperWrapper next) {
- MapperWrapper mapper = super.wrapMapper(next);
+ protected MapperWrapper wrapMapperForNormalUsage(Mapper next) {
+ MapperWrapper mapper = super.wrapMapperForNormalUsage(next);
mapper = new CustomMapper(mapper, Entity.class, "entityProxy");
mapper = new CustomMapper(mapper, Location.class, "locationProxy");
return mapper;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9fca8a27/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 3f468ba..7b00ff8 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
@@ -72,12 +72,14 @@ import org.apache.brooklyn.core.feed.AbstractFeed;
import org.apache.brooklyn.core.location.AbstractLocation;
import org.apache.brooklyn.core.location.internal.LocationInternal;
import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.core.mgmt.classloading.JavaBrooklynClassLoadingContext;
import org.apache.brooklyn.core.mgmt.internal.BrooklynObjectManagementMode;
import org.apache.brooklyn.core.mgmt.internal.BrooklynObjectManagerInternal;
import org.apache.brooklyn.core.mgmt.internal.EntityManagerInternal;
import org.apache.brooklyn.core.mgmt.internal.LocationManagerInternal;
import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
import org.apache.brooklyn.core.mgmt.internal.ManagementTransitionMode;
+import org.apache.brooklyn.core.mgmt.persist.DeserializingClassRenamesProvider;
import org.apache.brooklyn.core.mgmt.persist.PersistenceActivityMetrics;
import org.apache.brooklyn.core.mgmt.rebind.RebindManagerImpl.RebindTracker;
import org.apache.brooklyn.core.objs.AbstractBrooklynObject;
@@ -211,7 +213,7 @@ public abstract class RebindIteration {
managementContext = rebindManager.getManagementContext();
rebindContext = new RebindContextImpl(managementContext, exceptionHandler, classLoader);
- reflections = new Reflections(classLoader);
+ reflections = new Reflections(classLoader).applyClassRenames(DeserializingClassRenamesProvider.loadDeserializingClassRenames());
instantiator = new BrooklynObjectInstantiator(classLoader, rebindContext, reflections);
if (mode==ManagementNodeState.HOT_STANDBY || mode==ManagementNodeState.HOT_BACKUP) {
@@ -822,17 +824,14 @@ public abstract class RebindIteration {
//As a last resort go through all catalog items trying to load the type and use the first that succeeds.
//But first check if can be loaded from the default classpath
- try {
- cl.loadClass(entityManifest.getType());
+ if (JavaBrooklynClassLoadingContext.create(managementContext).tryLoadClass(entityManifest.getType()).isPresent())
return null;
- } catch (ClassNotFoundException e) {
- }
for (CatalogItem<?, ?> item : catalog.getCatalogItems()) {
BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(managementContext, item);
boolean canLoadClass = loader.tryLoadClass(entityManifest.getType()).isPresent();
if (canLoadClass) {
- LOG.warn("Missing catalog item for "+entityManifest.getId()+", inferring as "+item.getId()+" because that is able to load the item");
+ LOG.warn("Missing catalog item for "+entityManifest.getId()+" ("+entityManifest.getType()+"), inferring as "+item.getId()+" because that is able to load the item");
return item.getId();
}
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9fca8a27/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java b/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java
index 6f74855..a2e6500 100644
--- a/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java
+++ b/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java
@@ -101,7 +101,8 @@ public class PlanToSpecFactory {
(Strings.isNonBlank(e.getMessage()) ? " ("+e.getMessage()+")" : ""));
} catch (Exception e) {
Exceptions.propagateIfFatal(e);
- otherProblemsFromTransformers.add(new IllegalArgumentException("Transformer for "+t.getShortDescription()+" gave an error creating this plan", e));
+ otherProblemsFromTransformers.add(new IllegalArgumentException("Transformer for "+t.getShortDescription()+" gave an error creating this plan: "+
+ Exceptions.collapseText(e), e));
}
}
// failed
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9fca8a27/core/src/main/java/org/apache/brooklyn/util/core/xstream/ClassRenamingMapper.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/xstream/ClassRenamingMapper.java b/core/src/main/java/org/apache/brooklyn/util/core/xstream/ClassRenamingMapper.java
index 13fd032..aae4a6e 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/xstream/ClassRenamingMapper.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/xstream/ClassRenamingMapper.java
@@ -22,7 +22,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
-import org.apache.brooklyn.core.mgmt.persist.DeserializingClassRenamesProvider;
+import org.apache.brooklyn.util.javalang.Reflections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -41,32 +41,13 @@ public class ClassRenamingMapper extends MapperWrapper {
}
@Override
- public Class realClass(String elementName) {
- String nameToUse;
- Optional<String> mappedName = DeserializingClassRenamesProvider.tryFindMappedName(nameToType, elementName);
- if (mappedName.isPresent()) {
- LOG.debug("Transforming xstream "+elementName+" to "+mappedName);
- nameToUse = mappedName.get();
- } else {
- nameToUse = elementName;
+ public Class<?> realClass(String elementName) {
+ Optional<String> elementNameOpt = Reflections.tryFindMappedName(nameToType, elementName);
+ if (elementNameOpt.isPresent()) {
+ LOG.debug("Mapping class '"+elementName+"' to '"+elementNameOpt.get()+"'");
+ elementName = elementNameOpt.get();
}
- return super.realClass(nameToUse);
+ return super.realClass(elementName);
}
-// public boolean aliasIsAttribute(String name) {
-// return nameToType.containsKey(name);
-// }
-//
-// private Object readResolve() {
-// nameToType = new HashMap();
-// for (final Iterator iter = classToName.keySet().iterator(); iter.hasNext();) {
-// final Object type = iter.next();
-// nameToType.put(classToName.get(type), type);
-// }
-// for (final Iterator iter = typeToName.keySet().iterator(); iter.hasNext();) {
-// final Class type = (Class)iter.next();
-// nameToType.put(typeToName.get(type), type.getName());
-// }
-// return this;
-// }
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9fca8a27/core/src/main/java/org/apache/brooklyn/util/core/xstream/XmlSerializer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/xstream/XmlSerializer.java b/core/src/main/java/org/apache/brooklyn/util/core/xstream/XmlSerializer.java
index 9ed5b88..c83e25c 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/xstream/XmlSerializer.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/xstream/XmlSerializer.java
@@ -34,12 +34,16 @@ import org.apache.brooklyn.util.collections.MutableSet;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.converters.extended.JavaClassConverter;
+import com.thoughtworks.xstream.mapper.DefaultMapper;
+import com.thoughtworks.xstream.mapper.Mapper;
import com.thoughtworks.xstream.mapper.MapperWrapper;
public class XmlSerializer<T> {
private final Map<String, String> deserializingClassRenames;
- protected final XStream xstream;
+ // XXX protected
+ public final XStream xstream;
public XmlSerializer() {
this(ImmutableMap.<String, String>of());
@@ -50,11 +54,12 @@ public class XmlSerializer<T> {
this.xstream = new XStream() {
@Override
protected MapperWrapper wrapMapper(MapperWrapper next) {
- MapperWrapper result = super.wrapMapper(next);
- return XmlSerializer.this.wrapMapper(result);
+ return XmlSerializer.this.wrapMapperForNormalUsage( super.wrapMapper(next) );
}
};
+ xstream.registerConverter(newCustomJavaClassConverter(), XStream.PRIORITY_NORMAL);
+
// list as array list is default
xstream.alias("map", Map.class, LinkedHashMap.class);
xstream.alias("set", Set.class, LinkedHashSet.class);
@@ -77,11 +82,36 @@ public class XmlSerializer<T> {
xstream.registerConverter(new EnumCaseForgivingConverter());
xstream.registerConverter(new Inet4AddressConverter());
}
+
+ /**
+ * JCC is used when class names are serialized/deserialized and no alias is defined;
+ * it is configured in XStream *without* access to the XStream mapper.
+ * However we need a few selected mappers (see {@link #wrapMapperForAllLowLevelMentions(Mapper)} )
+ * in order to effect renames at the low level, but many of the mappers must NOT be used,
+ * e.g. because some might intercept all Class<? extends Entity> references
+ * (and that interception is only wanted when serializing <i>instances</i>,
+ * as in {@link #wrapMapperForNormalUsage(Mapper)}).
+ * <p>
+ * This can typically be done simply by registering our own instance (due to order guarantee of PrioritizedList),
+ * after the instance added by XStream.setupConverters()
+ */
+ private JavaClassConverter newCustomJavaClassConverter() {
+ return new JavaClassConverter(wrapMapperForAllLowLevelMentions(new DefaultMapper(xstream.getClassLoaderReference()))) {};
+ }
- protected MapperWrapper wrapMapper(MapperWrapper next) {
+ /** Adds mappers needed for *any* reference to a class, e.g. when names are used for inner classes, or classes are renamed;
+ * this *excludes* basic mentions, however, because most rewrites should *not* be applied at this deep level;
+ * mappers which effect aliases or intercept references to entities are usually NOT be invoked in this low-level pathway.
+ * See {@link #newCustomJavaClassConverter()}. */
+ protected MapperWrapper wrapMapperForAllLowLevelMentions(Mapper next) {
MapperWrapper result = new CompilerIndependentOuterClassFieldMapper(next);
return new ClassRenamingMapper(result, deserializingClassRenames);
}
+ /** Extension point where sub-classes can add mappers wanted when instances of a class are serialized,
+ * including {@link #wrapMapperForAllLowLevelMentions(Mapper)}, plus any usual domain mappings. */
+ protected MapperWrapper wrapMapperForNormalUsage(Mapper next) {
+ return wrapMapperForAllLowLevelMentions(next);
+ }
public void serialize(Object object, Writer writer) {
xstream.toXML(object, writer);
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9fca8a27/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java
index 0d94819..8f1a248 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java
@@ -71,7 +71,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
-import com.google.common.net.HostAndPort;
+import com.thoughtworks.xstream.converters.Converter;
public class XmlMementoSerializerTest {
@@ -263,7 +263,6 @@ public class XmlMementoSerializerTest {
final TestApplication app = TestApplication.Factory.newManagedInstanceForTests();
ManagementContext managementContext = app.getManagementContext();
try {
- @SuppressWarnings("deprecation")
final Location loc = managementContext.getLocationManager().createLocation(LocationSpec.create(SimulatedLocation.class));
serializer.setLookupContext(new LookupContextImpl(managementContext,
ImmutableList.<Entity>of(), ImmutableList.of(loc), ImmutableList.<Policy>of(),
@@ -401,6 +400,8 @@ public class XmlMementoSerializerTest {
@SuppressWarnings("unchecked")
private <T> T assertSerializeAndDeserialize(T obj) throws Exception {
+Converter x = serializer.xstream.getConverterLookup().lookupConverterForType(Class.class);
+System.out.println("XXX: "+x);
String serializedForm = serializer.toString(obj);
LOG.info("serializedForm=" + serializedForm);
Object deserialized = serializer.fromString(serializedForm);
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9fca8a27/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/BrooklynServiceTypeResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/BrooklynServiceTypeResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/BrooklynServiceTypeResolver.java
index c6251df..f4bc9aa 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/BrooklynServiceTypeResolver.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/BrooklynServiceTypeResolver.java
@@ -48,14 +48,7 @@ public class BrooklynServiceTypeResolver implements ServiceTypeResolver {
private static final Logger LOG = LoggerFactory.getLogger(ServiceTypeResolver.class);
- private final Map<String, String> deserializingClassRenames;
-
public BrooklynServiceTypeResolver() {
- this(DeserializingClassRenamesProvider.loadDeserializingClassRenames());
- }
-
- public BrooklynServiceTypeResolver(Map<String, String> deserializingClassRenames) {
- this.deserializingClassRenames = checkNotNull(deserializingClassRenames, "deserializingClassRenames");
}
@Override
@@ -87,20 +80,7 @@ public class BrooklynServiceTypeResolver implements ServiceTypeResolver {
}
protected CatalogItem<Entity,EntitySpec<?>> getCatalogItemImpl(ManagementContext mgmt, String brooklynType) {
- try {
- return CatalogUtils.getCatalogItemOptionalVersion(mgmt, Entity.class, brooklynType);
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- Optional<String> alternativeType = DeserializingClassRenamesProvider.tryFindMappedName(deserializingClassRenames, brooklynType);
- if (alternativeType.isPresent()) {
- LOG.debug("Transforming entity "+brooklynType+" to "+alternativeType.get());
- try {
- return CatalogUtils.getCatalogItemOptionalVersion(mgmt, Entity.class, alternativeType.get());
- } catch (Exception e2) {
- LOG.debug("Problem getting catalog for transformed type "+alternativeType.get()+"; throwing of untransformed type "+brooklynType, e);
- }
- }
- throw Exceptions.propagate(e);
- }
+ brooklynType = DeserializingClassRenamesProvider.findMappedName(brooklynType);
+ return CatalogUtils.getCatalogItemOptionalVersion(mgmt, Entity.class, brooklynType);
}
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9fca8a27/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/Exceptions.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/Exceptions.java b/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/Exceptions.java
index 583104b..eac137d 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/Exceptions.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/Exceptions.java
@@ -27,16 +27,19 @@ import java.lang.reflect.UndeclaredThrowableException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.ExecutionException;
import javax.annotation.Nullable;
+import org.apache.brooklyn.util.collections.MutableSet;
import org.apache.brooklyn.util.text.Strings;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
@@ -137,17 +140,18 @@ public class Exceptions {
/** as {@link #collapse(Throwable)} but includes causal messages in the message as per {@link #collapseTextIncludingAllCausalMessages(Throwable)};
* use with care (limit once) as repeated usage can result in multiple copies of the same message */
public static Throwable collapseIncludingAllCausalMessages(Throwable source) {
- return collapse(source, true, true);
+ return collapse(source, true, true, ImmutableSet.<Throwable>of());
}
/** creates (but does not throw) a new {@link PropagatedRuntimeException} whose
* message is taken from the first _interesting_ element in the source,
* and optionally also the causal chain */
public static Throwable collapse(Throwable source, boolean collapseCausalChain) {
- return collapse(source, collapseCausalChain, false);
+ return collapse(source, collapseCausalChain, false, ImmutableSet.<Throwable>of());
}
- private static Throwable collapse(Throwable source, boolean collapseCausalChain, boolean includeAllCausalMessages) {
+ private static Throwable collapse(Throwable source, boolean collapseCausalChain, boolean includeAllCausalMessages, Set<Throwable> visited) {
+ visited = MutableSet.copyOf(visited);
String message = "";
Throwable collapsed = source;
int collapseCount = 0;
@@ -156,9 +160,14 @@ public class Exceptions {
while (isBoring(collapsed) && !messageIsFinal) {
collapseCount++;
Throwable cause = collapsed.getCause();
- if (cause==null)
+ if (cause==null) {
// everything in the tree is boring...
return source;
+ }
+ if (visited.add(collapsed)) {
+ // there is a recursive loop
+ break;
+ }
String collapsedS = collapsed.getMessage();
if (collapsed instanceof PropagatedRuntimeException && ((PropagatedRuntimeException)collapsed).isCauseEmbeddedInMessage()) {
message = collapsed.getMessage();
@@ -180,7 +189,7 @@ public class Exceptions {
messagesCause = messagesCause.getCause();
break;
}
- messagesCause = messagesCause.getCause();
+ visited.add(messagesCause); messagesCause = messagesCause.getCause();
}
if (collapseCount==0 && !includeAllCausalMessages)
@@ -191,15 +200,12 @@ public class Exceptions {
messagesCause = messagesCause.getCause();
}
- if (Strings.isBlank(message)) {
- return new PropagatedRuntimeException(collapseCausalChain ? collapsed : source);
- } else {
- if (messagesCause!=null && !messageIsFinal) {
- String extraMessage = collapseText(messagesCause, includeAllCausalMessages);
- message = appendSeparator(message, extraMessage);
- }
- return new PropagatedRuntimeException(message, collapseCausalChain ? collapsed : source, true);
+ if (messagesCause!=null && !messageIsFinal) {
+ String extraMessage = collapseText(messagesCause, includeAllCausalMessages, ImmutableSet.copyOf(visited));
+ message = appendSeparator(message, extraMessage);
}
+ if (message==null) message = "";
+ return new PropagatedRuntimeException(message, collapseCausalChain ? collapsed : source, true);
}
static String appendSeparator(String message, String next) {
@@ -233,14 +239,25 @@ public class Exceptions {
}
private static String collapseText(Throwable t, boolean includeAllCausalMessages) {
+ return collapseText(t, includeAllCausalMessages, ImmutableSet.<Throwable>of());
+ }
+ private static String collapseText(Throwable t, boolean includeAllCausalMessages, Set<Throwable> visited) {
if (t == null) return null;
- Throwable t2 = collapse(t, true, includeAllCausalMessages);
+ if (visited.contains(t)) {
+ // IllegalStateException sometimes refers to itself; guard against stack overflows
+ if (Strings.isNonBlank(t.getMessage())) return t.getMessage();
+ else return "("+t.getClass().getName()+", recursive cause)";
+ }
+ Throwable t2 = collapse(t, true, includeAllCausalMessages, visited);
+ visited = MutableSet.copyOf(visited);
+ visited.add(t);
+ visited.add(t2);
if (t2 instanceof PropagatedRuntimeException) {
if (((PropagatedRuntimeException)t2).isCauseEmbeddedInMessage())
// normally
return t2.getMessage();
else if (t2.getCause()!=null)
- return ""+t2.getCause();
+ return collapseText(t2.getCause(), includeAllCausalMessages, ImmutableSet.copyOf(visited));
return ""+t2.getClass();
}
String result = t2.toString();
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9fca8a27/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 decc1f0..c622ffc 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
@@ -38,12 +38,14 @@ import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.Stack;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -83,10 +85,17 @@ public class Reflections {
}
private final ClassLoader classLoader;
+ private final Map<String, String> classRenameMap = MutableMap.of();
public Reflections(ClassLoader classLoader) {
this.classLoader = checkNotNull(classLoader);
}
+
+ /** supply a map of known renames, of the form "old-class -> new-class" */
+ public Reflections applyClassRenames(Map<String,String> newClassRenames) {
+ this.classRenameMap.putAll(newClassRenames);
+ return this;
+ }
public Object loadInstance(String classname, Object...argValues) throws ReflectionNotFoundException, ReflectionAccessException {
Class<?> clazz = loadClass(classname);
@@ -119,6 +128,7 @@ public class Reflections {
/** instantiates the given class from its binary name */
public Class<?> loadClass(String classname) throws ReflectionNotFoundException {
try {
+ classname = findMappedNameAndLog(classRenameMap, classname);
return classLoader.loadClass(classname);
} catch (ClassNotFoundException e) {
throw new ReflectionNotFoundException("Failed to load class '" + classname + "' using class loader " + classLoader + ": " + Exceptions.collapseText(e), e);
@@ -785,4 +795,35 @@ public class Reflections {
if (clazz.getDeclaredFields().length>0) return false;
return hasNoNonObjectFields(clazz.getSuperclass());
}
+
+ /** Takes a map of old-class-names to renames classes, and returns the mapped name if matched, or absent */
+ public static Optional<String> tryFindMappedName(Map<String, String> renames, String name) {
+ if (renames==null) return Optional.absent();
+
+ String mappedName = renames.get(name);
+ if (mappedName != null) {
+ return Optional.of(mappedName);
+ }
+
+ // look for inner classes by mapping outer class
+ if (name.contains("$")) {
+ String outerClassName = name.substring(0, name.indexOf('$'));
+ mappedName = renames.get(outerClassName);
+ if (mappedName != null) {
+ return Optional.of(mappedName + name.substring(name.indexOf('$')));
+ }
+ }
+
+ return Optional.absent();
+ }
+
+ public static String findMappedNameAndLog(Map<String, String> renames, String name) {
+ Optional<String> rename = Reflections.tryFindMappedName(renames, name);
+ if (rename.isPresent()) {
+ LOG.debug("Mapping class '"+name+"' to '"+rename.get()+"'");
+ return rename.get();
+ }
+ return name;
+ }
+
}