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 2020/11/17 17:50:38 UTC

[brooklyn-server] 01/03: correct DSL serialization problem and allow $brooklyn:object to load registered types

This is an automated email from the ASF dual-hosted git repository.

heneveld pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git

commit ff24c90745b8e94657e095539f3c8c0fe01cdccb
Author: Alex Heneveld <al...@cloudsoftcorp.com>
AuthorDate: Tue Nov 17 17:25:43 2020 +0000

    correct DSL serialization problem and allow $brooklyn:object to load registered types
---
 .../brooklyn/spi/dsl/DslDeferredFunctionCall.java  | 27 ++++++++++++++--------
 .../spi/dsl/methods/BrooklynDslCommon.java         | 22 +++++++++++++++++-
 .../spi/dsl/methods/DslToStringHelpers.java        |  2 +-
 .../brooklyn/util/core/ClassLoaderUtils.java       | 10 ++++++--
 4 files changed, 48 insertions(+), 13 deletions(-)

diff --git a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslDeferredFunctionCall.java b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslDeferredFunctionCall.java
index 30b8416..9ef74d0 100644
--- a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslDeferredFunctionCall.java
+++ b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslDeferredFunctionCall.java
@@ -30,6 +30,7 @@ import org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.DslToStringHelpers;
 import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
 import org.apache.brooklyn.util.core.task.ImmediateSupplier;
 import org.apache.brooklyn.util.core.task.Tasks;
+import org.apache.brooklyn.util.core.task.ValueResolver;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.javalang.Reflections;
@@ -84,7 +85,7 @@ public class DslDeferredFunctionCall extends BrooklynDslDeferredSupplier<Object>
     }
 
     protected Maybe<Object> invokeOnDeferred(Object obj, boolean immediate) {
-        Maybe<?> resolvedMaybe = resolve(obj, immediate);
+        Maybe<?> resolvedMaybe = resolve(obj, immediate, true);
         if (resolvedMaybe.isPresent()) {
             Object instance = resolvedMaybe.get();
 
@@ -93,7 +94,11 @@ public class DslDeferredFunctionCall extends BrooklynDslDeferredSupplier<Object>
                         object + " evaluates to null (wanting to call " + toStringF(fnName, args) + ")");
             }
 
-            return invokeOn(instance);
+            Maybe<Object> tentative = invokeOn(instance);
+            if (tentative.isAbsent()) {
+                return tentative;
+            }
+            return (Maybe) resolve(tentative.get(), immediate, false);
         } else {
             if (immediate) {
                 return Maybe.absent(new ImmediateSupplier.ImmediateValueNotAvailableException("Could not evaluate immediately: " + obj));
@@ -183,13 +188,17 @@ public class DslDeferredFunctionCall extends BrooklynDslDeferredSupplier<Object>
         }
     }
     
