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/02/01 18:49:27 UTC

[23/50] brooklyn-server git commit: XML serialisation: avoid error if try to serialize entity

XML serialisation: avoid error if try to serialize entity

- If entity/location/policy sneaks through to be serialized
  (e.g. through config key of LocationConfigKeys.CALLER_CONTEXT
  pointing at Entity)...
- Don't blow up: instead let it deserialize as null, which is better
  than failing to serialize+deserialize everything about the entity.
- Logs at WARN for first time encountered, and debug subsequently.


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

Branch: refs/heads/0.6.0
Commit: c7ff592232e1e3f6812e946304da03e03b017d83
Parents: 224fca6
Author: Aled Sage <al...@gmail.com>
Authored: Tue Nov 12 11:13:59 2013 +0000
Committer: Aled Sage <al...@gmail.com>
Committed: Tue Nov 12 21:52:59 2013 +0000

----------------------------------------------------------------------
 .../rebind/persister/XmlMementoSerializer.java  | 74 +++++++++++++++++++-
 1 file changed, 72 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/c7ff5922/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java b/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java
index c8c8d36..68d8ae1 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java
@@ -4,24 +4,41 @@ import static com.google.common.base.Preconditions.checkNotNull;
 
 import java.io.IOException;
 import java.io.Writer;
+import java.util.concurrent.atomic.AtomicBoolean;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.entity.Entity;
 import brooklyn.entity.rebind.dto.BasicEntityMemento;
 import brooklyn.entity.rebind.dto.BasicLocationMemento;
 import brooklyn.entity.rebind.dto.MutableBrooklynMemento;
 import brooklyn.event.basic.BasicAttributeSensor;
 import brooklyn.event.basic.BasicConfigKey;
+import brooklyn.location.Location;
+import brooklyn.policy.EntityAdjunct;
 import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.xstream.XmlSerializer;
 
+import com.google.common.base.Function;
+import com.thoughtworks.xstream.converters.Converter;
+import com.thoughtworks.xstream.converters.MarshallingContext;
+import com.thoughtworks.xstream.converters.UnmarshallingContext;
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+
 /* uses xml, cleaned up a bit
  * 
  * there is an early attempt at doing this with JSON in pull request #344 but 
  * it is not nicely deserializable, see comments at http://xstream.codehaus.org/json-tutorial.html */  
 public class XmlMementoSerializer<T> extends XmlSerializer<T> implements MementoSerializer<T> {
-    
+
+    private static final Logger LOG = LoggerFactory.getLogger(XmlMementoSerializer.class);
+
     @SuppressWarnings("unused")
     private final ClassLoader classLoader;
 
+    @SuppressWarnings({ "unchecked", "rawtypes" })
     public XmlMementoSerializer(ClassLoader classLoader) {
         this.classLoader = checkNotNull(classLoader, "classLoader");
         xstream.alias("brooklyn", MutableBrooklynMemento.class);
@@ -29,6 +46,18 @@ public class XmlMementoSerializer<T> extends XmlSerializer<T> implements Memento
         xstream.alias("location", BasicLocationMemento.class);
         xstream.alias("configKey", BasicConfigKey.class);
         xstream.alias("attributeSensor", BasicAttributeSensor.class);
+        xstream.registerConverter(new ConverterImpl(Location.class, new Function<Location,String>() {
+            @Override public String apply(Location input) {
+                return (input != null) ? input.getId() : null;
+            }}));
+        xstream.registerConverter(new ConverterImpl(Entity.class, new Function<Entity,String>() {
+            @Override public String apply(Entity input) {
+                return (input != null) ? input.getId() : null;
+            }}));
+        xstream.registerConverter(new ConverterImpl(EntityAdjunct.class, new Function<EntityAdjunct,String>() {
+            @Override public String apply(EntityAdjunct input) {
+                return (input != null) ? input.getId() : null;
+            }}));
     }
     
     @Override
@@ -41,4 +70,45 @@ public class XmlMementoSerializer<T> extends XmlSerializer<T> implements Memento
         }
     }
 
-}
\ No newline at end of file
+    public static class ConverterImpl<T> implements Converter {
+        private final AtomicBoolean hasWarned = new AtomicBoolean(false);
+        private final Class<?> converatable;
+        private final Function<T,String> idExtractor;
+        
+        ConverterImpl(Class<T> converatable, Function<T,String> idExtractor) {
+            this.converatable = checkNotNull(converatable, "converatable");
+            this.idExtractor = checkNotNull(idExtractor, "idExtractor");
+        }
+        
+        @SuppressWarnings({ "rawtypes" })
+        @Override
+        public boolean canConvert(Class type) {
+            return converatable.isAssignableFrom(type);
+        }
+        
+        @SuppressWarnings("unchecked")
+        @Override
+        public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
+            if (source != null) {
+                if (hasWarned.compareAndSet(false, true)) {
+                    LOG.warn("Cannot marshall to xml (for persistence) {} {}; should have been intercepted; unmarshalling will give null!", converatable.getSimpleName(), source);
+                } else {
+                    LOG.debug("Cannot marshall to xml (for persistence) {} {}; should have been intercepted; unmarshalling will give null!", converatable.getSimpleName(), source);
+                }
+            }
+            // no-op; can't marshall this; deserializing will give null!
+            writer.startNode("unserializableLocation");
+            writer.setValue(idExtractor.apply((T)source));
+            writer.endNode();
+        }
+
+        @Override
+        public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
+            reader.moveDown();
+            String id = reader.getValue();
+            reader.moveUp();
+            LOG.warn("Cannot unmarshall from persisted xml {} {}; should have been intercepted; returning null!", converatable.getSimpleName(), id);
+            return null;
+        }
+    }
+}