Merge pull request #1079 from jcabrerizo/feature/session-timeout

Adding logic to manage a max session age
diff --git a/NOTICE b/NOTICE
index ee9424a..c2f8899 100644
--- a/NOTICE
+++ b/NOTICE
@@ -69,9 +69,9 @@
     Developed by: QOS.ch (http://www.qos.ch)
     License name: Eclipse Public License, version 1.0
   
-  com.fasterxml.jackson:2.9.7: 
+  com.fasterxml.jackson:2.9.8: 
     Project:      Jackson FasterXML
-    Version:      2.9.7
+    Version:      2.9.8
     Available at: 
       - http://github.com/FasterXML/jackson
       - https://github.com/FasterXML/jackson-core
@@ -189,11 +189,11 @@
     License name: Apache License, version 2.0
     Notice:       Copyright (c) Square, Inc.
   
-  com.thoughtworks.xstream:1.4.8: 
+  com.thoughtworks.xstream:1.4.11.1: 
     Project:      XStream Core
-    Version:      1.4.8
+    Version:      1.4.11.1
     Available at: http://x-stream.github.io/
-    Developed by: XStream (http://xstream.codehaus.org)
+    Developed by: XStream (http://x-stream.github.io)
     License name: BSD 3-Clause (New BSD) License
   
   commons-beanutils:1.9.3: 
@@ -231,11 +231,11 @@
     Developed by: The Apache Software Foundation (http://www.apache.org/)
     License name: Apache License, version 2.0
   
-  io.cloudsoft.windows:0.6.1: 
+  io.cloudsoft.windows:0.7.0: 
     Project: 
       - Java WinRM library
       - WinRM Client
-    Version:      0.6.1
+    Version:      0.7.0
     Available at: http://github.com/cloudsoft/winrm4j
     License name: Apache License, version 2.0
   
@@ -292,11 +292,11 @@
     Developed by: Chemouni Uriel (http://www.minidev.net/)
     License name: Apache License, version 2.0
   
-  org.apache.commons.commons-compress:1.4: 
-    Project:      Commons Compress
-    Version:      1.4
-    Available at: http://commons.apache.org/compress/
-    Developed by: The Apache Software Foundation (http://www.apache.org/)
+  org.apache.commons.commons-compress:1.18: 
+    Project:      Apache Commons Compress
+    Version:      1.18
+    Available at: https://commons.apache.org/proper/commons-compress/
+    Developed by: The Apache Software Foundation (https://www.apache.org/)
     License name: Apache License, version 2.0
   
   org.apache.commons.commons-lang3:3.3.2: 
@@ -306,16 +306,16 @@
     Developed by: The Apache Software Foundation (http://www.apache.org/)
     License name: Apache License, version 2.0
   
-  org.apache.cxf:3.2.7: 
+  org.apache.cxf:3.2.8: 
     Project:      Apache CXF
-    Version:      3.2.7
+    Version:      3.2.8
     Available at: http://cxf.apache.org
     Developed by: The Apache Software Foundation (http://www.apache.org/)
     License name: Apache License, version 2.0
   
-  org.apache.felix.org.apache.felix.framework:5.6.10: 
+  org.apache.felix.org.apache.felix.framework:5.6.12: 
     Project:      Apache Felix Framework
-    Version:      5.6.10
+    Version:      5.6.12
     Available at: http://felix.apache.org/
     Developed by: The Apache Software Foundation (http://www.apache.org/)
     License name: Apache License, version 2.0
@@ -362,16 +362,16 @@
     Developed by: The Apache Software Foundation (http://www.apache.org/)
     License name: Apache License, version 2.0
   
-  org.apache.karaf.jaas.org.apache.karaf.jaas.boot:4.2.2: 
+  org.apache.karaf.jaas.org.apache.karaf.jaas.boot:4.2.7: 
     Project:      Apache Karaf :: JAAS :: Boot
-    Version:      4.2.2
+    Version:      4.2.7
     Available at: https://www.apache.org/
     Developed by: The Apache Software Foundation (https://www.apache.org/)
     License name: Apache License, version 2.0
   
-  org.apache.karaf.shell.org.apache.karaf.shell.core:4.2.2: 
+  org.apache.karaf.shell.org.apache.karaf.shell.core:4.2.7: 
     Project:      Apache Karaf :: Shell :: Core
-    Version:      4.2.2
+    Version:      4.2.7
     Available at: https://www.apache.org/
     Developed by: The Apache Software Foundation (https://www.apache.org/)
     License name: Apache License, version 2.0
@@ -390,9 +390,9 @@
     Developed by: The Apache Software Foundation (http://www.apache.org/)
     License name: Apache License, version 2.0
   
-  org.apache.ws.xmlschema.xmlschema-core:2.2.3: 
+  org.apache.ws.xmlschema.xmlschema-core:2.2.4: 
     Project:      XmlSchema Core
-    Version:      2.2.3
+    Version:      2.2.4
     Available at: http://ws.apache.org/commons/xmlschema20/
     Developed by: The Apache Software Foundation (http://www.apache.org/)
     License name: Apache License, version 2.0
@@ -446,9 +446,9 @@
     License name: Apache License, version 2.0
     Notice:       Copyright (c) Shigeru Chiba
   
-  org.jline:3.9.0: 
+  org.jline:3.12.1: 
     Project:      JLine Bundle
-    Version:      3.9.0
+    Version:      3.12.1
     Available at: http://nexus.sonatype.org/oss-repository-hosting.html
     License name: BSD 3-Clause (New BSD) License
     Notice: 
@@ -483,12 +483,6 @@
     Developed by: QOS.ch (http://www.qos.ch)
     License name: MIT License
   
-  org.tukaani.xz:1.0: 
-    Project:      XZ for Java
-    Version:      1.0
-    Available at: http://tukaani.org/xz/java.html
-    License name: Public Domain
-  
   org.xmlunit:2.3.0: 
     Project: 
       - org.xmlunit:xmlunit-core
diff --git a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
index b4233a1..a193165 100644
--- a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
+++ b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
@@ -60,6 +60,7 @@
 import org.apache.brooklyn.core.mgmt.ManagementContextInjectable;
 import org.apache.brooklyn.core.mgmt.classloading.JavaBrooklynClassLoadingContext;
 import org.apache.brooklyn.core.resolve.entity.EntitySpecResolver;
+import org.apache.brooklyn.core.typereg.RegisteredTypeLoadingContexts;
 import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.collections.MutableSet;
@@ -68,11 +69,13 @@
 import org.apache.brooklyn.util.core.flags.FlagUtils.FlagConfigKeyAndValueRecord;
 import org.apache.brooklyn.util.core.task.DeferredSupplier;
 import org.apache.brooklyn.util.core.task.Tasks;
+import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.net.Urls;
 import org.apache.brooklyn.util.text.Strings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.yaml.snakeyaml.Yaml;
 
 import com.google.common.base.Function;
 import com.google.common.base.Functions;
@@ -505,6 +508,7 @@
 
         private class EntitySpecSupplier implements DeferredSupplier<EntitySpec<?>> {
             EntitySpecConfiguration flag;
+            transient EntitySpec<?> cached = null;
             public EntitySpecSupplier(EntitySpecConfiguration flag) {
                 this.flag = flag;
             }
@@ -513,9 +517,59 @@
                 // And have transformSpecialFlags(Object flag, ManagementContext mgmt) drill into the Object flag if it's a map or iterable?
                 @SuppressWarnings("unchecked")
                 Map<String, Object> resolvedConfig = (Map<String, Object>)transformSpecialFlags(flag.getSpecConfiguration());
-                EntitySpec<?> entitySpec = Factory.newInstance(getLoader(), resolvedConfig).resolveSpec(encounteredRegisteredTypeIds);
-
-                return EntityManagementUtils.unwrapEntity(entitySpec);
+                EntitySpec<?> entitySpec;
+                try {
+                    // first parse as a CAMP entity
+                    entitySpec = Factory.newInstance(getLoader(), resolvedConfig).resolveSpec(encounteredRegisteredTypeIds);
+                } catch (Exception e1) {
+                    Exceptions.propagateIfFatal(e1);
+                    
+                    // if that doesn't work, try full multi-format plan parsing 
+                    String yamlPlan = null;
+                    try {
+                        yamlPlan = new Yaml().dump(resolvedConfig);
+                        entitySpec = mgmt.getTypeRegistry().createSpecFromPlan(null, yamlPlan, 
+                            RegisteredTypeLoadingContexts.alreadyEncountered(encounteredRegisteredTypeIds), EntitySpec.class);
+                    } catch (Exception e2) {
+                        String errorMessage = "entitySpec plan parse error";
+                        if (Thread.currentThread().isInterrupted()) {
+                            // plans which read/write to a file might not work in interrupted state
+                            if (cached!=null) {
+                                log.debug("EntitySpecSupplier returning cached spec "+cached+" because being invoked in a context which must return immediately");
+                                return cached;
+                            } else {
+                                errorMessage += " (note, it is being invoked in a context which must return immediately and there is no cache)";
+                            }
+                        }
+                        Exceptions.propagateIfFatal(e2);
+                        
+                        Exception exceptionToInclude;
+                        // heuristic
+                        if (resolvedConfig.containsKey("type")) {
+                            // if it has a key 'type' then it is likely a CAMP entity, abbreviated syntax (giving a type), so just give e1
+                            exceptionToInclude = e1;
+                        } else if (resolvedConfig.containsKey("brooklyn.services")) {
+                            // seems like a CAMP app, just give e2
+                            exceptionToInclude = e2;
+                        } else {
+                            // can't tell if it was short form eg `entitySpec: { type: x, ... }`
+                            // or long form (camp or something else), eg `entitySpec: { brooklyn.services: [ ... ] }`.
+                            // the error from the latter is a bit nicer so return it, but log the former.
+                            errorMessage += "; consult log for more information";
+                            log.debug("Suppressed error in entity spec where unclear whether abbreviated or full syntax, is (from abbreviated form parse, where error parsing full form will be reported subsequently): "+e1);
+                            exceptionToInclude = e2;
+                            // don't use the list as that causes unhelpful "2 errors including"...
+                        }
+                        // first exception might include the plan, so we don't need to here
+                        boolean yamlPlanAlreadyIncluded = exceptionToInclude.toString().contains(yamlPlan);
+                        if (!yamlPlanAlreadyIncluded) {
+                            errorMessage += ":\n"+yamlPlan;
+                        }
+                        throw Exceptions.propagateAnnotated(errorMessage, exceptionToInclude);
+                    }
+                }
+                cached = EntityManagementUtils.unwrapEntity(entitySpec);
+                return cached;
             }
         }
         
diff --git a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeInstantiator.java b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeInstantiator.java
index aa1dfe9..d63ff7a 100644
--- a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeInstantiator.java
+++ b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeInstantiator.java
@@ -92,7 +92,7 @@
 
         @Override
         public Maybe<String> getTypeName() {
-            Maybe<Object> result = data.getStringKeyMaybe(getPreferredKeyName());
+            Maybe<Object> result = data.getStringKeyMaybe(getTypedKeyName());
             if (result.isAbsent() && typeKeyPrefix!=null) {
                 // try alternatives if a prefix was specified
                 result = data.getStringKeyMaybe(typeKeyPrefix+"Type");
@@ -100,15 +100,15 @@
             }
             
             if (result.isAbsent() || result.get()==null) 
-                return Maybe.absent("Missing key '"+getPreferredKeyName()+"'");
+                return Maybe.absent("Missing key 'type'"+(typeKeyPrefix!=null ? " (or '"+getTypedKeyName()+"')" : ""));
             
             if (result.get() instanceof String) return Maybe.of((String)result.get());
             
-            throw new IllegalArgumentException("Invalid value "+result.get().getClass()+" for "+getPreferredKeyName()+"; "
+            throw new IllegalArgumentException("Invalid value "+result.get().getClass()+" for "+getTypedKeyName()+"; "
                 + "expected String, got "+result.get());
         }
         
-        protected String getPreferredKeyName() {
+        protected String getTypedKeyName() {
             if (typeKeyPrefix!=null) return typeKeyPrefix+"_type";
             return "type";
         }
diff --git a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java
index eaa68b8..0ba74d8 100644
--- a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java
+++ b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java
@@ -20,16 +20,18 @@
 
 import java.util.List;
 import java.util.Map;
+import java.util.function.BiFunction;
 
 import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
+import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind;
 import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.api.typereg.RegisteredType.TypeImplementationPlan;
 import org.apache.brooklyn.api.typereg.RegisteredTypeLoadingContext;
-import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind;
 import org.apache.brooklyn.core.typereg.AbstractFormatSpecificTypeImplementationPlan;
 import org.apache.brooklyn.core.typereg.AbstractTypePlanTransformer;
 import org.apache.brooklyn.core.typereg.BasicTypeImplementationPlan;
 import org.apache.brooklyn.core.typereg.RegisteredTypes;
+import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.guava.Maybe;
 
 import com.google.common.collect.ImmutableList;
@@ -64,13 +66,27 @@
         }
         
         Maybe<Map<?,?>> plan = RegisteredTypes.getAsYamlMap(planData);
-        if (plan.isAbsent()) return 0;
-        if (plan.get().containsKey("services")) return weight*0.8;
-        if (plan.get().containsKey("type")) return weight*0.4;
-        // TODO these should become legacy
-        if (plan.get().containsKey("brooklyn.locations")) return weight*0.7;
-        if (plan.get().containsKey("brooklyn.policies")) return weight*0.7;
-        if (plan.get().containsKey("brooklyn.enrichers")) return weight*0.7;
+        if (plan.isPresent()) {
+            return weight * scoreObject(plan.get(), (map,s) -> map.containsKey(s));
+        }
+        if (planData==null) {
+            return 0;
+        }
+        double unparseableScore = scoreObject(planData.toString(), (p,s) -> p.contains(s));
+        if (unparseableScore>0) {
+            return 0.5 + 0.25 * unparseableScore;
+        }
+        return 0;
+    }
+    
+    protected <T> double scoreObject(T plan, BiFunction<T, String, Boolean> contains) {
+        if (contains.apply(plan, "services")) return 0.8;
+        if (contains.apply(plan, "type")) return 0.4;
+        if (contains.apply(plan, "brooklyn.locations")) return 0.7;
+        if (contains.apply(plan, "brooklyn.policies")) return 0.7;
+        if (contains.apply(plan, "brooklyn.enrichers")) return 0.7;
+        // score low so we can say it's the wrong place
+        if (contains.apply(plan, "catalog.bom")) return 0.2;
         return 0;
     }
 
@@ -84,8 +100,31 @@
 
     @Override
     protected AbstractBrooklynObjectSpec<?, ?> createSpec(RegisteredType type, RegisteredTypeLoadingContext context) throws Exception {
-        // TODO cache
-        return new CampResolver(mgmt, type, context).createSpec();
+        try {
+            return new CampResolver(mgmt, type, context).createSpec();
+        } catch (Exception e) {
+            Exceptions.propagateIfFatal(e);
+            String message = null;
+            // check a few common errors, annotate if so
+            if (type==null || type.getPlan()==null || type.getPlan().getPlanData()==null) {
+                // shouldn't happen
+                message = "Type/plan/data is null when resolving CAMP blueprint";
+            } else {
+                Object planData = type.getPlan().getPlanData();
+                if (RegisteredTypes.getAsYamlMap(planData).isAbsent()) {
+                    message = "Type or plan is invalid YAML when resolving CAMP blueprint";
+                } else if (planData.toString().contains("brooklyn.catalog")) {
+                    message = "CAMP blueprint for type definition looks like a catalog file";
+                } else {
+                    // leave null, don't annotate
+                }
+            }
+            if (message!=null) {
+                throw Exceptions.propagateAnnotated(message, e);
+            } else {
+                throw e;
+            }
+        }
     }
 
     @Override
diff --git a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslInterpreter.java b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslInterpreter.java
index 4105e19..77fa385 100644
--- a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslInterpreter.java
+++ b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslInterpreter.java
@@ -79,6 +79,8 @@
                 node.setNewValue( evaluate(parsedNode, true) );
             }
         } catch (Exception e) {
+            // we could try parsing it as yaml and if it comes back as a map or a list, reapply the interpreter;
+            // useful in some contexts where strings are required by the source (eg CFN, TOSCA)
             log.warn("Error evaluating node (rethrowing) '"+expression+"': "+e);
             Exceptions.propagateIfFatal(e);
             throw new IllegalArgumentException("Error evaluating node '"+expression+"'", e);
diff --git a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslUtils.java b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslUtils.java
index 9789c86..7cf5c88 100644
--- a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslUtils.java
+++ b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslUtils.java
@@ -19,8 +19,25 @@
 package org.apache.brooklyn.camp.brooklyn.spi.dsl;
 
 import java.util.Arrays;
+import java.util.Map;
 
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatform;
+import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynComponentTemplateResolver;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
+import org.apache.brooklyn.util.collections.MutableSet;
+import org.apache.brooklyn.util.core.flags.TypeCoercions;
 import org.apache.brooklyn.util.core.task.DeferredSupplier;
+import org.apache.brooklyn.util.yaml.Yamls;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import com.google.common.reflect.TypeToken;
 
 public class DslUtils {
 
@@ -42,4 +59,64 @@
         }
         return allResolved;
     }
+    
+    private static Object transformSpecialFlags(ManagementContext mgmt, AbstractBrooklynObjectSpec<?,?> spec, Object v) {
+        return new BrooklynComponentTemplateResolver.SpecialFlagsTransformer(
+            CatalogUtils.newClassLoadingContext(mgmt, spec.getCatalogItemId(), ImmutableList.of()),
+            MutableSet.of()).apply(v);
+    }
+
+    /** resolve an object which might be (or contain in a map or list) a $brooklyn DSL string expression */
+    private static Optional<Object> resolveBrooklynDslValueInternal(Object originalValue, @Nullable TypeToken<?> desiredType, @Nullable ManagementContext mgmt, @Nullable AbstractBrooklynObjectSpec<?,?> specForCatalogItemIdContext, boolean requireType) {
+        if (originalValue == null) {
+            return Optional.absent();
+        }
+        Object value = originalValue;
+        if (mgmt!=null) {
+            if (value instanceof String && ((String)value).matches("\\$brooklyn:[A-Za-z_]+:\\s(?s).*")) {
+                // input is a map as a string, parse it as yaml first
+                value = Iterables.getOnlyElement( Yamls.parseAll((String)value) );
+            }
+            
+            // The 'dsl' key is arbitrary, but the interpreter requires a map
+            ImmutableMap<String, Object> inputToPdpParse = ImmutableMap.of("dsl", value);
+            Map<String, Object> resolvedConfigMap = BrooklynCampPlatform.findPlatform(mgmt)
+                    .pdp()
+                    .applyInterpreters(inputToPdpParse);
+            value = resolvedConfigMap.get("dsl");
+            // TODO if it fails log a warning -- eg entitySpec with root.war that doesn't exist
+
+            if (specForCatalogItemIdContext!=null) {
+                value = transformSpecialFlags(mgmt, specForCatalogItemIdContext, value);
+            }
+        }
+        
+        if (requireType && value instanceof DeferredSupplier) {
+            // Don't cast - let Brooklyn evaluate it later (the value is a resolved DSL expression).
+            return Optional.of(value);
+        }
+        
+        if (desiredType!=null) {
+            // coerce to _raw_ type as per other config-setting coercion; config _retrieval_ does type correctness
+            return Optional.of(TypeCoercions.coerce(value, desiredType.getRawType()));
+
+        } else {
+            return Optional.of(value);
+        }
+    }
+
+    /** Resolve an object which might be (or contain in a map or list) a $brooklyn DSL string expression,
+     * attempting to coerce if a type is supplied (unless it is a {@link DeferredSupplier}) */
+    public static Optional<Object> resolveBrooklynDslValue(Object originalValue, @Nullable TypeToken<?> desiredType, @Nullable ManagementContext mgmt, @Nullable AbstractBrooklynObjectSpec<?,?> specForCatalogItemIdContext) {
+        return resolveBrooklynDslValueInternal(originalValue, desiredType, mgmt, specForCatalogItemIdContext, false);
+        
+    }
+    
+    /** As {@link #resolveBrooklynDslValue(Object, TypeToken, ManagementContext, AbstractBrooklynObjectSpec)}
+     * but returning absent if the object is DeferredSupplier, ensuring type correctness.
+     * This is particularly useful for maps and other objects which might contain deferred suppliers but won't be one. */
+    @SuppressWarnings("unchecked")
+    public static <T> Optional<T> resolveNonDeferredBrooklynDslValue(Object originalValue, @Nullable TypeToken<T> desiredType, @Nullable ManagementContext mgmt, @Nullable AbstractBrooklynObjectSpec<?,?> specForCatalogItemIdContext) {
+        return (Optional<T>) resolveBrooklynDslValueInternal(originalValue, desiredType, mgmt, specForCatalogItemIdContext, true);
+    }
 }
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 518b501..20efc95 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
@@ -287,6 +287,8 @@
 
     // Build complex things
 
+    // TODO allow entitySpec to take string, parsed as YAML, and if just a string that's taken as the type
+    
     @DslAccessible
     public static EntitySpecConfiguration entitySpec(Map<String, Object> arguments) {
         return new EntitySpecConfiguration(arguments);
@@ -368,10 +370,10 @@
      * are not yet fully resolved.
      */
     @DslAccessible
-    public static Object formatString(final String pattern, final Object...args) {
-        if (resolved(args)) {
+    public static Object formatString(final Object pattern, final Object...args) {
+        if (resolved(Lists.asList(pattern, args))) {
             // if all args are resolved, apply the format string now
-            return String.format(pattern, args);
+            return String.format(String.valueOf(pattern), args);
         } else {
             return new DslFormatString(pattern, args);
         }
@@ -433,16 +435,16 @@
     /**
      * Deferred execution of String formatting.
      *
-     * @see DependentConfiguration#formatString(String, Object...)
+     * @see DependentConfiguration#formatString(Object, Object...)
      */
     protected static class DslFormatString extends BrooklynDslDeferredSupplier<String> {
 
         private static final long serialVersionUID = -4849297712650560863L;
 
-        private final String pattern;
+        private final Object pattern;
         private final Object[] args;
 
-        public DslFormatString(String pattern, Object ...args) {
+        public DslFormatString(Object pattern, Object ...args) {
             this.pattern = pattern;
             this.args = args;
         }
@@ -526,7 +528,7 @@
     @SuppressWarnings({ "serial", "unused" })
     @Deprecated
     private static class FormatString extends DslFormatString {
-        public FormatString(String pattern, Object[] args) {
+        public FormatString(Object pattern, Object[] args) {
             super(pattern, args);
         }
     }
diff --git a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/parse/DslParser.java b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/parse/DslParser.java
index 7b0f359..2b88d7f 100644
--- a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/parse/DslParser.java
+++ b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/parse/DslParser.java
@@ -85,7 +85,7 @@
         } while (true);
         String fn = expression.substring(fnStart, index);
         if (fn.length()==0)
-            throw new IllegalStateException("Expected a function name at position "+start);
+            throw new IllegalStateException("Expected a function name or double-quoted string at position "+start);
         skipWhitespace();
         
         if (index < expression.length() && expression.charAt(index)=='(') {
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ValidationMissingTypeYamlTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ValidationMissingTypeYamlTest.java
index d71f381..2a62d45 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ValidationMissingTypeYamlTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ValidationMissingTypeYamlTest.java
@@ -57,14 +57,14 @@
                     "  itemType: entity",
                     "  item:",
                     "    foo: " + TestEntity.class.getName());
+            Asserts.shouldHaveFailedPreviously();
         } catch (Exception e) {
             Asserts.expectedFailureContains(e, "must declare a type");
         }
     }
 
     @Test
-    public void testNoEntityTypeInTopLevelCatalogApp() throws Exception {
-        try {
+    public void testNoEntityTypeInTopLevelCatalogAppAsTemplateErrorIsAllowed() throws Exception {
             addCatalogItems(
                     "brooklyn.catalog:",
                     "  id: " + Identifiers.makeRandomId(8),
@@ -73,9 +73,6 @@
                     "  item:",
                     "    services:",
                     "    - foo: " + TestEntity.class.getName());
-        } catch (Exception e) {
-            Asserts.expectedFailureContains(e, "must declare a type");
-        }
     }
 
     @Test
@@ -140,13 +137,22 @@
                     "        foo: " + TestEntityImpl.class.getName());
             Asserts.shouldHaveFailedPreviously();
         } catch (Exception e) {
-            Asserts.expectedFailureContains(e, "No type defined");
+//            org.apache.brooklyn.util.exceptions.PropagatedRuntimeException: brooklyn-camp plan creation error: 
+//                entitySpec plan parse error; consult log for more information: 
+//                UnsupportedTypePlanException: Invalid plan; format could not be recognized, 
+//                none of the available transformers 
+//                  [brooklyn-camp:CampTypePlanTransformer, 
+//                  java-type-name:JavaClassNameTypePlanTransformer]
+//                support plan:
+//            {foo: org.apache.brooklyn.core.test.entity.TestEntityImpl}
+
+            Asserts.expectedFailureContains(e, "entitySpec plan parse error");
+            Asserts.expectedFailureContains(e, "format could not be recognized");
         }
     }
     
     @Test
-    public void testNoEntityTypeInEntitySpecInCatalogEntity() throws Exception {
-        try {
+    public void testNoEntityTypeInEntitySpecInCatalogEntityIsAllowed() throws Exception {
             addCatalogItems(
                     "brooklyn.catalog:",
                     "  id: " + Identifiers.makeRandomId(8),
@@ -159,14 +165,10 @@
                     "      memberSpec: ",
                     "        $brooklyn:entitySpec:",
                     "          foo: " + TestEntityImpl.class.getName());
-        } catch (Exception e) {
-            Asserts.expectedFailureContains(e, "No type defined");
-        }
     }
 
     @Test
-    public void testNoEntityTypeInEntitySpecInCatalogApp() throws Exception {
-        try {
+    public void testNoEntityTypeInEntitySpecInCatalogAppIsAllowed() throws Exception {
             addCatalogItems(
                     "brooklyn.catalog:",
                     "  id: " + Identifiers.makeRandomId(8),
@@ -180,15 +182,26 @@
                     "        memberSpec: ",
                     "          $brooklyn:entitySpec:",
                     "            foo: " + TestEntityImpl.class.getName());
-        } catch (Exception e) {
-            Asserts.expectedFailureContains(e, "No type defined");
-        }
     }
 
-    // TODO Preferred name should not be 'policy_type'; it should be 'type'!
     @Test
     public void testNoPolicyTypeSpecified() throws Exception {
+        // preferred syntax, okay
+        createAndStartApplication(
+            "services:",
+            "- type: " + TestApplication.class.getName(),
+            "  brooklyn.policies:",
+            "  - type: " + TestPolicy.class.getName());
+        
+        // legacy syntax okay
+        createAndStartApplication(
+            "services:",
+            "- type: " + TestApplication.class.getName(),
+            "  brooklyn.policies:",
+            "  - policy_type: " + TestPolicy.class.getName());
+        
         try {
+            // no type not okay
             createAndStartApplication(
                     "services:",
                     "- type: " + TestApplication.class.getName(),
@@ -196,13 +209,31 @@
                     "  - foo: " + TestPolicy.class.getName());
             Asserts.shouldHaveFailedPreviously();
         } catch (Exception e) {
-            Asserts.expectedFailureContains(e, "Missing key 'policy_type'");
+            Asserts.expectedFailureContains(e, "Missing key", "'type'", "'policy_type'");
         }
+        
+        try {
+            // invalid type not okay
+            createAndStartApplication(
+                    "services:",
+                    "- type: " + TestApplication.class.getName(),
+                    "  brooklyn.policies:",
+                    "  - type: does_not_exist");
+            Asserts.shouldHaveFailedPreviously();
+        } catch (Exception e) {
+            Asserts.expectedFailureContains(e, "does_not_exist");
+        }
+
     }
     
-    // TODO Preferred name should not be 'enricher_type'; it should be 'type'!
     @Test
     public void testNoEnricherTypeSpecified() throws Exception {
+        createAndStartApplication(
+            "services:",
+            "- type: " + TestApplication.class.getName(),
+            "  brooklyn.enrichers:",
+            "  - type: " + TestEnricher.class.getName());
+
         try {
             createAndStartApplication(
                     "services:",
@@ -211,7 +242,7 @@
                     "  - foo: " + TestEnricher.class.getName());
             Asserts.shouldHaveFailedPreviously();
         } catch (Exception e) {
-            Asserts.expectedFailureContains(e, "Missing key 'enricher_type'");
+            Asserts.expectedFailureContains(e, "Missing key", "'type'", "'enricher_type'");
         }
     }
     
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslParseComponentsTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslParseComponentsTest.java
index 1e8ccb8..ddd8a1f 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslParseComponentsTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslParseComponentsTest.java
@@ -57,6 +57,7 @@
                     "  brooklyn.config:",
                     "    dest: 1",
                     "    dest2: 1",
+                    "    pattern: '%s-%s'",
                     "  brooklyn.children:",
                     "  - type: "+BasicEntity.class.getName(),
                     "    id: two",
@@ -133,6 +134,17 @@
     }
 
     @Test
+    public void testFormatStringWithDslPatternEvaluation() throws Exception {
+        app();
+
+        Object y1 = parseDslExpression("$brooklyn:formatString($brooklyn:config(\"pattern\"), $brooklyn:config(\"dest\"), $brooklyn:config(\"dest2\"))");
+        Assert.assertEquals(y1.toString(), "$brooklyn:formatString(config(\"pattern\"), config(\"dest\"), config(\"dest2\"))");
+
+        String y2 = Tasks.resolveValue(y1, String.class, ((EntityInternal) find("one")).getExecutionContext());
+        Assert.assertEquals(y2.toString(), "1-1");
+    }
+
+    @Test
     public void testEntityReferenceAndAttributeWhenReady() throws Exception {
         app();
         find("one").sensors().set(Attributes.ADDRESS, "1");
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslYamlTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslYamlTest.java
index 57fee74..a2922a1 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslYamlTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslYamlTest.java
@@ -45,7 +45,6 @@
 import org.apache.brooklyn.entity.stock.BasicStartable;
 import org.apache.brooklyn.test.Asserts;
 import org.apache.brooklyn.util.collections.MutableMap;
-import org.apache.brooklyn.util.exceptions.CompoundRuntimeException;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.testng.annotations.Test;
 
@@ -551,7 +550,7 @@
                     "  brooklyn.config:",
                     "    dest: $brooklyn:self().invalidMethod()");
             Asserts.shouldHaveFailedPreviously("Non-existing non-deferred method should fail deployment");
-        } catch (CompoundRuntimeException e) {
+        } catch (Exception e) {
             Asserts.expectedFailureContains(e, "No such function 'invalidMethod'");
         }
     }
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/TagsYamlTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/TagsYamlTest.java
index f6d06d3..70895dc 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/TagsYamlTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/TagsYamlTest.java
@@ -15,20 +15,19 @@
  */
 package org.apache.brooklyn.camp.brooklyn.spi.dsl;
 
-import com.google.common.base.Predicate;
-import com.google.common.collect.Iterables;
+import static org.testng.Assert.assertTrue;
+
+import javax.annotation.Nullable;
+
 import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
 import org.apache.brooklyn.entity.stock.BasicApplication;
 import org.apache.brooklyn.test.Asserts;
-import org.apache.brooklyn.util.exceptions.CompoundRuntimeException;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.testng.annotations.Test;
 
-import javax.annotation.Nullable;
-
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
 
 public class TagsYamlTest extends AbstractYamlTest {
     @Test
@@ -64,9 +63,11 @@
                     "  brooklyn.tags:",
                     "    tag1: true",
                     "    tag2: 2");
-            fail("Should throw IllegalArgumentException exception; instead got: "+app);
-        } catch (CompoundRuntimeException e) {
-            Asserts.assertStringContainsAtLeastOne(Exceptions.getFirstInteresting(e).getMessage(),"brooklyn.tags must be a list, is: ");
+            Asserts.shouldHaveFailedPreviously("Should throw IllegalArgumentException exception; instead got: "+app);
+        } catch (Exception e) {
+            Asserts.expectedFailureContainsIgnoreCase(e, "brooklyn.tags must be a list");
+            Asserts.assertStringContainsAtLeastOne(Exceptions.getFirstInteresting(e).getMessage(),
+                "brooklyn.tags must be a list, is: ");
         }
     }
 
@@ -112,9 +113,13 @@
                     "      type: "+TagsTestObject.class.getName(),
                     "      constructor.args:",
                     "      - $brooklyn:attributeWhenReady(\"host.name\")");
-            fail("Should throw IllegalArgumentException exception; instead got "+app);
-        } catch (CompoundRuntimeException e) {
-            Asserts.assertStringContainsAtLeastOne(Exceptions.getFirstInteresting(e).getMessage(),"brooklyn.tags should not contain DeferredSupplier. A DeferredSupplier is made when using $brooklyn:attributeWhenReady");
+            Asserts.shouldHaveFailedPreviously("Should throw IllegalArgumentException exception; instead got "+app);
+        } catch (Exception e) {
+            Asserts.expectedFailureContainsIgnoreCase(e, 
+                "brooklyn.tags should not contain DeferredSupplier",
+                "A DeferredSupplier is made when using $brooklyn:attributeWhenReady");
+            Asserts.assertStringContainsAtLeastOne(Exceptions.getFirstInteresting(e).getMessage(),
+                "brooklyn.tags should not contain DeferredSupplier");
         }
     }
 
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/EntityManagementSupport.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/EntityManagementSupport.java
index 4a5c23b..b13f384 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/EntityManagementSupport.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/EntityManagementSupport.java
@@ -30,11 +30,12 @@
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.mgmt.SubscriptionContext;
 import org.apache.brooklyn.api.mgmt.entitlement.EntitlementManager;
+import org.apache.brooklyn.api.objs.EntityAdjunct;
 import org.apache.brooklyn.api.policy.Policy;
 import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.api.sensor.AttributeSensor.SensorPersistenceMode;
 import org.apache.brooklyn.api.sensor.Enricher;
 import org.apache.brooklyn.api.sensor.Feed;
-import org.apache.brooklyn.api.sensor.AttributeSensor.SensorPersistenceMode;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.entity.AbstractEntity;
 import org.apache.brooklyn.core.entity.Entities;
@@ -44,6 +45,7 @@
 import org.apache.brooklyn.core.mgmt.entitlement.Entitlements.EntityAndItem;
 import org.apache.brooklyn.core.mgmt.entitlement.Entitlements.StringAndArgument;
 import org.apache.brooklyn.core.mgmt.internal.NonDeploymentManagementContext.NonDeploymentManagementContextMode;
+import org.apache.brooklyn.core.objs.AbstractEntityAdjunct;
 import org.apache.brooklyn.util.core.task.Tasks;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.slf4j.Logger;
@@ -304,11 +306,16 @@
                 nonDeploymentManagementContext.setMode(NonDeploymentManagementContextMode.MANAGEMENT_STOPPING);
             }
         }
-        // TODO custom stopping activities
-        // TODO framework stopping events - no more sensors, executions, etc
-        // (elaborate or remove ^^^ ? -AH, Sept 2014)
         
         if (!isReadOnly() && info.getMode().isDestroying()) {
+            // ensure adjuncts get a destroy callback
+            // note they don't get any alert if the entity is being locally unmanaged to run somewhere else.
+            // framework should introduce a call for that ideally, but in interim if needed they
+            // can listen to the entity becoming locally unmanaged
+            entity.feeds().forEach(this::destroyAdjunct);
+            entity.enrichers().forEach(this::destroyAdjunct);
+            entity.policies().forEach(this::destroyAdjunct);
+                
             // if we support remote parent of local child, the following call will need to be properly remoted
             if (entity.getParent()!=null) entity.getParent().removeChild(entity.getProxyIfAvailable());
         }
@@ -323,6 +330,18 @@
         }
     }
     
+    protected void destroyAdjunct(EntityAdjunct adjunct) {
+        if (adjunct instanceof AbstractEntityAdjunct) {
+            try {
+                ((AbstractEntityAdjunct)adjunct).destroy();
+            } catch (Exception e) {
+                Exceptions.propagateIfFatal(e);
+                log.error("Error destroying "+adjunct+" (ignoring): "+e);
+                log.trace("Trace for error", e);
+            }
+        }
+    }
+    
     public void onManagementStopped(ManagementTransitionInfo info) {
         synchronized (this) {
             if (managementContext == null && nonDeploymentManagementContext.getMode() == NonDeploymentManagementContextMode.MANAGEMENT_STOPPED) {
diff --git a/core/src/main/java/org/apache/brooklyn/core/sensor/DependentConfiguration.java b/core/src/main/java/org/apache/brooklyn/core/sensor/DependentConfiguration.java
index c2a9804..0e1a22a 100644
--- a/core/src/main/java/org/apache/brooklyn/core/sensor/DependentConfiguration.java
+++ b/core/src/main/java/org/apache/brooklyn/core/sensor/DependentConfiguration.java
@@ -510,27 +510,29 @@
      * </pre>
      */
     @SuppressWarnings("unchecked")
-    public static Task<String> formatString(final String spec, final Object ...args) {
+    public static Task<String> formatString(final Object spec, final Object ...args) {
         List<TaskAdaptable<Object>> taskArgs = Lists.newArrayList();
-        for (Object arg: args) {
+
+        Object[] newArgs = Lists.asList(spec, args).toArray();
+        for (Object arg: newArgs) {
             if (arg instanceof TaskAdaptable) taskArgs.add((TaskAdaptable<Object>)arg);
             else if (arg instanceof TaskFactory) taskArgs.add( ((TaskFactory<TaskAdaptable<Object>>)arg).newTask() );
         }
         
         return transformMultiple(
-            MutableMap.<String,String>of("displayName", "formatting '"+spec+"' with "+taskArgs.size()+" task"+(taskArgs.size()!=1?"s":"")), 
+            MutableMap.<String,String>of("displayName", "formatting '"+spec.toString()+"' with "+taskArgs.size()+" task"+(taskArgs.size()!=1?"s":"")),
             new Function<List<Object>, String>() {
                 @Override public String apply(List<Object> input) {
                     Iterator<?> tri = input.iterator();
-                    Object[] vv = new Object[args.length];
+                    Object[] vv = new Object[newArgs.length];
                     int i=0;
-                    for (Object arg : args) {
+                    for (Object arg : newArgs) {
                         if (arg instanceof TaskAdaptable || arg instanceof TaskFactory) vv[i] = tri.next();
                         else if (arg instanceof DeferredSupplier) vv[i] = ((DeferredSupplier<?>) arg).get();
                         else vv[i] = arg;
                         i++;
                     }
-                    return String.format(spec, vv);
+                    return String.format(vv[0].toString(), Arrays.copyOfRange(vv, 1, vv.length));
                 }},
             taskArgs);
     }
@@ -538,7 +540,13 @@
     /**
      * @throws ImmediateSupplier.ImmediateUnsupportedException if cannot evaluate this in a timely manner
      */
-    public static Maybe<String> formatStringImmediately(final String spec, final Object ...args) {
+    public static Maybe<String> formatStringImmediately(final Object spec, final Object ...args) {
+        String pattern = "";
+        Maybe<?> resolvedSpec = resolveImmediately(spec);
+        if (resolvedSpec.isPresent()) {
+            pattern = resolvedSpec.get().toString();
+        }
+
         List<Object> resolvedArgs = Lists.newArrayList();
         for (Object arg : args) {
             Maybe<?> argVal = resolveImmediately(arg);
@@ -546,7 +554,7 @@
             resolvedArgs.add(argVal.get());
         }
 
-        return Maybe.of(String.format(spec, resolvedArgs.toArray()));
+        return Maybe.of(String.format(pattern, resolvedArgs.toArray()));
     }
 
     /**
diff --git a/core/src/main/java/org/apache/brooklyn/core/sensor/StaticSensor.java b/core/src/main/java/org/apache/brooklyn/core/sensor/StaticSensor.java
index 4c10f41..1c44011 100644
--- a/core/src/main/java/org/apache/brooklyn/core/sensor/StaticSensor.java
+++ b/core/src/main/java/org/apache/brooklyn/core/sensor/StaticSensor.java
@@ -70,6 +70,7 @@
         class ResolveValue implements Callable<Maybe<T>> {
             @Override
             public Maybe<T> call() throws Exception {
+                // TODO resolve deep?
                 return Tasks.resolving(value).as(sensor.getTypeToken()).timeout(timeout).getMaybe();
             }
         }
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
index 7dd24cf..2854598 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
@@ -307,26 +307,28 @@
                 .build();
         }
         try {
-            return (SpecT) BasicBrooklynCatalog.internalCreateSpecLegacy(mgmt, item, constraint.getAlreadyEncounteredTypes(), false);
-        } catch (Exception e) {
-            Exceptions.propagateIfFatal(e);
+            SpecT resultLegacy = (SpecT) BasicBrooklynCatalog.internalCreateSpecLegacy(mgmt, item, constraint.getAlreadyEncounteredTypes(), false);
+            log.warn("Item '"+item+"' was only parseable using legacy transformers; may not be supported in future versions: "+resultLegacy);
+            return resultLegacy;
+        } catch (Exception exceptionFromLegacy) {
+            Exceptions.propagateIfFatal(exceptionFromLegacy);
             // for now, combine this failure with the original
             try {
                 result.get();
                 // above will throw -- so won't come here
                 throw new IllegalStateException("should have failed getting type resolution for "+symbolicName);
-            } catch (Exception e0) {
-                Set<Exception> exceptionsInOrder = MutableSet.of();
-                if (e0.toString().indexOf("none of the available transformers")>=0) {
-                    // put the legacy exception first if none of the new transformers support the type
-                    // (until the new transformer is the primary pathway)
-                    exceptionsInOrder.add(e);
-                    exceptionsInOrder.add(e0);
-                } else {
-                    exceptionsInOrder.add(e0);
-                    exceptionsInOrder.add(e);
+            } catch (Exception exceptionFromPrimary) {
+                // ignore the legacy error. means much nicer errors in the happy case.
+                
+                if (log.isTraceEnabled()) {
+                    log.trace("Unable to instantiate "+(symbolicName==null ? "item" : symbolicName)+", primary error", 
+                        exceptionFromPrimary);
+                    log.trace("Unable to instantiate "+(symbolicName==null ? "item" : symbolicName)+", legacy error", 
+                        exceptionFromLegacy);
                 }
-                throw Exceptions.create("Unable to instantiate "+(symbolicName==null ? "item" : symbolicName), exceptionsInOrder); 
+
+                Throwable exception = Exceptions.collapse(exceptionFromPrimary);
+                throw symbolicName==null ? Exceptions.propagate(exception) : Exceptions.propagateAnnotated("Unable to instantiate "+symbolicName, exception);
             }
         }
     }
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynTypePlanTransformer.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynTypePlanTransformer.java
index 1001268..fb28082 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynTypePlanTransformer.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynTypePlanTransformer.java
@@ -64,8 +64,11 @@
      * 1 means this is clearly the intended transformer and no others need be tried 
      * (for instance because the format is explicitly specified),
      * and values between 0 and 1 indicate how likely a transformer believes it should be used.
+     * <p>
      * Values greater than 0.5 are generally reserved for the presence of marker tags or files
      * which strongly indicate that the format is compatible.
+     * Such a value should be returned even if the plan is not actually parseable, but if it looks like a user error
+     * which prevents parsing (eg mal-formed YAML) and the transformer could likely be the intended target.
      * <p>
      * */
     double scoreForType(@Nonnull RegisteredType type, @Nonnull RegisteredTypeLoadingContext context);
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/TypePlanTransformers.java b/core/src/main/java/org/apache/brooklyn/core/typereg/TypePlanTransformers.java
index cc4845c..3d456c2 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/TypePlanTransformers.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/TypePlanTransformers.java
@@ -125,10 +125,13 @@
                     (Strings.isNonBlank(e.getMessage()) ? " ("+e.getMessage()+")" : ""));
             } catch (Throwable e) {
                 Exceptions.propagateIfFatal(e);
-                log.debug("Transformer for "+t.getFormatCode()+" gave an error creating this plan (retrying with others): "+e, e);
+                if (log.isTraceEnabled()) {
+                    log.trace("Transformer for "+t.getFormatCode()+" gave an error creating this plan (may retry): "+e, e);
+                }
                 failuresFromTransformers.add(new PropagatedRuntimeException(
-                    (type.getSymbolicName()!=null ? "Error in definition of "+type.getId() : 
-                        "Transformer for "+t.getFormatCode()+" gave an error creating this plan") + ": "+
+                    (type.getSymbolicName()!=null ? 
+                        t.getFormatCode()+" plan creation error in "+type.getId() :
+                        t.getFormatCode()+" plan creation error") + ": "+
                     Exceptions.collapseText(e), e));
             }
         }
@@ -150,7 +153,8 @@
                 Exceptions.create("All plan transformers failed", failuresFromTransformers);
         } else {
             if (transformers.isEmpty()) {
-                result = new UnsupportedTypePlanException("Invalid plan; format could not be recognized, none of the available transformers "+all(mgmt)+" support "+type);
+                result = new UnsupportedTypePlanException("Invalid plan; format could not be recognized, none of the available transformers "+all(mgmt)+" support "+
+                    (type.getId()!=null ? type.getId() : "plan:\n"+type.getPlan().getPlanData()));
             } else {
                 result = new UnsupportedTypePlanException("Invalid plan; potentially applicable transformers "+transformers+" do not support it, and other available transformers "+
 //                    // the removeAll call below won't work until "all" caches it
diff --git a/core/src/main/java/org/apache/brooklyn/enricher/stock/aggregator/DashboardAggregator.java b/core/src/main/java/org/apache/brooklyn/enricher/stock/aggregator/DashboardAggregator.java
index de9964b..8fe05f0 100644
--- a/core/src/main/java/org/apache/brooklyn/enricher/stock/aggregator/DashboardAggregator.java
+++ b/core/src/main/java/org/apache/brooklyn/enricher/stock/aggregator/DashboardAggregator.java
@@ -51,7 +51,7 @@
 
     private ScheduledTask task;
 
-    public static BasicAttributeSensorAndConfigKey<Duration> DASHBOARD_COST_PER_MONTH = new BasicAttributeSensorAndConfigKey(Duration.class,
+    public static BasicAttributeSensorAndConfigKey<Duration> DASHBOARD_AGGREGATION_PERIOD = new BasicAttributeSensorAndConfigKey(Duration.class,
             "dashboard.period",
             "The amount of time to wait between aggregation jobs",
             Duration.seconds(1));
@@ -61,7 +61,7 @@
     public void setEntity(EntityLocal entity) {
         super.setEntity(entity);
 
-        Duration duration = config().get(DASHBOARD_COST_PER_MONTH);
+        Duration duration = config().get(DASHBOARD_AGGREGATION_PERIOD);
 
         Callable<Task<?>> taskFactory = () -> Tasks.builder()
                 .dynamic(false)
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
index 3f6381b..91dc577 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/ClassLoaderUtils.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/ClassLoaderUtils.java
@@ -347,7 +347,15 @@
         } else {
             Maybe<T> result = dispatcher.tryLoadFrom(classLoader, name);
             if (result.isAbsent()) {
-                log.warn("Request for bundle '"+symbolicName+"' "+(Strings.isNonBlank(version) ? "("+version+") " : "")+"was ignored as no framework available; and failed to find '"+name+"' in plain old classpath");
+                if (name==null || name.startsWith("//") || symbolicName==null || "classpath".equals(symbolicName) || "http".equals(symbolicName) || "https".equals(symbolicName) || "file".equals(symbolicName)) {
+                    // this is called speculatively by BasicBrooklynCatalog.PlanInterpreterGuessingType so can log a lot of warnings where URLs are passed
+                    if (log.isTraceEnabled()) {
+                        log.trace("Request for bundle '"+symbolicName+"' "+(Strings.isNonBlank(version) ? "("+version+") " : "")+"was ignored as no framework available; and failed to find '"+name+"' in plain old classpath");
+                    }
+                } else {
+                    // TODO not sure warning is appropriate, but won't hide that in all cases yet
+                    log.warn("Request for bundle '"+symbolicName+"' "+(Strings.isNonBlank(version) ? "("+version+") " : "")+"was ignored as no framework available; and failed to find '"+name+"' in plain old classpath");
+                }
             }
             return result;
         }
diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java
index 8d9a889..7cf9f0d 100644
--- a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java
+++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java
@@ -312,12 +312,21 @@
 
     @Override
     public String toString() {
-        Object identity = getIdentity();
+        String className = getClass().getSimpleName();
         String configDescription = config().getLocalBag().getDescription();
-        if (configDescription!=null && configDescription.startsWith(getClass().getSimpleName()))
+        String displayName = getDisplayName();
+
+        if (configDescription != null && configDescription.startsWith(className))
             return configDescription;
-        return getClass().getSimpleName()+"["+getDisplayName()+":"+(identity != null ? identity : null)+
-                (configDescription!=null ? "/"+configDescription : "") + "@" + getId() + "]";
+
+        if (displayName != null)
+            return className + "['" + displayName + "']";
+
+        return className + "[" +
+                getIdentity() +
+                (configDescription == null ? "" : "/" + configDescription) +
+                "@" + getId() +
+                "]";
     }
 
     @Override
diff --git a/policy/src/main/java/org/apache/brooklyn/policy/action/AbstractScheduledEffectorPolicy.java b/policy/src/main/java/org/apache/brooklyn/policy/action/AbstractScheduledEffectorPolicy.java
index 9350d52..1c49e7e 100644
--- a/policy/src/main/java/org/apache/brooklyn/policy/action/AbstractScheduledEffectorPolicy.java
+++ b/policy/src/main/java/org/apache/brooklyn/policy/action/AbstractScheduledEffectorPolicy.java
@@ -53,6 +53,7 @@
 import org.slf4j.LoggerFactory;
 
 import com.google.common.annotations.Beta;
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Predicates;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
@@ -137,6 +138,7 @@
         if (executor != null) {
             executor.shutdownNow();
         }
+        // TODO instead of a custom executor it would be nicer to use scheduled tasks
         executor = Executors.newSingleThreadScheduledExecutor();
         running = new AtomicBoolean(false);
     }
@@ -289,4 +291,9 @@
             }
         }
     }
+    
+    @VisibleForTesting
+    public ScheduledExecutorService getExecutor() {
+        return executor;
+    }
 }
diff --git a/policy/src/main/java/org/apache/brooklyn/policy/action/PeriodicEffectorPolicy.java b/policy/src/main/java/org/apache/brooklyn/policy/action/PeriodicEffectorPolicy.java
index dafc69c..a33503e 100644
--- a/policy/src/main/java/org/apache/brooklyn/policy/action/PeriodicEffectorPolicy.java
+++ b/policy/src/main/java/org/apache/brooklyn/policy/action/PeriodicEffectorPolicy.java
@@ -58,6 +58,7 @@
 @Beta
 public class PeriodicEffectorPolicy extends AbstractScheduledEffectorPolicy {
 
+    @SuppressWarnings("unused")
     private static final Logger LOG = LoggerFactory.getLogger(PeriodicEffectorPolicy.class);
 
     public static final ConfigKey<Duration> PERIOD = ConfigKeys.builder(Duration.class)
diff --git a/policy/src/test/java/org/apache/brooklyn/policy/action/PeriodicEffectorPolicyTest.java b/policy/src/test/java/org/apache/brooklyn/policy/action/PeriodicEffectorPolicyTest.java
index a2aa4a6..75b00a0 100644
--- a/policy/src/test/java/org/apache/brooklyn/policy/action/PeriodicEffectorPolicyTest.java
+++ b/policy/src/test/java/org/apache/brooklyn/policy/action/PeriodicEffectorPolicyTest.java
@@ -26,6 +26,8 @@
 import org.apache.brooklyn.test.Asserts;
 import org.apache.brooklyn.util.time.Duration;
 import org.apache.brooklyn.util.time.Time;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.testng.annotations.Test;
 
 import com.google.common.base.Predicates;
@@ -34,6 +36,9 @@
 
 public class PeriodicEffectorPolicyTest extends AbstractEffectorPolicyTest {
 
+    @SuppressWarnings("unused")
+    private static final Logger log = LoggerFactory.getLogger(PeriodicEffectorPolicyTest.class);
+    
     @Test
     public void testPeriodicEffectorFires() {
         TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class)
@@ -52,6 +57,9 @@
         entity.sensors().set(START, Boolean.TRUE);
         assertConfigEqualsEventually(policy, PeriodicEffectorPolicy.RUNNING, true);
         assertCallHistoryEventually(entity, "myEffector", 2);
+        
+        app.stop();
+        Asserts.assertTrue( ((PeriodicEffectorPolicy)policy).getExecutor().isShutdown(), "Executor should have been shut down");
     }
 
     // Integration because of long wait
diff --git a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/AdjunctApi.java b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/AdjunctApi.java
index 87a95b5..970546c 100644
--- a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/AdjunctApi.java
+++ b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/AdjunctApi.java
@@ -68,6 +68,7 @@
             @QueryParam("adjunctType") final String adjunctType);
 
     // TODO support YAML ?
+    // TODO support timeout
     @POST
     @ApiOperation(value = "Create and add an adjunct (e.g. a policy, enricher, or feed) to this entity", notes = "Returns a summary of the added adjunct")
     @ApiResponses(value = {
diff --git a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/domain/AdjunctDetail.java b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/domain/AdjunctDetail.java
index a2f348c..02c14da 100644
--- a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/domain/AdjunctDetail.java
+++ b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/domain/AdjunctDetail.java
@@ -57,6 +57,14 @@
         return tags;
     }
     
+    public Map<String, Object> getConfig() {
+        return config;
+    }
+    
+    public Set<ConfigSummary> getParameters() {
+        return parameters;
+    }
+
     public AdjunctDetail parameter(ConfigSummary p) {
         parameters.add(p); return this;
     }
@@ -68,5 +76,5 @@
     public AdjunctDetail config(Map<String,Object> vals) {
         config.putAll(vals); return this;
     }
-
+    
 }
diff --git a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/AdjunctResource.java b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/AdjunctResource.java
index 9e48d4f..d417a6e 100644
--- a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/AdjunctResource.java
+++ b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/AdjunctResource.java
@@ -39,6 +39,7 @@
 import org.apache.brooklyn.api.sensor.EnricherSpec;
 import org.apache.brooklyn.api.sensor.Feed;
 import org.apache.brooklyn.api.typereg.RegisteredType;
+import org.apache.brooklyn.camp.brooklyn.spi.dsl.DslUtils;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.config.ConfigPredicates;
 import org.apache.brooklyn.core.entity.EntityInternal;
@@ -68,11 +69,13 @@
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Function;
+import com.google.common.base.Optional;
 import com.google.common.base.Predicates;
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.io.Files;
+import com.google.common.reflect.TypeToken;
 
 @HaHotStateRequired
 public class AdjunctResource extends AbstractBrooklynRestResource implements AdjunctApi {
@@ -148,7 +151,13 @@
             }
         }
 
-        spec.configure(config);
+        try {
+            Optional<Map> configResolved = DslUtils.resolveNonDeferredBrooklynDslValue(config, TypeToken.of(Map.class), mgmt(), spec);
+            spec.configure(configResolved.or(config));
+        } catch (Exception e) {
+            log.debug("Error resolving config (rethrowing) "+config+": "+e, e);
+            throw Exceptions.propagate(e);
+        }
 
         EntityAdjunct instance;
         if (spec instanceof PolicySpec) {
diff --git a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
index 5e1be91..1a7ef61 100644
--- a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
+++ b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
@@ -513,7 +513,7 @@
         } catch (Exception e) {
             Exceptions.propagateIfFatal(e);
             legacyFormatException = e;
-            log.debug("Input is not legacy ApplicationSpec JSON (will try others): "+e, e);
+            log.debug("Input is not legacy ApplicationSpec JSON (will try others)");
         }
 
         //TODO infer encoding from request
diff --git a/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/AdjunctResourceTest.java b/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/AdjunctResourceTest.java
index 2bd9f2d..444a680 100644
--- a/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/AdjunctResourceTest.java
+++ b/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/AdjunctResourceTest.java
@@ -25,12 +25,15 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.Function;
 
 import javax.ws.rs.core.GenericType;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
+import org.apache.brooklyn.api.objs.BrooklynObjectType;
 import org.apache.brooklyn.api.objs.HighlightTuple;
+import org.apache.brooklyn.core.test.policy.TestPolicy;
 import org.apache.brooklyn.rest.domain.AdjunctDetail;
 import org.apache.brooklyn.rest.domain.AdjunctSummary;
 import org.apache.brooklyn.rest.domain.ApplicationSpec;
@@ -41,8 +44,11 @@
 import org.apache.brooklyn.rest.testing.mocks.RestMockSimplePolicy;
 import org.apache.brooklyn.test.Asserts;
 import org.apache.brooklyn.util.collections.MutableList;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.cxf.jaxrs.client.WebClient;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.testng.Assert;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
@@ -79,7 +85,6 @@
         AdjunctDetail response = pResponse.readEntity(AdjunctDetail.class);
         assertNotNull(response.getId());
         policyId = response.getId();
-
     }
 
     @Test
@@ -87,11 +92,13 @@
         Set<AdjunctSummary> adjuncts = client().path(ENDPOINT)
                 .get(new GenericType<Set<AdjunctSummary>>() {});
         
-        AdjunctSummary policy = null;
+        AdjunctSummary initialPolicy = null;
         List<AdjunctSummary> others = MutableList.of();
         for (AdjunctSummary adj : adjuncts) {
             if (adj.getId().equals(policyId)) {
-                policy = adj;
+                initialPolicy = adj;
+            } else if (adj.getAdjunctType()==BrooklynObjectType.POLICY){
+                // policy from another test, just skip
             } else {
                 others.add(adj);
             }
@@ -100,7 +107,7 @@
         log.info("Non-policy adjuncts: "+others);
         Asserts.assertSize(others, 4);
 
-        assertEquals(policy.getName(), RestMockSimplePolicy.class.getName());
+        assertEquals(initialPolicy.getName(), RestMockSimplePolicy.class.getName());
     }
     
 
@@ -195,4 +202,39 @@
         assertEquals(highlightTupleNoTask.getTime(), 123L);
         assertEquals(highlightTupleNoTask.getTaskId(), null);
     }
+
+    protected AdjunctDetail doTestAddPolicyExpectX(Function<WebClient,WebClient> mutator, Object postBody) throws Exception {
+        AdjunctDetail result = mutator.apply(
+                client().path(ENDPOINT)
+            ).post(postBody, AdjunctDetail.class);
+        Assert.assertEquals(result.getConfig().get(TestPolicy.CONF_FROM_FUNCTION.getName()), "x");
+        return result;
+    }
+        
+    @Test
+    public void testAddPolicyX() throws Exception {
+        doTestAddPolicyExpectX(x -> x.query("type", TestPolicy.class.getName()), 
+            toJsonEntity(MutableMap.of(
+                TestPolicy.CONF_FROM_FUNCTION.getName(), "x")));
+    }
+    
+    @Test
+    public void testAddPolicyFn() throws Exception {
+        doTestAddPolicyExpectX(x -> x.query("type", TestPolicy.class.getName()), 
+            toJsonEntity(MutableMap.of(
+                TestPolicy.CONF_FROM_FUNCTION.getName(), "$brooklyn:literal(\"x\")")));
+    }
+
+//    // TODO support YAML posts
+//    @Test(groups = "WIP")
+//    public void testAddPolicyYaml() throws Exception {
+//        doTestAddPolicyExpectX(x -> x, 
+//            javax.ws.rs.client.Entity.entity(
+//              "type: "+TestPolicy.class.getName()+"\n"+
+//              "brooklyn.config:\n"+
+//              "  "+TestPolicy.CONF_FROM_FUNCTION.getName()+": "+
+//                  "$brooklyn.literal('x')", 
+//              "application/yaml"));
+//    }
+
 }
diff --git a/server-cli/NOTICE b/server-cli/NOTICE
index 9274c4f..3f419af 100644
--- a/server-cli/NOTICE
+++ b/server-cli/NOTICE
@@ -69,9 +69,9 @@
     Developed by: QOS.ch (http://www.qos.ch)
     License name: Eclipse Public License, version 1.0
   
-  com.fasterxml.jackson:2.9.7: 
+  com.fasterxml.jackson:2.9.8: 
     Project:      Jackson FasterXML
-    Version:      2.9.7
+    Version:      2.9.8
     Available at: 
       - http://github.com/FasterXML/jackson
       - http://wiki.fasterxml.com/JacksonExtensionXmlDataBinding
@@ -196,11 +196,11 @@
     License name: Apache License, version 2.0
     Notice:       Copyright (c) Square, Inc.
   
-  com.thoughtworks.xstream:1.4.8: 
+  com.thoughtworks.xstream:1.4.11.1: 
     Project:      XStream Core
-    Version:      1.4.8
+    Version:      1.4.11.1
     Available at: http://x-stream.github.io/
-    Developed by: XStream (http://xstream.codehaus.org)
+    Developed by: XStream (http://x-stream.github.io)
     License name: BSD 3-Clause (New BSD) License
   
   commons-beanutils:1.9.3: 
@@ -251,11 +251,11 @@
     Available at: https://github.com/airlift/airline
     License name: Apache License, version 2.0
   
-  io.cloudsoft.windows:0.6.1: 
+  io.cloudsoft.windows:0.7.0: 
     Project: 
       - Java WinRM library
       - WinRM Client
-    Version:      0.6.1
+    Version:      0.7.0
     Available at: http://github.com/cloudsoft/winrm4j
     License name: Apache License, version 2.0
   
@@ -269,12 +269,6 @@
     Available at: https://github.com/swagger-api/swagger-core
     License name: Apache License, version 2.0
   
-  javax.activation:1.1.1: 
-    Project:      JavaBeans(TM) Activation Framework
-    Version:      1.1.1
-    Available at: http://java.sun.com/javase/technologies/desktop/javabeans/jaf/index.jsp
-    License name: Common Development and Distribution License, version 1.0
-  
   javax.annotation.javax.annotation-api:1.3: 
     Project:      javax.annotation API
     Version:      1.3
@@ -314,13 +308,6 @@
     Developed by: Eclipse Foundation (https://www.eclipse.org/org/foundation/)
     License name: Common Development and Distribution License, version 1.1
   
-  javax.xml.bind.jaxb-api:2.2.11: 
-    Project:      Java Architecture for XML Binding
-    Version:      2.2.11
-    Available at: http://jaxb.java.net/
-    Developed by: Oracle Corporation (http://www.oracle.com/)
-    License name: Common Development and Distribution License, version 1.1
-  
   joda-time:2.7: 
     Project:      Joda-Time
     Version:      2.7
@@ -362,11 +349,11 @@
     Developed by: Chemouni Uriel (http://www.minidev.net/)
     License name: Apache License, version 2.0
   
-  org.apache.commons.commons-compress:1.4: 
-    Project:      Commons Compress
-    Version:      1.4
-    Available at: http://commons.apache.org/compress/
-    Developed by: The Apache Software Foundation (http://www.apache.org/)
+  org.apache.commons.commons-compress:1.18: 
+    Project:      Apache Commons Compress
+    Version:      1.18
+    Available at: https://commons.apache.org/proper/commons-compress/
+    Developed by: The Apache Software Foundation (https://www.apache.org/)
     License name: Apache License, version 2.0
   
   org.apache.commons.commons-lang3:3.3.2: 
@@ -376,20 +363,34 @@
     Developed by: The Apache Software Foundation (http://www.apache.org/)
     License name: Apache License, version 2.0
   
-  org.apache.cxf:3.2.7: 
+  org.apache.cxf:3.2.8: 
     Project:      Apache CXF
-    Version:      3.2.7
+    Version:      3.2.8
     Available at: http://cxf.apache.org
     Developed by: The Apache Software Foundation (http://www.apache.org/)
     License name: Apache License, version 2.0
   
-  org.apache.felix.org.apache.felix.framework:5.6.10: 
+  org.apache.felix.org.apache.felix.framework:5.6.12: 
     Project:      Apache Felix Framework
-    Version:      5.6.10
+    Version:      5.6.12
     Available at: http://felix.apache.org/
     Developed by: The Apache Software Foundation (http://www.apache.org/)
     License name: Apache License, version 2.0
   
+  org.apache.geronimo.specs.geronimo-activation_1.1_spec:1.1: 
+    Project:      Activation 1.1
+    Version:      1.1
+    Available at: http://geronimo.apache.org/maven/specs/geronimo-activation_1.1_spec/1.1
+    Developed by: The Apache Software Foundation (http://www.apache.org)
+    License name: Apache License, version 2.0
+  
+  org.apache.geronimo.specs.geronimo-stax-api_1.0_spec:1.0.1: 
+    Project:      Streaming API for XML (STAX API 1.0)
+    Version:      1.0.1
+    Available at: http://geronimo.apache.org/specs/geronimo-stax-api_1.0_spec
+    Developed by: Apache Software Foundation (http://www.apache.org)
+    License name: Apache License, version 2.0
+  
   org.apache.geronimo.specs.geronimo-ws-metadata_2.0_spec:1.1.3: 
     Project:      Web Services Metadata 2.0
     Version:      1.1.3
@@ -439,9 +440,20 @@
     Developed by: The Apache Software Foundation (http://www.apache.org/)
     License name: Apache License, version 2.0
   
-  org.apache.ws.xmlschema.xmlschema-core:2.2.3: 
+  org.apache.servicemix.specs:2.9.0: 
+    Project: 
+      - Apache ServiceMix :: Specs :: Activation API 1.4
+      - Apache ServiceMix :: Specs :: Activator
+      - Apache ServiceMix :: Specs :: JAXB API 2.2
+      - Apache ServiceMix :: Specs :: Stax API 1.0
+    Version:      2.9.0
+    Available at: http://servicemix.apache.org/
+    Developed by: The Apache Software Foundation (http://www.apache.org/)
+    License name: Apache License, version 2.0
+  
+  org.apache.ws.xmlschema.xmlschema-core:2.2.4: 
     Project:      XmlSchema Core
-    Version:      2.2.3
+    Version:      2.2.4
     Available at: http://ws.apache.org/commons/xmlschema20/
     Developed by: The Apache Software Foundation (http://www.apache.org/)
     License name: Apache License, version 2.0
@@ -469,28 +481,18 @@
     Developed by: fasterxml.com (http://fasterxml.com)
     License name: BSD 2-Clause (Simplified or FreeBSD) License
   
-  org.eclipse.jetty.toolchain.jetty-schemas:3.1.M0: 
-    Project:      Jetty :: Schemas
-    Version:      3.1.M0
-    Available at: http://www.eclipse.org/jetty
-    Developed by: Mort Bay Consulting (http://www.mortbay.com)
-    License name: Apache License, version 2.0
-  
-  org.eclipse.jetty:9.4.12.v20180830: 
+  org.eclipse.jetty:9.4.20.v20190813: 
     Project: 
       - Jetty :: Http Utility
       - Jetty :: IO Utility
-      - Jetty :: JAAS
       - Jetty :: Security
       - Jetty :: Server Core
       - Jetty :: Servlet Handling
       - Jetty :: Utilities
       - Jetty :: Webapp Application Support
       - Jetty :: XML utilities
-    Version:      9.4.12.v20180830
-    Available at: 
-      - http://www.eclipse.org/jetty
-      - https://eclipse.org/jetty
+    Version:      9.4.20.v20190813
+    Available at: http://www.eclipse.org/jetty
     Developed by: Webtide (https://webtide.com)
     License name: Apache License, version 2.0
   
@@ -548,12 +550,6 @@
     Developed by: QOS.ch (http://www.qos.ch)
     License name: MIT License
   
-  org.tukaani.xz:1.0: 
-    Project:      XZ for Java
-    Version:      1.0
-    Available at: http://tukaani.org/xz/java.html
-    License name: Public Domain
-  
   org.xmlunit:2.3.0: 
     Project: 
       - org.xmlunit:xmlunit-core