http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshEffectorTasks.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshEffectorTasks.java b/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshEffectorTasks.java new file mode 100644 index 0000000..37e582d --- /dev/null +++ b/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshEffectorTasks.java @@ -0,0 +1,335 @@ +/* + * 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.core.effector.ssh; + +import java.util.List; +import java.util.Map; + +import javax.annotation.Nullable; + +import org.apache.brooklyn.api.effector.Effector; +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.location.Location; +import org.apache.brooklyn.api.mgmt.Task; +import org.apache.brooklyn.config.ConfigKey; +import org.apache.brooklyn.config.StringConfigMap; +import org.apache.brooklyn.core.config.ConfigKeys; +import org.apache.brooklyn.core.config.ConfigUtils; +import org.apache.brooklyn.core.effector.EffectorBody; +import org.apache.brooklyn.core.effector.EffectorTasks; +import org.apache.brooklyn.core.effector.EffectorTasks.EffectorTaskFactory; +import org.apache.brooklyn.core.effector.ssh.SshEffectorTasks; +import org.apache.brooklyn.core.entity.EntityInternal; +import org.apache.brooklyn.core.location.internal.LocationInternal; +import org.apache.brooklyn.core.mgmt.BrooklynTaskTags; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.apache.brooklyn.location.ssh.SshMachineLocation; +import org.apache.brooklyn.util.core.config.ConfigBag; +import org.apache.brooklyn.util.core.internal.ssh.SshTool; +import org.apache.brooklyn.util.core.task.Tasks; +import org.apache.brooklyn.util.core.task.ssh.SshFetchTaskFactory; +import org.apache.brooklyn.util.core.task.ssh.SshFetchTaskWrapper; +import org.apache.brooklyn.util.core.task.ssh.SshPutTaskFactory; +import org.apache.brooklyn.util.core.task.ssh.SshPutTaskWrapper; +import org.apache.brooklyn.util.core.task.ssh.SshTasks; +import org.apache.brooklyn.util.core.task.ssh.internal.AbstractSshExecTaskFactory; +import org.apache.brooklyn.util.core.task.ssh.internal.PlainSshExecTaskFactory; +import org.apache.brooklyn.util.core.task.system.ProcessTaskFactory; +import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper; +import org.apache.brooklyn.util.ssh.BashCommands; + +import com.google.common.annotations.Beta; +import com.google.common.base.Function; +import com.google.common.collect.Maps; + +/** + * Conveniences for generating {@link Task} instances to perform SSH activities. + * <p> + * If the {@link SshMachineLocation machine} is not specified directly it + * will be inferred from the {@link Entity} context of either the {@link Effector} + * or the current {@link Task}. + * + * @see SshTasks + * @since 0.6.0 + */ +@Beta +public class SshEffectorTasks { + + private static final Logger log = LoggerFactory.getLogger(SshEffectorTasks.class); + + public static final ConfigKey<Boolean> IGNORE_ENTITY_SSH_FLAGS = ConfigKeys.newBooleanConfigKey("ignoreEntitySshFlags", + "Whether to ignore any ssh flags (behaviour constraints) set on the entity or location " + + "where this is running, using only flags explicitly specified", false); + + /** + * Like {@link EffectorBody} but providing conveniences when in an entity with a single machine location. + */ + public abstract static class SshEffectorBody<T> extends EffectorBody<T> { + + /** convenience for accessing the machine */ + public SshMachineLocation machine() { + return EffectorTasks.getSshMachine(entity()); + } + + /** convenience for generating an {@link PlainSshExecTaskFactory} which can be further customised if desired, and then (it must be explicitly) queued */ + public ProcessTaskFactory<Integer> ssh(String ...commands) { + return new SshEffectorTaskFactory<Integer>(commands).machine(machine()); + } + } + + /** variant of {@link PlainSshExecTaskFactory} which fulfills the {@link EffectorTaskFactory} signature so can be used directly as an impl for an effector, + * also injects the machine automatically; can also be used outwith effector contexts, and machine is still injected if it is + * run from inside a task at an entity with a single SshMachineLocation */ + public static class SshEffectorTaskFactory<RET> extends AbstractSshExecTaskFactory<SshEffectorTaskFactory<RET>,RET> implements EffectorTaskFactory<RET> { + + public SshEffectorTaskFactory(String ...commands) { + super(commands); + } + public SshEffectorTaskFactory(SshMachineLocation machine, String ...commands) { + super(machine, commands); + } + @Override + public ProcessTaskWrapper<RET> newTask(Entity entity, Effector<RET> effector, ConfigBag parameters) { + markDirty(); + if (summary==null) summary(effector.getName()+" (ssh)"); + machine(EffectorTasks.getSshMachine(entity)); + return newTask(); + } + @Override + public synchronized ProcessTaskWrapper<RET> newTask() { + Entity entity = BrooklynTaskTags.getTargetOrContextEntity(Tasks.current()); + if (machine==null) { + if (log.isDebugEnabled()) + log.debug("Using an ssh task not in an effector without any machine; will attempt to infer the machine: "+this); + if (entity!=null) + machine(EffectorTasks.getSshMachine(entity)); + } + applySshFlags(getConfig(), entity, getMachine()); + return super.newTask(); + } + + @Override + public <T2> SshEffectorTaskFactory<T2> returning(ScriptReturnType type) { + return (SshEffectorTaskFactory<T2>) super.<T2>returning(type); + } + + @Override + public SshEffectorTaskFactory<Boolean> returningIsExitCodeZero() { + return (SshEffectorTaskFactory<Boolean>) super.returningIsExitCodeZero(); + } + + public SshEffectorTaskFactory<String> requiringZeroAndReturningStdout() { + return (SshEffectorTaskFactory<String>) super.requiringZeroAndReturningStdout(); + } + + public <RET2> SshEffectorTaskFactory<RET2> returning(Function<ProcessTaskWrapper<?>, RET2> resultTransformation) { + return (SshEffectorTaskFactory<RET2>) super.returning(resultTransformation); + } + } + + public static class SshPutEffectorTaskFactory extends SshPutTaskFactory implements EffectorTaskFactory<Void> { + public SshPutEffectorTaskFactory(String remoteFile) { + super(remoteFile); + } + public SshPutEffectorTaskFactory(SshMachineLocation machine, String remoteFile) { + super(machine, remoteFile); + } + @Override + public SshPutTaskWrapper newTask(Entity entity, Effector<Void> effector, ConfigBag parameters) { + machine(EffectorTasks.getSshMachine(entity)); + applySshFlags(getConfig(), entity, getMachine()); + return super.newTask(); + } + @Override + public SshPutTaskWrapper newTask() { + Entity entity = BrooklynTaskTags.getTargetOrContextEntity(Tasks.current()); + if (machine==null) { + if (log.isDebugEnabled()) + log.debug("Using an ssh put task not in an effector without any machine; will attempt to infer the machine: "+this); + if (entity!=null) { + machine(EffectorTasks.getSshMachine(entity)); + } + + } + applySshFlags(getConfig(), entity, getMachine()); + return super.newTask(); + } + } + + public static class SshFetchEffectorTaskFactory extends SshFetchTaskFactory implements EffectorTaskFactory<String> { + public SshFetchEffectorTaskFactory(String remoteFile) { + super(remoteFile); + } + public SshFetchEffectorTaskFactory(SshMachineLocation machine, String remoteFile) { + super(machine, remoteFile); + } + @Override + public SshFetchTaskWrapper newTask(Entity entity, Effector<String> effector, ConfigBag parameters) { + machine(EffectorTasks.getSshMachine(entity)); + applySshFlags(getConfig(), entity, getMachine()); + return super.newTask(); + } + @Override + public SshFetchTaskWrapper newTask() { + Entity entity = BrooklynTaskTags.getTargetOrContextEntity(Tasks.current()); + if (machine==null) { + if (log.isDebugEnabled()) + log.debug("Using an ssh fetch task not in an effector without any machine; will attempt to infer the machine: "+this); + if (entity!=null) + machine(EffectorTasks.getSshMachine(entity)); + } + applySshFlags(getConfig(), entity, getMachine()); + return super.newTask(); + } + } + + public static SshEffectorTaskFactory<Integer> ssh(String ...commands) { + return new SshEffectorTaskFactory<Integer>(commands); + } + + public static SshEffectorTaskFactory<Integer> ssh(List<String> commands) { + return ssh(commands.toArray(new String[commands.size()])); + } + + public static SshPutTaskFactory put(String remoteFile) { + return new SshPutEffectorTaskFactory(remoteFile); + } + + public static SshFetchEffectorTaskFactory fetch(String remoteFile) { + return new SshFetchEffectorTaskFactory(remoteFile); + } + + /** task which returns 0 if pid is running */ + public static SshEffectorTaskFactory<Integer> codePidRunning(Integer pid) { + return ssh("ps -p "+pid).summary("PID "+pid+" is-running check (exit code)").allowingNonZeroExitCode(); + } + + /** task which fails if the given PID is not running */ + public static SshEffectorTaskFactory<?> requirePidRunning(Integer pid) { + return codePidRunning(pid).summary("PID "+pid+" is-running check (required)").requiringExitCodeZero("Process with PID "+pid+" is required to be running"); + } + + /** as {@link #codePidRunning(Integer)} but returning boolean */ + public static SshEffectorTaskFactory<Boolean> isPidRunning(Integer pid) { + return codePidRunning(pid).summary("PID "+pid+" is-running check (boolean)").returning(new Function<ProcessTaskWrapper<?>, Boolean>() { + public Boolean apply(@Nullable ProcessTaskWrapper<?> input) { return Integer.valueOf(0).equals(input.getExitCode()); } + }); + } + + + /** task which returns 0 if pid in the given file is running; + * method accepts wildcards so long as they match a single file on the remote end + * <p> + * returns 1 if no matching file, + * 1 if matching file but no matching process, + * and 2 if 2+ matching files */ + public static SshEffectorTaskFactory<Integer> codePidFromFileRunning(final String pidFile) { + return ssh(BashCommands.chain( + // this fails, but isn't an error + BashCommands.requireTest("-f "+pidFile, "The PID file "+pidFile+" does not exist."), + // this fails and logs an error picked up later + BashCommands.requireTest("`ls "+pidFile+" | wc -w` -eq 1", "ERROR: there are multiple matching PID files"), + // this fails and logs an error picked up later + BashCommands.require("cat "+pidFile, "ERROR: the PID file "+pidFile+" cannot be read (permissions?)."), + // finally check the process + "ps -p `cat "+pidFile+"`")).summary("PID file "+pidFile+" is-running check (exit code)") + .allowingNonZeroExitCode() + .addCompletionListener(new Function<ProcessTaskWrapper<?>,Void>() { + public Void apply(ProcessTaskWrapper<?> input) { + if (input.getStderr().contains("ERROR:")) + throw new IllegalStateException("Invalid or inaccessible PID filespec: "+pidFile); + return null; + } + }); + } + + /** task which fails if the pid in the given file is not running (or if there is no such PID file); + * method accepts wildcards so long as they match a single file on the remote end (fails if 0 or 2+ matching files) */ + public static SshEffectorTaskFactory<?> requirePidFromFileRunning(String pidFile) { + return codePidFromFileRunning(pidFile) + .summary("PID file "+pidFile+" is-running check (required)") + .requiringExitCodeZero("Process with PID from file "+pidFile+" is required to be running"); + } + + /** as {@link #codePidFromFileRunning(String)} but returning boolean */ + public static SshEffectorTaskFactory<Boolean> isPidFromFileRunning(String pidFile) { + return codePidFromFileRunning(pidFile).summary("PID file "+pidFile+" is-running check (boolean)"). + returning(new Function<ProcessTaskWrapper<?>, Boolean>() { + public Boolean apply(@Nullable ProcessTaskWrapper<?> input) { return ((Integer)0).equals(input.getExitCode()); } + }); + } + + /** extracts the values for the main brooklyn.ssh.config.* config keys (i.e. those declared in ConfigKeys) + * as declared on the entity, and inserts them in a map using the unprefixed state, for ssh. + * <p> + * currently this is computed for each call, which may be wasteful, but it is reliable in the face of config changes. + * we could cache the Map. note that we do _not_ cache (or even own) the SshTool; + * the SshTool is created or re-used by the SshMachineLocation making use of these properties */ + @Beta + public static Map<String, Object> getSshFlags(Entity entity, Location optionalLocation) { + ConfigBag allConfig = ConfigBag.newInstance(); + + StringConfigMap globalConfig = ((EntityInternal)entity).getManagementContext().getConfig(); + allConfig.putAll(globalConfig.getAllConfig()); + + if (optionalLocation!=null) + allConfig.putAll(((LocationInternal)optionalLocation).config().getBag()); + + allConfig.putAll(((EntityInternal)entity).getAllConfig()); + + Map<String, Object> result = Maps.newLinkedHashMap(); + for (String keyS : allConfig.getAllConfig().keySet()) { + if (keyS.startsWith(SshTool.BROOKLYN_CONFIG_KEY_PREFIX)) { + ConfigKey<?> key = ConfigKeys.newConfigKey(Object.class, keyS); + + Object val = allConfig.getStringKey(keyS); + + /* + * NOV 2013 changing this to rely on config above being inserted in the right order, + * so entity config will be preferred over location, and location over global. + * If that is consistent then remove the lines below. + * (We can also accept null entity and so combine with SshTasks.getSshFlags.) + */ + +// // have to use raw config to test whether the config is set +// Object val = ((EntityInternal)entity).getConfigMap().getRawConfig(key); +// if (val!=null) { +// val = entity.getConfig(key); +// } else { +// val = globalConfig.getRawConfig(key); +// if (val!=null) val = globalConfig.getConfig(key); +// } +// if (val!=null) { + result.put(ConfigUtils.unprefixedKey(SshTool.BROOKLYN_CONFIG_KEY_PREFIX, key).getName(), val); +// } + } + } + return result; + } + + private static void applySshFlags(ConfigBag config, Entity entity, Location machine) { + if (entity!=null) { + if (!config.get(IGNORE_ENTITY_SSH_FLAGS)) { + config.putIfAbsent(getSshFlags(entity, machine)); + } + } + } + +}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/main/java/org/apache/brooklyn/core/entity/Entities.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/Entities.java b/core/src/main/java/org/apache/brooklyn/core/entity/Entities.java index e35205a..ca561e1 100644 --- a/core/src/main/java/org/apache/brooklyn/core/entity/Entities.java +++ b/core/src/main/java/org/apache/brooklyn/core/entity/Entities.java @@ -62,6 +62,7 @@ import org.apache.brooklyn.api.sensor.Sensor; import org.apache.brooklyn.config.ConfigKey; import org.apache.brooklyn.config.ConfigKey.HasConfigKey; import org.apache.brooklyn.core.config.Sanitizer; +import org.apache.brooklyn.core.effector.Effectors; import org.apache.brooklyn.core.entity.trait.Startable; import org.apache.brooklyn.core.entity.trait.StartableMethods; import org.apache.brooklyn.core.internal.BrooklynProperties; @@ -76,7 +77,6 @@ import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal; import org.apache.brooklyn.core.mgmt.internal.NonDeploymentManagementContext; import org.apache.brooklyn.core.objs.BrooklynObjectInternal; import org.apache.brooklyn.core.objs.proxy.EntityProxyImpl; -import org.apache.brooklyn.effector.core.Effectors; import org.apache.brooklyn.sensor.core.DependentConfiguration; import org.apache.brooklyn.util.collections.MutableMap; import org.apache.brooklyn.util.core.ResourceUtils; http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/main/java/org/apache/brooklyn/core/entity/EntityDynamicType.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/EntityDynamicType.java b/core/src/main/java/org/apache/brooklyn/core/entity/EntityDynamicType.java index 0db0d46..6d65f41 100644 --- a/core/src/main/java/org/apache/brooklyn/core/entity/EntityDynamicType.java +++ b/core/src/main/java/org/apache/brooklyn/core/entity/EntityDynamicType.java @@ -31,14 +31,14 @@ import org.apache.brooklyn.api.entity.Entity; import org.apache.brooklyn.api.entity.EntityType; import org.apache.brooklyn.api.sensor.Sensor; import org.apache.brooklyn.config.ConfigKey.HasConfigKey; +import org.apache.brooklyn.core.effector.EffectorAndBody; +import org.apache.brooklyn.core.effector.EffectorBody; +import org.apache.brooklyn.core.effector.EffectorWithBody; +import org.apache.brooklyn.core.effector.Effectors; +import org.apache.brooklyn.core.effector.MethodEffector; +import org.apache.brooklyn.core.effector.EffectorTasks.EffectorBodyTaskFactory; +import org.apache.brooklyn.core.effector.EffectorTasks.EffectorTaskFactory; import org.apache.brooklyn.core.objs.BrooklynDynamicType; -import org.apache.brooklyn.effector.core.EffectorAndBody; -import org.apache.brooklyn.effector.core.EffectorBody; -import org.apache.brooklyn.effector.core.EffectorWithBody; -import org.apache.brooklyn.effector.core.Effectors; -import org.apache.brooklyn.effector.core.MethodEffector; -import org.apache.brooklyn.effector.core.EffectorTasks.EffectorBodyTaskFactory; -import org.apache.brooklyn.effector.core.EffectorTasks.EffectorTaskFactory; import org.apache.brooklyn.util.javalang.Reflections; import org.slf4j.Logger; import org.slf4j.LoggerFactory; http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/main/java/org/apache/brooklyn/core/entity/trait/MemberReplaceable.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/trait/MemberReplaceable.java b/core/src/main/java/org/apache/brooklyn/core/entity/trait/MemberReplaceable.java index a67b1af..238e261 100644 --- a/core/src/main/java/org/apache/brooklyn/core/entity/trait/MemberReplaceable.java +++ b/core/src/main/java/org/apache/brooklyn/core/entity/trait/MemberReplaceable.java @@ -22,7 +22,7 @@ import java.util.NoSuchElementException; import org.apache.brooklyn.core.annotation.Effector; import org.apache.brooklyn.core.annotation.EffectorParam; -import org.apache.brooklyn.effector.core.MethodEffector; +import org.apache.brooklyn.core.effector.MethodEffector; import org.apache.brooklyn.entity.group.StopFailedRuntimeException; public interface MemberReplaceable { http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/main/java/org/apache/brooklyn/core/entity/trait/Resizable.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/trait/Resizable.java b/core/src/main/java/org/apache/brooklyn/core/entity/trait/Resizable.java index ebf37d0..68c9398 100644 --- a/core/src/main/java/org/apache/brooklyn/core/entity/trait/Resizable.java +++ b/core/src/main/java/org/apache/brooklyn/core/entity/trait/Resizable.java @@ -21,7 +21,7 @@ package org.apache.brooklyn.core.entity.trait; import org.apache.brooklyn.core.annotation.Effector; import org.apache.brooklyn.core.annotation.EffectorParam; -import org.apache.brooklyn.effector.core.MethodEffector; +import org.apache.brooklyn.core.effector.MethodEffector; /** * Defines an entity group that can be re-sized dynamically. http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/main/java/org/apache/brooklyn/core/entity/trait/Startable.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/trait/Startable.java b/core/src/main/java/org/apache/brooklyn/core/entity/trait/Startable.java index 304dba2..96812ce 100644 --- a/core/src/main/java/org/apache/brooklyn/core/entity/trait/Startable.java +++ b/core/src/main/java/org/apache/brooklyn/core/entity/trait/Startable.java @@ -26,10 +26,10 @@ import org.apache.brooklyn.api.sensor.AttributeSensor; import org.apache.brooklyn.config.ConfigKey; import org.apache.brooklyn.core.annotation.EffectorParam; import org.apache.brooklyn.core.config.ConfigKeys; +import org.apache.brooklyn.core.effector.EffectorBody; +import org.apache.brooklyn.core.effector.Effectors; +import org.apache.brooklyn.core.effector.MethodEffector; import org.apache.brooklyn.core.entity.Attributes; -import org.apache.brooklyn.effector.core.EffectorBody; -import org.apache.brooklyn.effector.core.Effectors; -import org.apache.brooklyn.effector.core.MethodEffector; import org.apache.brooklyn.util.core.config.ConfigBag; import org.apache.brooklyn.util.core.task.Tasks; import org.slf4j.Logger; http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/main/java/org/apache/brooklyn/core/entity/trait/StartableMethods.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/trait/StartableMethods.java b/core/src/main/java/org/apache/brooklyn/core/entity/trait/StartableMethods.java index 47d1623..b49d259 100644 --- a/core/src/main/java/org/apache/brooklyn/core/entity/trait/StartableMethods.java +++ b/core/src/main/java/org/apache/brooklyn/core/entity/trait/StartableMethods.java @@ -26,9 +26,9 @@ import org.apache.brooklyn.api.entity.Entity; import org.apache.brooklyn.api.entity.EntityLocal; import org.apache.brooklyn.api.location.Location; import org.apache.brooklyn.api.mgmt.TaskAdaptable; +import org.apache.brooklyn.core.effector.Effectors; import org.apache.brooklyn.core.entity.Entities; import org.apache.brooklyn.core.entity.EntityPredicates; -import org.apache.brooklyn.effector.core.Effectors; import org.apache.brooklyn.util.collections.MutableMap; import org.apache.brooklyn.util.core.config.ConfigBag; import org.apache.brooklyn.util.core.task.DynamicTasks; http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java index 4a018e3..49e1c1c 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java @@ -36,13 +36,13 @@ import org.apache.brooklyn.api.mgmt.ManagementContext; import org.apache.brooklyn.api.mgmt.Task; import org.apache.brooklyn.config.ConfigKey; import org.apache.brooklyn.core.config.ConfigKeys; +import org.apache.brooklyn.core.effector.Effectors; import org.apache.brooklyn.core.entity.Entities; import org.apache.brooklyn.core.entity.EntityFunctions; import org.apache.brooklyn.core.entity.trait.Startable; import org.apache.brooklyn.core.plan.PlanNotRecognizedException; import org.apache.brooklyn.core.plan.PlanToSpecFactory; import org.apache.brooklyn.core.plan.PlanToSpecTransformer; -import org.apache.brooklyn.effector.core.Effectors; import org.apache.brooklyn.util.collections.MutableList; import org.apache.brooklyn.util.collections.MutableMap; import org.apache.brooklyn.util.core.task.TaskBuilder; http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/EffectorUtils.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/EffectorUtils.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/EffectorUtils.java index 9429836..fa7eaaa 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/EffectorUtils.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/EffectorUtils.java @@ -33,9 +33,9 @@ import org.apache.brooklyn.api.effector.Effector; import org.apache.brooklyn.api.effector.ParameterType; import org.apache.brooklyn.api.entity.Entity; import org.apache.brooklyn.api.mgmt.Task; +import org.apache.brooklyn.core.effector.BasicParameterType; import org.apache.brooklyn.core.entity.EntityInternal; import org.apache.brooklyn.core.mgmt.BrooklynTaskTags; -import org.apache.brooklyn.effector.core.BasicParameterType; import org.apache.brooklyn.util.collections.MutableList; import org.apache.brooklyn.util.collections.MutableMap; import org.apache.brooklyn.util.core.config.ConfigBag; http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalManagementContext.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalManagementContext.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalManagementContext.java index 24392e6..f464d3b 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalManagementContext.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalManagementContext.java @@ -43,6 +43,7 @@ import org.apache.brooklyn.api.mgmt.SubscriptionManager; import org.apache.brooklyn.api.mgmt.Task; import org.apache.brooklyn.api.mgmt.TaskAdaptable; import org.apache.brooklyn.core.BrooklynFeatureEnablement; +import org.apache.brooklyn.core.effector.Effectors; import org.apache.brooklyn.core.entity.drivers.downloads.BasicDownloadsManager; import org.apache.brooklyn.core.internal.BrooklynProperties; import org.apache.brooklyn.core.internal.BrooklynProperties.Factory.Builder; @@ -52,7 +53,6 @@ import org.apache.brooklyn.core.mgmt.ha.OsgiManager; import org.apache.brooklyn.core.objs.proxy.InternalEntityFactory; import org.apache.brooklyn.core.objs.proxy.InternalLocationFactory; import org.apache.brooklyn.core.objs.proxy.InternalPolicyFactory; -import org.apache.brooklyn.effector.core.Effectors; import org.apache.brooklyn.util.core.task.BasicExecutionContext; import org.apache.brooklyn.util.core.task.BasicExecutionManager; import org.apache.brooklyn.util.core.task.DynamicTasks; http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java index eb07bc1..e1d704b 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java @@ -44,6 +44,10 @@ import org.apache.brooklyn.api.sensor.Feed; import org.apache.brooklyn.core.catalog.internal.CatalogBundleDto; import org.apache.brooklyn.core.catalog.internal.CatalogUtils; import org.apache.brooklyn.core.config.BasicConfigKey; +import org.apache.brooklyn.core.effector.BasicParameterType; +import org.apache.brooklyn.core.effector.EffectorAndBody; +import org.apache.brooklyn.core.effector.EffectorTasks.EffectorBodyTaskFactory; +import org.apache.brooklyn.core.effector.EffectorTasks.EffectorTaskFactory; import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext; import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContextSequential; import org.apache.brooklyn.core.mgmt.classloading.ClassLoaderFromBrooklynClassLoadingContext; @@ -55,10 +59,6 @@ import org.apache.brooklyn.core.mgmt.rebind.dto.BasicFeedMemento; import org.apache.brooklyn.core.mgmt.rebind.dto.BasicLocationMemento; import org.apache.brooklyn.core.mgmt.rebind.dto.BasicPolicyMemento; import org.apache.brooklyn.core.mgmt.rebind.dto.MutableBrooklynMemento; -import org.apache.brooklyn.effector.core.BasicParameterType; -import org.apache.brooklyn.effector.core.EffectorAndBody; -import org.apache.brooklyn.effector.core.EffectorTasks.EffectorBodyTaskFactory; -import org.apache.brooklyn.effector.core.EffectorTasks.EffectorTaskFactory; import org.apache.brooklyn.sensor.core.BasicAttributeSensor; import org.apache.brooklyn.util.core.xstream.XmlSerializer; import org.apache.brooklyn.util.exceptions.Exceptions; http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/main/java/org/apache/brooklyn/core/objs/proxy/EntityProxyImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/objs/proxy/EntityProxyImpl.java b/core/src/main/java/org/apache/brooklyn/core/objs/proxy/EntityProxyImpl.java index 3b6e52a..97b8f39 100644 --- a/core/src/main/java/org/apache/brooklyn/core/objs/proxy/EntityProxyImpl.java +++ b/core/src/main/java/org/apache/brooklyn/core/objs/proxy/EntityProxyImpl.java @@ -33,6 +33,7 @@ import org.apache.brooklyn.api.entity.Entity; import org.apache.brooklyn.api.entity.EntityLocal; import org.apache.brooklyn.api.mgmt.ManagementContext; import org.apache.brooklyn.api.mgmt.TaskAdaptable; +import org.apache.brooklyn.core.effector.EffectorWithBody; import org.apache.brooklyn.core.entity.AbstractEntity; import org.apache.brooklyn.core.entity.EntityInternal; import org.apache.brooklyn.core.entity.internal.EntityTransientCopyInternal; @@ -41,7 +42,6 @@ import org.apache.brooklyn.core.mgmt.internal.EffectorUtils; import org.apache.brooklyn.core.mgmt.internal.EntityManagerInternal; import org.apache.brooklyn.core.mgmt.internal.ManagementTransitionMode; import org.apache.brooklyn.core.mgmt.rebind.RebindManagerImpl.RebindTracker; -import org.apache.brooklyn.effector.core.EffectorWithBody; import org.apache.brooklyn.util.core.config.ConfigBag; import org.apache.brooklyn.util.core.task.DynamicTasks; import org.apache.brooklyn.util.core.task.TaskTags; http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/main/java/org/apache/brooklyn/effector/core/AbstractEffector.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/effector/core/AbstractEffector.java b/core/src/main/java/org/apache/brooklyn/effector/core/AbstractEffector.java deleted file mode 100644 index 74863c8..0000000 --- a/core/src/main/java/org/apache/brooklyn/effector/core/AbstractEffector.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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.effector.core; - -import java.util.List; -import java.util.Map; -import java.util.concurrent.Callable; - -import org.apache.brooklyn.api.effector.Effector; -import org.apache.brooklyn.api.effector.ParameterType; -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.mgmt.Task; -import org.apache.brooklyn.core.mgmt.internal.EffectorUtils; -import org.apache.brooklyn.effector.core.EffectorTasks.EffectorTaskFactory; -import org.apache.brooklyn.util.core.config.ConfigBag; -import org.apache.brooklyn.util.core.task.DynamicSequentialTask; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.collect.ImmutableMap; - -/** - * The abstract {@link Effector} implementation. - * - * The concrete subclass (often anonymous) will supply the {@link #call(Entity, Map)} implementation, - * and the fields in the constructor. - */ -public abstract class AbstractEffector<T> extends EffectorBase<T> implements EffectorWithBody<T> { - - private static final long serialVersionUID = 1832435915652457843L; - - @SuppressWarnings("unused") - private static final Logger LOG = LoggerFactory.getLogger(AbstractEffector.class); - - public AbstractEffector(String name, Class<T> returnType, List<ParameterType<?>> parameters, String description) { - super(name, returnType, parameters, description); - } - - public abstract T call(Entity entity, @SuppressWarnings("rawtypes") Map parameters); - - /** Convenience for named-parameter syntax (needs map in first argument) */ - public T call(Entity entity) { return call(ImmutableMap.of(), entity); } - - /** Convenience for named-parameter syntax (needs map in first argument) */ - public T call(@SuppressWarnings("rawtypes") Map parameters, Entity entity) { return call(entity, parameters); } - - /** @deprecated since 0.7.0 use {@link #getFlagsForTaskInvocationAt(Entity, Effector, ConfigBag)} */ @Deprecated - protected final Map<Object,Object> getFlagsForTaskInvocationAt(Entity entity) { - return getFlagsForTaskInvocationAt(entity, this, null); - } - /** subclasses may override to add additional flags, but they should include the flags returned here - * unless there is very good reason not to */ - protected Map<Object,Object> getFlagsForTaskInvocationAt(Entity entity, Effector<T> effector, ConfigBag parameters) { - return EffectorUtils.getTaskFlagsForEffectorInvocation(entity, effector, parameters); - } - - /** not meant for overriding; subclasses should override the abstract {@link #call(Entity, Map)} method in this class */ - @Override - public final EffectorTaskFactory<T> getBody() { - return new EffectorTaskFactory<T>() { - @Override - public Task<T> newTask(final Entity entity, final Effector<T> effector, final ConfigBag parameters) { - return new DynamicSequentialTask<T>( - getFlagsForTaskInvocationAt(entity, AbstractEffector.this, parameters), - new Callable<T>() { - @Override public T call() { - return AbstractEffector.this.call(parameters.getAllConfig(), entity); - } - }); - } - }; - } - -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/main/java/org/apache/brooklyn/effector/core/AddChildrenEffector.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/effector/core/AddChildrenEffector.java b/core/src/main/java/org/apache/brooklyn/effector/core/AddChildrenEffector.java deleted file mode 100644 index 8a96e37..0000000 --- a/core/src/main/java/org/apache/brooklyn/effector/core/AddChildrenEffector.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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.effector.core; - -import java.util.List; -import java.util.Map; - -import org.apache.brooklyn.api.effector.Effector; -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.config.ConfigKey; -import org.apache.brooklyn.core.config.ConfigKeys; -import org.apache.brooklyn.core.mgmt.EntityManagementUtils; -import org.apache.brooklyn.core.mgmt.EntityManagementUtils.CreationResult; -import org.apache.brooklyn.effector.core.Effectors.EffectorBuilder; -import org.apache.brooklyn.util.core.config.ConfigBag; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.annotations.Beta; -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); - CreationResult<List<Entity>, List<String>> result = EntityManagementUtils.addChildren(entity(), blueprint, autostart); - log.debug(this+" added children to "+entity()+": "+result.get()); - return result.task().getUnchecked(); - } - } - -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/main/java/org/apache/brooklyn/effector/core/AddEffector.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/effector/core/AddEffector.java b/core/src/main/java/org/apache/brooklyn/effector/core/AddEffector.java deleted file mode 100644 index 44f1d04..0000000 --- a/core/src/main/java/org/apache/brooklyn/effector/core/AddEffector.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * 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.effector.core; - -import java.util.Collections; -import java.util.Map; - -import org.apache.brooklyn.api.effector.Effector; -import org.apache.brooklyn.api.effector.ParameterType; -import org.apache.brooklyn.api.entity.EntityInitializer; -import org.apache.brooklyn.api.entity.EntityLocal; -import org.apache.brooklyn.config.ConfigKey; -import org.apache.brooklyn.core.config.ConfigKeys; -import org.apache.brooklyn.core.config.MapConfigKey; -import org.apache.brooklyn.core.entity.EntityInternal; -import org.apache.brooklyn.effector.core.Effectors.EffectorBuilder; -import org.apache.brooklyn.util.core.config.ConfigBag; -import org.apache.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. - * <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 { - - public static final ConfigKey<String> EFFECTOR_NAME = ConfigKeys.newStringConfigKey("name"); - public static final ConfigKey<String> EFFECTOR_DESCRIPTION = ConfigKeys.newStringConfigKey("description"); - - public static final ConfigKey<Map<String,Object>> EFFECTOR_PARAMETER_DEFS = new MapConfigKey<Object>(Object.class, "parameters"); - - final Effector<?> effector; - - public AddEffector(Effector<?> effector) { - this.effector = Preconditions.checkNotNull(effector, "effector"); - } - - @Override - public void apply(EntityLocal entity) { - ((EntityInternal)entity).getMutableEntityType().addEffector(effector); - } - - public static <T> EffectorBuilder<T> newEffectorBuilder(Class<T> type, ConfigBag params) { - String name = Preconditions.checkNotNull(params.get(EFFECTOR_NAME), "name must be supplied when defining an effector: %s", params); - EffectorBuilder<T> eff = Effectors.effector(type, name); - eff.description(params.get(EFFECTOR_DESCRIPTION)); - - Map<String, Object> paramDefs = params.get(EFFECTOR_PARAMETER_DEFS); - if (paramDefs!=null) { - for (Map.Entry<String, Object> paramDef: paramDefs.entrySet()){ - if (paramDef!=null) { - String paramName = paramDef.getKey(); - Object value = paramDef.getValue(); - if (value==null) value = Collections.emptyMap(); - if (!(value instanceof Map)) { - if (value instanceof CharSequence && Strings.isBlank((CharSequence) value)) - value = Collections.emptyMap(); - } - if (!(value instanceof Map)) - throw new IllegalArgumentException("Illegal argument of type "+value.getClass()+" value '"+value+"' supplied as parameter definition " - + "'"+paramName); - eff.parameter(ConfigKeys.DynamicKeys.newNamedInstance(paramName, (Map<?, ?>) value)); - } - } - } - - 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/8dbb0e4b/core/src/main/java/org/apache/brooklyn/effector/core/AddSensor.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/effector/core/AddSensor.java b/core/src/main/java/org/apache/brooklyn/effector/core/AddSensor.java deleted file mode 100644 index 84c2239..0000000 --- a/core/src/main/java/org/apache/brooklyn/effector/core/AddSensor.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * 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.effector.core; - -import java.util.Map; - -import org.apache.brooklyn.api.entity.EntityInitializer; -import org.apache.brooklyn.api.entity.EntityLocal; -import org.apache.brooklyn.api.sensor.AttributeSensor; -import org.apache.brooklyn.config.ConfigKey; -import org.apache.brooklyn.core.config.ConfigKeys; -import org.apache.brooklyn.core.entity.EntityInternal; -import org.apache.brooklyn.sensor.core.Sensors; -import org.apache.brooklyn.util.core.config.ConfigBag; -import org.apache.brooklyn.util.guava.Maybe; -import org.apache.brooklyn.util.javalang.Boxing; -import org.apache.brooklyn.util.time.Duration; - -import com.google.common.annotations.Beta; -import com.google.common.base.Preconditions; - -/** - * Creates a new {@link AttributeSensor} on an entity. - * <p> - * The configuration can include the sensor {@code name}, {@code period} and {@code targetType}. - * For the targetType, currently this only supports classes on the initial classpath, not those in - * OSGi bundles added at runtime. - * - * @since 0.7.0 - */ -@Beta -public class AddSensor<T> implements EntityInitializer { - - public static final ConfigKey<String> SENSOR_NAME = ConfigKeys.newStringConfigKey("name", "The name of the sensor to create"); - public static final ConfigKey<Duration> SENSOR_PERIOD = ConfigKeys.newConfigKey(Duration.class, "period", "Period, including units e.g. 1m or 5s or 200ms; default 5 minutes", Duration.FIVE_MINUTES); - public static final ConfigKey<String> SENSOR_TYPE = ConfigKeys.newStringConfigKey("targetType", "Target type for the value; default String", "java.lang.String"); - - protected final String name; - protected final Duration period; - protected final String type; - protected final AttributeSensor<T> sensor; - - public AddSensor(Map<String, String> params) { - this(ConfigBag.newInstance(params)); - } - - public AddSensor(final ConfigBag params) { - this.name = Preconditions.checkNotNull(params.get(SENSOR_NAME), "Name must be supplied when defining a sensor"); - this.period = params.get(SENSOR_PERIOD); - this.type = params.get(SENSOR_TYPE); - this.sensor = newSensor(); - } - - @Override - public void apply(EntityLocal entity) { - ((EntityInternal) entity).getMutableEntityType().addSensor(sensor); - } - - private AttributeSensor<T> newSensor() { - String className = getFullClassName(type); - Class<T> clazz = getType(className); - return Sensors.newSensor(clazz, name); - } - - @SuppressWarnings("unchecked") - protected Class<T> getType(String className) { - try { - // TODO use OSGi loader (low priority however); also ensure that allows primitives - Maybe<Class<?>> primitive = Boxing.getPrimitiveType(className); - if (primitive.isPresent()) return (Class<T>) primitive.get(); - return (Class<T>) Class.forName(className); - } catch (ClassNotFoundException e) { - if (!className.contains(".")) { - // could be assuming "java.lang" package; try again with that - try { - return (Class<T>) Class.forName("java.lang."+className); - } catch (ClassNotFoundException e2) { - throw new IllegalArgumentException("Invalid target type for sensor "+name+": " + className+" (also tried java.lang."+className+")"); - } - } else { - throw new IllegalArgumentException("Invalid target type for sensor "+name+": " + className); - } - } - } - - protected String getFullClassName(String className) { - if (className.equalsIgnoreCase("string")) { - return "java.lang.String"; - } else if (className.equalsIgnoreCase("int") || className.equalsIgnoreCase("integer")) { - return "java.lang.Integer"; - } else if (className.equalsIgnoreCase("long")) { - return "java.lang.Long"; - } else if (className.equalsIgnoreCase("float")) { - return "java.lang.Float"; - } else if (className.equalsIgnoreCase("double")) { - return "java.lang.Double"; - } else if (className.equalsIgnoreCase("bool") || className.equalsIgnoreCase("boolean")) { - return "java.lang.Boolean"; - } else if (className.equalsIgnoreCase("byte")) { - return "java.lang.Byte"; - } else if (className.equalsIgnoreCase("char") || className.equalsIgnoreCase("character")) { - return "java.lang.Character"; - } else if (className.equalsIgnoreCase("object")) { - return "java.lang.Object"; - } else { - return className; - } - } - -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/main/java/org/apache/brooklyn/effector/core/BasicParameterType.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/effector/core/BasicParameterType.java b/core/src/main/java/org/apache/brooklyn/effector/core/BasicParameterType.java deleted file mode 100644 index 2367cd0..0000000 --- a/core/src/main/java/org/apache/brooklyn/effector/core/BasicParameterType.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * 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.effector.core; - -import java.util.Collections; -import java.util.Map; - -import org.apache.brooklyn.api.effector.ParameterType; - -import com.google.common.base.Objects; - -public class BasicParameterType<T> implements ParameterType<T> { - private static final long serialVersionUID = -5521879180483663919L; - - private String name; - private Class<T> type; - private String description; - private Boolean hasDefaultValue = null; - private T defaultValue = null; - - public BasicParameterType() { - this(Collections.emptyMap()); - } - - @SuppressWarnings("unchecked") - public BasicParameterType(Map<?, ?> arguments) { - if (arguments.containsKey("name")) name = (String) arguments.get("name"); - if (arguments.containsKey("type")) type = (Class<T>) arguments.get("type"); - if (arguments.containsKey("description")) description = (String) arguments.get("description"); - if (arguments.containsKey("defaultValue")) defaultValue = (T) arguments.get("defaultValue"); - } - - public BasicParameterType(String name, Class<T> type) { - this(name, type, null, null, false); - } - - public BasicParameterType(String name, Class<T> type, String description) { - this(name, type, description, null, false); - } - - public BasicParameterType(String name, Class<T> type, String description, T defaultValue) { - this(name, type, description, defaultValue, true); - } - - public BasicParameterType(String name, Class<T> type, String description, T defaultValue, boolean hasDefaultValue) { - this.name = name; - this.type = type; - this.description = description; - this.defaultValue = defaultValue; - if (defaultValue!=null && !defaultValue.getClass().equals(Object.class)) { - // if default value is null (or is an Object, which is ambiguous on resolution to to rebind), - // don't bother to set this as it creates noise in the persistence files - this.hasDefaultValue = hasDefaultValue; - } - } - - @Override - public String getName() { return name; } - - @Override - public Class<T> getParameterClass() { return type; } - - @Override - public String getParameterClassName() { return type.getCanonicalName(); } - - @Override - public String getDescription() { return description; } - - @Override - public T getDefaultValue() { - return hasDefaultValue() ? defaultValue : null; - } - - public boolean hasDefaultValue() { - // a new Object() was previously used to indicate no default value, but that doesn't work well across serialization boundaries! - return hasDefaultValue!=null ? hasDefaultValue : defaultValue!=null && !defaultValue.getClass().equals(Object.class); - } - - @Override - public String toString() { - return Objects.toStringHelper(this).omitNullValues() - .add("name", name).add("description", description).add("type", getParameterClassName()) - .add("defaultValue", defaultValue) - .toString(); - } - - @Override - public int hashCode() { - return Objects.hashCode(name, description, type, defaultValue); - } - - @Override - public boolean equals(Object obj) { - return (obj instanceof ParameterType) && - Objects.equal(name, ((ParameterType<?>)obj).getName()) && - Objects.equal(description, ((ParameterType<?>)obj).getDescription()) && - Objects.equal(type, ((ParameterType<?>)obj).getParameterClass()) && - Objects.equal(defaultValue, ((ParameterType<?>)obj).getDefaultValue()); - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/main/java/org/apache/brooklyn/effector/core/EffectorAndBody.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/effector/core/EffectorAndBody.java b/core/src/main/java/org/apache/brooklyn/effector/core/EffectorAndBody.java deleted file mode 100644 index 71fbadb..0000000 --- a/core/src/main/java/org/apache/brooklyn/effector/core/EffectorAndBody.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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.effector.core; - -import java.util.List; - -import org.apache.brooklyn.api.effector.Effector; -import org.apache.brooklyn.api.effector.ParameterType; -import org.apache.brooklyn.effector.core.EffectorTasks.EffectorTaskFactory; - -import com.google.common.annotations.Beta; -import com.google.common.base.Objects; - -@Beta // added in 0.6.0 -public class EffectorAndBody<T> extends EffectorBase<T> implements EffectorWithBody<T> { - - private static final long serialVersionUID = -6023389678748222968L; - private final EffectorTaskFactory<T> body; - - public EffectorAndBody(Effector<T> original, EffectorTaskFactory<T> body) { - this(original.getName(), original.getReturnType(), original.getParameters(), original.getDescription(), body); - } - - public EffectorAndBody(String name, Class<T> returnType, List<ParameterType<?>> parameters, String description, EffectorTaskFactory<T> body) { - super(name, returnType, parameters, description); - this.body = body; - } - - @Override - public EffectorTaskFactory<T> getBody() { - return body; - } - - @Override - public int hashCode() { - return Objects.hashCode(super.hashCode(), getBody()); - } - - @Override - public boolean equals(Object other) { - return super.equals(other) && Objects.equal(getBody(), ((EffectorAndBody<?>)other).getBody()); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/main/java/org/apache/brooklyn/effector/core/EffectorBase.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/effector/core/EffectorBase.java b/core/src/main/java/org/apache/brooklyn/effector/core/EffectorBase.java deleted file mode 100644 index 511b50b..0000000 --- a/core/src/main/java/org/apache/brooklyn/effector/core/EffectorBase.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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.effector.core; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.brooklyn.api.effector.Effector; -import org.apache.brooklyn.api.effector.ParameterType; -import org.apache.brooklyn.effector.core.EffectorTasks.EffectorTaskFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.Joiner; -import com.google.common.base.Objects; - -/** concrete implementation of Effector interface, - * but not (at this level of the hirarchy) defining an implementation - * (see {@link EffectorTaskFactory} and {@link EffectorWithBody}) */ -public class EffectorBase<T> implements Effector<T> { - - @SuppressWarnings("unused") - private static final Logger log = LoggerFactory.getLogger(EffectorBase.class); - - private static final long serialVersionUID = -4153962199078384835L; - - private final String name; - private final Class<T> returnType; - private final List<ParameterType<?>> parameters; - private final String description; - - public EffectorBase(String name, Class<T> returnType, List<ParameterType<?>> parameters, String description) { - this.name = name; - this.returnType = returnType; - this.parameters = new ArrayList<ParameterType<?>>(parameters); - this.description = description; - } - - @Override - public String getName() { - return name; - } - - @Override - public Class<T> getReturnType() { - return returnType; - } - - @Override - public String getReturnTypeName() { - return returnType.getCanonicalName(); - } - - @Override - public List<ParameterType<?>> getParameters() { - return parameters; - } - - @Override - public String getDescription() { - return description; - } - - @Override - public String toString() { - List<String> parameterNames = new ArrayList<String>(parameters.size()); - for (ParameterType<?> parameter: parameters) { - String parameterName = (parameter.getName() != null) ? parameter.getName() : "<unknown>"; - parameterNames.add(parameterName); - } - return name+"["+Joiner.on(",").join(parameterNames)+"]"; - } - - @Override - public int hashCode() { - return Objects.hashCode(name, returnType, parameters, description); - } - - @Override - public boolean equals(Object other) { - if (!(other instanceof EffectorBase)) return false; - if (!(other.getClass().equals(getClass()))) return false; - if (!Objects.equal(hashCode(), other.hashCode())) return false; - return Objects.equal(getName(), ((EffectorBase<?>)other).getName()) && - Objects.equal(getReturnType(), ((EffectorBase<?>)other).getReturnType()) && - Objects.equal(getParameters(), ((EffectorBase<?>)other).getParameters()) && - Objects.equal(getDescription(), ((EffectorBase<?>)other).getDescription()); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/main/java/org/apache/brooklyn/effector/core/EffectorBody.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/effector/core/EffectorBody.java b/core/src/main/java/org/apache/brooklyn/effector/core/EffectorBody.java deleted file mode 100644 index 099bc71..0000000 --- a/core/src/main/java/org/apache/brooklyn/effector/core/EffectorBody.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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.effector.core; - -import org.apache.brooklyn.api.mgmt.Task; -import org.apache.brooklyn.api.mgmt.TaskAdaptable; -import org.apache.brooklyn.api.mgmt.TaskFactory; -import org.apache.brooklyn.core.entity.EntityInternal; -import org.apache.brooklyn.core.mgmt.BrooklynTaskTags; -import org.apache.brooklyn.util.core.config.ConfigBag; -import org.apache.brooklyn.util.core.flags.TypeCoercions; -import org.apache.brooklyn.util.core.task.DynamicSequentialTask; -import org.apache.brooklyn.util.core.task.DynamicTasks; -import org.apache.brooklyn.util.core.task.Tasks; - -import com.google.common.annotations.Beta; - -/** Typical implementations override {@link #main(ConfigBag)} to do the work of the effector - * <p> - * See also {@link EffectorTasks}: possibly this will be deleted in preference for an approach based on {@link EffectorTasks}. - * - * @since 0.6.0 - **/ -@Beta -public abstract class EffectorBody<T> { - /** Does the work of the effector, either in place, or (better) by building up - * subtasks, which can by added using {@link DynamicTasks} methods - * (and various convenience methods which do that automatically; see subclasses of EffectorBody - * for more info on usage; or see {@link DynamicSequentialTask} for details of the threading model - * by which added tasks are placed in a secondary thread) - * <p> - * The associated entity can be accessed through the {@link #entity()} method. - */ - public abstract T call(ConfigBag parameters); - - // NB: we could also support an 'init' method which is done at creation, - // as a place where implementers can describe the structure of the task before it executes - // (and init gets invoked in EffectorBodyTaskFactory.newTask _before_ the task is submitted and main is called) - - - // ---- convenience method(s) for implementers of main -- see subclasses and *Tasks statics for more - - protected EntityInternal entity() { - return (EntityInternal) BrooklynTaskTags.getTargetOrContextEntity(Tasks.current()); - } - - protected <V extends TaskAdaptable<?>> V queue(V task) { - return DynamicTasks.queue(task); - } - - protected <V extends TaskAdaptable<?>> void queue(V task1, V task2, V ...tasks) { - DynamicTasks.queue(task1); - DynamicTasks.queue(task2); - for (V task: tasks) - DynamicTasks.queue(task); - } - - protected <V extends TaskFactory<?>> void queue(V task1, V task2, V ...tasks) { - DynamicTasks.queue(task1.newTask()); - DynamicTasks.queue(task2.newTask()); - for (V task: tasks) - DynamicTasks.queue(task.newTask()); - } - - protected <U extends TaskAdaptable<?>> U queue(TaskFactory<U> task) { - return DynamicTasks.queue(task.newTask()); - } - - /** see {@link DynamicTasks#waitForLast()} */ - protected Task<?> waitForLast() { - return DynamicTasks.waitForLast(); - } - - /** Returns the result of the last task queued in this context, coerced to the given type */ - protected <V> V last(Class<V> type) { - Task<?> last = waitForLast(); - if (last==null) - throw new IllegalStateException("No last task available (in "+DynamicTasks.getTaskQueuingContext()+")"); - if (!Tasks.isQueuedOrSubmitted(last)) - throw new IllegalStateException("Last task "+last+" has not been queued or submitted; will not block on its result"); - - return TypeCoercions.coerce(last.getUnchecked(), type); - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/main/java/org/apache/brooklyn/effector/core/EffectorTasks.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/effector/core/EffectorTasks.java b/core/src/main/java/org/apache/brooklyn/effector/core/EffectorTasks.java deleted file mode 100644 index 249da53..0000000 --- a/core/src/main/java/org/apache/brooklyn/effector/core/EffectorTasks.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * 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.effector.core; - -import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.atomic.AtomicReference; - -import org.apache.brooklyn.api.effector.Effector; -import org.apache.brooklyn.api.effector.ParameterType; -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.mgmt.Task; -import org.apache.brooklyn.api.mgmt.TaskAdaptable; -import org.apache.brooklyn.config.ConfigKey; -import org.apache.brooklyn.core.config.ConfigKeys; -import org.apache.brooklyn.core.location.Machines; -import org.apache.brooklyn.core.mgmt.BrooklynTaskTags; -import org.apache.brooklyn.core.mgmt.internal.EffectorUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.apache.brooklyn.location.ssh.SshMachineLocation; -import org.apache.brooklyn.location.winrm.WinRmMachineLocation; -import org.apache.brooklyn.util.core.config.ConfigBag; -import org.apache.brooklyn.util.core.task.DynamicSequentialTask; -import org.apache.brooklyn.util.core.task.DynamicTasks; -import org.apache.brooklyn.util.core.task.TaskBuilder; -import org.apache.brooklyn.util.core.task.Tasks; -import org.apache.brooklyn.util.javalang.Reflections; - -import com.google.common.annotations.Beta; -import com.google.common.base.Preconditions; - -/** - * Miscellaneous tasks which are useful in effectors. - * @since 0.6.0 - */ -@Beta -public class EffectorTasks { - - @SuppressWarnings("unused") - private static final Logger log = LoggerFactory.getLogger(EffectorTasks.class); - - public interface EffectorTaskFactory<T> { - public abstract TaskAdaptable<T> newTask(Entity entity, Effector<T> effector, ConfigBag parameters); - } - - /** wrapper for {@link EffectorBody} which simply runs that body on each invocation; - * the body must be thread safe and ideally stateless */ - public static class EffectorBodyTaskFactory<T> implements EffectorTaskFactory<T> { - private final EffectorBody<T> effectorBody; - public EffectorBodyTaskFactory(EffectorBody<T> effectorBody) { - this.effectorBody = effectorBody; - } - - @Override - public Task<T> newTask(final Entity entity, final org.apache.brooklyn.api.effector.Effector<T> effector, final ConfigBag parameters) { - final AtomicReference<DynamicSequentialTask<T>> dst = new AtomicReference<DynamicSequentialTask<T>>(); - - dst.set(new DynamicSequentialTask<T>( - getFlagsForTaskInvocationAt(entity, effector, parameters), - new Callable<T>() { - @Override - public T call() throws Exception { - try { - DynamicTasks.setTaskQueueingContext(dst.get()); - return effectorBody.call(parameters); - } finally { - DynamicTasks.removeTaskQueueingContext(); - } - } - }) { - @Override - public void handleException(Throwable throwable) throws Exception { - EffectorUtils.handleEffectorException(entity, effector, throwable); - } - }); - return dst.get(); - }; - - /** @deprecated since 0.7.0 use {@link #getFlagsForTaskInvocationAt(Entity, Effector, ConfigBag)} */ @Deprecated - protected final Map<Object,Object> getFlagsForTaskInvocationAt(Entity entity, Effector<?> effector) { - return getFlagsForTaskInvocationAt(entity, effector, null); - } - /** subclasses may override to add additional flags, but they should include the flags returned here - * unless there is very good reason not to; default impl returns a MutableMap */ - protected Map<Object,Object> getFlagsForTaskInvocationAt(Entity entity, Effector<?> effector, ConfigBag parameters) { - return EffectorUtils.getTaskFlagsForEffectorInvocation(entity, effector, parameters); - } - } - - /** wrapper for {@link EffectorTaskFactory} which ensures effector task tags are applied to it if needed - * (wrapping in a task if needed); without this, {@link EffectorBody}-based effectors get it by - * virtue of the call to {@link #getFlagsForTaskInvocationAt(Entity,Effector,ConfigBag)} therein - * but {@link EffectorTaskFactory}-based effectors generate a task without the right tags - * to be able to tell using {@link BrooklynTaskTags} the effector-context of the task - * <p> - * this gets applied automatically so marked as package-private */ - static class EffectorMarkingTaskFactory<T> implements EffectorTaskFactory<T> { - private final EffectorTaskFactory<T> effectorTaskFactory; - public EffectorMarkingTaskFactory(EffectorTaskFactory<T> effectorTaskFactory) { - this.effectorTaskFactory = effectorTaskFactory; - } - - @Override - public Task<T> newTask(final Entity entity, final org.apache.brooklyn.api.effector.Effector<T> effector, final ConfigBag parameters) { - if (effectorTaskFactory instanceof EffectorBodyTaskFactory) - return effectorTaskFactory.newTask(entity, effector, parameters).asTask(); - // if we're in an effector context for this effector already, then also pass through - if (BrooklynTaskTags.isInEffectorTask(Tasks.current(), entity, effector, false)) - return effectorTaskFactory.newTask(entity, effector, parameters).asTask(); - // otherwise, create the task inside an appropriate effector body so tags, name, etc are set correctly - return new EffectorBodyTaskFactory<T>(new EffectorBody<T>() { - @Override - public T call(ConfigBag parameters) { - TaskAdaptable<T> t = DynamicTasks.queue(effectorTaskFactory.newTask(entity, effector, parameters)); - return t.asTask().getUnchecked(); - } - }).newTask(entity, effector, parameters); - } - } - - public static <T> ConfigKey<T> asConfigKey(ParameterType<T> t) { - return ConfigKeys.newConfigKey(t.getParameterClass(), t.getName()); - } - - public static <T> ParameterTask<T> parameter(ParameterType<T> t) { - return new ParameterTask<T>(asConfigKey(t)). - name("parameter "+t); - } - public static <T> ParameterTask<T> parameter(Class<T> type, String name) { - return new ParameterTask<T>(ConfigKeys.newConfigKey(type, name)). - name("parameter "+name+" ("+type+")"); - } - public static <T> ParameterTask<T> parameter(final ConfigKey<T> p) { - return new ParameterTask<T>(p); - } - public static class ParameterTask<T> implements EffectorTaskFactory<T> { - final ConfigKey<T> p; - private TaskBuilder<T> builder; - public ParameterTask(ConfigKey<T> p) { - this.p = p; - this.builder = Tasks.<T>builder().name("parameter "+p); - } - public ParameterTask<T> name(String taskName) { - builder.name(taskName); - return this; - } - @Override - public Task<T> newTask(Entity entity, Effector<T> effector, final ConfigBag parameters) { - return builder.body(new Callable<T>() { - @Override - public T call() throws Exception { - return parameters.get(p); - } - - }).build(); - } - - } - - public static <T> EffectorTaskFactory<T> of(final Task<T> task) { - return new EffectorTaskFactory<T>() { - @Override - public Task<T> newTask(Entity entity, Effector<T> effector, ConfigBag parameters) { - return task; - } - }; - } - - /** Finds the entity where this task is running - * @throws NullPointerException if there is none (no task, or no context entity for that task) */ - public static Entity findEntity() { - return Preconditions.checkNotNull(BrooklynTaskTags.getTargetOrContextEntity(Tasks.current()), - "This must be executed in a task whose execution context has a target or context entity " + - "(i.e. it must be run from within an effector)"); - } - - /** Finds the entity where this task is running, casted to the given Entity subtype - * @throws NullPointerException if there is none - * @throws IllegalArgumentException if it is not of the indicated type */ - public static <T extends Entity> T findEntity(Class<T> type) { - Entity t = findEntity(); - return Reflections.cast(t, type); - } - - /** Finds a unique {@link SshMachineLocation} attached to the entity - * where this task is running - * @throws NullPointerException if {@link #findEntity()} fails - * @throws IllegalStateException if call to {@link #getSshMachine(Entity)} fails */ - public static SshMachineLocation findSshMachine() { - return getSshMachine(findEntity()); - } - - /** Finds a unique {@link SshMachineLocation} attached to the supplied entity - * @throws IllegalStateException if there is not a unique such {@link SshMachineLocation} */ - public static SshMachineLocation getSshMachine(Entity entity) { - try { - return Machines.findUniqueSshMachineLocation(entity.getLocations()).get(); - } catch (Exception e) { - throw new IllegalStateException("Entity "+entity+" (in "+Tasks.current()+") requires a single SshMachineLocation, but has "+entity.getLocations(), e); - } - } - - /** Finds a unique {@link WinRmMachineLocation} attached to the supplied entity - * @throws IllegalStateException if there is not a unique such {@link WinRmMachineLocation} */ - public static WinRmMachineLocation getWinRmMachine(Entity entity) { - try { - return Machines.findUniqueWinRmMachineLocation(entity.getLocations()).get(); - } catch (Exception e) { - throw new IllegalStateException("Entity "+entity+" (in "+Tasks.current()+") requires a single WinRmMachineLocation, but has "+entity.getLocations(), e); - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8dbb0e4b/core/src/main/java/org/apache/brooklyn/effector/core/EffectorWithBody.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/effector/core/EffectorWithBody.java b/core/src/main/java/org/apache/brooklyn/effector/core/EffectorWithBody.java deleted file mode 100644 index 6ba2d30..0000000 --- a/core/src/main/java/org/apache/brooklyn/effector/core/EffectorWithBody.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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.effector.core; - -import org.apache.brooklyn.api.effector.Effector; -import org.apache.brooklyn.effector.core.EffectorTasks.EffectorTaskFactory; - -import com.google.common.annotations.Beta; - -@Beta // added in 0.6.0 -public interface EffectorWithBody<T> extends Effector<T> { - - /** returns the body of the effector, i.e. a factory which can generate tasks which can run */ - public EffectorTaskFactory<T> getBody(); - -}
