You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by sv...@apache.org on 2016/09/26 16:11:57 UTC
[2/3] brooklyn-server git commit: tweaks to background TypeRegistry
and *ClassLoadingContext
tweaks to background TypeRegistry and *ClassLoadingContext
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/4e761709
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/4e761709
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/4e761709
Branch: refs/heads/master
Commit: 4e76170993ff2330ac8a04e98b97b64ec307f295
Parents: f97b9eb
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Sep 5 18:52:32 2016 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Wed Sep 7 15:58:59 2016 +0100
----------------------------------------------------------------------
.../BrooklynClassLoadingContext.java | 25 ++--------
.../api/typereg/BrooklynTypeRegistry.java | 13 +++++-
.../core/typereg/BasicBrooklynTypeRegistry.java | 33 ++++++++++++--
.../typereg/BrooklynTypePlanTransformer.java | 11 +++--
.../brooklyn/core/typereg/RegisteredTypes.java | 17 ++++---
.../java/org/apache/brooklyn/test/Asserts.java | 27 ++++++++++-
.../brooklyn/util/exceptions/Exceptions.java | 10 ++++
.../util/javalang/ClassLoadingContext.java | 48 ++++++++++++++++++++
8 files changed, 146 insertions(+), 38 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/4e761709/api/src/main/java/org/apache/brooklyn/api/mgmt/classloading/BrooklynClassLoadingContext.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/classloading/BrooklynClassLoadingContext.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/classloading/BrooklynClassLoadingContext.java
index f95c0d8..2441af5 100644
--- a/api/src/main/java/org/apache/brooklyn/api/mgmt/classloading/BrooklynClassLoadingContext.java
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/classloading/BrooklynClassLoadingContext.java
@@ -18,33 +18,14 @@
*/
package org.apache.brooklyn.api.mgmt.classloading;
-import java.net.URL;
-
-import javax.annotation.Nullable;
-
import org.apache.brooklyn.api.mgmt.ManagementContext;
-import org.apache.brooklyn.util.guava.Maybe;
+import org.apache.brooklyn.util.javalang.ClassLoadingContext;
/**
- * Provides functionality for loading classes based on the current context
- * (e.g. the bundles of a registered type from which an entity is created)
+ * As {@link ClassLoadingContext} but the {@link ManagementContext} is also available.
*/
-public interface BrooklynClassLoadingContext {
+public interface BrooklynClassLoadingContext extends ClassLoadingContext {
public ManagementContext getManagementContext();
- public Class<?> loadClass(String className);
- public <T> Class<? extends T> loadClass(String className, @Nullable Class<T> supertype);
-
- public Maybe<Class<?>> tryLoadClass(String className);
- public <T> Maybe<Class<? extends T>> tryLoadClass(String className, @Nullable Class<T> supertype);
-
- /** As {@link ClassLoader#getResource(String)} */
- public URL getResource(String name);
-
- /**
- * As {@link ClassLoader#getResources(String)} but returning an {@link Iterable} rather than
- * an {@link java.util.Enumeration}.
- */
- public Iterable<URL> getResources(String name);
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/4e761709/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java b/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java
index 17a7fb3..ae26ac1 100644
--- a/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java
+++ b/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java
@@ -63,16 +63,27 @@ public interface BrooklynTypeRegistry {
* including a detailed message if absent */
public Maybe<RegisteredType> getMaybe(String symbolicNameOrAliasWithOptionalVersion, RegisteredTypeLoadingContext context);
+ /** Creates an instance of the given type, either a bean or spec as appropriate. */
+ @Beta
+ <T> T create(RegisteredType type, @Nullable RegisteredTypeLoadingContext optionalContext, @Nullable Class<T> optionalResultSuperType);
+ /** Creates a bean or spec (depending on the super-type hint) for the given plan data (e.g. a yaml string) for the given format (optional, will auto-detect if null) */
+ @Beta
+ <T> T createFromPlan(Class<T> requiredSuperTypeHint, @Nullable String planFormat, Object planData, @Nullable RegisteredTypeLoadingContext optionalConstraint);
+
+ /** Typesafe {@link AbstractBrooklynObjectSpec} variant of {@link #create(RegisteredType, RegisteredTypeLoadingContext, Class)} */
// NB the seemingly more correct generics <T,SpecT extends AbstractBrooklynObjectSpec<T,SpecT>>
// cause compile errors, not in Eclipse, but in maven (?)
// TODO do these belong here, or in a separate master TypePlanTransformer ? see also BrooklynTypePlanTransformer
@Beta
<SpecT extends AbstractBrooklynObjectSpec<?,?>> SpecT createSpec(RegisteredType type, @Nullable RegisteredTypeLoadingContext optionalContext, @Nullable Class<SpecT> optionalSpecSuperType);
+ /** Typesafe {@link AbstractBrooklynObjectSpec} variant of {@link #createFromPlan(Class, String, Object, RegisteredTypeLoadingContext)} */
@Beta
<SpecT extends AbstractBrooklynObjectSpec<?,?>> SpecT createSpecFromPlan(@Nullable String planFormat, Object planData, @Nullable RegisteredTypeLoadingContext optionalContext, @Nullable Class<SpecT> optionalSpecSuperType);
+ /** Typesafe non-spec variant of {@link #create(RegisteredType, RegisteredTypeLoadingContext, Class)} */
@Beta
<T> T createBean(RegisteredType type, @Nullable RegisteredTypeLoadingContext optionalContext, @Nullable Class<T> optionalResultSuperType);
@Beta
+ /** Typesafe non-spec variant of {@link #createFromPlan(Class, String, Object, RegisteredTypeLoadingContext)} */
<T> T createBeanFromPlan(String planFormat, Object planData, @Nullable RegisteredTypeLoadingContext optionalConstraint, @Nullable Class<T> optionalBeanSuperType);
-
+
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/4e761709/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
----------------------------------------------------------------------
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 e28c7b2..c112779 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
@@ -247,8 +247,8 @@ public class BasicBrooklynTypeRegistry implements BrooklynTypeRegistry {
@Override
public <T> T createBean(RegisteredType type, RegisteredTypeLoadingContext constraint, Class<T> optionalResultSuperType) {
Preconditions.checkNotNull(type, "type");
- if (type.getKind()!=RegisteredTypeKind.SPEC) {
- throw new IllegalStateException("Cannot create spec from type "+type+" (kind "+type.getKind()+")");
+ if (type.getKind()!=RegisteredTypeKind.BEAN) {
+ throw new IllegalStateException("Cannot create bean from type "+type+" (kind "+type.getKind()+")");
}
if (constraint!=null) {
if (constraint.getExpectedKind()!=null && constraint.getExpectedKind()!=RegisteredTypeKind.SPEC) {
@@ -268,9 +268,34 @@ public class BasicBrooklynTypeRegistry implements BrooklynTypeRegistry {
}
@Override
- public <T> T createBeanFromPlan(String planFormat, Object planData, RegisteredTypeLoadingContext optionalConstraint, Class<T> optionalBeanSuperType) {
+ public <T> T createBeanFromPlan(String planFormat, Object planData, RegisteredTypeLoadingContext optionalConstraint, Class<T> optionalSuperType) {
return createBean(RegisteredTypes.bean(null, null, new BasicTypeImplementationPlan(planFormat, planData), null),
- optionalConstraint, optionalBeanSuperType);
+ optionalConstraint, optionalSuperType);
+ }
+
+ @Override
+ public <T> T create(RegisteredType type, RegisteredTypeLoadingContext constraint, Class<T> optionalResultSuperType) {
+ Preconditions.checkNotNull(type, "type");
+ if (type.getKind()==RegisteredTypeKind.BEAN) {
+ return createBean(type, constraint, optionalResultSuperType);
+ }
+ if (type.getKind()==RegisteredTypeKind.SPEC) {
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ T result = (T) createSpec(type, constraint, (Class)optionalResultSuperType);
+ return result;
+ }
+ throw new IllegalArgumentException("Kind-agnostic create method can only be used when the registered type declares its kind, which "+type+" does not");
+ }
+
+ @Override
+ public <T> T createFromPlan(Class<T> requiredSuperTypeHint, String planFormat, Object planData, RegisteredTypeLoadingContext optionalConstraint) {
+ if (AbstractBrooklynObjectSpec.class.isAssignableFrom(requiredSuperTypeHint)) {
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ T result = (T) createSpecFromPlan(planFormat, planData, optionalConstraint, (Class)requiredSuperTypeHint);
+ return result;
+ }
+
+ return createBeanFromPlan(planFormat, planData, optionalConstraint, requiredSuperTypeHint);
}
@Beta // API is stabilising
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/4e761709/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynTypePlanTransformer.java
----------------------------------------------------------------------
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 5609cf9..1001268 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
@@ -55,7 +55,10 @@ public interface BrooklynTypePlanTransformer extends ManagementContextInjectable
/**
* Determines how appropriate is this transformer for the {@link RegisteredType#getPlan()} of the type.
* The framework guarantees arguments are nonnull, and that the {@link RegisteredType#getPlan()} is also not-null.
- * However the format in that plan may be null.
+ * However many fields on the {@link RegisteredType} may be null,
+ * including {@link RegisteredType#getId()} for an ad hoc creation
+ * (eg if invoked from {@link BrooklynTypeRegistry#createBeanFromPlan(String, Object, RegisteredTypeLoadingContext, Class)})
+ *
* @return A co-ordinated score / confidence value in the range 0 to 1.
* 0 means not compatible,
* 1 means this is clearly the intended transformer and no others need be tried
@@ -69,13 +72,13 @@ public interface BrooklynTypePlanTransformer extends ManagementContextInjectable
/** Creates a new instance of the indicated type, or throws if not supported;
* this method is used by the {@link BrooklynTypeRegistry} when it creates instances,
* so implementations must respect the {@link RegisteredTypeKind} semantics and the {@link RegisteredTypeLoadingContext}
- * if they return an instance.
+ * (or return null / throw).
* <p>
* The framework guarantees this will only be invoked when {@link #scoreForType(RegisteredType, RegisteredTypeLoadingContext)}
- * has returned a positive value.
+ * has returned a positive value, and the same constraints on the inputs as for that method apply.
* <p>
* Implementations should either return null or throw {@link UnsupportedTypePlanException}
- * if the {@link RegisteredType#getPlan()} is not supported. */
+ * if they cannot instantiate the given {@link RegisteredType#getPlan()}. */
@Nullable Object create(@Nonnull RegisteredType type, @Nonnull RegisteredTypeLoadingContext context);
// TODO sketch methods for loading *catalog* definitions. note some potential overlap
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/4e761709/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
index 0c7b09b..72e05ea 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
@@ -118,20 +118,25 @@ public class RegisteredTypes {
return addSuperType(new BasicRegisteredType(RegisteredTypeKind.SPEC, symbolicName, version, plan), superType);
}
- /** returns the {@link Class} object corresponding to the given java type name,
- * using the cache on the type and the loader defined on the type
- * @param mgmt */
+ /** returns the {@link Class} object corresponding to the given java type name and registered type,
+ * using the cache on the type in the first instance, falling back to the loader defined the type and context. */
@Beta
// TODO should this be on the AbstractTypePlanTransformer ?
public static Class<?> loadActualJavaType(String javaTypeName, ManagementContext mgmt, RegisteredType type, RegisteredTypeLoadingContext context) {
- Class<?> result = ((BasicRegisteredType)type).getCache().get(ACTUAL_JAVA_TYPE);
+ Class<?> result = peekActualJavaType(type);
if (result!=null) return result;
result = CatalogUtils.newClassLoadingContext(mgmt, type, context==null ? null : context.getLoader()).loadClass( javaTypeName );
- ((BasicRegisteredType)type).getCache().put(ACTUAL_JAVA_TYPE, result);
+ cacheActualJavaType(type, result);
return result;
}
+ @Beta public static Class<?> peekActualJavaType(RegisteredType type) {
+ return ((BasicRegisteredType)type).getCache().get(ACTUAL_JAVA_TYPE);
+ }
+ @Beta public static void cacheActualJavaType(RegisteredType type, Class<?> clazz) {
+ ((BasicRegisteredType)type).getCache().put(ACTUAL_JAVA_TYPE, clazz);
+ }
@Beta
public static RegisteredType addSuperType(RegisteredType type, @Nullable Class<?> superType) {
@@ -372,7 +377,7 @@ public class RegisteredTypes {
}
if (context!=null) {
- if (context.getExpectedKind()!=RegisteredTypeKind.BEAN)
+ if (context.getExpectedKind()!=null && context.getExpectedKind()!=RegisteredTypeKind.BEAN)
return Maybe.absent("Validating a bean when constraint expected "+context.getExpectedKind());
if (context.getExpectedJavaSuperType()!=null && !context.getExpectedJavaSuperType().isInstance(object))
return Maybe.absent(object+" is not of the expected java supertype "+context.getExpectedJavaSuperType());
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/4e761709/utils/common/src/main/java/org/apache/brooklyn/test/Asserts.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/test/Asserts.java b/utils/common/src/main/java/org/apache/brooklyn/test/Asserts.java
index 43dcaa1..23624d9 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/test/Asserts.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/test/Asserts.java
@@ -1113,6 +1113,18 @@ public class Asserts {
}
}
+ public static void assertStringDoesNotContain(String input, String phrase1ToNotContain, String ...optionalOtherPhrasesToNotContain) {
+ if (input==null) fail("Input is null.");
+ if (phrase1ToNotContain!=null) {
+ assertThat(input, Predicates.not(StringPredicates.containsLiteral(phrase1ToNotContain)));
+ }
+ for (String otherPhrase: optionalOtherPhrasesToNotContain) {
+ if (otherPhrase!=null) {
+ assertThat(input, Predicates.not(StringPredicates.containsLiteral(otherPhrase)));
+ }
+ }
+ }
+
public static void assertStringContainsAtLeastOne(String input, String possiblePhrase1ToContain, String ...optionalOtherPossiblePhrasesToContain) {
if (input==null) fail("Input is null.");
List<String> missing = MutableList.of();
@@ -1232,7 +1244,20 @@ public class Asserts {
}
}
- /** Implements the return beahvior for {@link #expectedFailureOfType(Throwable, Class...)} and others. */
+ /** Tests {@link #expectedFailure(Throwable)} and that the <code>toString</code>
+ * satisfies {@link #assertStringContains(String, String, String...)}.
+ * @return as per {@link #expectedFailureOfType(Throwable, Class...)} */
+ public static void expectedFailureDoesNotContain(Throwable e, String phrase1ToNotContain, String ...optionalOtherPhrasesToNotContain) {
+ if (e instanceof ShouldHaveFailedPreviouslyAssertionError) throw (Error)e;
+ try {
+ assertStringDoesNotContain(e.toString(), phrase1ToNotContain, optionalOtherPhrasesToNotContain);
+ } catch (AssertionError ee) {
+ rethrowPreferredException(e, ee);
+ }
+ }
+
+ /** Implements the return behavior for {@link #expectedFailureOfType(Throwable, Class...)} and others,
+ * to log interesting earlier errors but to suppress those which are internal or redundant. */
private static void rethrowPreferredException(Throwable earlierPreferredIfFatalElseLogged, Throwable laterPreferredOtherwise) throws AssertionError {
if (!(earlierPreferredIfFatalElseLogged instanceof AssertionError)) {
Exceptions.propagateIfFatal(earlierPreferredIfFatalElseLogged);
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/4e761709/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/Exceptions.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/Exceptions.java b/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/Exceptions.java
index 2dfd28e..e4c9980 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/Exceptions.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/Exceptions.java
@@ -461,4 +461,14 @@ public class Exceptions {
return appendSeparator(getPrefixText(t), t.getMessage());
}
+ /** Returns true if the root cause is a "boring" CNF, ie a straightforward declaration that the clazz is not found;
+ * this permits callers to include the cause only when it is interesting, ie caused by a dependent class not loadable.
+ */
+ public static boolean isRootBoringClassNotFound(Exception e, String clazz) {
+ Throwable root = Throwables.getRootCause(e);
+ if (!(root instanceof ClassNotFoundException)) return false;
+ if (clazz.equals(root.getMessage())) return true;
+ return false;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/4e761709/utils/common/src/main/java/org/apache/brooklyn/util/javalang/ClassLoadingContext.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/ClassLoadingContext.java b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/ClassLoadingContext.java
new file mode 100644
index 0000000..1b2fbf4
--- /dev/null
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/ClassLoadingContext.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.util.javalang;
+
+import java.net.URL;
+
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.util.guava.Maybe;
+
+/**
+ * Provides functionality for loading classes based on the current context
+ * (e.g. the bundles of a registered type from which an entity is created)
+ */
+public interface ClassLoadingContext {
+
+ public Class<?> loadClass(String className);
+ public <T> Class<? extends T> loadClass(String className, @Nullable Class<T> supertype);
+
+ public Maybe<Class<?>> tryLoadClass(String className);
+ public <T> Maybe<Class<? extends T>> tryLoadClass(String className, @Nullable Class<T> supertype);
+
+ /** As {@link ClassLoader#getResource(String)} */
+ public URL getResource(String name);
+
+ /**
+ * As {@link ClassLoader#getResources(String)} but returning an {@link Iterable} rather than
+ * an {@link java.util.Enumeration}.
+ */
+ public Iterable<URL> getResources(String name);
+
+}