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 2014/09/10 00:49:20 UTC
[17/19] git commit: support an EntityInitializer which makes an
effector which adds a child from a blueprint,
with config keys from parameters. refactor addition of children from
EntityResource and BrooklynAssemblyTemplateInstantiator to share code, temp
support an EntityInitializer which makes an effector which adds a child from a blueprint, with config keys from parameters.
refactor addition of children from EntityResource and BrooklynAssemblyTemplateInstantiator to share code, temporarily in AddChildrenEffector.
also supply a default `restart` method for apps and improve the exceptions thrown when instantiation fails.
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/f7ce1a25
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/f7ce1a25
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/f7ce1a25
Branch: refs/heads/master
Commit: f7ce1a25f1cd8cc07716ef6fe7c6d9e320a7ed8a
Parents: f19ef81
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Sep 9 11:10:46 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Sep 9 12:24:12 2014 +0100
----------------------------------------------------------------------
.../entity/basic/AbstractApplication.java | 3 +-
.../entity/effector/AddChildrenEffector.java | 310 +++++++++++++++++++
.../brooklyn/entity/effector/AddEffector.java | 32 +-
.../brooklyn/entity/trait/StartableMethods.java | 2 +-
.../java/brooklyn/util/config/ConfigBag.java | 4 +-
.../brooklyn/camp/lite/CampYamlLiteTest.java | 47 ++-
.../camp/lite/TestAppAssemblyInstantiator.java | 41 ++-
.../entity/software/ssh/SshCommandEffector.java | 6 +-
.../BrooklynAssemblyTemplateInstantiator.java | 51 +--
.../brooklyn/rest/resources/EntityResource.java | 141 +--------
.../brooklyn/util/javalang/Reflections.java | 45 +--
11 files changed, 459 insertions(+), 223 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f7ce1a25/core/src/main/java/brooklyn/entity/basic/AbstractApplication.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/AbstractApplication.java b/core/src/main/java/brooklyn/entity/basic/AbstractApplication.java
index 4cab77c..f4044f7 100644
--- a/core/src/main/java/brooklyn/entity/basic/AbstractApplication.java
+++ b/core/src/main/java/brooklyn/entity/basic/AbstractApplication.java
@@ -228,9 +228,10 @@ public abstract class AbstractApplication extends AbstractEntity implements Star
StartableMethods.stop(this);
}
+ /** default impl invokes restart on all children simultaneously */
@Override
public void restart() {
- throw new UnsupportedOperationException();
+ StartableMethods.restart(this);
}
@Override
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f7ce1a25/core/src/main/java/brooklyn/entity/effector/AddChildrenEffector.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/effector/AddChildrenEffector.java b/core/src/main/java/brooklyn/entity/effector/AddChildrenEffector.java
new file mode 100644
index 0000000..f216a53
--- /dev/null
+++ b/core/src/main/java/brooklyn/entity/effector/AddChildrenEffector.java
@@ -0,0 +1,310 @@
+/*
+ * 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 brooklyn.entity.effector;
+
+import io.brooklyn.camp.CampPlatform;
+import io.brooklyn.camp.spi.AssemblyTemplate;
+import io.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
+
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator;
+import brooklyn.config.BrooklynServerConfig;
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.Effector;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.BrooklynTaskTags;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntityFunctions;
+import brooklyn.entity.basic.EntityLocal;
+import brooklyn.entity.effector.Effectors.EffectorBuilder;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.entity.trait.Startable;
+import brooklyn.management.ManagementContext;
+import brooklyn.management.Task;
+import brooklyn.management.classloading.BrooklynClassLoadingContext;
+import brooklyn.management.classloading.JavaBrooklynClassLoadingContext;
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.config.ConfigBag;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.task.TaskBuilder;
+import brooklyn.util.task.Tasks;
+import brooklyn.util.text.Strings;
+import brooklyn.util.time.Duration;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import com.google.gson.Gson;
+
+/** Entity initializer which defines an effector which adds a child blueprint to an entity.
+ * <p>
+ * One of the config keys {@link #BLUEPRINT_YAML} (containing a YAML blueprint (map or string))
+ * or {@link #BLUEPRINT_TYPE} (containing a string referring to a catalog type) should be supplied, but not both.
+ * Parameters defined here are supplied as config during the entity creation.
+ *
+ * @since 0.7.0 */
+@Beta
+public class AddChildrenEffector extends AddEffector {
+
+ private static final Logger log = LoggerFactory.getLogger(AddChildrenEffector.class);
+
+ public static final ConfigKey<Object> BLUEPRINT_YAML = ConfigKeys.newConfigKey(Object.class, "blueprint_yaml");
+ public static final ConfigKey<String> BLUEPRINT_TYPE = ConfigKeys.newStringConfigKey("blueprint_type");
+ public static final ConfigKey<Boolean> AUTO_START = ConfigKeys.newBooleanConfigKey("auto_start");
+
+ public AddChildrenEffector(ConfigBag params) {
+ super(newEffectorBuilder(params).build());
+ }
+
+ public AddChildrenEffector(Map<String,String> params) {
+ this(ConfigBag.newInstance(params));
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public static EffectorBuilder<List<String>> newEffectorBuilder(ConfigBag params) {
+ EffectorBuilder<List<String>> eff = (EffectorBuilder) AddEffector.newEffectorBuilder(List.class, params);
+ eff.impl(new Body(eff.buildAbstract(), params));
+ return eff;
+ }
+
+ protected static class Body extends EffectorBody<List<String>> {
+
+ private final Effector<?> effector;
+ private final String blueprintBase;
+ private final Boolean autostart;
+
+ public Body(Effector<?> eff, ConfigBag params) {
+ this.effector = eff;
+ String newBlueprint = null;
+ Object yaml = params.get(BLUEPRINT_YAML);
+ if (yaml instanceof Map) {
+ newBlueprint = new Gson().toJson(yaml);
+ } else if (yaml instanceof String) {
+ newBlueprint = (String) yaml;
+ } else if (yaml!=null) {
+ throw new IllegalArgumentException(this+" requires map or string in "+BLUEPRINT_YAML+"; not "+yaml.getClass()+" ("+yaml+")");
+ }
+ String blueprintType = params.get(BLUEPRINT_TYPE);
+ if (blueprintType!=null) {
+ if (newBlueprint!=null) {
+ throw new IllegalArgumentException(this+" cannot take both "+BLUEPRINT_TYPE+" and "+BLUEPRINT_YAML);
+ }
+ newBlueprint = "services: [ { type: "+blueprintType+" } ]";
+ }
+ if (newBlueprint==null) {
+ throw new IllegalArgumentException(this+" requires either "+BLUEPRINT_TYPE+" or "+BLUEPRINT_YAML);
+ }
+ blueprintBase = newBlueprint;
+ autostart = params.get(AUTO_START);
+ }
+
+ @Override
+ public List<String> call(ConfigBag params) {
+ params = getMergedParams(effector, params);
+
+ String blueprint = blueprintBase;
+ if (!params.isEmpty()) {
+ blueprint = blueprint+"\n"+"brooklyn.config: "+
+ new Gson().toJson(params.getAllConfig());
+ }
+
+ log.debug(this+" adding children to "+entity()+":\n"+blueprint);
+ AddChildrenResult result = addChildren(entity(), blueprint, autostart, Duration.ZERO);
+ log.debug(this+" added children to "+entity()+": "+result.getChildren());
+ return result.getTask().getUnchecked();
+ }
+ }
+
+ public static class AddChildrenResult {
+ public final List<Entity> children;
+ public final Task<List<String>> task;
+ public AddChildrenResult(List<Entity> children, Task<List<String>> task) {
+ super();
+ this.children = children;
+ this.task = task;
+ }
+ public List<Entity> getChildren() {
+ return children;
+ }
+ public Task<List<String>> getTask() {
+ return task;
+ }
+ }
+
+ public static AddChildrenResult addChildren(final EntityLocal parent, String yaml, Boolean start, Duration timeout) {
+ log.debug("Creating child of "+parent+" from yaml:\n{}", yaml);
+
+ ManagementContext mgmt = parent.getApplication().getManagementContext();
+ CampPlatform camp = BrooklynServerConfig.getCampPlatform(mgmt).get();
+
+ Reader input = new StringReader(yaml);
+ AssemblyTemplate at = camp.pdp().registerDeploymentPlan(input);
+
+ AssemblyTemplateInstantiator instantiator;
+ try {
+ instantiator = at.getInstantiator().newInstance();
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
+ if (instantiator instanceof AssemblyTemplateSpecInstantiator) {
+ BrooklynClassLoadingContext loader = JavaBrooklynClassLoadingContext.newDefault(mgmt);
+ EntitySpec<?> specA = ((AssemblyTemplateSpecInstantiator) instantiator).createSpec(at, camp, loader, false);
+
+ boolean promoted;
+
+ // see whether we can promote children
+ List<EntitySpec<?>> specs = MutableList.of();
+ if (hasNoNameOrCustomKeysOrRoot(at, specA)) {
+ // we can promote
+ promoted = true;
+ for (EntitySpec<?> specC: specA.getChildren()) {
+ collapseSpec(specA, specC);
+ specs.add(specC);
+ }
+ } else {
+ // if not promoting, set a nice name if needed
+ if (Strings.isEmpty(specA.getDisplayName())) {
+ int size = specA.getChildren().size();
+ String childrenCountString = size+" "+(size!=1 ? "children" : "child");
+ specA.displayName("Dynamically added "+childrenCountString);
+ }
+ promoted = false;
+ specs.add(specA);
+ }
+
+ final List<Entity> children = MutableList.of();
+ for (EntitySpec<?> spec: specs) {
+ Entity child = (Entity)parent.addChild(spec);
+ Entities.manage(child);
+ children.add(child);
+ }
+
+ String childrenCountString;
+ if (promoted) {
+ int size = children.size();
+ childrenCountString = size+" "+(size!=1 ? "children" : "child");
+ } else {
+ int size = specA.getChildren().size();
+ childrenCountString = "entity with "+size+" "+(size!=1 ? "children" : "child");
+ }
+
+ TaskBuilder<List<String>> taskM = Tasks.<List<String>>builder().name("add children")
+ .dynamic(true)
+ .tag(BrooklynTaskTags.NON_TRANSIENT_TASK_TAG)
+ .body(new Callable<List<String>>() {
+ @Override public List<String> call() throws Exception {
+ return ImmutableList.copyOf(Iterables.transform(children, EntityFunctions.id()));
+ }})
+ .description("Add" + (start==null ? " and potentially start" : start ? " and start" : "") + " "+childrenCountString);
+ TaskBuilder<?> taskS = Tasks.builder().parallel(true).name("add (parallel)")
+ .description(
+ (start==null ? "Add or start" : start ? "Start" : "Add")+" each new entity");
+
+ // should we autostart?
+ for (Entity child: children) {
+ if (Boolean.TRUE.equals(start) || (start==null && child instanceof Startable)) {
+ taskS.add(Effectors.invocation(child, Startable.START, ImmutableMap.of("locations", ImmutableList.of())));
+ } else {
+ taskS.add(Tasks.builder().name("create").description("Created and added as child of "+parent)
+ .body(new Runnable() { public void run() {} })
+ .tag(BrooklynTaskTags.tagForTargetEntity(child))
+ .build());
+ }
+ }
+ taskM.add(taskS.build());
+ Task<List<String>> task = Entities.submit(parent, taskM.build());
+
+ // wait a few ms in case start is trivially simple, save the client a call to get the task result
+ task.blockUntilEnded(timeout);
+
+ return new AddChildrenResult(children, task);
+ } else {
+ throw new IllegalStateException("Spec could not be parsed to supply a compatible instantiator");
+ }
+ }
+
+ /** worker method to combine specs */
+ @Beta //where should this live long-term?
+ public static void collapseSpec(EntitySpec<?> sourceToBeCollapsed, EntitySpec<?> targetToBeExpanded) {
+ if (Strings.isEmpty(targetToBeExpanded.getDisplayName()))
+ targetToBeExpanded.displayName(sourceToBeCollapsed.getDisplayName());
+ if (!sourceToBeCollapsed.getLocations().isEmpty())
+ targetToBeExpanded.locations(sourceToBeCollapsed.getLocations());
+
+ // NB: this clobbers child config; might prefer to deeply merge maps etc
+ // (but this should not be surprising, as unwrapping is often parameterising the nested blueprint, so outer config should dominate)
+ targetToBeExpanded.configure(sourceToBeCollapsed.getConfig());
+ targetToBeExpanded.configure(sourceToBeCollapsed.getFlags());
+
+ // TODO copying tags to all entities is not ideal;
+ // in particular the BrooklynTags.YAML_SPEC tag will show all entities if the root has multiple
+ targetToBeExpanded.tags(sourceToBeCollapsed.getTags());
+ }
+
+ /** worker method to help determine whether child/children can be promoted */
+ @Beta //where should this live long-term?
+ public static boolean hasNoNameOrCustomKeysOrRoot(AssemblyTemplate template, EntitySpec<?> spec) {
+ if (!Strings.isEmpty(template.getName())) {
+ if (spec.getChildren().size()==1) {
+ String childName = Iterables.getOnlyElement(spec.getChildren()).getDisplayName();
+ if (Strings.isEmpty(childName) || childName.equals(template.getName())) {
+ // if child has no name, or it's the same, could still promote
+ } else {
+ return false;
+ }
+ } else {
+ // if name set at root and promoting children would be ambiguous, do not promote
+ return false;
+ }
+ } else if (spec.getChildren().size()>1) {
+ // don't allow multiple children if a name is specified as a root
+ return false;
+ }
+
+ Set<String> rootAttrs = template.getCustomAttributes().keySet();
+ for (String rootAttr: rootAttrs) {
+ if (rootAttr.equals("brooklyn.catalog") || rootAttr.equals("brooklyn.config")) {
+ // these do not block promotion
+ continue;
+ }
+ if (rootAttr.startsWith("brooklyn.")) {
+ // any others in 'brooklyn' namespace will block promotion
+ return false;
+ }
+ // location is allowed in both, and is copied on promotion
+ // (name also copied)
+ // others are root currently are ignored on promotion; they are usually metadata
+ // TODO might be nice to know what we are excluding
+ }
+
+ return true;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f7ce1a25/core/src/main/java/brooklyn/entity/effector/AddEffector.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/effector/AddEffector.java b/core/src/main/java/brooklyn/entity/effector/AddEffector.java
index 7bea8f8..12ec10c 100644
--- a/core/src/main/java/brooklyn/entity/effector/AddEffector.java
+++ b/core/src/main/java/brooklyn/entity/effector/AddEffector.java
@@ -23,6 +23,7 @@ import java.util.Map;
import brooklyn.config.ConfigKey;
import brooklyn.entity.Effector;
+import brooklyn.entity.ParameterType;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.basic.EntityLocal;
@@ -35,7 +36,24 @@ import brooklyn.util.text.Strings;
import com.google.common.annotations.Beta;
import com.google.common.base.Preconditions;
-/** Entity initializer which adds an effector to an entity
+/**
+ * Entity initializer which adds an effector to an entity.
+ * <p>
+ * This instance provides a {@link #newEffectorBuilder(Class, ConfigBag)}
+ * which returns an abstract (body-less) effector defining:
+ * <li> the name from {@link #EFFECTOR_NAME};
+ * <li> the description from {@link #EFFECTOR_DESCRIPTION}
+ * <li> the parameters from {@link #EFFECTOR_PARAMETER_DEFS}
+ * <p>
+ * Callers should pass the effector to instantiate into the constructor.
+ * Often subclasses will supply a constructor which takes a ConfigBag of parameters,
+ * and a custom {@link #newEffectorBuilder(Class, ConfigBag)} which adds the body
+ * before passing to this class.
+ * <p>
+ * Note that the parameters passed to the call method in the body of the effector implementation
+ * are only those supplied by a user at runtime; in order to merge with default
+ * values, use {@link #getMergedParams(Effector, ConfigBag)}.
+ *
* @since 0.7.0 */
@Beta
public class AddEffector implements EntityInitializer {
@@ -83,4 +101,16 @@ public class AddEffector implements EntityInitializer {
return eff;
}
+ /** returns a ConfigBag containing the merger of the supplied parameters with default values on the effector-defined parameters */
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ public static ConfigBag getMergedParams(Effector<?> eff, ConfigBag params) {
+ ConfigBag result = ConfigBag.newInstanceCopying(params);
+ for (ParameterType<?> param: eff.getParameters()) {
+ ConfigKey key = Effectors.asConfigKey(param);
+ if (!result.containsKey(key))
+ result.configure(key, params.get(key));
+ }
+ return result;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f7ce1a25/core/src/main/java/brooklyn/entity/trait/StartableMethods.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/trait/StartableMethods.java b/core/src/main/java/brooklyn/entity/trait/StartableMethods.java
index e8f1039..b5be1ae 100644
--- a/core/src/main/java/brooklyn/entity/trait/StartableMethods.java
+++ b/core/src/main/java/brooklyn/entity/trait/StartableMethods.java
@@ -60,7 +60,7 @@ public class StartableMethods {
if (log.isDebugEnabled()) log.debug("Stopped entity "+e);
}
- /** Common implementation for restart in parent nodes; just invokes stop on all children of the entity */
+ /** Common implementation for restart in parent nodes; just invokes restart on all children of the entity */
public static void restart(EntityLocal e) {
log.debug("Restarting entity "+e);
DynamicTasks.queueIfPossible(restartingChildren(e)).orSubmitAsync(e).getTask().getUnchecked();
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f7ce1a25/core/src/main/java/brooklyn/util/config/ConfigBag.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/config/ConfigBag.java b/core/src/main/java/brooklyn/util/config/ConfigBag.java
index d35fb78..72bd28c 100644
--- a/core/src/main/java/brooklyn/util/config/ConfigBag.java
+++ b/core/src/main/java/brooklyn/util/config/ConfigBag.java
@@ -396,11 +396,11 @@ public class ConfigBag {
}
}
- protected <T> T get(ConfigKey<T> key, boolean remove) {
+ protected <T> T get(ConfigKey<T> key, boolean markUsed) {
// TODO for now, no evaluation -- closure content / smart (self-extracting) keys are NOT supported
// (need a clean way to inject that behaviour, as well as desired TypeCoercions)
if (config.containsKey(key.getName()))
- return coerceFirstNonNullKeyValue(key, getStringKey(key.getName(), remove));
+ return coerceFirstNonNullKeyValue(key, getStringKey(key.getName(), markUsed));
return coerceFirstNonNullKeyValue(key);
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f7ce1a25/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java b/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
index 8eedabf..d8b2698 100644
--- a/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
+++ b/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
@@ -43,7 +43,13 @@ import brooklyn.catalog.CatalogPredicates;
import brooklyn.catalog.internal.BasicBrooklynCatalog;
import brooklyn.catalog.internal.CatalogDto;
import brooklyn.entity.Entity;
+import brooklyn.entity.basic.ApplicationBuilder;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.effector.AddChildrenEffector;
+import brooklyn.entity.effector.Effectors;
import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.management.Task;
import brooklyn.management.internal.LocalManagementContext;
import brooklyn.management.osgi.OsgiStandaloneTest;
import brooklyn.test.entity.LocalManagementContextForTests;
@@ -51,6 +57,8 @@ import brooklyn.test.entity.TestApplication;
import brooklyn.test.entity.TestEntity;
import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableList;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.config.ConfigBag;
import brooklyn.util.stream.Streams;
import com.google.common.base.Predicates;
@@ -89,7 +97,7 @@ public class CampYamlLiteTest {
Assert.assertEquals(at.getName(), "sample");
Assert.assertEquals(at.getPlatformComponentTemplates().links().size(), 1);
- // now use brooklyn to instantiate
+ // now use brooklyn to instantiate - note it won't be faithful, but it will set some config keys
Assembly assembly = at.getInstantiator().newInstance().instantiate(at, platform);
TestApplication app = ((TestAppAssembly)assembly).getBrooklynApp();
@@ -106,6 +114,43 @@ public class CampYamlLiteTest {
Assert.assertEquals( map.get("desc"), MockWebPlatform.APPSERVER.getDescription() );
}
+ /** based on {@link PdpYamlTest} for parsing,
+ * then creating a {@link TestAppAssembly} */
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ @Test
+ public void testAddChildrenEffector() throws Exception {
+ // NB: as above, with this mock instantiator, not everything will be set nicely
+ MockWebPlatform.populate(platform, TestAppAssemblyInstantiator.class);
+
+ String childYaml = Streams.readFullyString(getClass().getResourceAsStream("test-app-service-blueprint.yaml"));
+ AddChildrenEffector newEff = new AddChildrenEffector(ConfigBag.newInstance()
+ .configure(AddChildrenEffector.EFFECTOR_NAME, "add_tomcat")
+ .configure(AddChildrenEffector.BLUEPRINT_YAML, childYaml)
+ .configure(AddChildrenEffector.EFFECTOR_PARAMETER_DEFS, MutableMap.of("war", (Object)MutableMap.of(
+ "defaultValue", "foo.war"))) ) ;
+ TestApplication app = ApplicationBuilder.newManagedApp(EntitySpec.create(TestApplication.class).addInitializer(newEff), mgmt);
+
+ // test adding, with a parameter
+ Task<List> task = app.invoke(Effectors.effector(List.class, "add_tomcat").buildAbstract(), MutableMap.of("war", "foo.bar"));
+ List result = task.get();
+
+ Entity newChild = Iterables.getOnlyElement(app.getChildren());
+ Assert.assertEquals(newChild.getConfig(ConfigKeys.newStringConfigKey("war")), "foo.bar");
+
+ Assert.assertEquals(Iterables.getOnlyElement(result), newChild.getId());
+ Entities.unmanage(newChild);
+
+ // and test default value
+ task = app.invoke(Effectors.effector(List.class, "add_tomcat").buildAbstract(), MutableMap.<String,Object>of());
+ result = task.get();
+
+ newChild = Iterables.getOnlyElement(app.getChildren());
+ Assert.assertEquals(newChild.getConfig(ConfigKeys.newStringConfigKey("war")), "foo.war");
+
+ Assert.assertEquals(Iterables.getOnlyElement(result), newChild.getId());
+ Entities.unmanage(newChild);
+ }
+
@Test
public void testYamlServiceForCatalog() {
MockWebPlatform.populate(platform, TestAppAssemblyInstantiator.class);
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f7ce1a25/core/src/test/java/brooklyn/camp/lite/TestAppAssemblyInstantiator.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/camp/lite/TestAppAssemblyInstantiator.java b/core/src/test/java/brooklyn/camp/lite/TestAppAssemblyInstantiator.java
index 6e242c8..e63bd1f 100644
--- a/core/src/test/java/brooklyn/camp/lite/TestAppAssemblyInstantiator.java
+++ b/core/src/test/java/brooklyn/camp/lite/TestAppAssemblyInstantiator.java
@@ -19,20 +19,24 @@
package brooklyn.camp.lite;
import io.brooklyn.camp.CampPlatform;
+import io.brooklyn.camp.spi.AbstractResource;
import io.brooklyn.camp.spi.Assembly;
import io.brooklyn.camp.spi.AssemblyTemplate;
import io.brooklyn.camp.spi.PlatformComponentTemplate;
import io.brooklyn.camp.spi.collection.ResolvableLink;
import io.brooklyn.camp.spi.instantiate.BasicAssemblyTemplateInstantiator;
+
+import java.util.Map;
+
import brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator;
import brooklyn.camp.brooklyn.api.HasBrooklynManagementContext;
-import brooklyn.entity.basic.ApplicationBuilder;
import brooklyn.entity.proxying.EntitySpec;
import brooklyn.management.ManagementContext;
import brooklyn.management.classloading.BrooklynClassLoadingContext;
import brooklyn.test.entity.TestApplication;
import brooklyn.test.entity.TestEntity;
import brooklyn.util.collections.MutableMap;
+import brooklyn.util.config.ConfigBag;
/** simple illustrative instantiator which always makes a {@link TestApplication}, populated with {@link TestEntity} children,
* all setting {@link TestEntity#CONF_NAME} for the name in the plan and in the service specs
@@ -47,21 +51,8 @@ public class TestAppAssemblyInstantiator extends BasicAssemblyTemplateInstantiat
}
ManagementContext mgmt = ((HasBrooklynManagementContext)platform).getBrooklynManagementContext();
- // TODO when createSpec is working:
-// TestApplication app = (TestApplication) mgmt.getEntityManager().createEntity( createSpec(template, platform) );
-// mgmt.getEntityManager().manage(app);
-
- // workaround until above is reacy
- TestApplication app = ApplicationBuilder.newManagedApp(EntitySpec.create(TestApplication.class)
- .configure(TestEntity.CONF_NAME, template.getName())
- .configure(TestEntity.CONF_MAP_THING, MutableMap.of("type", template.getType(), "desc", template.getDescription()))
- , mgmt);
- for (ResolvableLink<PlatformComponentTemplate> t: template.getPlatformComponentTemplates().links()) {
- app.createAndManageChild(EntitySpec.create(TestEntity.class)
- .configure(TestEntity.CONF_NAME, t.getName())
- .configure(TestEntity.CONF_MAP_THING, MutableMap.of("type", t.resolve().getType(), "desc", t.resolve().getDescription()))
- );
- }
+ TestApplication app = (TestApplication) mgmt.getEntityManager().createEntity( createSpec(template, platform, null, false) );
+ mgmt.getEntityManager().manage(app);
return new TestAppAssembly(app);
}
@@ -71,16 +62,24 @@ public class TestAppAssemblyInstantiator extends BasicAssemblyTemplateInstantiat
EntitySpec<TestApplication> app = EntitySpec.create(TestApplication.class)
.configure(TestEntity.CONF_NAME, template.getName())
.configure(TestEntity.CONF_MAP_THING, MutableMap.of("type", template.getType(), "desc", template.getDescription()));
+ applyBrooklynConfig(template, app);
for (ResolvableLink<PlatformComponentTemplate> t: template.getPlatformComponentTemplates().links()) {
- // TODO use EntitySpec.child(...)
-// app.child(EntitySpec.create(TestEntity.class)
-// .configure(TestEntity.CONF_NAME, t.getName())
-// .configure(TestEntity.CONF_MAP_THING, MutableMap.of("type", t.resolve().getType(), "desc", t.resolve().getDescription()))
-// );
+ EntitySpec<TestEntity> spec = EntitySpec.create(TestEntity.class)
+ .configure(TestEntity.CONF_NAME, t.getName())
+ .configure(TestEntity.CONF_MAP_THING, MutableMap.of("type", t.resolve().getType(), "desc", t.resolve().getDescription()));
+ applyBrooklynConfig(t.resolve(), app);
+ app.child(spec);
}
return app;
}
+ @SuppressWarnings("rawtypes")
+ private void applyBrooklynConfig(AbstractResource template, EntitySpec<TestApplication> app) {
+ Object bc = template.getCustomAttributes().get("brooklyn.config");
+ if (bc instanceof Map)
+ app.configure(ConfigBag.newInstance().putAll((Map)bc).getAllConfigAsConfigKeyMap());
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f7ce1a25/software/base/src/main/java/brooklyn/entity/software/ssh/SshCommandEffector.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/software/ssh/SshCommandEffector.java b/software/base/src/main/java/brooklyn/entity/software/ssh/SshCommandEffector.java
index 3cd537b..4cc1b5c 100644
--- a/software/base/src/main/java/brooklyn/entity/software/ssh/SshCommandEffector.java
+++ b/software/base/src/main/java/brooklyn/entity/software/ssh/SshCommandEffector.java
@@ -57,12 +57,12 @@ public final class SshCommandEffector extends AddEffector {
protected static class Body extends EffectorBody<String> {
- private Effector<?> effector;
- private String command;
+ private final Effector<?> effector;
+ private final String command;
public Body(Effector<?> eff, ConfigBag params) {
this.effector = eff;
- this.command = Preconditions.checkNotNull(params.get(EFFECTOR_COMMAND), "command must be supplied when defining an effector");
+ this.command = Preconditions.checkNotNull(params.get(EFFECTOR_COMMAND), "command must be supplied when defining this effector");
// TODO could take a custom "env" aka effectorShellEnv
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f7ce1a25/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
index 1d86581..d21259d 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
@@ -49,6 +49,7 @@ import brooklyn.entity.Entity;
import brooklyn.entity.basic.BasicApplicationImpl;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityLocal;
+import brooklyn.entity.effector.AddChildrenEffector;
import brooklyn.entity.proxying.EntitySpec;
import brooklyn.entity.trait.Startable;
import brooklyn.management.ManagementContext;
@@ -61,9 +62,7 @@ import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.net.Urls;
-import brooklyn.util.text.Strings;
-import com.google.common.annotations.Beta;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
@@ -127,11 +126,10 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
if (autoUnwrapIfPossible && shouldUnwrap(template, app)) {
EntitySpec<? extends Application> oldApp = app;
app = (EntitySpec<? extends Application>) Iterables.getOnlyElement( app.getChildren() );
+
// if promoted, apply the transformations done to the app
- // (normally this will be done by the resolveSpec call above)
- if (app.getDisplayName()==null) app.displayName(oldApp.getDisplayName());
- app.tags(oldApp.getTags());
- app.locations(oldApp.getLocations());
+ // (transformations will be done by the resolveSpec call above, but we are collapsing oldApp so transfer to app=newApp)
+ AddChildrenEffector.collapseSpec(oldApp, app);
}
return app;
@@ -165,46 +163,7 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
if (childSpec.getType()==null || !Application.class.isAssignableFrom(childSpec.getType()))
return false;
- return hasNoNameOrCustomKeysOrRoot(template, app);
- }
-
- /** worker method to help determine whether child/children can be promoted */
- @Beta
- public static boolean hasNoNameOrCustomKeysOrRoot(AssemblyTemplate template, EntitySpec<?> spec) {
- if (!Strings.isEmpty(template.getName())) {
- if (spec.getChildren().size()==1) {
- String childName = Iterables.getOnlyElement(spec.getChildren()).getDisplayName();
- if (Strings.isEmpty(childName) || childName.equals(template.getName())) {
- // if child has no name, or it's the same, could still promote
- } else {
- return false;
- }
- } else {
- // if name set at root and promoting children would be ambiguous, do not promote
- return false;
- }
- } else if (spec.getChildren().size()>1) {
- // don't allow multiple children if a name is specified as a root
- return false;
- }
-
- Set<String> rootAttrs = template.getCustomAttributes().keySet();
- for (String rootAttr: rootAttrs) {
- if (rootAttr.equals("brooklyn.catalog")) {
- // this attr does not block promotion
- continue;
- }
- if (rootAttr.startsWith("brooklyn.")) {
- // any others in 'brooklyn' namespace will block promotion
- return false;
- }
- // location is allowed in both, and is copied on promotion
- // (name also copied)
- // others are root currently are ignored on promotion; they are usually metadata
- // TODO might be nice to know what we are excluding
- }
-
- return true;
+ return AddChildrenEffector.hasNoNameOrCustomKeysOrRoot(template, app);
}
private List<EntitySpec<?>> buildTemplateServicesAsSpecs(BrooklynClassLoadingContext loader, AssemblyTemplate template, CampPlatform platform) {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f7ce1a25/usage/rest-server/src/main/java/brooklyn/rest/resources/EntityResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/resources/EntityResource.java b/usage/rest-server/src/main/java/brooklyn/rest/resources/EntityResource.java
index d9cd740..9792c28 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/resources/EntityResource.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/resources/EntityResource.java
@@ -21,43 +21,31 @@ package brooklyn.rest.resources;
import static javax.ws.rs.core.Response.created;
import static javax.ws.rs.core.Response.status;
import static javax.ws.rs.core.Response.Status.ACCEPTED;
-import io.brooklyn.camp.brooklyn.spi.creation.BrooklynAssemblyTemplateInstantiator;
-import io.brooklyn.camp.spi.AssemblyTemplate;
-import io.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
-import java.io.Reader;
-import java.io.StringReader;
import java.net.URI;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.concurrent.Callable;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator;
import brooklyn.entity.Entity;
import brooklyn.entity.basic.BrooklynTags;
import brooklyn.entity.basic.BrooklynTags.NamedStringTag;
import brooklyn.entity.basic.BrooklynTaskTags;
-import brooklyn.entity.basic.Entities;
-import brooklyn.entity.basic.EntityFunctions;
import brooklyn.entity.basic.EntityLocal;
-import brooklyn.entity.effector.Effectors;
-import brooklyn.entity.proxying.EntitySpec;
-import brooklyn.entity.trait.Startable;
+import brooklyn.entity.effector.AddChildrenEffector;
import brooklyn.location.Location;
import brooklyn.management.Task;
-import brooklyn.management.classloading.BrooklynClassLoadingContext;
-import brooklyn.management.classloading.JavaBrooklynClassLoadingContext;
import brooklyn.management.entitlement.EntitlementPredicates;
import brooklyn.management.entitlement.Entitlements;
import brooklyn.rest.api.EntityApi;
@@ -71,16 +59,10 @@ import brooklyn.rest.transform.TaskTransformer;
import brooklyn.rest.util.WebResourceUtils;
import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableList;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.task.TaskBuilder;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.text.Strings;
import brooklyn.util.time.Duration;
import com.google.common.collect.Collections2;
import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.io.Files;
@@ -126,119 +108,28 @@ public class EntityResource extends AbstractBrooklynRestResource implements Enti
return getChildren(application, entity);
}
- @Override
- public Response addChildren(String applicationToken, String entityToken, Boolean start, String timeoutS, String yaml) {
+ @Override
+ public Response addChildren(String applicationToken, String entityToken, Boolean start, String timeoutS, String yaml) {
final EntityLocal parent = brooklyn().getEntity(applicationToken, entityToken);
if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.MODIFY_ENTITY, parent)) {
throw WebResourceUtils.unauthorized("User '%s' is not authorized to modify entity '%s'",
Entitlements.getEntitlementContext().user(), entityToken);
}
- Duration timeout = timeoutS==null ? Duration.millis(20) : Duration.of(timeoutS);
+ AddChildrenEffector.AddChildrenResult added = AddChildrenEffector.addChildren(parent, yaml, start, timeoutS==null ? Duration.millis(20) : Duration.of(timeoutS));
+ ResponseBuilder response;
- log.debug("Creating child of "+parent+" from yaml:\n{}", yaml);
- Reader input = new StringReader(yaml);
- AssemblyTemplate at = camp().pdp().registerDeploymentPlan(input);
-
- AssemblyTemplateInstantiator instantiator;
- try {
- instantiator = at.getInstantiator().newInstance();
- } catch (Exception e) {
- throw Exceptions.propagate(e);
- }
- if (instantiator instanceof AssemblyTemplateSpecInstantiator) {
- BrooklynClassLoadingContext loader = JavaBrooklynClassLoadingContext.newDefault(mgmt());
- EntitySpec<?> specA = ((AssemblyTemplateSpecInstantiator) instantiator).createSpec(at, camp(), loader, false);
-
- boolean promoted;
-
- // see whether we can promote children
- List<EntitySpec<?>> specs = MutableList.of();
- if (BrooklynAssemblyTemplateInstantiator.hasNoNameOrCustomKeysOrRoot(at, specA)) {
- // we can promote
- promoted = true;
- for (EntitySpec<?> specC: specA.getChildren()) {
- if (!specA.getLocations().isEmpty()) {
- specC.locations(specA.getLocations());
-
- // TODO copying tags to all entities is not ideal;
- // in particular the BrooklynTags.YAML_SPEC tag will show all entities
- // even if just one was created
- specC.tags(specA.getTags());
- if (Strings.isEmpty(specC.getDisplayName()))
- specC.displayName(specA.getDisplayName());
- }
- specs.add(specC);
- }
- } else {
- // if not promoting, set a nice name if needed
- if (Strings.isEmpty(specA.getDisplayName())) {
- int size = specA.getChildren().size();
- String childrenCountString = size+" "+(size!=1 ? "children" : "child");
- specA.displayName("Dynamically added "+childrenCountString);
- }
- promoted = false;
- specs.add(specA);
- }
-
- final List<Entity> children = MutableList.of();
- for (EntitySpec<?> spec: specs) {
- Entity child = (Entity)parent.addChild(spec);
- Entities.manage(child);
- children.add(child);
- }
-
- String childrenCountString;
- if (promoted) {
- int size = children.size();
- childrenCountString = size+" "+(size!=1 ? "children" : "child");
- } else {
- int size = specA.getChildren().size();
- childrenCountString = "entity with "+size+" "+(size!=1 ? "children" : "child");
- }
-
- TaskBuilder<List<String>> taskM = Tasks.<List<String>>builder().name("add children")
- .dynamic(true)
- .tag(BrooklynTaskTags.NON_TRANSIENT_TASK_TAG)
- .body(new Callable<List<String>>() {
- @Override public List<String> call() throws Exception {
- return ImmutableList.copyOf(Iterables.transform(children, EntityFunctions.id()));
- }})
- .description("Add" + (start==null ? " and potentially start" : start ? " and start" : "") + " "+childrenCountString);
- TaskBuilder<?> taskS = Tasks.builder().parallel(true).name("add (parallel)")
- .description(
- (start==null ? "Add or start" : start ? "Start" : "Add")+" each new entity");
-
- // should we autostart?
- for (Entity child: children) {
- if (Boolean.TRUE.equals(start) || (start==null && child instanceof Startable)) {
- taskS.add(Effectors.invocation(child, Startable.START, ImmutableMap.of("locations", ImmutableList.of())));
- } else {
- taskS.add(Tasks.builder().name("create").description("Created and added as child of "+parent)
- .body(new Runnable() { public void run() {} })
- .tag(BrooklynTaskTags.tagForTargetEntity(child))
- .build());
- }
- }
- taskM.add(taskS.build());
- Task<List<String>> task = Entities.submit(parent, taskM.build());
-
- // wait a few ms in case start is trivially simple, save the client a call to get the task result
- task.blockUntilEnded(timeout);
-
- if (children.size()==1) {
- Entity child = Iterables.getOnlyElement(children);
- URI ref = uriInfo.getBaseUriBuilder()
- .path(EntityApi.class)
- .path(EntityApi.class, "get")
- .build(child.getApplicationId(), child.getId());
- return created(ref).entity(TaskTransformer.taskSummary(task)).build();
- } else {
- return Response.status(Status.CREATED).entity(TaskTransformer.taskSummary(task)).build();
- }
+ if (added.getChildren().size()==1) {
+ Entity child = Iterables.getOnlyElement(added.getChildren());
+ URI ref = uriInfo.getBaseUriBuilder()
+ .path(EntityApi.class)
+ .path(EntityApi.class, "get")
+ .build(child.getApplicationId(), child.getId());
+ response = created(ref);
} else {
- throw new IllegalStateException("Spec could not be parsed to supply a compatible instantiator");
+ response = Response.status(Status.CREATED);
}
- }
+ return response.entity(TaskTransformer.taskSummary(added.getTask())).build();
+ }
@Override
public List<TaskSummary> listTasks(String applicationId, String entityId) {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f7ce1a25/utils/common/src/main/java/brooklyn/util/javalang/Reflections.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/javalang/Reflections.java b/utils/common/src/main/java/brooklyn/util/javalang/Reflections.java
index e5b78c6..3aaeca6 100644
--- a/utils/common/src/main/java/brooklyn/util/javalang/Reflections.java
+++ b/utils/common/src/main/java/brooklyn/util/javalang/Reflections.java
@@ -47,6 +47,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.util.collections.MutableList;
+import brooklyn.util.exceptions.Exceptions;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
@@ -95,7 +96,7 @@ public class Reflections {
v = invokeConstructorWithArgs(clazz, argValues);
if (v.isPresent()) return v.get();
} catch (Exception e) {
- throw new IllegalStateException("Error invoking constructor for "+clazz+Arrays.toString(argValues)+": "+e);
+ throw new IllegalStateException("Error invoking constructor for "+clazz+Arrays.toString(argValues) + ": " + Exceptions.collapseText(e));
}
throw new IllegalStateException("No suitable constructor for "+clazz+Arrays.toString(argValues));
}
@@ -110,9 +111,9 @@ public class Reflections {
try {
return clazz.newInstance();
} catch (InstantiationException e) {
- throw new ReflectionAccessException("Failed to create instance of class '" + classname + "' using class loader " + classLoader, e);
+ throw new ReflectionAccessException("Failed to create instance of class '" + classname + "' using class loader " + classLoader + ": " + Exceptions.collapseText(e), e);
} catch (IllegalAccessException e) {
- throw new ReflectionAccessException("Failed to create instance of class '" + classname + "' using class loader " + classLoader, e);
+ throw new ReflectionAccessException("Failed to create instance of class '" + classname + "' using class loader " + classLoader + ": " + Exceptions.collapseText(e), e);
}
}
@@ -121,11 +122,11 @@ public class Reflections {
try {
return classLoader.loadClass(classname);
} catch (ClassNotFoundException e) {
- throw new ReflectionNotFoundException("Failed to load class '" + classname + "' using class loader " + classLoader, e);
+ throw new ReflectionNotFoundException("Failed to load class '" + classname + "' using class loader " + classLoader + ": " + Exceptions.collapseText(e), e);
} catch (NoClassDefFoundError e) {
- throw new ReflectionNotFoundException("Failed to load class '" + classname + "' using class loader " + classLoader, e);
+ throw new ReflectionNotFoundException("Failed to load class '" + classname + "' using class loader " + classLoader + ": " + Exceptions.collapseText(e), e);
} catch (UnsupportedClassVersionError e) {
- throw new ReflectionNotFoundException("Failed to load class '" + classname + "' using class loader " + classLoader, e);
+ throw new ReflectionNotFoundException("Failed to load class '" + classname + "' using class loader " + classLoader + ": " + Exceptions.collapseText(e), e);
}
}
@@ -200,9 +201,9 @@ public class Reflections {
try {
return clazz.getConstructor(argTypes);
} catch (SecurityException e) {
- throw new ReflectionAccessException("Failed to load constructor of class '" + clazz + " with argument types " + Arrays.asList(argTypes), e);
+ throw new ReflectionAccessException("Failed to load constructor of class '" + clazz + " with argument types " + Arrays.asList(argTypes) + ": " + Exceptions.collapseText(e), e);
} catch (NoSuchMethodException e) {
- throw new ReflectionAccessException("Failed to load constructor of class '" + clazz + " with argument types " + Arrays.asList(argTypes), e);
+ throw new ReflectionAccessException("Failed to load constructor of class '" + clazz + " with argument types " + Arrays.asList(argTypes) + ": " + Exceptions.collapseText(e), e);
}
}
@@ -293,13 +294,13 @@ public class Reflections {
}
}
} catch (IllegalArgumentException e) {
- throw new IllegalArgumentException(getIllegalArgumentsErrorMessage(constructor, argValues), e);
+ throw new IllegalArgumentException(getIllegalArgumentsErrorMessage(constructor, argValues)+": " + Exceptions.collapseText(e), e);
} catch (InstantiationException e) {
- throw new ReflectionAccessException("Failed to create instance of '" + constructor.getDeclaringClass(), e);
+ throw new ReflectionAccessException("Failed to create instance of " + constructor.getDeclaringClass() + ": " + Exceptions.collapseText(e), e);
} catch (IllegalAccessException e) {
- throw new ReflectionAccessException("Failed to create instance of '" + constructor.getDeclaringClass(), e);
+ throw new ReflectionAccessException("Failed to create instance of " + constructor.getDeclaringClass() + ": " + Exceptions.collapseText(e), e);
} catch (InvocationTargetException e) {
- throw new ReflectionAccessException("Failed to create instance of '" + constructor.getDeclaringClass(), e);
+ throw new ReflectionAccessException("Failed to create instance of " + constructor.getDeclaringClass() + ": " + Exceptions.collapseText(e), e);
}
}
@@ -307,11 +308,11 @@ public class Reflections {
try {
return clazz.getMethod(methodName, argTypes);
} catch (NoClassDefFoundError e) {
- throw new ReflectionNotFoundException("Failed to invoke method '" + methodName + " on class " + clazz + " with argument types " + Arrays.asList(argTypes) + ", using class loader " + clazz.getClassLoader(), e);
+ throw new ReflectionNotFoundException("Failed to invoke method " + methodName + " on class " + clazz + " with argument types " + Arrays.asList(argTypes) + ", using class loader " + clazz.getClassLoader() + ": " + Exceptions.collapseText(e), e);
} catch (NoSuchMethodException e) {
- throw new ReflectionNotFoundException("Failed to invoke method '" + methodName + " on class " + clazz + " with argument types " + Arrays.asList(argTypes), e);
+ throw new ReflectionNotFoundException("Failed to invoke method " + methodName + " on class " + clazz + " with argument types " + Arrays.asList(argTypes) + ": " + Exceptions.collapseText(e), e);
} catch (SecurityException e) {
- throw new ReflectionAccessException("Failed to invoke method '" + methodName + " on class " + clazz + " with argument types " + Arrays.asList(argTypes), e);
+ throw new ReflectionAccessException("Failed to invoke method " + methodName + " on class " + clazz + " with argument types " + Arrays.asList(argTypes) + ": " + Exceptions.collapseText(e), e);
}
}
@@ -327,7 +328,7 @@ public class Reflections {
throw new ReflectionNotFoundException("Cannot find method " + methodName + " on class " + clazz);
} catch (SecurityException e) {
- throw new ReflectionAccessException("Failed to invoke method '" + methodName + " on class " + clazz, e);
+ throw new ReflectionAccessException("Failed to invoke method '" + methodName + " on class " + clazz + ": " + Exceptions.collapseText(e), e);
}
}
@@ -342,9 +343,9 @@ public class Reflections {
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException(getIllegalArgumentsErrorMessage(method, argValues), e);
} catch (IllegalAccessException e) {
- throw new ReflectionAccessException("Failed to invoke method '" + method.toGenericString() + " on class " + method.getDeclaringClass() + " with argument values " + Arrays.asList(argValues), e);
+ throw new ReflectionAccessException("Failed to invoke method '" + method.toGenericString() + " on class " + method.getDeclaringClass() + " with argument values " + Arrays.asList(argValues) + ": " + Exceptions.collapseText(e), e);
} catch (InvocationTargetException e) {
- throw new ReflectionAccessException("Failed to invoke method '" + method.toGenericString() + " on class " + method.getDeclaringClass() + " with argument values " + Arrays.asList(argValues), e);
+ throw new ReflectionAccessException("Failed to invoke method '" + method.toGenericString() + " on class " + method.getDeclaringClass() + " with argument values " + Arrays.asList(argValues) + ": " + Exceptions.collapseText(e), e);
}
}
@@ -354,9 +355,9 @@ public class Reflections {
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException(getIllegalArgumentsErrorMessage(method, argValues), e);
} catch (IllegalAccessException e) {
- throw new ReflectionAccessException("Failed to invoke method '" + method.toGenericString() + " on class " + method.getDeclaringClass() + " with argument values " + Arrays.asList(argValues), e);
+ throw new ReflectionAccessException("Failed to invoke method '" + method.toGenericString() + " on class " + method.getDeclaringClass() + " with argument values " + Arrays.asList(argValues) + ": " + Exceptions.collapseText(e), e);
} catch (InvocationTargetException e) {
- throw new ReflectionAccessException("Failed to invoke method '" + method.toGenericString() + " on class " + method.getDeclaringClass() + " with argument values " + Arrays.asList(argValues), e);
+ throw new ReflectionAccessException("Failed to invoke method '" + method.toGenericString() + " on class " + method.getDeclaringClass() + " with argument values " + Arrays.asList(argValues) + ": " + Exceptions.collapseText(e), e);
}
}
@@ -382,9 +383,9 @@ public class Reflections {
try {
result[index] = field.get(null);
} catch (IllegalArgumentException e) {
- throw new ReflectionAccessException("Failed to load field '" + field.getName() + " from class " + clazz, e);
+ throw new ReflectionAccessException("Failed to load field '" + field.getName() + " from class " + clazz + ": " + Exceptions.collapseText(e), e);
} catch (IllegalAccessException e) {
- throw new ReflectionAccessException("Failed to load field '" + field.getName() + " from class " + clazz, e);
+ throw new ReflectionAccessException("Failed to load field '" + field.getName() + " from class " + clazz + ": " + Exceptions.collapseText(e), e);
}
}
}