-    protected Maybe<?> resolve(Object object, boolean immediate) {
-        return Tasks.resolving(object, Object.class)
-            .context(entity().getExecutionContext())
-            .deep()
-            .immediately(immediate)
-            .iterator()
-            .nextOrLast(DslFunctionSource.class);
+    protected Maybe<?> resolve(Object object, boolean immediate, boolean dslFunctionSource) {
+        ValueResolver<Object> r = Tasks.resolving(object, Object.class)
+                .context(entity().getExecutionContext())
+                .deep()
+                .immediately(immediate);
+        if (dslFunctionSource) {
+            return r.iterator()
+                    .nextOrLast(DslFunctionSource.class);
+        } else {
+            return r.getMaybe();
+        }
     }
 
     private static void checkCallAllowed(Method m) {
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 d027b30..fa96c84 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
@@ -22,6 +22,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
 import java.util.*;
+import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.camp.brooklyn.spi.dsl.DslUtils;
 import static org.apache.brooklyn.camp.brooklyn.spi.dsl.DslUtils.resolved;
 
@@ -45,6 +46,7 @@ import org.apache.brooklyn.core.config.external.ExternalConfigSupplier;
 import org.apache.brooklyn.core.entity.EntityDynamicType;
 import org.apache.brooklyn.core.entity.EntityInternal;
 import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
+import org.apache.brooklyn.core.mgmt.classloading.OsgiBrooklynClassLoadingContext;
 import org.apache.brooklyn.core.mgmt.internal.ExternalConfigSupplierRegistry;
 import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 import org.apache.brooklyn.core.mgmt.persist.DeserializingClassRenamesProvider;
@@ -52,6 +54,7 @@ import org.apache.brooklyn.core.objs.AbstractConfigurationSupportInternal;
 import org.apache.brooklyn.core.objs.BrooklynObjectInternal;
 import org.apache.brooklyn.core.resolve.jackson.BrooklynJacksonSerializationUtils;
 import org.apache.brooklyn.core.sensor.DependentConfiguration;
+import org.apache.brooklyn.core.typereg.RegisteredTypeLoadingContexts;
 import org.apache.brooklyn.util.collections.Jsonya;
 import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.collections.MutableMap;
@@ -68,6 +71,7 @@ import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.javalang.Reflections;
 import org.apache.brooklyn.util.javalang.coerce.TypeCoercer;
 import org.apache.brooklyn.util.net.Urls;
+import org.apache.brooklyn.util.os.Os;
 import org.apache.brooklyn.util.text.StringEscapes.JavaStringEscapes;
 import org.apache.brooklyn.util.yaml.Yamls;
 import org.apache.commons.beanutils.BeanUtils;
@@ -328,7 +332,7 @@ public class BrooklynDslCommon {
         try {
             type = new ClassLoaderUtils(BrooklynDslCommon.class).loadClass(mappedTypeName);
         } catch (ClassNotFoundException e) {
-            LOG.debug("Cannot load class " + typeName + " for DLS object; assuming it is in OSGi bundle; will defer its loading");
+            LOG.debug("Cannot load class " + typeName + " for DSL 'object'; assuming it is in OSGi bundle; will defer its loading");
             return new DslObject(mappedTypeName, constructorArgs, objectFields, brooklynConfig);
         }
 
@@ -667,6 +671,9 @@ public class BrooklynDslCommon {
 
         @Override @JsonIgnore
         public Maybe<Object> getImmediately() {
+            // TODO reconcile with "bean-with-type" usage and constructors;
+            // for now, if it's a registered type we use that to get the java instance but we ignore fields on it
+
             final Class<?> clazz = getOrLoadType();
             final ExecutionContext executionContext = entity().getExecutionContext();
 
@@ -720,6 +727,8 @@ public class BrooklynDslCommon {
                     .body(new Callable<Object>() {
                         @Override
                         public Object call() throws Exception {
+                            // TODO de-dupe with getImmediately
+
                             Map<String, Object> resolvedFields = MutableMap.copyOf(Maps.transformValues(fields, resolver));
                             Map<String, Object> resolvedConfig = MutableMap.copyOf(Maps.transformValues(config, resolver));
                             List<Object> resolvedConstructorArgs = MutableList.copyOf(Lists.transform(constructorArgs, resolver));
@@ -737,12 +746,23 @@ public class BrooklynDslCommon {
         @JsonIgnore
         protected Class<?> getOrLoadType() {
             Class<?> type = this.type;
+
             if (type == null) {
                 EntityInternal entity = entity();
                 try {
                     if (entity==null) {
                         throw new IllegalStateException("Cannot invoke without a Task running the context of an entity");
                     }
+                    RegisteredType rt = managementContext().getTypeRegistry().get(typeName, RegisteredTypeLoadingContexts.loader(new OsgiBrooklynClassLoadingContext(entity)));
+                    if (rt!=null) {
+                        Object inst = managementContext().getTypeRegistry().create(rt, null, null);
+                        if (inst!=null) {
+                            // we ignore the actually instance for now; see comments at start of this class
+                            return inst.getClass();
+                        }
+                    }
+
+                    // fall back to trying to load as a class
                     type = new ClassLoaderUtils(BrooklynDslCommon.class, entity).loadClass(typeName);
                 } catch (ClassNotFoundException e) {
                     throw Exceptions.propagate(e);
diff --git a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslToStringHelpers.java b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslToStringHelpers.java
index 03b1a33..8bf4460 100644
--- a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslToStringHelpers.java
+++ b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslToStringHelpers.java
@@ -44,7 +44,7 @@ public class DslToStringHelpers {
     }
 
     /** convenience for functions, inserting parentheses and commas */
-    public static String fn(String functionName, Iterable<Object> args) {
+    public static String fn(String functionName, Iterable<?> args) {
         StringBuilder out = new StringBuilder();
         out.append(BrooklynDslCommon.PREFIX);
         out.append(functionName);
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 91dc577..db80482 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
@@ -287,8 +287,14 @@ public class ClassLoaderUtils {
                 CatalogItem<?, ?> item = CatalogUtils.getCatalogItemOptionalVersion(mgmt, catalogItemId);
                 if (item != null) {
                     BrooklynClassLoadingContextSequential loader = new BrooklynClassLoadingContextSequential(mgmt);
-                    loader.add(newClassLoadingContextForCatalogItems(mgmt, item.getCatalogItemId(),
-                        item.getCatalogItemIdSearchPath()));
+                    try {
+                        loader.add(newClassLoadingContextForCatalogItems(mgmt, item.getCatalogItemId(),
+                                item.getCatalogItemIdSearchPath()));
+                    } catch (UnsupportedOperationException e) {
+                        // normal if item comes from the type; could suppress load attempt
+                    } catch (Exception e) {
+                        log.warn("Error accessing looking up "+className+" relative to "+catalogItemId+" (ignoring, will try loading other ways but may fail): "+e, e);
+                    }
                     cls = dispatcher.tryLoadFrom(loader, className);
                     if (cls.isPresent()) {
                         return cls;