You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by ha...@apache.org on 2015/08/17 21:17:32 UTC
[01/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/policy
Repository: incubator-brooklyn
Updated Branches:
refs/heads/master ff7f58041 -> 6eacb3c38
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/policy/src/main/java/brooklyn/policy/autoscaling/AutoScalerPolicy.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/policy/autoscaling/AutoScalerPolicy.java b/policy/src/main/java/brooklyn/policy/autoscaling/AutoScalerPolicy.java
index 9da5e12..18480bd 100644
--- a/policy/src/main/java/brooklyn/policy/autoscaling/AutoScalerPolicy.java
+++ b/policy/src/main/java/brooklyn/policy/autoscaling/AutoScalerPolicy.java
@@ -40,6 +40,7 @@ import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.core.util.flags.TypeCoercions;
import org.apache.brooklyn.core.util.task.Tasks;
@@ -52,7 +53,6 @@ import brooklyn.entity.trait.Startable;
import brooklyn.event.basic.BasicConfigKey;
import brooklyn.event.basic.BasicNotificationSensor;
import brooklyn.policy.autoscaling.SizeHistory.WindowSummary;
-import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.policy.loadbalancing.LoadBalancingPolicy;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/policy/src/main/java/brooklyn/policy/followthesun/FollowTheSunPolicy.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/policy/followthesun/FollowTheSunPolicy.java b/policy/src/main/java/brooklyn/policy/followthesun/FollowTheSunPolicy.java
index dde1609..b76682c 100644
--- a/policy/src/main/java/brooklyn/policy/followthesun/FollowTheSunPolicy.java
+++ b/policy/src/main/java/brooklyn/policy/followthesun/FollowTheSunPolicy.java
@@ -38,12 +38,12 @@ import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.entity.basic.Attributes;
-import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.policy.followthesun.FollowTheSunPool.ContainerItemPair;
import brooklyn.policy.loadbalancing.Movable;
import brooklyn.util.collections.MutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/policy/src/main/java/brooklyn/policy/ha/AbstractFailureDetector.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/policy/ha/AbstractFailureDetector.java b/policy/src/main/java/brooklyn/policy/ha/AbstractFailureDetector.java
index 0c2f4d2..9d8c58f 100644
--- a/policy/src/main/java/brooklyn/policy/ha/AbstractFailureDetector.java
+++ b/policy/src/main/java/brooklyn/policy/ha/AbstractFailureDetector.java
@@ -28,6 +28,7 @@ import java.util.concurrent.atomic.AtomicReference;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.core.util.task.BasicTask;
import org.apache.brooklyn.core.util.task.ScheduledTask;
@@ -38,7 +39,6 @@ import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.EntityInternal;
-import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.policy.ha.HASensors.FailureDescriptor;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/policy/src/main/java/brooklyn/policy/ha/ConditionalSuspendPolicy.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/policy/ha/ConditionalSuspendPolicy.java b/policy/src/main/java/brooklyn/policy/ha/ConditionalSuspendPolicy.java
index 9a869ae..b347949 100644
--- a/policy/src/main/java/brooklyn/policy/ha/ConditionalSuspendPolicy.java
+++ b/policy/src/main/java/brooklyn/policy/ha/ConditionalSuspendPolicy.java
@@ -23,13 +23,13 @@ import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.util.javalang.JavaClassNames;
import com.google.common.base.Preconditions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/policy/src/main/java/brooklyn/policy/ha/ServiceReplacer.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/policy/ha/ServiceReplacer.java b/policy/src/main/java/brooklyn/policy/ha/ServiceReplacer.java
index 884f2df..6bea1d4 100644
--- a/policy/src/main/java/brooklyn/policy/ha/ServiceReplacer.java
+++ b/policy/src/main/java/brooklyn/policy/ha/ServiceReplacer.java
@@ -35,6 +35,7 @@ import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.core.util.flags.SetFromFlag;
@@ -47,7 +48,6 @@ import brooklyn.entity.group.StopFailedRuntimeException;
import brooklyn.entity.trait.MemberReplaceable;
import brooklyn.event.basic.BasicConfigKey;
import brooklyn.event.basic.BasicNotificationSensor;
-import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.policy.ha.HASensors.FailureDescriptor;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/policy/src/main/java/brooklyn/policy/ha/ServiceRestarter.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/policy/ha/ServiceRestarter.java b/policy/src/main/java/brooklyn/policy/ha/ServiceRestarter.java
index d53434e..ab1359d 100644
--- a/policy/src/main/java/brooklyn/policy/ha/ServiceRestarter.java
+++ b/policy/src/main/java/brooklyn/policy/ha/ServiceRestarter.java
@@ -28,6 +28,7 @@ import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.core.util.flags.SetFromFlag;
@@ -39,7 +40,6 @@ import brooklyn.entity.basic.Lifecycle;
import brooklyn.entity.basic.ServiceStateLogic;
import brooklyn.entity.trait.Startable;
import brooklyn.event.basic.BasicNotificationSensor;
-import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.policy.ha.HASensors.FailureDescriptor;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.javalang.JavaClassNames;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/policy/src/main/java/brooklyn/policy/loadbalancing/LoadBalancingPolicy.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/policy/loadbalancing/LoadBalancingPolicy.java b/policy/src/main/java/brooklyn/policy/loadbalancing/LoadBalancingPolicy.java
index 2c50883..57b736b 100644
--- a/policy/src/main/java/brooklyn/policy/loadbalancing/LoadBalancingPolicy.java
+++ b/policy/src/main/java/brooklyn/policy/loadbalancing/LoadBalancingPolicy.java
@@ -35,6 +35,7 @@ import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -42,7 +43,6 @@ import org.slf4j.LoggerFactory;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.policy.autoscaling.AutoScalerPolicy;
-import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.policy.loadbalancing.BalanceableWorkerPool.ContainerItemPair;
import brooklyn.util.collections.MutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/TestReferencingPolicy.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/TestReferencingPolicy.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/TestReferencingPolicy.java
index f175e0d..d3f550b 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/TestReferencingPolicy.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/TestReferencingPolicy.java
@@ -19,10 +19,10 @@
package org.apache.brooklyn.camp.brooklyn;
import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import brooklyn.config.ConfigKey;
import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.policy.basic.AbstractPolicy;
public class TestReferencingPolicy extends AbstractPolicy {
public static final ConfigKey<Entity> TEST_APPLICATION = new BasicConfigKey<Entity>(Entity.class, "test.reference.app");
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/usage/cli/src/main/java/org/apache/brooklyn/cli/lister/ClassFinder.java
----------------------------------------------------------------------
diff --git a/usage/cli/src/main/java/org/apache/brooklyn/cli/lister/ClassFinder.java b/usage/cli/src/main/java/org/apache/brooklyn/cli/lister/ClassFinder.java
index 4d22b3f..e25b47a 100644
--- a/usage/cli/src/main/java/org/apache/brooklyn/cli/lister/ClassFinder.java
+++ b/usage/cli/src/main/java/org/apache/brooklyn/cli/lister/ClassFinder.java
@@ -31,6 +31,7 @@ import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import org.apache.brooklyn.core.util.ResourceUtils;
import org.apache.brooklyn.core.util.javalang.UrlClassLoader;
import org.reflections.Reflections;
@@ -45,7 +46,6 @@ import brooklyn.enricher.basic.AbstractEnricher;
import brooklyn.entity.basic.AbstractApplication;
import brooklyn.entity.basic.AbstractEntity;
import brooklyn.entity.basic.SoftwareProcessImpl;
-import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.util.net.Urls;
import brooklyn.util.os.Os;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/PolicyResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/PolicyResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/PolicyResource.java
index 31a3b99..c5ea74a 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/PolicyResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/PolicyResource.java
@@ -25,13 +25,11 @@ import javax.ws.rs.core.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
-import brooklyn.policy.basic.Policies;
-
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.policy.basic.Policies;
import org.apache.brooklyn.rest.api.PolicyApi;
import org.apache.brooklyn.rest.domain.PolicySummary;
import org.apache.brooklyn.rest.domain.Status;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/PolicyTransformer.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/PolicyTransformer.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/PolicyTransformer.java
index a43127c..35e62d6 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/PolicyTransformer.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/PolicyTransformer.java
@@ -22,11 +22,11 @@ import java.net.URI;
import java.util.Map;
import brooklyn.config.ConfigKey;
-import brooklyn.policy.basic.Policies;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.policy.basic.Policies;
import org.apache.brooklyn.rest.domain.ApplicationSummary;
import org.apache.brooklyn.rest.domain.PolicyConfigSummary;
import org.apache.brooklyn.rest.domain.PolicySummary;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
index d29b6e8..751eb22 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
@@ -53,6 +53,7 @@ import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.entitlement.Entitlements;
import org.apache.brooklyn.core.management.entitlement.Entitlements.StringAndArgument;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import org.apache.brooklyn.core.util.flags.TypeCoercions;
import brooklyn.config.ConfigKey;
@@ -64,7 +65,6 @@ import brooklyn.entity.basic.BasicApplication;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.trait.Startable;
-import brooklyn.policy.basic.AbstractPolicy;
import org.apache.brooklyn.rest.domain.ApplicationSpec;
import org.apache.brooklyn.rest.domain.EntitySpec;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/usage/rest-server/src/test/java/org/apache/brooklyn/rest/testing/mocks/CapitalizePolicy.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/testing/mocks/CapitalizePolicy.java b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/testing/mocks/CapitalizePolicy.java
index d324507..5881990 100644
--- a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/testing/mocks/CapitalizePolicy.java
+++ b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/testing/mocks/CapitalizePolicy.java
@@ -19,8 +19,7 @@
package org.apache.brooklyn.rest.testing.mocks;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
-
-import brooklyn.policy.basic.AbstractPolicy;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
public class CapitalizePolicy extends AbstractPolicy {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/usage/rest-server/src/test/java/org/apache/brooklyn/rest/testing/mocks/RestMockSimplePolicy.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/testing/mocks/RestMockSimplePolicy.java b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/testing/mocks/RestMockSimplePolicy.java
index d6e2b77..f1546ff 100644
--- a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/testing/mocks/RestMockSimplePolicy.java
+++ b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/testing/mocks/RestMockSimplePolicy.java
@@ -20,13 +20,13 @@ package org.apache.brooklyn.rest.testing.mocks;
import java.util.Map;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.config.ConfigKey;
import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.policy.basic.AbstractPolicy;
public class RestMockSimplePolicy extends AbstractPolicy {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/usage/rest-server/src/test/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtilsTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtilsTest.java b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtilsTest.java
index 484f6ab..2c5c1d6 100644
--- a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtilsTest.java
+++ b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtilsTest.java
@@ -36,12 +36,12 @@ import org.apache.brooklyn.core.catalog.internal.CatalogItemBuilder;
import org.apache.brooklyn.core.catalog.internal.CatalogTemplateItemDto;
import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import brooklyn.entity.basic.AbstractApplication;
import brooklyn.entity.basic.BasicEntity;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.proxying.EntityProxy;
-import brooklyn.policy.basic.AbstractPolicy;
import org.apache.brooklyn.rest.domain.ApplicationSpec;
import org.apache.brooklyn.rest.domain.EntitySpec;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/utils/test-bundles/entities/src/main/java/brooklyn/osgi/tests/SimplePolicy.java
----------------------------------------------------------------------
diff --git a/utils/test-bundles/entities/src/main/java/brooklyn/osgi/tests/SimplePolicy.java b/utils/test-bundles/entities/src/main/java/brooklyn/osgi/tests/SimplePolicy.java
index f70b60b..a034886 100644
--- a/utils/test-bundles/entities/src/main/java/brooklyn/osgi/tests/SimplePolicy.java
+++ b/utils/test-bundles/entities/src/main/java/brooklyn/osgi/tests/SimplePolicy.java
@@ -19,11 +19,11 @@
package brooklyn.osgi.tests;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.config.ConfigKey;
-import brooklyn.policy.basic.AbstractPolicy;
public class SimplePolicy extends AbstractPolicy {
@SetFromFlag("config1")
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/utils/test-bundles/more-entities-v1/src/main/java/brooklyn/osgi/tests/more/MorePolicy.java
----------------------------------------------------------------------
diff --git a/utils/test-bundles/more-entities-v1/src/main/java/brooklyn/osgi/tests/more/MorePolicy.java b/utils/test-bundles/more-entities-v1/src/main/java/brooklyn/osgi/tests/more/MorePolicy.java
index 50b5945..466d8e2 100644
--- a/utils/test-bundles/more-entities-v1/src/main/java/brooklyn/osgi/tests/more/MorePolicy.java
+++ b/utils/test-bundles/more-entities-v1/src/main/java/brooklyn/osgi/tests/more/MorePolicy.java
@@ -20,8 +20,7 @@ package brooklyn.osgi.tests.more;
import org.apache.brooklyn.api.catalog.Catalog;
-
-import brooklyn.policy.basic.AbstractPolicy;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
public class MorePolicy extends AbstractPolicy {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/utils/test-bundles/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MorePolicy.java
----------------------------------------------------------------------
diff --git a/utils/test-bundles/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MorePolicy.java b/utils/test-bundles/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MorePolicy.java
index 4bfa366..43c53b5 100644
--- a/utils/test-bundles/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MorePolicy.java
+++ b/utils/test-bundles/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MorePolicy.java
@@ -20,7 +20,7 @@ package brooklyn.osgi.tests.more;
import org.apache.brooklyn.api.catalog.Catalog;
-import brooklyn.policy.basic.AbstractPolicy;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
@Catalog(name="More Policy", description="Cataliog item OSGi test policy")
public class MorePolicy extends AbstractPolicy {
[28/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/flags/FlagUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/flags/FlagUtils.java b/core/src/main/java/org/apache/brooklyn/core/util/flags/FlagUtils.java
new file mode 100644
index 0000000..6f28f9b
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/flags/FlagUtils.java
@@ -0,0 +1,587 @@
+/*
+ * 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.util.flags;
+
+import static brooklyn.util.GroovyJavaMethods.elvis;
+import static brooklyn.util.GroovyJavaMethods.truth;
+import static com.google.common.base.Preconditions.checkNotNull;
+import groovy.lang.Closure;
+import groovy.lang.GroovyObject;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import org.apache.brooklyn.api.entity.trait.Configurable;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.config.ConfigKey.HasConfigKey;
+import brooklyn.util.GroovyJavaMethods;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.guava.Maybe;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.base.Throwables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+
+/** class to help transfer values passed as named arguments to other well-known variables/fields/objects;
+ * see the test case for example usage */
+public class FlagUtils {
+
+ public static final Logger log = LoggerFactory.getLogger(FlagUtils.class);
+
+ private FlagUtils() {}
+
+ /** see {@link #setFieldsFromFlags(Object o, ConfigBag)} */
+ public static Map<?, ?> setPublicFieldsFromFlags(Map<?, ?> flags, Object o) {
+ return setFieldsFromFlagsInternal(o, Arrays.asList(o.getClass().getFields()), flags, null, true);
+ }
+
+ /** see {@link #setFieldsFromFlags(Object, ConfigBag)} */
+ public static Map<?, ?> setFieldsFromFlags(Map<?, ?> flags, Object o) {
+ return setFieldsFromFlagsInternal(o, getAllFields(o.getClass()), flags, null, true);
+ }
+
+ /** sets all fields (including private and static, local and inherited) annotated {@link SetFromFlag} on the given object,
+ * from the given flags map, returning just those flag-value pairs passed in which do not correspond to SetFromFlags fields
+ * annotated ConfigKey and HasConfigKey fields are _configured_ (and we assume the object in that case is {@link Configurable});
+ * keys should be ConfigKey, HasConfigKey, or String;
+ * default values are also applied unless that is specified false on one of the variants of this method which takes such an argument
+ */
+ public static void setFieldsFromFlags(Object o, ConfigBag configBag) {
+ setFieldsFromFlagsInternal(o, getAllFields(o.getClass()), configBag.getAllConfig(), configBag, true);
+ }
+
+ /** as {@link #setFieldsFromFlags(Object, ConfigBag)}, but allowing control over whether default values should be set */
+ public static void setFieldsFromFlags(Object o, ConfigBag configBag, boolean setDefaultVals) {
+ setFieldsFromFlagsInternal(o, getAllFields(o.getClass()), configBag.getAllConfig(), configBag, setDefaultVals);
+ }
+
+ /** as {@link #setFieldsFromFlags(Object, ConfigBag)}, but specifying a subset of flags to use */
+ public static void setFieldsFromFlagsWithBag(Object o, Map<?,?> flags, ConfigBag configBag, boolean setDefaultVals) {
+ setFieldsFromFlagsInternal(o, getAllFields(o.getClass()), flags, configBag, setDefaultVals);
+ }
+
+ /**
+ * Sets the field with the given flag (if it exists) to the given value.
+ * Will attempt to coerce the value to the required type.
+ * Will respect "nullable" on the SetFromFlag annotation.
+ *
+ * @throws IllegalArgumentException If fieldVal is null and the SetFromFlag annotation set nullable=false
+ */
+ public static boolean setFieldFromFlag(Object o, String flagName, Object fieldVal) {
+ return setFieldFromFlagInternal(checkNotNull(flagName, "flagName"), fieldVal, o, getAllFields(o.getClass()));
+ }
+
+ /** get all fields (including private and static) on the given object and all supertypes,
+ * that are annotated with SetFromFlags.
+ */
+ public static Map<String, ?> getFieldsWithFlags(Object o) {
+ return getFieldsWithFlagsInternal(o, getAllFields(o.getClass()));
+ }
+
+ /**
+ * Finds the {@link Field} on the given object annotated with the given name flag.
+ */
+ public static Field findFieldForFlag(String flagName, Object o) {
+ return findFieldForFlagInternal(flagName, o, getAllFields(o.getClass()));
+ }
+
+ /** get all fields (including private and static) and their values on the given object and all supertypes,
+ * where the field is annotated with SetFromFlags.
+ */
+ public static Map<String, Object> getFieldsWithFlagsExcludingModifiers(Object o, int excludingModifiers) {
+ List<Field> filteredFields = Lists.newArrayList();
+ for (Field contender : getAllFields(o.getClass())) {
+ if ((contender.getModifiers() & excludingModifiers) == 0) {
+ filteredFields.add(contender);
+ }
+ }
+ return getFieldsWithFlagsInternal(o, filteredFields);
+ }
+
+ /** get all fields with the given modifiers, and their values on the given object and all supertypes,
+ * where the field is annotated with SetFromFlags.
+ */
+ public static Map<String, Object> getFieldsWithFlagsWithModifiers(Object o, int requiredModifiers) {
+ List<Field> filteredFields = Lists.newArrayList();
+ for (Field contender : getAllFields(o.getClass())) {
+ if ((contender.getModifiers() & requiredModifiers) == requiredModifiers) {
+ filteredFields.add(contender);
+ }
+ }
+ return getFieldsWithFlagsInternal(o, filteredFields);
+ }
+
+ /** sets _all_ accessible _{@link ConfigKey}_ and {@link HasConfigKey} fields on the given object,
+ * using the indicated flags/config-bag
+ * @deprecated since 0.7.0 use {@link #setAllConfigKeys(Map, Configurable, boolean)} */
+ public static Map<String, ?> setAllConfigKeys(Map<String, ?> flagsOrConfig, Configurable instance) {
+ return setAllConfigKeys(flagsOrConfig, instance, false);
+ }
+ /** sets _all_ accessible _{@link ConfigKey}_ and {@link HasConfigKey} fields on the given object,
+ * using the indicated flags/config-bag */
+ public static Map<String, ?> setAllConfigKeys(Map<String, ?> flagsOrConfig, Configurable instance, boolean includeFlags) {
+ ConfigBag bag = new ConfigBag().putAll(flagsOrConfig);
+ setAllConfigKeys(instance, bag, includeFlags);
+ return bag.getUnusedConfigMutable();
+ }
+
+ /** sets _all_ accessible _{@link ConfigKey}_ and {@link HasConfigKey} fields on the given object,
+ * using the indicated flags/config-bag
+ * @deprecated since 0.7.0 use {@link #setAllConfigKeys(Configurable, ConfigBag, boolean)} */
+ public static void setAllConfigKeys(Configurable o, ConfigBag bag) {
+ setAllConfigKeys(o, bag, false);
+ }
+ /** sets _all_ accessible _{@link ConfigKey}_ and {@link HasConfigKey} fields on the given object,
+ * using the indicated flags/config-bag */
+ public static void setAllConfigKeys(Configurable o, ConfigBag bag, boolean includeFlags) {
+ for (Field f: getAllFields(o.getClass())) {
+ ConfigKey<?> key = getFieldAsConfigKey(o, f);
+ if (key!=null) {
+ FlagConfigKeyAndValueRecord record = getFlagConfigKeyRecord(f, key, bag);
+ if ((includeFlags && record.isValuePresent()) || record.getConfigKeyMaybeValue().isPresent()) {
+ setField(o, f, record.getValueOrNullPreferringConfigKey(), null);
+ }
+ }
+ }
+ }
+
+ public static class FlagConfigKeyAndValueRecord {
+ private String flagName = null;
+ private ConfigKey<?> configKey = null;
+ private Maybe<Object> flagValue = Maybe.absent();
+ private Maybe<Object> configKeyValue = Maybe.absent();
+
+ public String getFlagName() {
+ return flagName;
+ }
+ public ConfigKey<?> getConfigKey() {
+ return configKey;
+ }
+ public Maybe<Object> getFlagMaybeValue() {
+ return flagValue;
+ }
+ public Maybe<Object> getConfigKeyMaybeValue() {
+ return configKeyValue;
+ }
+ public Object getValueOrNullPreferringConfigKey() {
+ return getConfigKeyMaybeValue().or(getFlagMaybeValue()).orNull();
+ }
+ public Object getValueOrNullPreferringFlag() {
+ return getFlagMaybeValue().or(getConfigKeyMaybeValue()).orNull();
+ }
+ /** true if value is present for either flag or config key */
+ public boolean isValuePresent() {
+ return flagValue.isPresent() || configKeyValue.isPresent();
+ }
+
+ @Override
+ public String toString() {
+ return Objects.toStringHelper(this).omitNullValues()
+ .add("flag", flagName)
+ .add("configKey", configKey)
+ .add("flagValue", flagValue.orNull())
+ .add("configKeyValue", configKeyValue.orNull())
+ .toString();
+ }
+ }
+
+ /** gets all the flags/keys in the given config bag which are applicable to the given type's config keys and flags */
+ public static <T> List<FlagConfigKeyAndValueRecord> findAllFlagsAndConfigKeys(T optionalInstance, Class<? extends T> type, ConfigBag input) {
+ List<FlagConfigKeyAndValueRecord> output = new ArrayList<FlagUtils.FlagConfigKeyAndValueRecord>();
+ for (Field f: getAllFields(type)) {
+ ConfigKey<?> key = getFieldAsConfigKey(optionalInstance, f);
+ FlagConfigKeyAndValueRecord record = getFlagConfigKeyRecord(f, key, input);
+ if (record.isValuePresent())
+ output.add(record);
+ }
+ return output;
+ }
+
+ /** returns the flag/config-key record for the given input */
+ private static FlagConfigKeyAndValueRecord getFlagConfigKeyRecord(Field f, ConfigKey<?> key, ConfigBag input) {
+ FlagConfigKeyAndValueRecord result = new FlagConfigKeyAndValueRecord();
+ result.configKey = key;
+ if (key!=null && input.containsKey(key))
+ result.configKeyValue = Maybe.<Object>of(input.getStringKey(key.getName()));
+ SetFromFlag flag = f.getAnnotation(SetFromFlag.class);
+ if (flag!=null) {
+ result.flagName = flag.value();
+ if (input.containsKey(flag.value()))
+ result.flagValue = Maybe.of(input.getStringKey(flag.value()));
+ }
+ return result;
+ }
+
+ /** returns all fields on the given class, superclasses, and interfaces thereof, in that order of preference,
+ * (excluding fields on Object) */
+ public static List<Field> getAllFields(Class<?> base, Closure<Boolean> filter) {
+ return getAllFields(base, GroovyJavaMethods.<Field>predicateFromClosure(filter));
+ }
+ public static List<Field> getAllFields(Class<?> base) {
+ return getAllFields(base, Predicates.<Field>alwaysTrue());
+ }
+ public static List<Field> getAllFields(Class<?> base, Predicate<Field> filter) {
+ return getLocalFields(getAllAssignableTypes(base), filter);
+ }
+ /** returns all fields explicitly declared on the given classes */
+ public static List<Field> getLocalFields(List<Class<?>> classes) {
+ return getLocalFields(classes, Predicates.<Field>alwaysTrue());
+ }
+ public static List<Field> getLocalFields(List<Class<?>> classes, Closure<Boolean> filter) {
+ return getLocalFields(classes, GroovyJavaMethods.<Field>predicateFromClosure(filter));
+ }
+ public static List<Field> getLocalFields(List<Class<?>> classes, Predicate<Field> filter) {
+ List<Field> fields = Lists.newArrayList();
+ for (Class<?> c : classes) {
+ for (Field f : c.getDeclaredFields()) {
+ if (filter.apply(f)) fields.add(f);
+ }
+ }
+ return fields;
+ }
+
+ /** returns base, superclasses, then interfaces */
+ public static List<Class<?>> getAllAssignableTypes(Class<?> base) {
+ return getAllAssignableTypes(base, new Predicate<Class<?>>() {
+ @Override public boolean apply(Class<?> it) {
+ return (it != Object.class) && (it != GroovyObject.class);
+ }
+ });
+ }
+ public static List<Class<?>> getAllAssignableTypes(Class<?> base, Closure<Boolean> filter) {
+ return getAllAssignableTypes(base, GroovyJavaMethods.<Class<?>>predicateFromClosure(filter));
+ }
+ public static List<Class<?>> getAllAssignableTypes(Class<?> base, Predicate<Class<?>> filter) {
+ List<Class<?>> classes = Lists.newArrayList();
+ for (Class<?> c = base; c != null; c = c.getSuperclass()) {
+ if (filter.apply(c)) classes.add(c);
+ }
+ for (int i=0; i<classes.size(); i++) {
+ for (Class<?> interf : classes.get(i).getInterfaces()) {
+ if (filter.apply(interf) && !(classes.contains(interf))) classes.add(interf);
+ }
+ }
+ return classes;
+ }
+
+ private static Map<String, Object> getFieldsWithFlagsInternal(Object o, Collection<Field> fields) {
+ Map<String, Object> result = Maps.newLinkedHashMap();
+ for (Field f: fields) {
+ SetFromFlag cf = f.getAnnotation(SetFromFlag.class);
+ if (cf != null) {
+ String flagName = elvis(cf.value(), f.getName());
+ if (truth(flagName)) {
+ result.put(flagName, getField(o, f));
+ } else {
+ log.warn("Ignoring field {} of object {} as no flag name available", f, o);
+ }
+ }
+ }
+ return result;
+ }
+
+ private static Field findFieldForFlagInternal(String flagName, Object o, Collection<Field> fields) {
+ for (Field f: fields) {
+ SetFromFlag cf = f.getAnnotation(SetFromFlag.class);
+ if (cf != null) {
+ String contenderName = elvis(cf.value(), f.getName());
+ if (flagName.equals(contenderName)) {
+ return f;
+ }
+ }
+ }
+ throw new NoSuchElementException("Field with flag "+flagName+" not found on "+o+" of type "+(o != null ? o.getClass() : null));
+ }
+
+ private static boolean setFieldFromFlagInternal(String flagName, Object fieldVal, Object o, Collection<Field> fields) {
+ for (Field f: fields) {
+ SetFromFlag cf = f.getAnnotation(SetFromFlag.class);
+ if (cf != null && flagName.equals(elvis(cf.value(), f.getName()))) {
+ setField(o, f, fieldVal, cf);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static Map<String, ?> setFieldsFromFlagsInternal(Object o, Collection<Field> fields, Map<?,?> flagsOrConfig, ConfigBag bag, boolean setDefaultVals) {
+ if (bag==null) bag = new ConfigBag().putAll(flagsOrConfig);
+ for (Field f: fields) {
+ SetFromFlag cf = f.getAnnotation(SetFromFlag.class);
+ if (cf!=null) setFieldFromConfig(o, f, bag, cf, setDefaultVals);
+ }
+ return bag.getUnusedConfigMutable();
+ }
+
+ private static void setFieldFromConfig(Object o, Field f, ConfigBag bag, SetFromFlag optionalAnnotation, boolean setDefaultVals) {
+ String flagName = optionalAnnotation==null ? null : (String)elvis(optionalAnnotation.value(), f.getName());
+ // prefer flag name, if present
+ if (truth(flagName) && bag.containsKey(flagName)) {
+ setField(o, f, bag.getStringKey(flagName), optionalAnnotation);
+ return;
+ }
+ // first check whether it is a key
+ ConfigKey<?> key = getFieldAsConfigKey(o, f);
+ if (key!=null && bag.containsKey(key)) {
+ Object uncoercedValue = bag.getStringKey(key.getName());
+ setField(o, f, uncoercedValue, optionalAnnotation);
+ return;
+ }
+ if (setDefaultVals && optionalAnnotation!=null && truth(optionalAnnotation.defaultVal())) {
+ Object oldValue;
+ try {
+ f.setAccessible(true);
+ oldValue = f.get(o);
+ if (oldValue==null || oldValue.equals(getDefaultValueForType(f.getType()))) {
+ setField(o, f, optionalAnnotation.defaultVal(), optionalAnnotation);
+ }
+ } catch (Exception e) {
+ Exceptions.propagate(e);
+ }
+ return;
+ }
+ }
+
+ /** returns the given field as a config key, if it is an accessible config key, otherwise null */
+ private static ConfigKey<?> getFieldAsConfigKey(Object optionalInstance, Field f) {
+ if (optionalInstance==null) {
+ if ((f.getModifiers() & Modifier.STATIC)==0)
+ // non-static field on null instance, can't be set
+ return null;
+ }
+ if (ConfigKey.class.isAssignableFrom(f.getType())) {
+ return (ConfigKey<?>) getField(optionalInstance, f);
+ } else if (HasConfigKey.class.isAssignableFrom(f.getType())) {
+ return ((HasConfigKey<?>)getField(optionalInstance, f)).getConfigKey();
+ }
+ return null;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public static void setConfig(Object objectOfField, ConfigKey<?> key, Object value, SetFromFlag optionalAnnotation) {
+ if (objectOfField instanceof Configurable) {
+ ((Configurable)objectOfField).setConfig((ConfigKey)key, value);
+ return;
+ } else {
+ if (optionalAnnotation==null) {
+ log.warn("Cannot set key "+key.getName()+" on "+objectOfField+": containing class is not Configurable");
+ } else if (!key.getName().equals(optionalAnnotation.value())) {
+ log.warn("Cannot set key "+key.getName()+" on "+objectOfField+" from flag "+optionalAnnotation.value()+": containing class is not Configurable");
+ } else {
+ // if key and flag are the same, then it will probably happen automatically
+ if (log.isDebugEnabled())
+ log.debug("Cannot set key "+key.getName()+" on "+objectOfField+" from flag "+optionalAnnotation.value()+": containing class is not Configurable");
+ }
+ return;
+ }
+ }
+
+ /** sets the field to the value, after checking whether the given value can be set
+ * respecting the constraints of the annotation
+ */
+ public static void setField(Object objectOfField, Field f, Object value, SetFromFlag optionalAnnotation) {
+ try {
+ ConfigKey<?> key = getFieldAsConfigKey(objectOfField, f);
+ if (key!=null) {
+ setConfig(objectOfField, key, value, optionalAnnotation);
+ return;
+ }
+
+ if (!f.isAccessible()) f.setAccessible(true);
+ if (optionalAnnotation!=null && optionalAnnotation.immutable()) {
+ Object oldValue = f.get(objectOfField);
+ if (!Objects.equal(oldValue, getDefaultValueForType(f.getType())) && oldValue != value) {
+ throw new IllegalStateException("Forbidden modification to immutable field "+
+ f+" in "+objectOfField+": attempting to change to "+value+" when was already "+oldValue);
+ }
+ }
+ if (optionalAnnotation!=null && !optionalAnnotation.nullable() && value==null) {
+ throw new IllegalArgumentException("Forbidden null assignment to non-nullable field "+
+ f+" in "+objectOfField);
+ }
+ if (optionalAnnotation!=null && (f.getModifiers() & Modifier.STATIC)==Modifier.STATIC)
+ log.warn("Setting static field "+f+" in "+objectOfField+" from flag "+optionalAnnotation.value()+": discouraged");
+
+ Object newValue;
+ try {
+ newValue = TypeCoercions.coerce(value, f.getType());
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Cannot set "+f+" in "+objectOfField+" from type "+value.getClass()+" ("+value+"): "+e, e);
+ }
+ f.set(objectOfField, newValue);
+ if (log.isTraceEnabled()) log.trace("FlagUtils for "+objectOfField+", setting field="+f.getName()+"; val="+value+"; newVal="+newValue+"; key="+key);
+
+ } catch (IllegalAccessException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+
+ /** gets the value of the field.
+ */
+ public static Object getField(Object objectOfField, Field f) {
+ try {
+ if (!f.isAccessible()) f.setAccessible(true);
+ return f.get(objectOfField);
+ } catch (IllegalAccessException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+
+ /** returns the default/inital value that is assigned to fields of the givien type;
+ * if the type is not primitive this value is null;
+ * for primitive types it is obvious but not AFAIK programmatically visible
+ * (e.g. 0 for int, false for boolean)
+ */
+ public static Object getDefaultValueForType(Class<?> t) {
+ if (!t.isPrimitive()) return null;
+ if (t==Integer.TYPE) return (int)0;
+ if (t==Long.TYPE) return (long)0;
+ if (t==Double.TYPE) return (double)0;
+ if (t==Float.TYPE) return (float)0;
+ if (t==Byte.TYPE) return (byte)0;
+ if (t==Short.TYPE) return (short)0;
+ if (t==Character.TYPE) return (char)0;
+ if (t==Boolean.TYPE) return false;
+ //should never happen
+ throw new IllegalStateException("Class "+t+" is an unknown primitive.");
+ }
+
+ /** returns a map of all fields which are annotated 'SetFromFlag', along with the annotation */
+ public static Map<Field,SetFromFlag> getAnnotatedFields(Class<?> type) {
+ Map<Field, SetFromFlag> result = Maps.newLinkedHashMap();
+ for (Field f: getAllFields(type)) {
+ SetFromFlag cf = f.getAnnotation(SetFromFlag.class);
+ if (truth(cf)) result.put(f, cf);
+ }
+ return result;
+ }
+
+ /** returns a map of all {@link ConfigKey} fields which are annotated 'SetFromFlag', along with the annotation */
+ public static Map<ConfigKey<?>,SetFromFlag> getAnnotatedConfigKeys(Class<?> type) {
+ Map<ConfigKey<?>, SetFromFlag> result = Maps.newLinkedHashMap();
+ List<Field> fields = getAllFields(type, new Predicate<Field>() {
+ @Override public boolean apply(Field f) {
+ return (f != null) && ConfigKey.class.isAssignableFrom(f.getType()) && ((f.getModifiers() & Modifier.STATIC)!=0);
+ }});
+ for (Field f: fields) {
+ SetFromFlag cf = f.getAnnotation(SetFromFlag.class);
+ if (cf != null) {
+ ConfigKey<?> key = getFieldAsConfigKey(null, f);
+ if (key != null) {
+ result.put(key, cf);
+ }
+ }
+ }
+ return result;
+ }
+
+ /** returns a map of all fields which are annotated 'SetFromFlag' with their current values;
+ * useful if you want to clone settings from one object
+ */
+ public static Map<String,Object> getFieldsWithValues(Object o) {
+ try {
+ Map<String, Object> result = Maps.newLinkedHashMap();
+ for (Map.Entry<Field, SetFromFlag> entry : getAnnotatedFields(o.getClass()).entrySet()) {
+ Field f = entry.getKey();
+ SetFromFlag cf = entry.getValue();
+ String flagName = elvis(cf.value(), f.getName());
+ if (truth(flagName)) {
+ if (!f.isAccessible()) f.setAccessible(true);
+ result.put(flagName, f.get(o));
+ }
+ }
+ return result;
+ } catch (IllegalAccessException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+
+ /**
+ * @throws an IllegalStateException if there are fields required (nullable=false) which are unset
+ * @throws wrapped IllegalAccessException
+ */
+ public static void checkRequiredFields(Object o) {
+ try {
+ Set<String> unsetFields = Sets.newLinkedHashSet();
+ for (Map.Entry<Field, SetFromFlag> entry : getAnnotatedFields(o.getClass()).entrySet()) {
+ Field f = entry.getKey();
+ SetFromFlag cf = entry.getValue();
+ if (!cf.nullable()) {
+ String flagName = elvis(cf.value(), f.getName());
+ if (!f.isAccessible()) f.setAccessible(true);
+ Object v = f.get(o);
+ if (v==null) unsetFields.add(flagName);
+ }
+ }
+ if (truth(unsetFields)) {
+ throw new IllegalStateException("Missing required "+(unsetFields.size()>1 ? "fields" : "field")+": "+unsetFields);
+ }
+ } catch (IllegalAccessException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+
+// /** sets all fields in target annotated with @SetFromFlag using the configuration in the given config bag */
+// public static void setFieldsFromConfigFlags(Object target, ConfigBag configBag) {
+// setFieldsFromConfigFlags(target, configBag.getAllConfig(), configBag);
+// }
+//
+//
+// /** sets all fields in target annotated with @SetFromFlag using the configuration in the given configToUse,
+// * marking used in the given configBag */
+// public static void setFieldsFromConfigFlags(Object target, Map<?,?> configToUse, ConfigBag configBag) {
+// for (Map.Entry<?,?> entry: configToUse.entrySet()) {
+// setFieldFromConfigFlag(target, entry.getKey(), entry.getValue(), configBag);
+// }
+// }
+//
+// public static void setFieldFromConfigFlag(Object target, Object key, Object value, ConfigBag optionalConfigBag) {
+// String name = null;
+// if (key instanceof String) name = (String)key;
+// else if (key instanceof ConfigKey<?>) name = ((ConfigKey<?>)key).getName();
+// else if (key instanceof HasConfigKey<?>) name = ((HasConfigKey<?>)key).getConfigKey().getName();
+// else {
+// if (key!=null) {
+// log.warn("Invalid config type "+key.getClass().getCanonicalName()+" ("+key+") when configuring "+target+"; ignoring");
+// }
+// return;
+// }
+// if (setFieldFromFlag(name, value, target)) {
+// if (optionalConfigBag!=null)
+// optionalConfigBag.markUsed(name);
+// }
+// }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/flags/MethodCoercions.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/flags/MethodCoercions.java b/core/src/main/java/org/apache/brooklyn/core/util/flags/MethodCoercions.java
new file mode 100644
index 0000000..20116cf
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/flags/MethodCoercions.java
@@ -0,0 +1,183 @@
+/*
+ * 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.util.flags;
+
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.guava.Maybe;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+import com.google.common.reflect.TypeToken;
+
+import javax.annotation.Nullable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * A way of binding a loosely-specified method call into a strongly-typed Java method call.
+ */
+public class MethodCoercions {
+
+ /**
+ * Returns a predicate that matches a method with the given name, and a single parameter that
+ * {@link org.apache.brooklyn.core.util.flags.TypeCoercions#tryCoerce(Object, com.google.common.reflect.TypeToken)} can process
+ * from the given argument.
+ *
+ * @param methodName name of the method
+ * @param argument argument that is intended to be given
+ * @return a predicate that will match a compatible method
+ */
+ public static Predicate<Method> matchSingleParameterMethod(final String methodName, final Object argument) {
+ checkNotNull(methodName, "methodName");
+ checkNotNull(argument, "argument");
+
+ return new Predicate<Method>() {
+ @Override
+ public boolean apply(@Nullable Method input) {
+ if (input == null) return false;
+ if (!input.getName().equals(methodName)) return false;
+ Type[] parameterTypes = input.getGenericParameterTypes();
+ return parameterTypes.length == 1
+ && TypeCoercions.tryCoerce(argument, TypeToken.of(parameterTypes[0])).isPresentAndNonNull();
+
+ }
+ };
+ }
+
+ /**
+ * Tries to find a single-parameter method with a parameter compatible with (can be coerced to) the argument, and
+ * invokes it.
+ *
+ * @param instance the object to invoke the method on
+ * @param methodName the name of the method to invoke
+ * @param argument the argument to the method's parameter.
+ * @return the result of the method call, or {@link brooklyn.util.guava.Maybe#absent()} if method could not be matched.
+ */
+ public static Maybe<?> tryFindAndInvokeSingleParameterMethod(final Object instance, final String methodName, final Object argument) {
+ Class<?> clazz = instance.getClass();
+ Iterable<Method> methods = Arrays.asList(clazz.getMethods());
+ Optional<Method> matchingMethod = Iterables.tryFind(methods, matchSingleParameterMethod(methodName, argument));
+ if (matchingMethod.isPresent()) {
+ Method method = matchingMethod.get();
+ try {
+ Type paramType = method.getGenericParameterTypes()[0];
+ Object coercedArgument = TypeCoercions.coerce(argument, TypeToken.of(paramType));
+ return Maybe.of(method.invoke(instance, coercedArgument));
+ } catch (IllegalAccessException | InvocationTargetException e) {
+ throw Exceptions.propagate(e);
+ }
+ } else {
+ return Maybe.absent();
+ }
+ }
+
+ /**
+ * Returns a predicate that matches a method with the given name, and parameters that
+ * {@link org.apache.brooklyn.core.util.flags.TypeCoercions#tryCoerce(Object, com.google.common.reflect.TypeToken)} can process
+ * from the given list of arguments.
+ *
+ * @param methodName name of the method
+ * @param arguments arguments that is intended to be given
+ * @return a predicate that will match a compatible method
+ */
+ public static Predicate<Method> matchMultiParameterMethod(final String methodName, final List<?> arguments) {
+ checkNotNull(methodName, "methodName");
+ checkNotNull(arguments, "arguments");
+
+ return new Predicate<Method>() {
+ @Override
+ public boolean apply(@Nullable Method input) {
+ if (input == null) return false;
+ if (!input.getName().equals(methodName)) return false;
+ int numOptionParams = arguments.size();
+ Type[] parameterTypes = input.getGenericParameterTypes();
+ if (parameterTypes.length != numOptionParams) return false;
+
+ for (int paramCount = 0; paramCount < numOptionParams; paramCount++) {
+ if (!TypeCoercions.tryCoerce(((List) arguments).get(paramCount),
+ TypeToken.of(parameterTypes[paramCount])).isPresentAndNonNull()) return false;
+ }
+ return true;
+ }
+ };
+ }
+
+ /**
+ * Tries to find a multiple-parameter method with each parameter compatible with (can be coerced to) the
+ * corresponding argument, and invokes it.
+ *
+ * @param instance the object to invoke the method on
+ * @param methodName the name of the method to invoke
+ * @param argument a list of the arguments to the method's parameters.
+ * @return the result of the method call, or {@link brooklyn.util.guava.Maybe#absent()} if method could not be matched.
+ */
+ public static Maybe<?> tryFindAndInvokeMultiParameterMethod(final Object instance, final String methodName, final List<?> arguments) {
+ Class<?> clazz = instance.getClass();
+ Iterable<Method> methods = Arrays.asList(clazz.getMethods());
+ Optional<Method> matchingMethod = Iterables.tryFind(methods, matchMultiParameterMethod(methodName, arguments));
+ if (matchingMethod.isPresent()) {
+ Method method = matchingMethod.get();
+ try {
+ int numOptionParams = ((List)arguments).size();
+ Object[] coercedArguments = new Object[numOptionParams];
+ for (int paramCount = 0; paramCount < numOptionParams; paramCount++) {
+ Object argument = arguments.get(paramCount);
+ Type paramType = method.getGenericParameterTypes()[paramCount];
+ coercedArguments[paramCount] = TypeCoercions.coerce(argument, TypeToken.of(paramType));
+ }
+ return Maybe.of(method.invoke(instance, coercedArguments));
+ } catch (IllegalAccessException | InvocationTargetException e) {
+ throw Exceptions.propagate(e);
+ }
+ } else {
+ return Maybe.absent();
+ }
+ }
+
+ /**
+ * Tries to find a method with each parameter compatible with (can be coerced to) the corresponding argument, and invokes it.
+ *
+ * @param instance the object to invoke the method on
+ * @param methodName the name of the method to invoke
+ * @param argument a list of the arguments to the method's parameters, or a single argument for a single-parameter method.
+ * @return the result of the method call, or {@link brooklyn.util.guava.Maybe#absent()} if method could not be matched.
+ */
+ public static Maybe<?> tryFindAndInvokeBestMatchingMethod(final Object instance, final String methodName, final Object argument) {
+ if (argument instanceof List) {
+ List<?> arguments = (List<?>) argument;
+
+ // ambiguous case: we can't tell if the user is using the multi-parameter syntax, or the single-parameter
+ // syntax for a method which takes a List parameter. So we try one, then fall back to the other.
+
+ Maybe<?> maybe = tryFindAndInvokeMultiParameterMethod(instance, methodName, arguments);
+ if (maybe.isAbsent())
+ maybe = tryFindAndInvokeSingleParameterMethod(instance, methodName, argument);
+
+ return maybe;
+ } else {
+ return tryFindAndInvokeSingleParameterMethod(instance, methodName, argument);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/flags/SetFromFlag.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/flags/SetFromFlag.java b/core/src/main/java/org/apache/brooklyn/core/util/flags/SetFromFlag.java
new file mode 100644
index 0000000..3b69c05
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/flags/SetFromFlag.java
@@ -0,0 +1,71 @@
+/*
+ * 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.util.flags;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Annotation to indicate that a variable may be set through the use of a named argument,
+ * looking for the name specified here or inferred from the annotated field/argument/object.
+ * <p>
+ * This is used to automate the processing where named arguments are passed in constructors
+ * and other methods, and the values of those named arguments should be transferred to
+ * other known fields/arguments/objects at runtime.
+ * <p>
+ * Fields on a class are typically set from values in a map with a call to
+ * {@link FlagUtils#setFieldsFromFlags(java.util.Map, Object)}.
+ * That method (and related, in the same class) will attend to the arguments here.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface SetFromFlag {
+
+ /** the flag (key) which should be used to find the value; if empty defaults to field/argument/object name */
+ String value() default "";
+
+ /** whether the object should not be changed once set; defaults to false
+ * <p>
+ * this is partially tested for in many routines, but not all;
+ * when nullable=false the testing (when done) is guaranteed.
+ * however if nullable is allowed we do not distinguish between null and unset
+ * so explicitly setting null then setting to a value is not detected as an illegal mutating.
+ */
+ boolean immutable() default false;
+
+ /** whether the object is required & should not be set to null; defaults to true.
+ * (there is no 'required' parameter, but setting nullable false then invoking
+ * e.g. {@link FlagUtils#checkRequiredFields(Object)} has the effect of requiring a value)
+ * <p>
+ * code should call that method explicitly to enforce nullable false;
+ * errors are not done during a call to setFieldsFromFlags
+ * because fields may be initialised in multiple passes.)
+ * <p>
+ * this is partially tested for in many routines, but not all
+ */
+ boolean nullable() default true;
+
+ /** The default value, if it is not explicitly set.
+ * <p>
+ * The value will be coerced from String where required, for types supported by {@link TypeCoercions}.
+ * <p>
+ * The field will be initialised with its default value on the first call to setFieldsFromFlags
+ * (or related). (The field will not be initialised if that method is not called.)
+ */
+ String defaultVal() default "";
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/flags/TypeCoercions.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/flags/TypeCoercions.java b/core/src/main/java/org/apache/brooklyn/core/util/flags/TypeCoercions.java
new file mode 100644
index 0000000..2c03620
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/flags/TypeCoercions.java
@@ -0,0 +1,879 @@
+/*
+ * 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.util.flags;
+
+import groovy.lang.Closure;
+import groovy.time.TimeDuration;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.URI;
+import java.net.URL;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.GuardedBy;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.api.event.Sensor;
+import org.apache.brooklyn.core.internal.BrooklynInitialization;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.entity.basic.BrooklynTaskTags;
+import brooklyn.entity.basic.ClosureEntityFactory;
+import brooklyn.entity.basic.ConfigurableEntityFactory;
+import brooklyn.entity.basic.ConfigurableEntityFactoryFromEntityFactory;
+import brooklyn.event.basic.Sensors;
+import brooklyn.util.JavaGroovyEquivalents;
+import brooklyn.util.collections.MutableSet;
+import brooklyn.util.collections.QuorumCheck;
+import brooklyn.util.collections.QuorumCheck.QuorumChecks;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.guava.Maybe;
+import brooklyn.util.javalang.Enums;
+import brooklyn.util.net.Cidr;
+import brooklyn.util.net.Networking;
+import brooklyn.util.net.UserAndHostAndPort;
+import brooklyn.util.text.StringEscapes.JavaStringEscapes;
+import brooklyn.util.text.Strings;
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Time;
+import brooklyn.util.yaml.Yamls;
+
+import com.google.common.base.CaseFormat;
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.collect.HashBasedTable;
+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.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.common.collect.Table;
+import com.google.common.net.HostAndPort;
+import com.google.common.primitives.Primitives;
+import com.google.common.reflect.TypeToken;
+
+@SuppressWarnings("rawtypes")
+public class TypeCoercions {
+
+ private static final Logger log = LoggerFactory.getLogger(TypeCoercions.class);
+
+ private TypeCoercions() {}
+
+ /** Store the coercion {@link Function functions} in a {@link Table table}. */
+ @GuardedBy("TypeCoercions.class")
+ private static Table<Class, Class, Function> registry = HashBasedTable.create();
+
+ /**
+ * Attempts to coerce {@code value} to {@code targetType}.
+ * <p>
+ * Maintains a registry of adapter functions for type pairs in a {@link Table} which
+ * is searched after checking various strategies, including the following:
+ * <ul>
+ * <li>{@code value.asTargetType()}
+ * <li>{@code TargetType.fromType(value)} (if {@code value instanceof Type})
+ * <li>{@code value.targetTypeValue()} (handy for primitives)
+ * <li>{@code TargetType.valueOf(value)} (for enums)
+ * </ul>
+ * <p>
+ * A default set of adapters will handle most common Java-type coercions
+ * as well as <code>String</code> coercion to:
+ * <ul>
+ * <li> {@link Set}, {@link List}, {@link Map} and similar -- parses as YAML
+ * <li> {@link Date} -- parses using {@link Time#parseDate(String)}
+ * <li> {@link Duration} -- parses using {@link Duration#parse(String)}
+ * </ul>
+ */
+ public static <T> T coerce(Object value, Class<T> targetType) {
+ return coerce(value, TypeToken.of(targetType));
+ }
+
+ /** @see #coerce(Object, Class) */
+ public static <T> Maybe<T> tryCoerce(Object value, TypeToken<T> targetTypeToken) {
+ try {
+ return Maybe.of( coerce(value, targetTypeToken) );
+ } catch (Throwable t) {
+ Exceptions.propagateIfFatal(t);
+ return Maybe.absent(t);
+ }
+ }
+
+ /** @see #coerce(Object, Class) */
+ @SuppressWarnings({ "unchecked" })
+ public static <T> T coerce(Object value, TypeToken<T> targetTypeToken) {
+ if (value==null) return null;
+ Class<? super T> targetType = targetTypeToken.getRawType();
+
+ //recursive coercion of parameterized collections and map entries
+ if (targetTypeToken.getType() instanceof ParameterizedType) {
+ if (value instanceof Collection && Collection.class.isAssignableFrom(targetType)) {
+ Type[] arguments = ((ParameterizedType) targetTypeToken.getType()).getActualTypeArguments();
+ if (arguments.length != 1) {
+ throw new IllegalStateException("Unexpected number of parameters in collection type: " + arguments);
+ }
+ Collection coerced = Lists.newLinkedList();
+ TypeToken<?> listEntryType = TypeToken.of(arguments[0]);
+ for (Object entry : (Iterable<?>) value) {
+ coerced.add(coerce(entry, listEntryType));
+ }
+ if (Set.class.isAssignableFrom(targetType)) {
+ return (T) Sets.newLinkedHashSet(coerced);
+ } else {
+ return (T) Lists.newArrayList(coerced);
+ }
+ } else if (value instanceof Map && Map.class.isAssignableFrom(targetType)) {
+ Type[] arguments = ((ParameterizedType) targetTypeToken.getType()).getActualTypeArguments();
+ if (arguments.length != 2) {
+ throw new IllegalStateException("Unexpected number of parameters in map type: " + arguments);
+ }
+ Map coerced = Maps.newLinkedHashMap();
+ TypeToken<?> mapKeyType = TypeToken.of(arguments[0]);
+ TypeToken<?> mapValueType = TypeToken.of(arguments[1]);
+ for (Map.Entry entry : ((Map<?,?>) value).entrySet()) {
+ coerced.put(coerce(entry.getKey(), mapKeyType), coerce(entry.getValue(), mapValueType));
+ }
+ return (T) Maps.newLinkedHashMap(coerced);
+ }
+ }
+
+ if (targetType.isInstance(value)) return (T) value;
+
+ // TODO use registry first?
+
+ //deal with primitive->primitive casting
+ if (isPrimitiveOrBoxer(targetType) && isPrimitiveOrBoxer(value.getClass())) {
+ // Don't just rely on Java to do its normal casting later; if caller writes
+ // long `l = coerce(new Integer(1), Long.class)` then letting java do its casting will fail,
+ // because an Integer will not automatically be unboxed and cast to a long
+ return castPrimitive(value, (Class<T>)targetType);
+ }
+
+ //deal with string->primitive
+ if (value instanceof String && isPrimitiveOrBoxer(targetType)) {
+ return stringToPrimitive((String)value, (Class<T>)targetType);
+ }
+
+ //deal with primitive->string
+ if (isPrimitiveOrBoxer(value.getClass()) && targetType.equals(String.class)) {
+ return (T) value.toString();
+ }
+
+ //look for value.asType where Type is castable to targetType
+ String targetTypeSimpleName = getVerySimpleName(targetType);
+ if (targetTypeSimpleName!=null && targetTypeSimpleName.length()>0) {
+ for (Method m: value.getClass().getMethods()) {
+ if (m.getName().startsWith("as") && m.getParameterTypes().length==0 &&
+ targetType.isAssignableFrom(m.getReturnType()) ) {
+ if (m.getName().equals("as"+getVerySimpleName(m.getReturnType()))) {
+ try {
+ return (T) m.invoke(value);
+ } catch (Exception e) {
+ throw new ClassCoercionException("Cannot coerce type "+value.getClass()+" to "+targetType.getCanonicalName()+" ("+value+"): "+m.getName()+" adapting failed, "+e);
+ }
+ }
+ }
+ }
+ }
+
+ //now look for static TargetType.fromType(Type t) where value instanceof Type
+ for (Method m: targetType.getMethods()) {
+ if (((m.getModifiers()&Modifier.STATIC)==Modifier.STATIC) &&
+ m.getName().startsWith("from") && m.getParameterTypes().length==1 &&
+ m.getParameterTypes()[0].isInstance(value)) {
+ if (m.getName().equals("from"+getVerySimpleName(m.getParameterTypes()[0]))) {
+ try {
+ return (T) m.invoke(null, value);
+ } catch (Exception e) {
+ throw new ClassCoercionException("Cannot coerce type "+value.getClass()+" to "+targetType.getCanonicalName()+" ("+value+"): "+m.getName()+" adapting failed, "+e);
+ }
+ }
+ }
+ }
+
+ //ENHANCEMENT could look in type hierarchy of both types for a conversion method...
+
+ //primitives get run through again boxed up
+ Class boxedT = UNBOXED_TO_BOXED_TYPES.get(targetType);
+ Class boxedVT = UNBOXED_TO_BOXED_TYPES.get(value.getClass());
+ if (boxedT!=null || boxedVT!=null) {
+ try {
+ if (boxedT==null) boxedT=targetType;
+ Object boxedV;
+ if (boxedVT==null) { boxedV = value; }
+ else { boxedV = boxedVT.getConstructor(value.getClass()).newInstance(value); }
+ return (T) coerce(boxedV, boxedT);
+ } catch (Exception e) {
+ throw new ClassCoercionException("Cannot coerce type "+value.getClass()+" to "+targetType.getCanonicalName()+" ("+value+"): unboxing failed, "+e);
+ }
+ }
+
+ //for enums call valueOf with the string representation of the value
+ if (targetType.isEnum()) {
+ T result = (T) stringToEnum((Class<Enum>) targetType, null).apply(String.valueOf(value));
+ if (result != null) return result;
+ }
+
+ //now look in registry
+ synchronized (TypeCoercions.class) {
+ Map<Class, Function> adapters = registry.row(targetType);
+ for (Map.Entry<Class, Function> entry : adapters.entrySet()) {
+ if (entry.getKey().isInstance(value)) {
+ T result = (T) entry.getValue().apply(value);
+
+ // Check if need to unwrap again (e.g. if want List<Integer> and are given a String "1,2,3"
+ // then we'll have so far converted to List.of("1", "2", "3"). Call recursively.
+ // First check that value has changed, to avoid stack overflow!
+ if (!Objects.equal(value, result) && targetTypeToken.getType() instanceof ParameterizedType) {
+ // Could duplicate check for `result instanceof Collection` etc; but recursive call
+ // will be fine as if that doesn't match we'll safely reach `targetType.isInstance(value)`
+ // and just return the result.
+ return coerce(result, targetTypeToken);
+ }
+ return result;
+ }
+ }
+ }
+
+ //not found
+ throw new ClassCoercionException("Cannot coerce type "+value.getClass()+" to "+targetType.getCanonicalName()+" ("+value+"): no adapter known");
+ }
+
+ /**
+ * Returns a function that does a type coercion to the given type. For example,
+ * {@code TypeCoercions.function(Double.class)} will return a function that will
+ * coerce its input value to a {@link Double} (or throw a {@link ClassCoercionException}
+ * if that is not possible).
+ */
+ public static <T> Function<Object, T> function(final Class<T> type) {
+ return new CoerceFunction<T>(type);
+ }
+
+ private static class CoerceFunction<T> implements Function<Object, T> {
+ private final Class<T> type;
+
+ public CoerceFunction(Class<T> type) {
+ this.type = type;
+ }
+ @Override
+ public T apply(Object input) {
+ return coerce(input, type);
+ }
+ }
+
+ /**
+ * Type coercion {@link Function function} for {@link Enum enums}.
+ * <p>
+ * Tries to convert the string to {@link CaseFormat#UPPER_UNDERSCORE} first,
+ * handling all of the different {@link CaseFormat format} possibilites. Failing
+ * that, it tries a case-insensitive comparison with the valid enum values.
+ * <p>
+ * Returns {@code defaultValue} if the string cannot be converted.
+ *
+ * @see TypeCoercions#coerce(Object, Class)
+ * @see Enum#valueOf(Class, String)
+ */
+ public static <E extends Enum<E>> Function<String, E> stringToEnum(final Class<E> type, @Nullable final E defaultValue) {
+ return new StringToEnumFunction<E>(type, defaultValue);
+ }
+
+ private static class StringToEnumFunction<E extends Enum<E>> implements Function<String, E> {
+ private final Class<E> type;
+ private final E defaultValue;
+
+ public StringToEnumFunction(Class<E> type, @Nullable E defaultValue) {
+ this.type = type;
+ this.defaultValue = defaultValue;
+ }
+ @Override
+ public E apply(String input) {
+ Preconditions.checkNotNull(input, "input");
+ List<String> options = ImmutableList.of(
+ input,
+ CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, input),
+ CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_UNDERSCORE, input),
+ CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, input),
+ CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, input));
+ for (String value : options) {
+ try {
+ return Enum.valueOf(type, value);
+ } catch (IllegalArgumentException iae) {
+ continue;
+ }
+ }
+ Maybe<E> result = Enums.valueOfIgnoreCase(type, input);
+ return (result.isPresent()) ? result.get() : defaultValue;
+ }
+ }
+
+ /**
+ * Sometimes need to explicitly cast primitives, rather than relying on Java casting.
+ * For example, when using generics then type-erasure means it doesn't actually cast,
+ * which causes tests to fail with 0 != 0.0
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T castPrimitive(Object value, Class<T> targetType) {
+ if (value==null) return null;
+ assert isPrimitiveOrBoxer(targetType) : "targetType="+targetType;
+ assert isPrimitiveOrBoxer(value.getClass()) : "value="+targetType+"; valueType="+value.getClass();
+
+ Class<?> sourceWrapType = Primitives.wrap(value.getClass());
+ Class<?> targetWrapType = Primitives.wrap(targetType);
+
+ // optimization, for when already correct type
+ if (sourceWrapType == targetWrapType) {
+ return (T) value;
+ }
+
+ if (targetWrapType == Boolean.class) {
+ // only char can be mapped to boolean
+ // (we could say 0=false, nonzero=true, but there is no compelling use case so better
+ // to encourage users to write as boolean)
+ if (sourceWrapType == Character.class)
+ return (T) stringToPrimitive(value.toString(), targetType);
+
+ throw new ClassCoercionException("Cannot cast "+sourceWrapType+" ("+value+") to "+targetType);
+ } else if (sourceWrapType == Boolean.class) {
+ // boolean can't cast to anything else
+
+ throw new ClassCoercionException("Cannot cast "+sourceWrapType+" ("+value+") to "+targetType);
+ }
+
+ // for whole-numbers (where casting to long won't lose anything)...
+ long v = 0;
+ boolean islong = true;
+ if (sourceWrapType == Character.class) {
+ v = (long) ((Character)value).charValue();
+ } else if (sourceWrapType == Byte.class) {
+ v = (long) ((Byte)value).byteValue();
+ } else if (sourceWrapType == Short.class) {
+ v = (long) ((Short)value).shortValue();
+ } else if (sourceWrapType == Integer.class) {
+ v = (long) ((Integer)value).intValue();
+ } else if (sourceWrapType == Long.class) {
+ v = ((Long)value).longValue();
+ } else {
+ islong = false;
+ }
+ if (islong) {
+ if (targetWrapType == Character.class) return (T) Character.valueOf((char)v);
+ if (targetWrapType == Byte.class) return (T) Byte.valueOf((byte)v);
+ if (targetWrapType == Short.class) return (T) Short.valueOf((short)v);
+ if (targetWrapType == Integer.class) return (T) Integer.valueOf((int)v);
+ if (targetWrapType == Long.class) return (T) Long.valueOf((long)v);
+ if (targetWrapType == Float.class) return (T) Float.valueOf((float)v);
+ if (targetWrapType == Double.class) return (T) Double.valueOf((double)v);
+ throw new IllegalStateException("Unexpected: sourceType="+sourceWrapType+"; targetType="+targetWrapType);
+ }
+
+ // for real-numbers (cast to double)...
+ double d = 0;
+ boolean isdouble = true;
+ if (sourceWrapType == Float.class) {
+ d = (double) ((Float)value).floatValue();
+ } else if (sourceWrapType == Double.class) {
+ d = (double) ((Double)value).doubleValue();
+ } else {
+ isdouble = false;
+ }
+ if (isdouble) {
+ if (targetWrapType == Character.class) return (T) Character.valueOf((char)d);
+ if (targetWrapType == Byte.class) return (T) Byte.valueOf((byte)d);
+ if (targetWrapType == Short.class) return (T) Short.valueOf((short)d);
+ if (targetWrapType == Integer.class) return (T) Integer.valueOf((int)d);
+ if (targetWrapType == Long.class) return (T) Long.valueOf((long)d);
+ if (targetWrapType == Float.class) return (T) Float.valueOf((float)d);
+ if (targetWrapType == Double.class) return (T) Double.valueOf((double)d);
+ throw new IllegalStateException("Unexpected: sourceType="+sourceWrapType+"; targetType="+targetWrapType);
+ } else {
+ throw new IllegalStateException("Unexpected: sourceType="+sourceWrapType+"; targetType="+targetWrapType);
+ }
+ }
+
+ public static boolean isPrimitiveOrBoxer(Class<?> type) {
+ return Primitives.allPrimitiveTypes().contains(type) || Primitives.allWrapperTypes().contains(type);
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <T> T stringToPrimitive(String value, Class<T> targetType) {
+ assert Primitives.allPrimitiveTypes().contains(targetType) || Primitives.allWrapperTypes().contains(targetType) : "targetType="+targetType;
+ // If char, then need to do explicit conversion
+ if (targetType == Character.class || targetType == char.class) {
+ if (value.length() == 1) {
+ return (T) (Character) value.charAt(0);
+ } else if (value.length() != 1) {
+ throw new ClassCoercionException("Cannot coerce type String to "+targetType.getCanonicalName()+" ("+value+"): adapting failed");
+ }
+ }
+ value = value.trim();
+ // For boolean we could use valueOf, but that returns false whereas we'd rather throw errors on bad values
+ if (targetType == Boolean.class || targetType == boolean.class) {
+ if ("true".equalsIgnoreCase(value)) return (T) Boolean.TRUE;
+ if ("false".equalsIgnoreCase(value)) return (T) Boolean.FALSE;
+ if ("yes".equalsIgnoreCase(value)) return (T) Boolean.TRUE;
+ if ("no".equalsIgnoreCase(value)) return (T) Boolean.FALSE;
+ if ("t".equalsIgnoreCase(value)) return (T) Boolean.TRUE;
+ if ("f".equalsIgnoreCase(value)) return (T) Boolean.FALSE;
+ if ("y".equalsIgnoreCase(value)) return (T) Boolean.TRUE;
+ if ("n".equalsIgnoreCase(value)) return (T) Boolean.FALSE;
+
+ throw new ClassCoercionException("Cannot coerce type String to "+targetType.getCanonicalName()+" ("+value+"): adapting failed");
+ }
+
+ // Otherwise can use valueOf reflectively
+ Class<?> wrappedType;
+ if (Primitives.allPrimitiveTypes().contains(targetType)) {
+ wrappedType = Primitives.wrap(targetType);
+ } else {
+ wrappedType = targetType;
+ }
+
+ try {
+ return (T) wrappedType.getMethod("valueOf", String.class).invoke(null, value);
+ } catch (Exception e) {
+ ClassCoercionException tothrow = new ClassCoercionException("Cannot coerce "+JavaStringEscapes.wrapJavaString(value)+" to "+targetType.getCanonicalName()+" ("+value+"): adapting failed");
+ tothrow.initCause(e);
+ throw tothrow;
+ }
+ }
+
+ /** returns the simple class name, and for any inner class the portion after the $ */
+ public static String getVerySimpleName(Class c) {
+ String s = c.getSimpleName();
+ if (s.indexOf('$')>=0)
+ s = s.substring(s.lastIndexOf('$')+1);
+ return s;
+ }
+ public static final Map<Class,Class> BOXED_TO_UNBOXED_TYPES = ImmutableMap.<Class,Class>builder().
+ put(Integer.class, Integer.TYPE).
+ put(Long.class, Long.TYPE).
+ put(Boolean.class, Boolean.TYPE).
+ put(Byte.class, Byte.TYPE).
+ put(Double.class, Double.TYPE).
+ put(Float.class, Float.TYPE).
+ put(Character.class, Character.TYPE).
+ put(Short.class, Short.TYPE).
+ build();
+ public static final Map<Class,Class> UNBOXED_TO_BOXED_TYPES = ImmutableMap.<Class,Class>builder().
+ put(Integer.TYPE, Integer.class).
+ put(Long.TYPE, Long.class).
+ put(Boolean.TYPE, Boolean.class).
+ put(Byte.TYPE, Byte.class).
+ put(Double.TYPE, Double.class).
+ put(Float.TYPE, Float.class).
+ put(Character.TYPE, Character.class).
+ put(Short.TYPE, Short.class).
+ build();
+
+ /** for automatic conversion */
+ public static Object getMatchingConstructor(Class target, Object ...arguments) {
+ Constructor[] cc = target.getConstructors();
+ for (Constructor c: cc) {
+ if (c.getParameterTypes().length != arguments.length)
+ continue;
+ boolean matches = true;
+ Class[] tt = c.getParameterTypes();
+ for (int i=0; i<tt.length; i++) {
+ if (arguments[i]!=null && !tt[i].isInstance(arguments[i])) {
+ matches=false;
+ break;
+ }
+ }
+ if (matches)
+ return c;
+ }
+ return null;
+ }
+
+ /** Registers an adapter for use with type coercion. Returns any old adapter. */
+ public synchronized static <A,B> Function registerAdapter(Class<A> sourceType, Class<B> targetType, Function<? super A,B> fn) {
+ return registry.put(targetType, sourceType, fn);
+ }
+
+ static { BrooklynInitialization.initTypeCoercionStandardAdapters(); }
+
+ public static void initStandardAdapters() {
+ registerAdapter(CharSequence.class, String.class, new Function<CharSequence,String>() {
+ @Override
+ public String apply(CharSequence input) {
+ return input.toString();
+ }
+ });
+ registerAdapter(byte[].class, String.class, new Function<byte[],String>() {
+ @Override
+ public String apply(byte[] input) {
+ return new String(input);
+ }
+ });
+ registerAdapter(Collection.class, Set.class, new Function<Collection,Set>() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public Set apply(Collection input) {
+ return Sets.newLinkedHashSet(input);
+ }
+ });
+ registerAdapter(Collection.class, List.class, new Function<Collection,List>() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public List apply(Collection input) {
+ return Lists.newArrayList(input);
+ }
+ });
+ registerAdapter(String.class, InetAddress.class, new Function<String,InetAddress>() {
+ @Override
+ public InetAddress apply(String input) {
+ return Networking.getInetAddressWithFixedName(input);
+ }
+ });
+ registerAdapter(String.class, HostAndPort.class, new Function<String,HostAndPort>() {
+ @Override
+ public HostAndPort apply(String input) {
+ return HostAndPort.fromString(input);
+ }
+ });
+ registerAdapter(String.class, UserAndHostAndPort.class, new Function<String,UserAndHostAndPort>() {
+ @Override
+ public UserAndHostAndPort apply(String input) {
+ return UserAndHostAndPort.fromString(input);
+ }
+ });
+ registerAdapter(String.class, Cidr.class, new Function<String,Cidr>() {
+ @Override
+ public Cidr apply(String input) {
+ return new Cidr(input);
+ }
+ });
+ registerAdapter(String.class, URL.class, new Function<String,URL>() {
+ @Override
+ public URL apply(String input) {
+ try {
+ return new URL(input);
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+ });
+ registerAdapter(String.class, URI.class, new Function<String,URI>() {
+ @Override
+ public URI apply(String input) {
+ return URI.create(input);
+ }
+ });
+ registerAdapter(Closure.class, ConfigurableEntityFactory.class, new Function<Closure,ConfigurableEntityFactory>() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public ConfigurableEntityFactory apply(Closure input) {
+ return new ClosureEntityFactory(input);
+ }
+ });
+ @SuppressWarnings({"unused", "deprecation"})
+ Function<?,?> ignoredVarHereToAllowSuppressDeprecationWarning1 = registerAdapter(brooklyn.entity.basic.EntityFactory.class, ConfigurableEntityFactory.class, new Function<brooklyn.entity.basic.EntityFactory,ConfigurableEntityFactory>() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public ConfigurableEntityFactory apply(brooklyn.entity.basic.EntityFactory input) {
+ if (input instanceof ConfigurableEntityFactory) return (ConfigurableEntityFactory)input;
+ return new ConfigurableEntityFactoryFromEntityFactory(input);
+ }
+ });
+ @SuppressWarnings({"unused", "deprecation"})
+ Function<?,?> ignoredVarHereToAllowSuppressDeprecationWarning2 = registerAdapter(Closure.class, brooklyn.entity.basic.EntityFactory.class, new Function<Closure,brooklyn.entity.basic.EntityFactory>() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public brooklyn.entity.basic.EntityFactory apply(Closure input) {
+ return new ClosureEntityFactory(input);
+ }
+ });
+ registerAdapter(Closure.class, Predicate.class, new Function<Closure,Predicate>() {
+ @Override
+ public Predicate<?> apply(final Closure closure) {
+ return new Predicate<Object>() {
+ @Override public boolean apply(Object input) {
+ return (Boolean) closure.call(input);
+ }
+ };
+ }
+ });
+ registerAdapter(Closure.class, Function.class, new Function<Closure,Function>() {
+ @Override
+ public Function apply(final Closure closure) {
+ return new Function() {
+ @Override public Object apply(Object input) {
+ return closure.call(input);
+ }
+ };
+ }
+ });
+ registerAdapter(Object.class, Duration.class, new Function<Object,Duration>() {
+ @Override
+ public Duration apply(final Object input) {
+ return brooklyn.util.time.Duration.of(input);
+ }
+ });
+ registerAdapter(Object.class, TimeDuration.class, new Function<Object,TimeDuration>() {
+ @SuppressWarnings("deprecation")
+ @Override
+ public TimeDuration apply(final Object input) {
+ log.warn("deprecated automatic coercion of Object to TimeDuration (set breakpoint in TypeCoercions to inspect, convert to Duration)");
+ return JavaGroovyEquivalents.toTimeDuration(input);
+ }
+ });
+ registerAdapter(TimeDuration.class, Long.class, new Function<TimeDuration,Long>() {
+ @Override
+ public Long apply(final TimeDuration input) {
+ log.warn("deprecated automatic coercion of TimeDuration to Long (set breakpoint in TypeCoercions to inspect, use Duration instead of Long!)");
+ return input.toMilliseconds();
+ }
+ });
+ registerAdapter(Integer.class, AtomicLong.class, new Function<Integer,AtomicLong>() {
+ @Override public AtomicLong apply(final Integer input) {
+ return new AtomicLong(input);
+ }
+ });
+ registerAdapter(Long.class, AtomicLong.class, new Function<Long,AtomicLong>() {
+ @Override public AtomicLong apply(final Long input) {
+ return new AtomicLong(input);
+ }
+ });
+ registerAdapter(String.class, AtomicLong.class, new Function<String,AtomicLong>() {
+ @Override public AtomicLong apply(final String input) {
+ return new AtomicLong(Long.parseLong(input.trim()));
+ }
+ });
+ registerAdapter(Integer.class, AtomicInteger.class, new Function<Integer,AtomicInteger>() {
+ @Override public AtomicInteger apply(final Integer input) {
+ return new AtomicInteger(input);
+ }
+ });
+ registerAdapter(String.class, AtomicInteger.class, new Function<String,AtomicInteger>() {
+ @Override public AtomicInteger apply(final String input) {
+ return new AtomicInteger(Integer.parseInt(input.trim()));
+ }
+ });
+ /** This always returns a {@link Double}, cast as a {@link Number};
+ * however primitives and boxers get exact typing due to call in #stringToPrimitive */
+ registerAdapter(String.class, Number.class, new Function<String,Number>() {
+ @Override
+ public Number apply(String input) {
+ return Double.valueOf(input);
+ }
+ });
+ registerAdapter(BigDecimal.class, Double.class, new Function<BigDecimal,Double>() {
+ @Override
+ public Double apply(BigDecimal input) {
+ return input.doubleValue();
+ }
+ });
+ registerAdapter(BigInteger.class, Long.class, new Function<BigInteger,Long>() {
+ @Override
+ public Long apply(BigInteger input) {
+ return input.longValue();
+ }
+ });
+ registerAdapter(BigInteger.class, Integer.class, new Function<BigInteger,Integer>() {
+ @Override
+ public Integer apply(BigInteger input) {
+ return input.intValue();
+ }
+ });
+ registerAdapter(String.class, BigDecimal.class, new Function<String,BigDecimal>() {
+ @Override
+ public BigDecimal apply(String input) {
+ return new BigDecimal(input);
+ }
+ });
+ registerAdapter(Double.class, BigDecimal.class, new Function<Double,BigDecimal>() {
+ @Override
+ public BigDecimal apply(Double input) {
+ return BigDecimal.valueOf(input);
+ }
+ });
+ registerAdapter(String.class, BigInteger.class, new Function<String,BigInteger>() {
+ @Override
+ public BigInteger apply(String input) {
+ return new BigInteger(input);
+ }
+ });
+ registerAdapter(Long.class, BigInteger.class, new Function<Long,BigInteger>() {
+ @Override
+ public BigInteger apply(Long input) {
+ return BigInteger.valueOf(input);
+ }
+ });
+ registerAdapter(Integer.class, BigInteger.class, new Function<Integer,BigInteger>() {
+ @Override
+ public BigInteger apply(Integer input) {
+ return BigInteger.valueOf(input);
+ }
+ });
+ registerAdapter(String.class, Date.class, new Function<String,Date>() {
+ @Override
+ public Date apply(final String input) {
+ return Time.parseDate(input);
+ }
+ });
+ registerAdapter(String.class, Class.class, new Function<String,Class>() {
+ @Override
+ public Class apply(final String input) {
+ try {
+ return Class.forName(input);
+ } catch (ClassNotFoundException e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+ });
+ registerAdapter(String.class, AttributeSensor.class, new Function<String,AttributeSensor>() {
+ @Override
+ public AttributeSensor apply(final String input) {
+ Entity entity = BrooklynTaskTags.getContextEntity(Tasks.current());
+ if (entity!=null) {
+ Sensor<?> result = entity.getEntityType().getSensor(input);
+ if (result instanceof AttributeSensor)
+ return (AttributeSensor) result;
+ }
+ return Sensors.newSensor(Object.class, input);
+ }
+ });
+ registerAdapter(String.class, Sensor.class, new Function<String,Sensor>() {
+ @Override
+ public AttributeSensor apply(final String input) {
+ Entity entity = BrooklynTaskTags.getContextEntity(Tasks.current());
+ if (entity!=null) {
+ Sensor<?> result = entity.getEntityType().getSensor(input);
+ if (result != null)
+ return (AttributeSensor) result;
+ }
+ return Sensors.newSensor(Object.class, input);
+ }
+ });
+ registerAdapter(String.class, List.class, new Function<String,List>() {
+ @Override
+ public List<String> apply(final String input) {
+ return JavaStringEscapes.unwrapJsonishListIfPossible(input);
+ }
+ });
+ registerAdapter(String.class, Set.class, new Function<String,Set>() {
+ @Override
+ public Set<String> apply(final String input) {
+ return MutableSet.copyOf(JavaStringEscapes.unwrapJsonishListIfPossible(input)).asUnmodifiable();
+ }
+ });
+ registerAdapter(String.class, QuorumCheck.class, new Function<String,QuorumCheck>() {
+ @Override
+ public QuorumCheck apply(final String input) {
+ return QuorumChecks.of(input);
+ }
+ });
+ registerAdapter(Iterable.class, String[].class, new Function<Iterable, String[]>() {
+ @Nullable
+ @Override
+ public String[] apply(@Nullable Iterable list) {
+ if (list == null) return null;
+ String[] result = new String[Iterables.size(list)];
+ int count = 0;
+ for (Object element : list) {
+ result[count++] = coerce(element, String.class);
+ }
+ return result;
+ }
+ });
+ registerAdapter(Iterable.class, Integer[].class, new Function<Iterable, Integer[]>() {
+ @Nullable
+ @Override
+ public Integer[] apply(@Nullable Iterable list) {
+ if (list == null) return null;
+ Integer[] result = new Integer[Iterables.size(list)];
+ int count = 0;
+ for (Object element : list) {
+ result[count++] = coerce(element, Integer.class);
+ }
+ return result;
+ }
+ });
+ registerAdapter(Iterable.class, int[].class, new Function<Iterable, int[]>() {
+ @Nullable
+ @Override
+ public int[] apply(@Nullable Iterable list) {
+ if (list == null) return null;
+ int[] result = new int[Iterables.size(list)];
+ int count = 0;
+ for (Object element : list) {
+ result[count++] = coerce(element, int.class);
+ }
+ return result;
+ }
+ });
+ registerAdapter(String.class, Map.class, new Function<String,Map>() {
+ @Override
+ public Map apply(final String input) {
+ Exception error = null;
+
+ // first try wrapping in braces if needed
+ if (!input.trim().startsWith("{")) {
+ try {
+ return apply("{ "+input+" }");
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ // prefer this error
+ error = e;
+ // fall back to parsing without braces, e.g. if it's multiline
+ }
+ }
+
+ try {
+ return Yamls.getAs( Yamls.parseAll(input), Map.class );
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ if (error!=null && input.indexOf('\n')==-1) {
+ // prefer the original error if it wasn't braced and wasn't multiline
+ e = error;
+ }
+ throw new IllegalArgumentException("Cannot parse string as map with flexible YAML parsing; "+
+ (e instanceof ClassCastException ? "yaml treats it as a string" :
+ (e instanceof IllegalArgumentException && Strings.isNonEmpty(e.getMessage())) ? e.getMessage() :
+ ""+e) );
+ }
+
+ // NB: previously we supported this also, when we did json above;
+ // yaml support is better as it supports quotes (and better than json because it allows dropping quotes)
+ // snake-yaml, our parser, also accepts key=value -- although i'm not sure this is strictly yaml compliant;
+ // our tests will catch it if snake behaviour changes, and we can reinstate this
+ // (but note it doesn't do quotes; see http://code.google.com/p/guava-libraries/issues/detail?id=412 for that):
+// return ImmutableMap.copyOf(Splitter.on(",").trimResults().omitEmptyStrings().withKeyValueSeparator("=").split(input));
+ }
+ });
+ }
+}
[09/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/xstream/CompilerCompatibilityTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/xstream/CompilerCompatibilityTest.java b/core/src/test/java/org/apache/brooklyn/core/util/xstream/CompilerCompatibilityTest.java
new file mode 100644
index 0000000..d18da28
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/xstream/CompilerCompatibilityTest.java
@@ -0,0 +1,158 @@
+/*
+ * 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.util.xstream;
+
+import static org.testng.Assert.assertTrue;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+
+import org.apache.brooklyn.core.util.xstream.CompilerIndependentOuterClassFieldMapper;
+import org.apache.brooklyn.core.util.xstream.CompilerCompatibilityTest.EnclosingClass.DynamicClass;
+import org.apache.brooklyn.core.util.xstream.CompilerCompatibilityTest.EnclosingClass.DynamicExtendingClass;
+import org.apache.brooklyn.core.util.xstream.CompilerCompatibilityTest.EnclosingClass.EnclosingDynamicClass;
+import org.apache.brooklyn.core.util.xstream.CompilerCompatibilityTest.EnclosingClass.EnclosingDynamicClass.NestedDynamicClass;
+import org.eclipse.jetty.util.log.Log;
+import org.testng.annotations.Test;
+
+import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.mapper.MapperWrapper;
+
+// To get the generated synthetic fields use the command:
+/*
+ find core/target/test-classes -name CompilerCompatibilityTest\$EnclosingClass\$* | \
+ sed s@core/target/test-classes/@@ | sed 's@.class$@@' | sed s@/@.@g | \
+ xargs javap -classpath core/target/test-classes/ | grep -B1 this
+*/
+@SuppressWarnings("unused")
+public class CompilerCompatibilityTest {
+ private EnclosingClass enclosingClass = new EnclosingClass();
+ private DynamicClass dynamicClass = enclosingClass.new DynamicClass();
+ private DynamicExtendingClass dynamicExtendingClass = enclosingClass.new DynamicExtendingClass();
+ private EnclosingDynamicClass enclosingDynamicClass = enclosingClass.new EnclosingDynamicClass();
+ private NestedDynamicClass nestedDynamicClass = enclosingDynamicClass.new NestedDynamicClass();
+// NOT SUPPORTED
+// private DynamicExtendingClassWithDifferentScope dynamicExtendingClassWithDifferentScope =
+// enclosingClass.new DynamicExtendingClassWithDifferentScope(enclosingDynamicClass);
+
+ public static class EnclosingClass {
+ public class DynamicClass {
+ //Oracle/OpenJDK/IBM generates
+ //final EnclosingClass this$0;
+
+ //eclipse-[groovy-]compiler generates
+ //final EnclosingClass this$1;
+ }
+
+ public class DynamicExtendingClass extends DynamicClass {
+ //The field here masks the parent field
+
+ //Oracle/OpenJDK/IBM generates
+ //final EnclosingClass this$0;
+
+ //eclipse-[groovy-]compiler generates
+ //final EnclosingClass this$1;
+ }
+
+ public class EnclosingDynamicClass {
+ //Oracle/OpenJDK/IBM generates
+ //final EnclosingClass this$0;
+
+ //eclipse-[groovy-]compiler generates
+ //final EnclosingClass this$1;
+
+ public class NestedDynamicClass {
+ //Oracle/OpenJDK/IBM generates
+ //final EnclosingClass this$1;
+
+ //eclipse-[groovy-]compiler generates
+ //final EnclosingClass this$2;
+ }
+ }
+
+// WARNING: Combination NOT SUPPORTED. Not enough information in XML to deserialize reliably,
+// having in mind that different compilers could be used for parent/child classes.
+// If we really need to, we can extend the heuristic to check for field types or assume that
+// only one compiler was used for the whole class hierarchy covering some more cases.
+//
+// The problem is that we have two fields with different names, without relation between the
+// indexes in each one. Changing compilers (or combination of compilers) could change the
+// indexes independently in each field. This makes it impossible to infer which field in the xml
+// maps to which field in the object.
+// When having identical field names with parent classes XStream will put a defined-in attribute
+// which makes it possible to deserialize, but it can't be forced to put it in each element.
+//
+ public class DynamicExtendingClassWithDifferentScope extends NestedDynamicClass {
+ //Oracle/OpenJDK/IBM generates
+ //final EnclosingClass this$0;
+
+ //eclipse-[groovy-]compiler generates
+ //final EnclosingClass this$1;
+
+ //constructor required to compile
+ public DynamicExtendingClassWithDifferentScope(EnclosingDynamicClass superEnclosingScope) {
+ superEnclosingScope.super();
+ }
+ }
+ }
+
+ @Test
+ public void testXStreamDeserialize() throws Exception {
+ deserialize("/brooklyn/entity/rebind/compiler_compatibility_eclipse.xml");
+ deserialize("/brooklyn/entity/rebind/compiler_compatibility_oracle.xml");
+ }
+
+ private void deserialize(String inputUrl) throws Exception {
+ XStream xstream = new XStream() {
+ @Override
+ protected MapperWrapper wrapMapper(MapperWrapper next) {
+ return new CompilerIndependentOuterClassFieldMapper(super.wrapMapper(next));
+ }
+ };
+
+ InputStream in = this.getClass().getResourceAsStream(inputUrl);
+ try {
+ Object obj = xstream.fromXML(in);
+ assertNonNullOuterFields(obj);
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ throw e;
+ } finally {
+ in.close();
+ }
+ }
+
+ private void assertNonNullOuterFields(Object obj) throws Exception {
+ Field[] testInstances = obj.getClass().getDeclaredFields();
+ for (Field instanceField : testInstances) {
+ Object instance = instanceField.get(obj);
+ Class<?> type = instance.getClass();
+ do {
+ for (Field field : type.getDeclaredFields()) {
+ if (field.getName().startsWith("this$")) {
+ Object value = field.get(instance);
+ assertTrue(value != null, field + " should not be null");
+ }
+ }
+ type = type.getSuperclass();
+ } while (type != null);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/xstream/ConverterTestFixture.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/xstream/ConverterTestFixture.java b/core/src/test/java/org/apache/brooklyn/core/util/xstream/ConverterTestFixture.java
new file mode 100644
index 0000000..16c7d71
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/xstream/ConverterTestFixture.java
@@ -0,0 +1,40 @@
+/*
+ * 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.util.xstream;
+
+import org.testng.Assert;
+
+import com.thoughtworks.xstream.XStream;
+
+public class ConverterTestFixture {
+
+ protected Object assertX(Object obj, String fmt) {
+ XStream xstream = new XStream();
+ registerConverters(xstream);
+ String s1 = xstream.toXML(obj);
+ Assert.assertEquals(s1, fmt);
+ Object out = xstream.fromXML(s1);
+ Assert.assertEquals(out, obj);
+ return out;
+ }
+
+ protected void registerConverters(XStream xstream) {
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/xstream/EnumCaseForgivingConverterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/xstream/EnumCaseForgivingConverterTest.java b/core/src/test/java/org/apache/brooklyn/core/util/xstream/EnumCaseForgivingConverterTest.java
new file mode 100644
index 0000000..65374e4
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/xstream/EnumCaseForgivingConverterTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.util.xstream;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
+import org.apache.brooklyn.core.util.xstream.EnumCaseForgivingConverter;
+import org.testng.annotations.Test;
+
+public class EnumCaseForgivingConverterTest {
+
+ public enum MyEnum {
+ FOO,
+ BaR;
+ }
+
+ @Test
+ public void testFindsCaseInsensitive() throws Exception {
+ assertEquals(EnumCaseForgivingConverter.resolve(MyEnum.class, "FOO"), MyEnum.FOO);
+ assertEquals(EnumCaseForgivingConverter.resolve(MyEnum.class, "foo"), MyEnum.FOO);
+ assertEquals(EnumCaseForgivingConverter.resolve(MyEnum.class, "Foo"), MyEnum.FOO);
+ assertEquals(EnumCaseForgivingConverter.resolve(MyEnum.class, "BAR"), MyEnum.BaR);
+ assertEquals(EnumCaseForgivingConverter.resolve(MyEnum.class, "bar"), MyEnum.BaR);
+ assertEquals(EnumCaseForgivingConverter.resolve(MyEnum.class, "Bar"), MyEnum.BaR);
+ }
+
+ @Test
+ public void testFailsIfNoMatch() throws Exception {
+ try {
+ assertEquals(EnumCaseForgivingConverter.resolve(MyEnum.class, "DoesNotExist"), MyEnum.BaR);
+ fail();
+ } catch (IllegalArgumentException e) {
+ if (!e.toString().matches(".*No enum.*MyEnum.DOESNOTEXIST")) throw e;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/xstream/ImmutableListConverterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/xstream/ImmutableListConverterTest.java b/core/src/test/java/org/apache/brooklyn/core/util/xstream/ImmutableListConverterTest.java
new file mode 100644
index 0000000..1a708ce
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/xstream/ImmutableListConverterTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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.util.xstream;
+
+import java.net.UnknownHostException;
+
+import org.apache.brooklyn.core.util.xstream.ImmutableListConverter;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.thoughtworks.xstream.XStream;
+
+@Test
+public class ImmutableListConverterTest extends ConverterTestFixture {
+
+ protected void registerConverters(XStream xstream) {
+ super.registerConverters(xstream);
+ xstream.aliasType("ImmutableList", ImmutableList.class);
+ xstream.registerConverter(new ImmutableListConverter(xstream.getMapper()));
+ }
+
+ @Test
+ public void testImmutableEmptyList() throws UnknownHostException {
+ assertX(ImmutableList.of(), "<ImmutableList/>");
+ }
+
+ @Test
+ public void testImmutableSingletonDoubleList() throws UnknownHostException {
+ assertX(ImmutableList.of(1.2d), "<ImmutableList>\n <double>1.2</double>\n</ImmutableList>");
+ }
+
+ @Test
+ public void testImmutableTwoValStringList() throws UnknownHostException {
+ assertX(ImmutableList.of("a","b"), "<ImmutableList>\n <string>a</string>\n <string>b</string>\n</ImmutableList>");
+ }
+
+ @Test
+ public void testImmutableEmptyListStaysImmutable() throws UnknownHostException {
+ Object x = assertX(ImmutableList.of(), "<ImmutableList/>");
+ Assert.assertTrue(x instanceof ImmutableList);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/xstream/InetAddressConverterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/xstream/InetAddressConverterTest.java b/core/src/test/java/org/apache/brooklyn/core/util/xstream/InetAddressConverterTest.java
new file mode 100644
index 0000000..bec2cc4
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/xstream/InetAddressConverterTest.java
@@ -0,0 +1,42 @@
+/*
+ * 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.util.xstream;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.apache.brooklyn.core.util.xstream.Inet4AddressConverter;
+import org.testng.annotations.Test;
+
+import com.thoughtworks.xstream.XStream;
+
+@Test
+public class InetAddressConverterTest extends ConverterTestFixture {
+
+ protected void registerConverters(XStream xstream) {
+ super.registerConverters(xstream);
+ xstream.registerConverter(new Inet4AddressConverter());
+ }
+
+ public void testFoo1234() throws UnknownHostException {
+ assertX(InetAddress.getByAddress("foo", new byte[] { 1, 2, 3, 4 }),
+ "<java.net.Inet4Address>foo/1.2.3.4</java.net.Inet4Address>");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/xstream/StringKeyMapConverterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/xstream/StringKeyMapConverterTest.java b/core/src/test/java/org/apache/brooklyn/core/util/xstream/StringKeyMapConverterTest.java
new file mode 100644
index 0000000..6a15ee9
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/xstream/StringKeyMapConverterTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.util.xstream;
+
+import java.net.UnknownHostException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.brooklyn.core.util.xstream.StringKeyMapConverter;
+import org.testng.annotations.Test;
+
+import brooklyn.util.collections.MutableMap;
+
+import com.google.common.collect.Maps;
+import com.thoughtworks.xstream.XStream;
+
+@SuppressWarnings({ "rawtypes", "unchecked" })
+@Test
+public class StringKeyMapConverterTest extends ConverterTestFixture {
+
+ protected void registerConverters(XStream xstream) {
+ super.registerConverters(xstream);
+ xstream.alias("map", Map.class, LinkedHashMap.class);
+ xstream.alias("MutableMap", MutableMap.class);
+ xstream.registerConverter(new StringKeyMapConverter(xstream.getMapper()), /* priority */ 10);
+ }
+
+ @Test
+ public void testSimple() throws UnknownHostException {
+ Map m = Maps.newLinkedHashMap();
+ m.put("a", "v");
+ assertX(m, "<map>\n <a>v</a>\n</map>");
+ }
+
+ @Test
+ public void testDouble() throws UnknownHostException {
+ Map m = Maps.newLinkedHashMap();
+ m.put("a", "v");
+ m.put("x", 1.0d);
+ assertX(m, "<map>\n <a>v</a>\n <x type=\"double\">1.0</x>\n</map>");
+ }
+
+ @Test
+ public void testEmpty() throws UnknownHostException {
+ Map m = Maps.newLinkedHashMap();
+ assertX(m, "<map/>");
+ }
+
+ @Test
+ public void testBigSpacedKeyInMutableMap() throws UnknownHostException {
+ Map m = MutableMap.of("a b", "x");
+ assertX(m, "<MutableMap>\n <entry key=\"a b\">x</entry>\n</MutableMap>");
+ }
+
+ @Test
+ public void testWithNumericKey() throws UnknownHostException {
+ Map m = Maps.newLinkedHashMap();
+ m.put("123", "v");
+ m.put("a", "v2");
+ assertX(m, "<map>\n <entry key=\"123\">v</entry>\n <a>v2</a>\n</map>");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/xstream/XmlUtilTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/xstream/XmlUtilTest.java b/core/src/test/java/org/apache/brooklyn/core/util/xstream/XmlUtilTest.java
new file mode 100644
index 0000000..dd97d17
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/xstream/XmlUtilTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.util.xstream;
+
+import static org.testng.Assert.assertEquals;
+
+import org.apache.brooklyn.core.util.xstream.XmlUtil;
+import org.testng.annotations.Test;
+
+
+public class XmlUtilTest {
+
+ @Test
+ public void testXpath() throws Exception {
+ String xml = "<a><b>myb</b></a>";
+ assertEquals(XmlUtil.xpath(xml, "/a/b[text()]"), "myb");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/location/basic/AbstractLocationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/AbstractLocationTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/AbstractLocationTest.java
index 089b719..d24ac65 100644
--- a/core/src/test/java/org/apache/brooklyn/location/basic/AbstractLocationTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/basic/AbstractLocationTest.java
@@ -29,6 +29,7 @@ import java.util.Map;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
@@ -37,7 +38,6 @@ import org.testng.annotations.Test;
import brooklyn.entity.basic.Entities;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/location/basic/LegacyAbstractLocationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/LegacyAbstractLocationTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/LegacyAbstractLocationTest.java
index 10e59b3..c53762e 100644
--- a/core/src/test/java/org/apache/brooklyn/location/basic/LegacyAbstractLocationTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/basic/LegacyAbstractLocationTest.java
@@ -26,11 +26,11 @@ import static org.testng.Assert.assertTrue;
import java.util.Collections;
import java.util.Map;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.Test;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/location/basic/LocationConfigTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/LocationConfigTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/LocationConfigTest.java
index 1f265fd..cbf1aaa 100644
--- a/core/src/test/java/org/apache/brooklyn/location/basic/LocationConfigTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/basic/LocationConfigTest.java
@@ -22,6 +22,7 @@ import static org.testng.Assert.assertEquals;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
@@ -31,7 +32,6 @@ import org.testng.annotations.Test;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.Entities;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/location/basic/LocationConfigUtilsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/LocationConfigUtilsTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/LocationConfigUtilsTest.java
index e9197a1..1360f6b 100644
--- a/core/src/test/java/org/apache/brooklyn/location/basic/LocationConfigUtilsTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/basic/LocationConfigUtilsTest.java
@@ -23,11 +23,10 @@ import static org.testng.Assert.assertTrue;
import java.io.File;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.testng.Assert;
import org.testng.annotations.Test;
-import brooklyn.util.config.ConfigBag;
-
@Test
public class LocationConfigUtilsTest {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/location/basic/PortRangesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/PortRangesTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/PortRangesTest.java
index 2b7ab69..de23b55 100644
--- a/core/src/test/java/org/apache/brooklyn/location/basic/PortRangesTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/basic/PortRangesTest.java
@@ -25,8 +25,7 @@ import java.util.Iterator;
import org.testng.Assert;
import org.testng.annotations.Test;
import org.apache.brooklyn.api.location.PortRange;
-
-import brooklyn.util.flags.TypeCoercions;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationIntegrationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationIntegrationTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationIntegrationTest.java
index 68a53c5..19b58fd 100644
--- a/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationIntegrationTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationIntegrationTest.java
@@ -23,12 +23,14 @@ import java.security.KeyPair;
import java.util.Arrays;
import java.util.Map;
-import brooklyn.util.internal.ssh.SshTool;
-
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.util.crypto.SecureKeys;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
+import org.apache.brooklyn.core.util.internal.ssh.sshj.SshjTool;
+import org.apache.brooklyn.core.util.internal.ssh.sshj.SshjTool.SshjToolBuilder;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.test.entity.TestApplication;
import org.testng.Assert;
@@ -38,9 +40,6 @@ import org.testng.annotations.Test;
import brooklyn.entity.basic.Entities;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.crypto.SecureKeys;
-import brooklyn.util.internal.ssh.sshj.SshjTool;
-import brooklyn.util.internal.ssh.sshj.SshjTool.SshjToolBuilder;
import com.google.common.base.Preconditions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationPerformanceTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationPerformanceTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationPerformanceTest.java
index 93e33a1..f7f8bf9 100644
--- a/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationPerformanceTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationPerformanceTest.java
@@ -25,6 +25,7 @@ import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
import org.apache.brooklyn.test.PerformanceTestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,7 +34,6 @@ import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.internal.ssh.SshTool;
import brooklyn.util.net.Networking;
import brooklyn.util.stream.Streams;
import brooklyn.util.text.Identifiers;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationReuseIntegrationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationReuseIntegrationTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationReuseIntegrationTest.java
index 6ba27e7..fd5884c 100644
--- a/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationReuseIntegrationTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationReuseIntegrationTest.java
@@ -35,11 +35,11 @@ import brooklyn.entity.basic.Entities;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
+import org.apache.brooklyn.core.util.internal.ssh.sshj.SshjTool;
import brooklyn.test.Asserts;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.internal.ssh.SshTool;
-import brooklyn.util.internal.ssh.sshj.SshjTool;
import brooklyn.util.net.Networking;
import brooklyn.util.stream.Streams;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationTest.java
index b4ee5ef..ca51182 100644
--- a/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationTest.java
@@ -43,6 +43,13 @@ import org.apache.brooklyn.api.location.MachineDetails;
import org.apache.brooklyn.api.location.MachineLocation;
import org.apache.brooklyn.api.location.PortRange;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.file.ArchiveUtils;
+import org.apache.brooklyn.core.util.internal.ssh.RecordingSshTool;
+import org.apache.brooklyn.core.util.internal.ssh.SshException;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
+import org.apache.brooklyn.core.util.task.BasicExecutionContext;
+import org.apache.brooklyn.core.util.task.BasicExecutionManager;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.test.entity.TestApplication;
import org.testng.annotations.AfterMethod;
@@ -58,18 +65,11 @@ import brooklyn.entity.effector.EffectorTaskTest;
import brooklyn.entity.effector.Effectors;
import brooklyn.test.Asserts;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.file.ArchiveUtils;
import brooklyn.util.guava.Maybe;
-import brooklyn.util.internal.ssh.RecordingSshTool;
-import brooklyn.util.internal.ssh.SshException;
-import brooklyn.util.internal.ssh.SshTool;
import brooklyn.util.net.Networking;
import brooklyn.util.net.Urls;
import brooklyn.util.os.Os;
import brooklyn.util.stream.Streams;
-import brooklyn.util.task.BasicExecutionContext;
-import brooklyn.util.task.BasicExecutionManager;
import brooklyn.util.time.Duration;
import com.google.common.base.Charsets;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/location/cloud/CloudMachineNamerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/cloud/CloudMachineNamerTest.java b/core/src/test/java/org/apache/brooklyn/location/cloud/CloudMachineNamerTest.java
index 9d4acad..fe26a43 100644
--- a/core/src/test/java/org/apache/brooklyn/location/cloud/CloudMachineNamerTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/cloud/CloudMachineNamerTest.java
@@ -22,6 +22,7 @@ import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.location.cloud.names.AbstractCloudMachineNamer;
import org.apache.brooklyn.location.cloud.names.CloudMachineNamer;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
@@ -35,8 +36,9 @@ import org.testng.annotations.Test;
import brooklyn.entity.basic.ApplicationBuilder;
import brooklyn.entity.basic.Entities;
+
import org.apache.brooklyn.location.cloud.names.BasicCloudMachineNamer;
-import brooklyn.util.config.ConfigBag;
+
import brooklyn.util.text.Strings;
public class CloudMachineNamerTest {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/location/cloud/CustomMachineNamerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/cloud/CustomMachineNamerTest.java b/core/src/test/java/org/apache/brooklyn/location/cloud/CustomMachineNamerTest.java
index f0e7d11..0afad81 100644
--- a/core/src/test/java/org/apache/brooklyn/location/cloud/CustomMachineNamerTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/cloud/CustomMachineNamerTest.java
@@ -19,6 +19,7 @@
package org.apache.brooklyn.location.cloud;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestEntity;
@@ -29,8 +30,8 @@ import org.testng.annotations.Test;
import brooklyn.entity.basic.ApplicationBuilder;
import brooklyn.entity.basic.Entities;
+
import org.apache.brooklyn.location.cloud.names.CustomMachineNamer;
-import brooklyn.util.config.ConfigBag;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/test/entity/BlockingEntity.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/test/entity/BlockingEntity.java b/core/src/test/java/org/apache/brooklyn/test/entity/BlockingEntity.java
index 3586701..7df9a89 100644
--- a/core/src/test/java/org/apache/brooklyn/test/entity/BlockingEntity.java
+++ b/core/src/test/java/org/apache/brooklyn/test/entity/BlockingEntity.java
@@ -21,10 +21,10 @@ package org.apache.brooklyn.test.entity;
import java.util.concurrent.CountDownLatch;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.util.flags.SetFromFlag;
/**
* Mock entity that blocks on startup via the {@link CountDownLatch} argument.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/test/entity/TestEntity.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/test/entity/TestEntity.java b/core/src/test/java/org/apache/brooklyn/test/entity/TestEntity.java
index 01b835e..8f0eff4 100644
--- a/core/src/test/java/org/apache/brooklyn/test/entity/TestEntity.java
+++ b/core/src/test/java/org/apache/brooklyn/test/entity/TestEntity.java
@@ -28,6 +28,7 @@ import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.testng.collections.Lists;
import org.testng.internal.annotations.Sets;
@@ -49,7 +50,6 @@ import brooklyn.event.basic.MapConfigKey;
import brooklyn.event.basic.Sensors;
import brooklyn.event.basic.SetConfigKey;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.flags.SetFromFlag;
/**
* Mock entity for testing.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/resources/brooklyn/entity/rebind/compiler_compatibility_eclipse.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/brooklyn/entity/rebind/compiler_compatibility_eclipse.xml b/core/src/test/resources/brooklyn/entity/rebind/compiler_compatibility_eclipse.xml
index dc972ef..7dd5ac6 100644
--- a/core/src/test/resources/brooklyn/entity/rebind/compiler_compatibility_eclipse.xml
+++ b/core/src/test/resources/brooklyn/entity/rebind/compiler_compatibility_eclipse.xml
@@ -17,25 +17,25 @@
specific language governing permissions and limitations
under the License.
-->
-<brooklyn.util.xstream.CompilerCompatibilityTest>
- <enclosingClass/>
+<org.apache.brooklyn.core.util.xstream.CompilerCompatibilityTest>
+ <enclosingClass />
<dynamicClass>
- <this_-1 reference="../../enclosingClass"/>
+ <this_-1 reference="../../enclosingClass" />
</dynamicClass>
<dynamicExtendingClass>
- <this_-1 defined-in="brooklyn.util.xstream.CompilerCompatibilityTest$EnclosingClass$DynamicClass" reference="../../enclosingClass"/>
- <this_-1 reference="../../enclosingClass"/>
+ <this_-1 defined-in="org.apache.brooklyn.core.util.xstream.CompilerCompatibilityTest$EnclosingClass$DynamicClass" reference="../../enclosingClass" />
+ <this_-1 reference="../../enclosingClass" />
</dynamicExtendingClass>
<enclosingDynamicClass>
- <this_-1 reference="../../enclosingClass"/>
+ <this_-1 reference="../../enclosingClass" />
</enclosingDynamicClass>
<nestedDynamicClass>
- <this_-2 reference="../../enclosingDynamicClass"/>
+ <this_-2 reference="../../enclosingDynamicClass" />
</nestedDynamicClass>
<!-- NOT SUPPORTED
<dynamicExtendingClassWithDifferentScope>
- <this_-2 reference="../../enclosingDynamicClass"/>
- <this_-1 reference="../../enclosingClass"/>
+ <this_-2 reference="../../enclosingDynamicClass" />
+ <this_-1 reference="../../enclosingClass" />
</dynamicExtendingClassWithDifferentScope>
-->
-</brooklyn.util.xstream.CompilerCompatibilityTest>
+</org.apache.brooklyn.core.util.xstream.CompilerCompatibilityTest>
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/resources/brooklyn/entity/rebind/compiler_compatibility_oracle.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/brooklyn/entity/rebind/compiler_compatibility_oracle.xml b/core/src/test/resources/brooklyn/entity/rebind/compiler_compatibility_oracle.xml
index a01692e..2b49251 100644
--- a/core/src/test/resources/brooklyn/entity/rebind/compiler_compatibility_oracle.xml
+++ b/core/src/test/resources/brooklyn/entity/rebind/compiler_compatibility_oracle.xml
@@ -17,25 +17,25 @@
specific language governing permissions and limitations
under the License.
-->
-<brooklyn.util.xstream.CompilerCompatibilityTest>
- <enclosingClass/>
+<org.apache.brooklyn.core.util.xstream.CompilerCompatibilityTest>
+ <enclosingClass />
<dynamicClass>
- <outer-class reference="../../enclosingClass"/>
+ <outer-class reference="../../enclosingClass" />
</dynamicClass>
<dynamicExtendingClass>
- <outer-class defined-in="brooklyn.util.xstream.CompilerCompatibilityTest$EnclosingClass$DynamicClass" reference="../../enclosingClass"/>
+ <outer-class defined-in="org.apache.brooklyn.core.util.xstream.CompilerCompatibilityTest$EnclosingClass$DynamicClass" reference="../../enclosingClass" />
<outer-class reference="../../enclosingClass"/>
</dynamicExtendingClass>
<enclosingDynamicClass>
- <outer-class reference="../../enclosingClass"/>
+ <outer-class reference="../../enclosingClass" />
</enclosingDynamicClass>
<nestedDynamicClass>
- <this_-1 reference="../../enclosingDynamicClass"/>
+ <this_-1 reference="../../enclosingDynamicClass" />
</nestedDynamicClass>
<!-- NOT SUPPORTED
<dynamicExtendingClassWithDifferentScope>
- <this_-1 reference="../../enclosingDynamicClass"/>
- <outer-class reference="../../enclosingClass"/>
+ <this_-1 reference="../../enclosingDynamicClass" />
+ <outer-class reference="../../enclosingClass" />
</dynamicExtendingClassWithDifferentScope>
-->
-</brooklyn.util.xstream.CompilerCompatibilityTest>
+</org.apache.brooklyn.core.util.xstream.CompilerCompatibilityTest>
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/examples/global-web-fabric/src/main/java/org/apache/brooklyn/demo/GlobalWebFabricExample.java
----------------------------------------------------------------------
diff --git a/examples/global-web-fabric/src/main/java/org/apache/brooklyn/demo/GlobalWebFabricExample.java b/examples/global-web-fabric/src/main/java/org/apache/brooklyn/demo/GlobalWebFabricExample.java
index d53cf44..6fd3462 100644
--- a/examples/global-web-fabric/src/main/java/org/apache/brooklyn/demo/GlobalWebFabricExample.java
+++ b/examples/global-web-fabric/src/main/java/org/apache/brooklyn/demo/GlobalWebFabricExample.java
@@ -28,6 +28,8 @@ import org.slf4j.LoggerFactory;
import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.catalog.CatalogConfig;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.core.util.BrooklynMavenArtifacts;
+import org.apache.brooklyn.core.util.ResourceUtils;
import org.apache.brooklyn.entity.dns.geoscaling.GeoscalingDnsService;
import org.apache.brooklyn.entity.proxy.AbstractController;
import org.apache.brooklyn.entity.webapp.ElasticJavaWebAppService;
@@ -43,11 +45,9 @@ import brooklyn.entity.group.DynamicRegionsFabric;
import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
import org.apache.brooklyn.launcher.BrooklynLauncher;
-
import org.apache.brooklyn.location.basic.PortRanges;
-import brooklyn.util.BrooklynMavenArtifacts;
+
import brooklyn.util.CommandLineUtil;
-import brooklyn.util.ResourceUtils;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/CumulusRDFApplication.java
----------------------------------------------------------------------
diff --git a/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/CumulusRDFApplication.java b/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/CumulusRDFApplication.java
index 507ed37..da88bff 100644
--- a/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/CumulusRDFApplication.java
+++ b/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/CumulusRDFApplication.java
@@ -34,6 +34,10 @@ import org.apache.brooklyn.api.event.SensorEventListener;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.policy.EnricherSpec;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.text.TemplateProcessor;
import org.apache.brooklyn.entity.nosql.cassandra.CassandraDatacenter;
import org.apache.brooklyn.entity.nosql.cassandra.CassandraFabric;
import org.apache.brooklyn.entity.nosql.cassandra.CassandraNode;
@@ -63,15 +67,11 @@ import brooklyn.policy.ha.ServiceFailureDetector;
import brooklyn.policy.ha.ServiceReplacer;
import brooklyn.policy.ha.ServiceRestarter;
import brooklyn.util.CommandLineUtil;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.task.DynamicTasks;
import brooklyn.util.text.StringEscapes.JavaStringEscapes;
import brooklyn.util.text.Strings;
-import brooklyn.util.text.TemplateProcessor;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExampleApp.java
----------------------------------------------------------------------
diff --git a/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExampleApp.java b/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExampleApp.java
index 5b72a58..441999f 100644
--- a/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExampleApp.java
+++ b/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExampleApp.java
@@ -30,6 +30,8 @@ import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.catalog.CatalogConfig;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.BrooklynMavenArtifacts;
+import org.apache.brooklyn.core.util.ResourceUtils;
import org.apache.brooklyn.entity.webapp.ControlledDynamicWebAppCluster;
import org.apache.brooklyn.entity.webapp.DynamicWebAppCluster;
import org.apache.brooklyn.entity.webapp.JavaWebAppService;
@@ -49,12 +51,10 @@ import brooklyn.entity.java.JavaEntityMethods;
import brooklyn.event.basic.Sensors;
import org.apache.brooklyn.launcher.BrooklynLauncher;
-
import org.apache.brooklyn.location.basic.PortRanges;
+
import brooklyn.policy.autoscaling.AutoScalerPolicy;
-import brooklyn.util.BrooklynMavenArtifacts;
import brooklyn.util.CommandLineUtil;
-import brooklyn.util.ResourceUtils;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/locations/jclouds/src/main/java/brooklyn/policy/os/CreateUserPolicy.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/brooklyn/policy/os/CreateUserPolicy.java b/locations/jclouds/src/main/java/brooklyn/policy/os/CreateUserPolicy.java
index bc8eab1..8327cf1 100644
--- a/locations/jclouds/src/main/java/brooklyn/policy/os/CreateUserPolicy.java
+++ b/locations/jclouds/src/main/java/brooklyn/policy/os/CreateUserPolicy.java
@@ -26,6 +26,8 @@ import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
import org.jclouds.compute.config.AdminAccessConfiguration;
import org.jclouds.scriptbuilder.functions.InitAdminAccess;
import org.jclouds.scriptbuilder.statements.login.AdminAccess;
@@ -42,8 +44,6 @@ import brooklyn.event.basic.Sensors;
import org.apache.brooklyn.location.basic.SshMachineLocation;
import brooklyn.policy.basic.AbstractPolicy;
-import brooklyn.util.flags.SetFromFlag;
-import brooklyn.util.internal.ssh.SshTool;
import brooklyn.util.text.Identifiers;
import com.google.common.annotations.Beta;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/BrooklynMachinePool.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/BrooklynMachinePool.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/BrooklynMachinePool.java
index fa71a3a..f447482 100644
--- a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/BrooklynMachinePool.java
+++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/BrooklynMachinePool.java
@@ -28,6 +28,7 @@ import java.util.concurrent.atomic.AtomicReference;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.location.MachineLocation;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.task.BasicExecutionContext;
import org.jclouds.compute.domain.NodeMetadata;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -40,7 +41,6 @@ import org.apache.brooklyn.location.jclouds.pool.MachineSet;
import org.apache.brooklyn.location.jclouds.pool.ReusableMachineTemplate;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.task.BasicExecutionContext;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/ComputeServiceRegistry.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/ComputeServiceRegistry.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/ComputeServiceRegistry.java
index a835e2c..8d48cf5 100644
--- a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/ComputeServiceRegistry.java
+++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/ComputeServiceRegistry.java
@@ -18,10 +18,9 @@
*/
package org.apache.brooklyn.location.jclouds;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.jclouds.compute.ComputeService;
-import brooklyn.util.config.ConfigBag;
-
public interface ComputeServiceRegistry {
public ComputeService findComputeService(ConfigBag conf, boolean allowReuse);
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/ComputeServiceRegistryImpl.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/ComputeServiceRegistryImpl.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/ComputeServiceRegistryImpl.java
index f3f39bb..670379d 100644
--- a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/ComputeServiceRegistryImpl.java
+++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/ComputeServiceRegistryImpl.java
@@ -27,6 +27,7 @@ import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.location.cloud.CloudLocationConfig;
import org.jclouds.Constants;
import org.jclouds.ContextBuilder;
@@ -41,7 +42,6 @@ import org.slf4j.LoggerFactory;
import brooklyn.entity.basic.Sanitizer;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.time.Duration;
import com.google.common.base.Predicates;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolver.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolver.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolver.java
index e8f63b3..eb9ebfa 100644
--- a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolver.java
+++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolver.java
@@ -31,6 +31,7 @@ import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.location.NoMachinesAvailableException;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.brooklyn.location.basic.BasicLocationRegistry;
@@ -41,7 +42,6 @@ import org.apache.brooklyn.location.basic.LocationInternal;
import org.apache.brooklyn.location.basic.LocationPropertiesFromBrooklynProperties;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.text.KeyValueParser;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java
index 2583234..1c1254c 100644
--- a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java
+++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java
@@ -57,6 +57,15 @@ import org.apache.brooklyn.api.location.MachineLocationCustomizer;
import org.apache.brooklyn.api.location.MachineManagementMixins;
import org.apache.brooklyn.api.location.NoMachinesAvailableException;
import org.apache.brooklyn.api.management.AccessController;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.crypto.SecureKeys;
+import org.apache.brooklyn.core.util.flags.MethodCoercions;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
+import org.apache.brooklyn.core.util.internal.ssh.ShellTool;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
+import org.apache.brooklyn.core.util.text.TemplateProcessor;
import org.apache.brooklyn.location.access.PortMapping;
import org.apache.brooklyn.location.basic.AbstractLocation;
import org.apache.brooklyn.location.cloud.AbstractCloudMachineProvisioningLocation;
@@ -146,21 +155,13 @@ import org.apache.brooklyn.location.cloud.names.CloudMachineNamer;
import org.apache.brooklyn.location.jclouds.JcloudsPredicates.NodeInLocation;
import org.apache.brooklyn.location.jclouds.templates.PortableTemplateBuilder;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.crypto.SecureKeys;
import brooklyn.util.exceptions.CompoundRuntimeException;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.exceptions.ReferenceWithError;
-import brooklyn.util.flags.MethodCoercions;
-import brooklyn.util.flags.SetFromFlag;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.guava.Maybe;
-import brooklyn.util.internal.ssh.ShellTool;
-import brooklyn.util.internal.ssh.SshTool;
import brooklyn.util.javalang.Enums;
import brooklyn.util.javalang.Reflections;
import brooklyn.util.net.Cidr;
@@ -177,7 +178,6 @@ import brooklyn.util.text.ByteSizeStrings;
import brooklyn.util.text.Identifiers;
import brooklyn.util.text.KeyValueParser;
import brooklyn.util.text.Strings;
-import brooklyn.util.text.TemplateProcessor;
import brooklyn.util.time.Duration;
import brooklyn.util.time.Time;
import io.cloudsoft.winrm4j.pywinrm.Session;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocationConfig.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocationConfig.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocationConfig.java
index 9fce742..1922b39 100644
--- a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocationConfig.java
+++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocationConfig.java
@@ -23,6 +23,7 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.Semaphore;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
import org.apache.brooklyn.location.jclouds.networking.JcloudsPortForwarderExtension;
import org.jclouds.Constants;
import org.jclouds.compute.domain.Image;
@@ -33,11 +34,11 @@ import org.jclouds.domain.LoginCredentials;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.event.basic.BasicConfigKey;
+
import org.apache.brooklyn.location.access.BrooklynAccessUtils;
import org.apache.brooklyn.location.access.PortForwardManager;
import org.apache.brooklyn.location.basic.LocationConfigKeys;
import org.apache.brooklyn.location.cloud.CloudLocationConfig;
-import brooklyn.util.internal.ssh.SshTool;
import com.google.common.annotations.Beta;
import com.google.common.base.Function;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocationCustomizer.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocationCustomizer.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocationCustomizer.java
index b6cb363..d7cf619 100644
--- a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocationCustomizer.java
+++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocationCustomizer.java
@@ -18,6 +18,7 @@
*/
package org.apache.brooklyn.location.jclouds;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
@@ -25,8 +26,6 @@ import org.jclouds.compute.options.TemplateOptions;
import com.google.common.annotations.Beta;
-import brooklyn.util.config.ConfigBag;
-
/**
* Customization hooks to allow apps to perform specific customisation at each stage of jclouds machine provisioning.
* For example, an app could attach an EBS volume to an EC2 node, or configure a desired availability zone.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsMachineNamer.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsMachineNamer.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsMachineNamer.java
index 4f4587e..e2cd2e1 100644
--- a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsMachineNamer.java
+++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsMachineNamer.java
@@ -18,8 +18,8 @@
*/
package org.apache.brooklyn.location.jclouds;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.location.cloud.names.BasicCloudMachineNamer;
-import brooklyn.util.config.ConfigBag;
public class JcloudsMachineNamer extends BasicCloudMachineNamer {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsPropertiesFromBrooklynProperties.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsPropertiesFromBrooklynProperties.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsPropertiesFromBrooklynProperties.java
index f307041..87e8ce4 100644
--- a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsPropertiesFromBrooklynProperties.java
+++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsPropertiesFromBrooklynProperties.java
@@ -20,14 +20,16 @@ package org.apache.brooklyn.location.jclouds;
import java.util.Map;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.location.basic.DeprecatedKeysMappingBuilder;
import org.apache.brooklyn.location.basic.LocationPropertiesFromBrooklynProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.config.ConfigUtils;
+
import org.apache.brooklyn.location.basic.LocationConfigKeys;
-import brooklyn.util.config.ConfigBag;
+
import brooklyn.util.javalang.JavaClassNames;
import com.google.common.base.Splitter;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsSshMachineLocation.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsSshMachineLocation.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsSshMachineLocation.java
index a2a5735..3ce7892 100644
--- a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsSshMachineLocation.java
+++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsSshMachineLocation.java
@@ -34,6 +34,7 @@ import javax.annotation.Nullable;
import org.apache.brooklyn.api.location.HardwareDetails;
import org.apache.brooklyn.api.location.MachineDetails;
import org.apache.brooklyn.api.location.OsDetails;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.location.basic.BasicHardwareDetails;
import org.apache.brooklyn.location.basic.BasicMachineDetails;
import org.apache.brooklyn.location.basic.BasicOsDetails;
@@ -55,7 +56,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.net.Networking;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsUtil.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsUtil.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsUtil.java
index e3026df..c981f26 100644
--- a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsUtil.java
+++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsUtil.java
@@ -36,6 +36,7 @@ import java.util.concurrent.TimeoutException;
import javax.annotation.Nullable;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.jclouds.Constants;
import org.jclouds.ContextBuilder;
import org.jclouds.aws.ec2.AWSEC2Api;
@@ -80,7 +81,6 @@ import com.google.inject.Module;
import brooklyn.entity.basic.Sanitizer;
import brooklyn.util.collections.MutableList;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.net.Protocol;
import brooklyn.util.ssh.BashCommands;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsWinRmMachineLocation.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsWinRmMachineLocation.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsWinRmMachineLocation.java
index 753d772..1204856 100644
--- a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsWinRmMachineLocation.java
+++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsWinRmMachineLocation.java
@@ -25,13 +25,13 @@ import java.net.UnknownHostException;
import java.util.Iterator;
import java.util.Set;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.location.basic.WinRmMachineLocation;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.net.Networking;
import com.google.common.base.Objects;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/SudoTtyFixingCustomizer.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/SudoTtyFixingCustomizer.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/SudoTtyFixingCustomizer.java
index d48a67c..f7bbc2c 100644
--- a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/SudoTtyFixingCustomizer.java
+++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/SudoTtyFixingCustomizer.java
@@ -18,16 +18,15 @@
*/
package org.apache.brooklyn.location.jclouds;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.ssh.SshTasks;
+import org.apache.brooklyn.core.util.task.ssh.SshTasks.OnFailingTask;
import org.apache.brooklyn.location.basic.SshMachineLocation;
import org.jclouds.compute.ComputeService;
import com.google.common.annotations.Beta;
import com.google.common.base.Preconditions;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.ssh.SshTasks;
-import brooklyn.util.task.ssh.SshTasks.OnFailingTask;
-
/**
* Wraps Brooklyn's sudo-tty mitigations in a {@link JcloudsLocationCustomizer} for easy(-ish) consumption
* in YAML blueprints:
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/networking/JcloudsLocationSecurityGroupCustomizer.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/networking/JcloudsLocationSecurityGroupCustomizer.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/networking/JcloudsLocationSecurityGroupCustomizer.java
index 687a486..eb01bb1 100644
--- a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/networking/JcloudsLocationSecurityGroupCustomizer.java
+++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/networking/JcloudsLocationSecurityGroupCustomizer.java
@@ -28,6 +28,7 @@ import java.util.concurrent.ExecutionException;
import javax.annotation.Nullable;
import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.apache.brooklyn.location.geo.LocalhostExternalIpLoader;
import org.apache.brooklyn.location.jclouds.JcloudsLocation;
import org.apache.brooklyn.location.jclouds.JcloudsLocationCustomizer;
@@ -45,11 +46,10 @@ import org.jclouds.providers.ProviderMetadata;
import org.jclouds.providers.Providers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
import org.apache.brooklyn.location.jclouds.BasicJcloudsLocationCustomizer;
+
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.net.Cidr;
-import brooklyn.util.task.Tasks;
import brooklyn.util.time.Duration;
import com.google.common.annotations.Beta;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreExpiryTest.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreExpiryTest.java b/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreExpiryTest.java
index 6260a8c..18211c1 100644
--- a/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreExpiryTest.java
+++ b/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreExpiryTest.java
@@ -28,6 +28,8 @@ import java.util.List;
import java.util.Map.Entry;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.util.http.HttpTool;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.apache.http.client.HttpClient;
import org.jclouds.blobstore.BlobStoreContext;
@@ -44,13 +46,13 @@ import org.testng.annotations.Test;
import brooklyn.config.BrooklynProperties;
import brooklyn.entity.basic.Entities;
+
import org.apache.brooklyn.location.basic.LocationConfigKeys;
import org.apache.brooklyn.location.cloud.CloudLocationConfig;
import org.apache.brooklyn.location.jclouds.JcloudsLocation;
import org.apache.brooklyn.location.jclouds.JcloudsUtil;
+
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.http.HttpTool;
-import brooklyn.util.http.HttpToolResponse;
import brooklyn.util.text.Identifiers;
import brooklyn.util.time.Duration;
import brooklyn.util.time.Time;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/locations/jclouds/src/test/java/brooklyn/policy/os/CreateUserPolicyLiveTest.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/brooklyn/policy/os/CreateUserPolicyLiveTest.java b/locations/jclouds/src/test/java/brooklyn/policy/os/CreateUserPolicyLiveTest.java
index bf5f87b..75eed65 100644
--- a/locations/jclouds/src/test/java/brooklyn/policy/os/CreateUserPolicyLiveTest.java
+++ b/locations/jclouds/src/test/java/brooklyn/policy/os/CreateUserPolicyLiveTest.java
@@ -29,6 +29,7 @@ import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
import org.apache.brooklyn.test.EntityTestUtils;
import org.apache.brooklyn.test.entity.TestEntity;
import org.slf4j.Logger;
@@ -40,7 +41,6 @@ import brooklyn.entity.BrooklynAppLiveTestSupport;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.internal.ssh.SshTool;
import brooklyn.util.text.Identifiers;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/locations/jclouds/src/test/java/brooklyn/policy/os/CreateUserPolicyTest.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/brooklyn/policy/os/CreateUserPolicyTest.java b/locations/jclouds/src/test/java/brooklyn/policy/os/CreateUserPolicyTest.java
index af248de..ed4e2ee 100644
--- a/locations/jclouds/src/test/java/brooklyn/policy/os/CreateUserPolicyTest.java
+++ b/locations/jclouds/src/test/java/brooklyn/policy/os/CreateUserPolicyTest.java
@@ -29,6 +29,7 @@ import java.util.regex.Pattern;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
import org.apache.brooklyn.test.EntityTestUtils;
import org.apache.brooklyn.test.entity.TestEntity;
import org.slf4j.Logger;
@@ -41,8 +42,6 @@ import brooklyn.entity.BrooklynAppUnitTestSupport;
import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.internal.ssh.SshTool;
-
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/AbstractJcloudsStubbedLiveTest.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/AbstractJcloudsStubbedLiveTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/AbstractJcloudsStubbedLiveTest.java
index 9c70305..1faa83b 100644
--- a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/AbstractJcloudsStubbedLiveTest.java
+++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/AbstractJcloudsStubbedLiveTest.java
@@ -21,6 +21,7 @@ package org.apache.brooklyn.location.jclouds;
import java.util.List;
import java.util.Set;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.RunNodesException;
import org.jclouds.compute.domain.NodeMetadata;
@@ -30,8 +31,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.BeforeMethod;
-import brooklyn.util.config.ConfigBag;
-
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/BailOutJcloudsLocation.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/BailOutJcloudsLocation.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/BailOutJcloudsLocation.java
index c323b7f..b83bce8 100644
--- a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/BailOutJcloudsLocation.java
+++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/BailOutJcloudsLocation.java
@@ -27,6 +27,7 @@ import javax.annotation.Nullable;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.Template;
@@ -41,7 +42,6 @@ import brooklyn.config.BrooklynProperties;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.CompoundRuntimeException;
import brooklyn.util.exceptions.Exceptions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationTemplateOptionsCustomisersLiveTest.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationTemplateOptionsCustomisersLiveTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationTemplateOptionsCustomisersLiveTest.java
index f173646..5e535e4 100644
--- a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationTemplateOptionsCustomisersLiveTest.java
+++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationTemplateOptionsCustomisersLiveTest.java
@@ -19,9 +19,11 @@
package org.apache.brooklyn.location.jclouds;
import brooklyn.config.ConfigKey;
-import brooklyn.util.config.ConfigBag;
+
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.ec2.domain.BlockDeviceMapping;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationTest.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationTest.java
index 83ffb78..de9f950 100644
--- a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationTest.java
+++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationTest.java
@@ -32,6 +32,7 @@ import org.apache.brooklyn.api.location.MachineLocation;
import org.apache.brooklyn.api.location.MachineLocationCustomizer;
import org.apache.brooklyn.api.location.NoMachinesAvailableException;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.location.cloud.names.CustomMachineNamer;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.jclouds.scriptbuilder.domain.OsFamily;
@@ -61,7 +62,6 @@ import org.apache.brooklyn.location.jclouds.JcloudsLocation.UserCreation;
import brooklyn.test.Asserts;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
/**
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsMachineNamerTest.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsMachineNamerTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsMachineNamerTest.java
index 5e25a8c..90c1bbb 100644
--- a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsMachineNamerTest.java
+++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsMachineNamerTest.java
@@ -18,12 +18,12 @@
*/
package org.apache.brooklyn.location.jclouds;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
import org.testng.annotations.Test;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.text.Strings;
public class JcloudsMachineNamerTest {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/RebindJcloudsLocationLiveTest.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/RebindJcloudsLocationLiveTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/RebindJcloudsLocationLiveTest.java
index 6043a09..5f717a3 100644
--- a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/RebindJcloudsLocationLiveTest.java
+++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/RebindJcloudsLocationLiveTest.java
@@ -27,6 +27,7 @@ import java.io.File;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.location.OsDetails;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.test.entity.TestApplication;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
@@ -35,7 +36,6 @@ import org.testng.annotations.Test;
import brooklyn.entity.basic.ApplicationBuilder;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.rebind.RebindTestUtils;
-import brooklyn.util.config.ConfigBag;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/RebindJcloudsLocationTest.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/RebindJcloudsLocationTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/RebindJcloudsLocationTest.java
index cc52ef2..746ff89 100644
--- a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/RebindJcloudsLocationTest.java
+++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/RebindJcloudsLocationTest.java
@@ -26,8 +26,9 @@ import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import brooklyn.entity.rebind.RebindTestFixtureWithApp;
+
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.config.ConfigBag;
import com.google.common.net.HostAndPort;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/policy/src/main/java/brooklyn/enricher/DeltaEnricher.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/enricher/DeltaEnricher.java b/policy/src/main/java/brooklyn/enricher/DeltaEnricher.java
index 39b052f..9b6128c 100644
--- a/policy/src/main/java/brooklyn/enricher/DeltaEnricher.java
+++ b/policy/src/main/java/brooklyn/enricher/DeltaEnricher.java
@@ -25,9 +25,9 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.event.SensorEvent;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import brooklyn.enricher.basic.AbstractTransformingEnricher;
-import brooklyn.util.flags.TypeCoercions;
/**
* Converts an absolute sensor into a delta sensor (i.e. the diff between the current and previous value)
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/policy/src/main/java/brooklyn/enricher/HttpLatencyDetector.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/enricher/HttpLatencyDetector.java b/policy/src/main/java/brooklyn/enricher/HttpLatencyDetector.java
index 209b45a..884d568 100644
--- a/policy/src/main/java/brooklyn/enricher/HttpLatencyDetector.java
+++ b/policy/src/main/java/brooklyn/enricher/HttpLatencyDetector.java
@@ -32,6 +32,7 @@ import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -44,7 +45,6 @@ import brooklyn.event.feed.http.HttpFeed;
import brooklyn.event.feed.http.HttpPollConfig;
import brooklyn.event.feed.http.HttpValueFunctions;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.javalang.AtomicReferences;
import brooklyn.util.javalang.Boxing;
import brooklyn.util.javalang.JavaClassNames;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/policy/src/main/java/brooklyn/enricher/RollingMeanEnricher.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/enricher/RollingMeanEnricher.java b/policy/src/main/java/brooklyn/enricher/RollingMeanEnricher.java
index 0eca706..13648af 100644
--- a/policy/src/main/java/brooklyn/enricher/RollingMeanEnricher.java
+++ b/policy/src/main/java/brooklyn/enricher/RollingMeanEnricher.java
@@ -24,9 +24,9 @@ import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.event.SensorEvent;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.enricher.basic.AbstractTypeTransformingEnricher;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.javalang.JavaClassNames;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/policy/src/main/java/brooklyn/enricher/RollingTimeWindowMeanEnricher.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/enricher/RollingTimeWindowMeanEnricher.java b/policy/src/main/java/brooklyn/enricher/RollingTimeWindowMeanEnricher.java
index 9993d28..b9688d9 100644
--- a/policy/src/main/java/brooklyn/enricher/RollingTimeWindowMeanEnricher.java
+++ b/policy/src/main/java/brooklyn/enricher/RollingTimeWindowMeanEnricher.java
@@ -25,12 +25,12 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.event.SensorEvent;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.enricher.basic.AbstractTypeTransformingEnricher;
import brooklyn.enricher.basic.YamlRollingTimeWindowMeanEnricher;
import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.javalang.JavaClassNames;
import brooklyn.util.time.Duration;
[27/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/http/HttpTool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/http/HttpTool.java b/core/src/main/java/org/apache/brooklyn/core/util/http/HttpTool.java
new file mode 100644
index 0000000..43b1aee
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/http/HttpTool.java
@@ -0,0 +1,387 @@
+/*
+ * 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.util.http;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import java.net.URI;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.http.ConnectionReuseStrategy;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.Credentials;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpHead;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpPut;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.scheme.SchemeSocketFactory;
+import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
+import org.apache.http.conn.ssl.TrustStrategy;
+import org.apache.http.conn.ssl.X509HostnameVerifier;
+import org.apache.http.entity.ByteArrayEntity;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.impl.client.LaxRedirectStrategy;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.params.BasicHttpParams;
+import org.apache.http.params.HttpConnectionParams;
+import org.apache.http.params.HttpParams;
+import org.apache.http.util.EntityUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.util.crypto.SslTrustUtils;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.net.URLParamEncoder;
+import brooklyn.util.text.Strings;
+import brooklyn.util.time.Duration;
+
+import com.google.common.base.Function;
+import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Multimap;
+
+public class HttpTool {
+
+ private static final Logger LOG = LoggerFactory.getLogger(HttpTool.class);
+
+ /** Apache HTTP commons utility for trusting all.
+ * <p>
+ * For generic java HTTP usage, see {@link SslTrustUtils#trustAll(java.net.URLConnection)}
+ * and static constants in the same class. */
+ public static class TrustAllStrategy implements TrustStrategy {
+ @Override
+ public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+ return true;
+ }
+ }
+
+ public static HttpClientBuilder httpClientBuilder() {
+ return new HttpClientBuilder();
+ }
+
+ public static class HttpClientBuilder {
+ private ClientConnectionManager clientConnectionManager;
+ private HttpParams httpParams;
+ private URI uri;
+ private Integer port;
+ private Credentials credentials;
+ private boolean laxRedirect;
+ private Boolean https;
+ private SchemeSocketFactory socketFactory;
+ private ConnectionReuseStrategy reuseStrategy;
+ private boolean trustAll;
+ private boolean trustSelfSigned;
+
+ public HttpClientBuilder clientConnectionManager(ClientConnectionManager val) {
+ this.clientConnectionManager = checkNotNull(val, "clientConnectionManager");
+ return this;
+ }
+ public HttpClientBuilder httpParams(HttpParams val) {
+ checkState(httpParams == null, "Must not call httpParams multiple times, or after other methods like connectionTimeout");
+ this.httpParams = checkNotNull(val, "httpParams");
+ return this;
+ }
+ public HttpClientBuilder connectionTimeout(Duration val) {
+ if (httpParams == null) httpParams = new BasicHttpParams();
+ long millis = checkNotNull(val, "connectionTimeout").toMilliseconds();
+ if (millis > Integer.MAX_VALUE) throw new IllegalStateException("HttpClient only accepts upto max-int millis for connectionTimeout, but given "+val);
+ HttpConnectionParams.setConnectionTimeout(httpParams, (int) millis);
+ return this;
+ }
+ public HttpClientBuilder socketTimeout(Duration val) {
+ if (httpParams == null) httpParams = new BasicHttpParams();
+ long millis = checkNotNull(val, "socketTimeout").toMilliseconds();
+ if (millis > Integer.MAX_VALUE) throw new IllegalStateException("HttpClient only accepts upto max-int millis for socketTimeout, but given "+val);
+ HttpConnectionParams.setSoTimeout(httpParams, (int) millis);
+ return this;
+ }
+ public HttpClientBuilder reuseStrategy(ConnectionReuseStrategy val) {
+ this.reuseStrategy = checkNotNull(val, "reuseStrategy");
+ return this;
+ }
+ public HttpClientBuilder uri(String val) {
+ return uri(URI.create(checkNotNull(val, "uri")));
+ }
+ public HttpClientBuilder uri(URI val) {
+ this.uri = checkNotNull(val, "uri");
+ if (https == null) https = ("https".equalsIgnoreCase(uri.getScheme()));
+ return this;
+ }
+ public HttpClientBuilder port(int val) {
+ this.port = val;
+ return this;
+ }
+ public HttpClientBuilder credentials(Credentials val) {
+ this.credentials = checkNotNull(val, "credentials");
+ return this;
+ }
+ public void credential(Optional<Credentials> val) {
+ if (val.isPresent()) credentials = val.get();
+ }
+ /** similar to curl --post301 -L` */
+ public HttpClientBuilder laxRedirect(boolean val) {
+ this.laxRedirect = val;
+ return this;
+ }
+ public HttpClientBuilder https(boolean val) {
+ this.https = val;
+ return this;
+ }
+ public HttpClientBuilder socketFactory(SchemeSocketFactory val) {
+ this.socketFactory = checkNotNull(val, "socketFactory");
+ return this;
+ }
+ public HttpClientBuilder trustAll() {
+ this.trustAll = true;
+ return this;
+ }
+ public HttpClientBuilder trustSelfSigned() {
+ this.trustSelfSigned = true;
+ return this;
+ }
+ public HttpClient build() {
+ final DefaultHttpClient httpClient = new DefaultHttpClient(clientConnectionManager);
+ httpClient.setParams(httpParams);
+
+ // support redirects for POST (similar to `curl --post301 -L`)
+ // http://stackoverflow.com/questions/3658721/httpclient-4-error-302-how-to-redirect
+ if (laxRedirect) {
+ httpClient.setRedirectStrategy(new LaxRedirectStrategy());
+ }
+ if (reuseStrategy != null) {
+ httpClient.setReuseStrategy(reuseStrategy);
+ }
+ if (https == Boolean.TRUE || (uri!=null && uri.toString().startsWith("https:"))) {
+ try {
+ if (port == null) {
+ port = (uri != null && uri.getPort() >= 0) ? uri.getPort() : 443;
+ }
+ if (socketFactory == null) {
+ if (trustAll) {
+ TrustStrategy trustStrategy = new TrustAllStrategy();
+ X509HostnameVerifier hostnameVerifier = SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
+ socketFactory = new SSLSocketFactory(trustStrategy, hostnameVerifier);
+ } else if (trustSelfSigned) {
+ TrustStrategy trustStrategy = new TrustSelfSignedStrategy();
+ X509HostnameVerifier hostnameVerifier = SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
+ socketFactory = new SSLSocketFactory(trustStrategy, hostnameVerifier);
+ } else {
+ // Using default https scheme: based on default java truststore, which is pretty strict!
+ }
+ }
+ if (socketFactory != null) {
+ Scheme sch = new Scheme("https", port, socketFactory);
+ httpClient.getConnectionManager().getSchemeRegistry().register(sch);
+ }
+ } catch (Exception e) {
+ LOG.warn("Error setting trust for uri {}", uri);
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ // Set credentials
+ if (uri != null && credentials != null) {
+ String hostname = uri.getHost();
+ int port = uri.getPort();
+ httpClient.getCredentialsProvider().setCredentials(new AuthScope(hostname, port), credentials);
+ }
+ if (uri==null && credentials!=null) {
+ LOG.warn("credentials have no effect in builder unless URI for host is specified");
+ }
+
+ return httpClient;
+ }
+ }
+
+ protected static abstract class HttpRequestBuilder<B extends HttpRequestBuilder<B, R>, R extends HttpRequest> {
+ protected R req;
+
+ protected HttpRequestBuilder(R req) {
+ this.req = req;
+ }
+ @SuppressWarnings("unchecked")
+ protected B self() {
+ return (B) this;
+ }
+ public B headers(Map<String,String> headers) {
+ if (headers!=null) {
+ for (Map.Entry<String,String> entry : headers.entrySet()) {
+ req.addHeader(entry.getKey(), entry.getValue());
+ }
+ }
+ return self();
+ }
+ public B headers(Multimap<String,String> headers) {
+ if (headers!=null) {
+ for (Map.Entry<String,String> entry : headers.entries()) {
+ req.addHeader(entry.getKey(), entry.getValue());
+ }
+ }
+ return self();
+ }
+ public R build() {
+ return req;
+ }
+ }
+
+ protected static abstract class HttpEntityEnclosingRequestBaseBuilder<B extends HttpEntityEnclosingRequestBaseBuilder<B,R>, R extends HttpEntityEnclosingRequestBase> extends HttpRequestBuilder<B, R> {
+ protected HttpEntityEnclosingRequestBaseBuilder(R req) {
+ super(req);
+ }
+ public B body(byte[] body) {
+ if (body != null) {
+ HttpEntity httpEntity = new ByteArrayEntity(body);
+ req.setEntity(httpEntity);
+ }
+ return self();
+ }
+ }
+
+ public static class HttpGetBuilder extends HttpRequestBuilder<HttpGetBuilder, HttpGet> {
+ public HttpGetBuilder(URI uri) {
+ super(new HttpGet(uri));
+ }
+ }
+
+ public static class HttpHeadBuilder extends HttpRequestBuilder<HttpHeadBuilder, HttpHead> {
+ public HttpHeadBuilder(URI uri) {
+ super(new HttpHead(uri));
+ }
+ }
+
+ public static class HttpDeleteBuilder extends HttpRequestBuilder<HttpDeleteBuilder, HttpDelete> {
+ public HttpDeleteBuilder(URI uri) {
+ super(new HttpDelete(uri));
+ }
+ }
+
+ public static class HttpPostBuilder extends HttpEntityEnclosingRequestBaseBuilder<HttpPostBuilder, HttpPost> {
+ HttpPostBuilder(URI uri) {
+ super(new HttpPost(uri));
+ }
+ }
+
+ public static class HttpFormPostBuilder extends HttpRequestBuilder<HttpFormPostBuilder, HttpPost> {
+ HttpFormPostBuilder(URI uri) {
+ super(new HttpPost(uri));
+ }
+
+ public HttpFormPostBuilder params(Map<String, String> params) {
+ if (params != null) {
+ Collection<NameValuePair> httpParams = new ArrayList<NameValuePair>(params.size());
+ for (Entry<String, String> param : params.entrySet()) {
+ httpParams.add(new BasicNameValuePair(param.getKey(), param.getValue()));
+ }
+ req.setEntity(new UrlEncodedFormEntity(httpParams));
+ }
+ return self();
+ }
+ }
+
+ public static class HttpPutBuilder extends HttpEntityEnclosingRequestBaseBuilder<HttpPutBuilder, HttpPut> {
+ public HttpPutBuilder(URI uri) {
+ super(new HttpPut(uri));
+ }
+ }
+
+ public static HttpToolResponse httpGet(HttpClient httpClient, URI uri, Map<String,String> headers) {
+ HttpGet req = new HttpGetBuilder(uri).headers(headers).build();
+ return execAndConsume(httpClient, req);
+ }
+
+ public static HttpToolResponse httpPost(HttpClient httpClient, URI uri, Map<String,String> headers, byte[] body) {
+ HttpPost req = new HttpPostBuilder(uri).headers(headers).body(body).build();
+ return execAndConsume(httpClient, req);
+ }
+
+ public static HttpToolResponse httpPut(HttpClient httpClient, URI uri, Map<String, String> headers, byte[] body) {
+ HttpPut req = new HttpPutBuilder(uri).headers(headers).body(body).build();
+ return execAndConsume(httpClient, req);
+ }
+
+ public static HttpToolResponse httpPost(HttpClient httpClient, URI uri, Map<String,String> headers, Map<String, String> params) {
+ HttpPost req = new HttpFormPostBuilder(uri).headers(headers).params(params).build();
+ return execAndConsume(httpClient, req);
+ }
+
+ public static HttpToolResponse httpDelete(HttpClient httpClient, URI uri, Map<String,String> headers) {
+ HttpDelete req = new HttpDeleteBuilder(uri).headers(headers).build();
+ return execAndConsume(httpClient, req);
+ }
+
+ public static HttpToolResponse httpHead(HttpClient httpClient, URI uri, Map<String,String> headers) {
+ HttpHead req = new HttpHeadBuilder(uri).headers(headers).build();
+ return execAndConsume(httpClient, req);
+ }
+
+ public static HttpToolResponse execAndConsume(HttpClient httpClient, HttpUriRequest req) {
+ long startTime = System.currentTimeMillis();
+ try {
+ HttpResponse httpResponse = httpClient.execute(req);
+
+ try {
+ return new HttpToolResponse(httpResponse, startTime);
+ } finally {
+ EntityUtils.consume(httpResponse.getEntity());
+ }
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ public static boolean isStatusCodeHealthy(int code) { return (code>=200 && code<=299); }
+
+ public static String toBasicAuthorizationValue(UsernamePasswordCredentials credentials) {
+ return "Basic "+Base64.encodeBase64String( (credentials.getUserName()+":"+credentials.getPassword()).getBytes() );
+ }
+
+ public static String encodeUrlParams(Map<?,?> data) {
+ if (data==null) return "";
+ Iterable<String> args = Iterables.transform(data.entrySet(),
+ new Function<Map.Entry<?,?>,String>() {
+ @Override public String apply(Map.Entry<?,?> entry) {
+ Object k = entry.getKey();
+ Object v = entry.getValue();
+ return URLParamEncoder.encode(Strings.toString(k)) + (v != null ? "=" + URLParamEncoder.encode(Strings.toString(v)) : "");
+ }
+ });
+ return Joiner.on("&").join(args);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/http/HttpToolResponse.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/http/HttpToolResponse.java b/core/src/main/java/org/apache/brooklyn/core/util/http/HttpToolResponse.java
new file mode 100644
index 0000000..97e7793
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/http/HttpToolResponse.java
@@ -0,0 +1,185 @@
+/*
+ * 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.util.http;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.http.Header;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.event.feed.http.HttpPollValue;
+import brooklyn.util.guava.Maybe;
+import brooklyn.util.stream.Streams;
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Time;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import com.google.common.io.ByteStreams;
+
+public class HttpToolResponse implements HttpPollValue {
+
+ private static final Logger log = LoggerFactory.getLogger(HttpToolResponse.class);
+
+ private final Object mutex = new Object();
+ private final HttpResponse response;
+ private final long startTime;
+ private final long durationMillisOfFirstResponse;
+ private final long durationMillisOfFullContent;
+ private int responseCode;
+ private String reasonPhrase;
+ private Map<String,List<String>> headerLists;
+ private byte[] content;
+
+
+ public HttpToolResponse(HttpResponse response, long startTime) {
+ this.response = response;
+ this.startTime = startTime;
+
+ try {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ HttpEntity entity = response.getEntity();
+ if (entity != null) {
+ entity.getContentLength();
+ durationMillisOfFirstResponse = Duration.sinceUtc(startTime).toMilliseconds();
+
+ ByteStreams.copy(entity.getContent(), out);
+ content = out.toByteArray();
+
+ entity.getContentLength();
+ } else {
+ durationMillisOfFirstResponse = Duration.sinceUtc(startTime).toMilliseconds();
+ content = new byte[0];
+ }
+ durationMillisOfFullContent = Duration.sinceUtc(startTime).toMilliseconds();
+ if (log.isTraceEnabled())
+ log.trace("HttpPollValue latency "+Time.makeTimeStringRounded(durationMillisOfFirstResponse)+" / "+Time.makeTimeStringRounded(durationMillisOfFullContent)+", content size "+content.length);
+ } catch (IOException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+
+ public HttpToolResponse(int responseCode, Map<String,? extends List<String>> headers, byte[] content,
+ long startTime, long durationMillisOfFirstResponse, long durationMillisOfFullContent) {
+ this.response = null;
+ this.responseCode = responseCode;
+ this.headerLists = ImmutableMap.copyOf(headers);
+ this.content = content;
+ this.startTime = startTime;
+ this.durationMillisOfFirstResponse = durationMillisOfFirstResponse;
+ this.durationMillisOfFullContent = durationMillisOfFullContent;
+ }
+
+ public int getResponseCode() {
+ synchronized (mutex) {
+ if (responseCode == 0) {
+ responseCode = response.getStatusLine().getStatusCode();
+ }
+ }
+ return responseCode;
+ }
+
+ public String getReasonPhrase() {
+ synchronized (mutex) {
+ if (reasonPhrase == null) {
+ reasonPhrase = response.getStatusLine().getReasonPhrase();
+ }
+ }
+ return reasonPhrase;
+ }
+
+ /** returns the timestamp (millis since 1970) when this request was started */
+ public long getStartTime() {
+ return startTime;
+ }
+
+ /** returns latency, in milliseconds, if value was initialized with a start time */
+ public long getLatencyFullContent() {
+ return durationMillisOfFullContent;
+ }
+
+ /** returns latency, in milliseconds, before response started coming in */
+ public long getLatencyFirstResponse() {
+ return durationMillisOfFirstResponse;
+ }
+
+ public Map<String, List<String>> getHeaderLists() {
+ synchronized (mutex) {
+ if (headerLists == null) {
+ Map<String, List<String>> headerListsMutable = Maps.newLinkedHashMap();
+ for (Header header : response.getAllHeaders()) {
+ List<String> vals = headerListsMutable.get(header.getName());
+ if (vals == null) {
+ vals = new ArrayList<String>();
+ headerListsMutable.put(header.getName(), vals);
+ }
+ vals.add(header.getValue());
+ }
+ headerLists = Collections.unmodifiableMap(headerListsMutable);
+ }
+ }
+ return headerLists;
+ }
+
+ public byte[] getContent() {
+ synchronized (mutex) {
+ if (content == null) {
+ InputStream in = null;
+ try {
+ in = response.getEntity().getContent();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteStreams.copy(in, out);
+ content = out.toByteArray();
+ } catch (IOException e) {
+ throw Throwables.propagate(e);
+ } finally {
+ Streams.closeQuietly(in);
+ }
+ }
+ }
+ return content;
+ }
+
+ public String getContentAsString() {
+ return new String(getContent());
+ }
+
+ public Maybe<HttpResponse> getResponse() {
+ return Maybe.fromNullable(response);
+ }
+
+ @Override
+ public String toString() {
+ return Objects.toStringHelper(getClass())
+ .add("responseCode", responseCode)
+ .toString();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/internal/ConfigKeySelfExtracting.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/internal/ConfigKeySelfExtracting.java b/core/src/main/java/org/apache/brooklyn/core/util/internal/ConfigKeySelfExtracting.java
new file mode 100644
index 0000000..a1d85ca
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/internal/ConfigKeySelfExtracting.java
@@ -0,0 +1,41 @@
+/*
+ * 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.util.internal;
+
+import java.util.Map;
+
+import org.apache.brooklyn.api.management.ExecutionContext;
+
+import brooklyn.config.ConfigKey;
+
+/** Interface for resolving key values; typically implemented by the config key,
+ * but discouraged for external usage.
+ */
+public interface ConfigKeySelfExtracting<T> extends ConfigKey<T> {
+
+ /**
+ * Extracts the value for this config key from the given map.
+ */
+ T extractValue(Map<?,?> configMap, ExecutionContext exec);
+
+ /**
+ * @return True if there is an entry in the configMap that could be extracted
+ */
+ boolean isSet(Map<?,?> configMap);
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/internal/Repeater.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/internal/Repeater.java b/core/src/main/java/org/apache/brooklyn/core/util/internal/Repeater.java
new file mode 100644
index 0000000..39e79da
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/internal/Repeater.java
@@ -0,0 +1,370 @@
+/*
+ * 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.util.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.brooklyn.core.util.flags.FlagUtils;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.util.JavaGroovyEquivalents;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.internal.TimeExtras;
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Time;
+
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.Callables;
+
+/**
+ * Simple DSL to repeat a fragment of code periodically until a condition is satisfied.
+ *
+ * In its simplest case, it is passed two {@link groovy.lang.Closure}s / {@link Callable} -
+ * the first is executed, then the second. If the second closure returns false, the loop
+ * is repeated; if true, it finishes. Further customization can be applied to set the period
+ * between loops and place a maximum limit on how long the loop should run for.
+ * <p>
+ * It is configured in a <em>fluent</em> manner. For example, in Groovy:
+ * <pre>
+ * {@code
+ * Repeater.create("Wait until the Frobnitzer is ready")
+ * .repeat {
+ * status = frobnitzer.getStatus()
+ * }
+ * .until {
+ * status == "Ready" || status == "Failed"
+ * }
+ * .limitIterationsTo(30)
+ * .run()
+ * }
+ * </pre>
+ *
+ * Or in Java:
+ * <pre>
+ * {@code
+ * Repeater.create("Wait until the Frobnitzer is ready")
+ * .until(new Callable<Boolean>() {
+ * public Boolean call() {
+ * String status = frobnitzer.getStatus()
+ * return "Ready".equals(status) || "Failed".equals(status);
+ * }})
+ * .limitIterationsTo(30)
+ * .run()
+ * }
+ * </pre>
+ *
+ * @deprecated since 0.7.0, use {@link brooklyn.util.repeat.Repeater} instead
+ */
+@Deprecated
+public class Repeater {
+
+ // TODO Was converted to Java, from groovy. Needs thorough review and improvements
+ // to use idiomatic java
+
+ private static final Logger log = LoggerFactory.getLogger(Repeater.class);
+
+ static { TimeExtras.init(); }
+
+ @SetFromFlag
+ private String description;
+ private Callable<?> body = Callables.returning(null);
+ private Callable<Boolean> exitCondition;
+ @SetFromFlag
+ private Long period = null;
+ @SetFromFlag("timeout")
+ private Long durationLimit = null;
+ private int iterationLimit = 0;
+ private boolean rethrowException = false;
+ private boolean rethrowExceptionImmediately = false;
+ private boolean warnOnUnRethrownException = true;
+
+ public Repeater() {
+ this(MutableMap.of(), null);
+ }
+
+ public Repeater(Map<?,?> flags) {
+ this(flags, null);
+ }
+
+ public Repeater(String description) {
+ this(MutableMap.of(), description);
+ }
+
+ /**
+ * Construct a new instance of Repeater.
+ *
+ * @param flags can include period, timeout, description
+ * @param description a description of the operation that will appear in debug logs.
+ */
+ public Repeater(Map<?,?> flags, String description) {
+ setFromFlags(flags);
+ this.description = JavaGroovyEquivalents.elvis(description, this.description, "Repeater");
+ }
+
+ public void setFromFlags(Map<?,?> flags) {
+ FlagUtils.setFieldsFromFlags(flags, this);
+ }
+
+ public static Repeater create() {
+ return create(MutableMap.of());
+ }
+ public static Repeater create(Map<?,?> flags) {
+ return create(flags, null);
+ }
+ public static Repeater create(String description) {
+ return create(MutableMap.of(), description);
+ }
+ public static Repeater create(Map<?,?> flags, String description) {
+ return new Repeater(flags, description);
+ }
+
+ /**
+ * Sets the main body of the loop to be a no-op.
+ *
+ * @return {@literal this} to aid coding in a fluent style.
+ */
+ public Repeater repeat() {
+ return repeat(Callables.returning(null));
+ }
+
+ /**
+ * Sets the main body of the loop.
+ *
+ * @param body a closure or other Runnable that is executed in the main body of the loop.
+ * @return {@literal this} to aid coding in a fluent style.
+ */
+ public Repeater repeat(Runnable body) {
+ checkNotNull(body, "body must not be null");
+ this.body = (body instanceof Callable) ? (Callable<?>)body : Executors.callable(body);
+ return this;
+ }
+
+ /**
+ * Sets the main body of the loop.
+ *
+ * @param body a closure or other Callable that is executed in the main body of the loop.
+ * @return {@literal this} to aid coding in a fluent style.
+ */
+ public Repeater repeat(Callable<?> body) {
+ checkNotNull(body, "body must not be null");
+ this.body = body;
+ return this;
+ }
+
+ /**
+ * Set how long to wait between loop iterations.
+ *
+ * @param period how long to wait between loop iterations.
+ * @param unit the unit of measurement of the period.
+ * @return {@literal this} to aid coding in a fluent style.
+ */
+ public Repeater every(long period, TimeUnit unit) {
+ Preconditions.checkArgument(period > 0, "period must be positive: %s", period);
+ checkNotNull(unit, "unit must not be null");
+ this.period = unit.toMillis(period);
+ return this;
+ }
+
+ /**
+ * @see #every(long, TimeUnit)
+ */
+ public Repeater every(Duration duration) {
+ Preconditions.checkNotNull(duration, "duration must not be null");
+ Preconditions.checkArgument(duration.toMilliseconds()>0, "period must be positive: %s", duration);
+ this.period = duration.toMilliseconds();
+ return this;
+ }
+
+ public Repeater every(groovy.time.Duration duration) {
+ return every(Duration.of(duration));
+ }
+
+ /**
+ * @see #every(long, TimeUnit)
+ * @deprecated specify unit
+ */
+ public Repeater every(long duration) {
+ return every(duration, TimeUnit.MILLISECONDS);
+ }
+
+ /**
+ * Set code fragment that tests if the loop has completed.
+ *
+ * @param exitCondition a closure or other Callable that returns a boolean. If this code returns {@literal true} then the
+ * loop will stop executing.
+ * @return {@literal this} to aid coding in a fluent style.
+ */
+ public Repeater until(Callable<Boolean> exitCondition) {
+ Preconditions.checkNotNull(exitCondition, "exitCondition must not be null");
+ this.exitCondition = exitCondition;
+ return this;
+ }
+
+ /**
+ * If the exit condition check throws an exception, it will be recorded and the last exception will be thrown on failure.
+ *
+ * @return {@literal this} to aid coding in a fluent style.
+ */
+ public Repeater rethrowException() {
+ this.rethrowException = true;
+ return this;
+ }
+
+ /**
+ * If the repeated body or the exit condition check throws an exception, then propagate that exception immediately.
+ *
+ * @return {@literal this} to aid coding in a fluent style.
+ */
+ public Repeater rethrowExceptionImmediately() {
+ this.rethrowExceptionImmediately = true;
+ return this;
+ }
+
+ public Repeater suppressWarnings() {
+ this.warnOnUnRethrownException = false;
+ return this;
+ }
+
+ /**
+ * Set the maximum number of iterations.
+ *
+ * The loop will exit if the condition has not been satisfied after this number of iterations.
+ *
+ * @param iterationLimit the maximum number of iterations.
+ * @return {@literal this} to aid coding in a fluent style.
+ */
+ public Repeater limitIterationsTo(int iterationLimit) {
+ Preconditions.checkArgument(iterationLimit > 0, "iterationLimit must be positive: %s", iterationLimit);
+ this.iterationLimit = iterationLimit;
+ return this;
+ }
+
+ /**
+ * Set the amount of time to wait for the condition.
+ * The repeater will wait at least this long for the condition to be true,
+ * and will exit soon after even if the condition is false.
+ *
+ * @param deadline the time that the loop should wait.
+ * @param unit the unit of measurement of the period.
+ * @return {@literal this} to aid coding in a fluent style.
+ */
+ public Repeater limitTimeTo(long deadline, TimeUnit unit) {
+ Preconditions.checkArgument(deadline > 0, "deadline must be positive: %s", deadline);
+ Preconditions.checkNotNull(unit, "unit must not be null");
+ this.durationLimit = unit.toMillis(deadline);
+ return this;
+ }
+
+ /**
+ * @see #limitTimeTo(long, TimeUnit)
+ */
+ public Repeater limitTimeTo(Duration duration) {
+ Preconditions.checkNotNull(duration, "duration must not be null");
+ Preconditions.checkArgument(duration.toMilliseconds() > 0, "deadline must be positive: %s", duration);
+ this.durationLimit = duration.toMilliseconds();
+ return this;
+ }
+
+ /**
+ * Run the loop.
+ *
+ * @return true if the exit condition was satisfied; false if the loop terminated for any other reason.
+ */
+ public boolean run() {
+ Preconditions.checkState(body != null, "repeat() method has not been called to set the body");
+ Preconditions.checkState(exitCondition != null, "until() method has not been called to set the exit condition");
+ Preconditions.checkState(period != null, "every() method has not been called to set the loop period time units");
+
+ Throwable lastError = null;
+ int iterations = 0;
+ long endTime = -1;
+ if (durationLimit != null) {
+ endTime = System.currentTimeMillis() + durationLimit;
+ }
+
+ while (true) {
+ iterations++;
+
+ try {
+ body.call();
+ } catch (Exception e) {
+ log.warn(description, e);
+ if (rethrowExceptionImmediately) throw Exceptions.propagate(e);
+ }
+
+ boolean done = false;
+ try {
+ lastError = null;
+ done = exitCondition.call();
+ } catch (Exception e) {
+ if (log.isDebugEnabled()) log.debug(description, e);
+ lastError = e;
+ if (rethrowExceptionImmediately) throw Exceptions.propagate(e);
+ }
+ if (done) {
+ if (log.isDebugEnabled()) log.debug("{}: condition satisfied", description);
+ return true;
+ } else {
+ if (log.isDebugEnabled()) {
+ String msg = String.format("%s: unsatisfied during iteration %s %s", description, iterations,
+ (iterationLimit > 0 ? "(max "+iterationLimit+" attempts)" : "") +
+ (endTime > 0 ? "("+Time.makeTimeStringRounded(endTime - System.currentTimeMillis())+" remaining)" : ""));
+ if (iterations == 1) {
+ log.debug(msg);
+ } else {
+ log.trace(msg);
+ }
+ }
+ }
+
+ if (iterationLimit > 0 && iterations == iterationLimit) {
+ if (log.isDebugEnabled()) log.debug("{}: condition not satisfied and exceeded iteration limit", description);
+ if (rethrowException && lastError != null) {
+ log.warn("{}: error caught checking condition (rethrowing): {}", description, lastError.getMessage());
+ throw Exceptions.propagate(lastError);
+ }
+ if (warnOnUnRethrownException && lastError != null)
+ log.warn("{}: error caught checking condition: {}", description, lastError.getMessage());
+ return false;
+ }
+
+ if (endTime > 0) {
+ if (System.currentTimeMillis() > endTime) {
+ if (log.isDebugEnabled()) log.debug("{}: condition not satisfied and deadline {} passed",
+ description, Time.makeTimeStringRounded(endTime - System.currentTimeMillis()));
+ if (rethrowException && lastError != null) {
+ log.error("{}: error caught checking condition: {}", description, lastError.getMessage());
+ throw Exceptions.propagate(lastError);
+ }
+ return false;
+ }
+ }
+
+ Time.sleep(period);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/BackoffLimitedRetryHandler.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/BackoffLimitedRetryHandler.java b/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/BackoffLimitedRetryHandler.java
new file mode 100644
index 0000000..b8d6eac
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/BackoffLimitedRetryHandler.java
@@ -0,0 +1,74 @@
+/*
+ * 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.util.internal.ssh;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.util.exceptions.Exceptions;
+
+/**
+ * Allow replayable request to be retried a limited number of times, and impose an exponential back-off
+ * delay before returning.
+ * <p>
+ * Copied and modified from jclouds; original author was James Murty
+ */
+public class BackoffLimitedRetryHandler {
+
+ private static final Logger LOG = LoggerFactory.getLogger(BackoffLimitedRetryHandler.class);
+
+ private final int retryCountLimit;
+
+ private final long delayStart;
+
+ public BackoffLimitedRetryHandler() {
+ this(5, 50L);
+ }
+
+ public BackoffLimitedRetryHandler(int retryCountLimit, long delayStart) {
+ this.retryCountLimit = retryCountLimit;
+ this.delayStart = delayStart;
+ }
+
+ public void imposeBackoffExponentialDelay(int failureCount, String commandDescription) {
+ imposeBackoffExponentialDelay(delayStart, 2, failureCount, retryCountLimit, commandDescription);
+ }
+
+ public void imposeBackoffExponentialDelay(long period, int pow, int failureCount, int max, String commandDescription) {
+ imposeBackoffExponentialDelay(period, period * 10l, pow, failureCount, max, commandDescription);
+ }
+
+ public void imposeBackoffExponentialDelay(long period,
+ long maxPeriod,
+ int pow,
+ int failureCount,
+ int max,
+ String commandDescription) {
+ long delayMs = (long) (period * Math.pow(failureCount, pow));
+ delayMs = (delayMs > maxPeriod) ? maxPeriod : delayMs;
+ if (LOG.isDebugEnabled()) LOG.debug("Retry {}/{}: delaying for {} ms: {}",
+ new Object[] {failureCount, max, delayMs, commandDescription});
+ try {
+ Thread.sleep(delayMs);
+ } catch (InterruptedException e) {
+ Exceptions.propagate(e);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/ShellAbstractTool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/ShellAbstractTool.java b/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/ShellAbstractTool.java
new file mode 100644
index 0000000..90dcffa
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/ShellAbstractTool.java
@@ -0,0 +1,442 @@
+/*
+ * 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.util.internal.ssh;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import java.io.ByteArrayInputStream;
+import java.io.Closeable;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.os.Os;
+import brooklyn.util.ssh.BashCommands;
+import brooklyn.util.text.Identifiers;
+import brooklyn.util.text.StringEscapes.BashStringEscapes;
+import brooklyn.util.text.Strings;
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Time;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
+
+public abstract class ShellAbstractTool implements ShellTool {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ShellAbstractTool.class);
+
+ protected final File localTempDir;
+
+ public ShellAbstractTool(String localTempDir) {
+ this(localTempDir == null ? null : new File(Os.tidyPath(localTempDir)));
+ }
+
+ public ShellAbstractTool(File localTempDir) {
+ if (localTempDir == null) {
+ localTempDir = new File(Os.tmp(), "tmpssh-"+Os.user());
+ if (!localTempDir.exists()) localTempDir.mkdir();
+ Os.deleteOnExitEmptyParentsUpTo(localTempDir, new File(Os.tmp()));
+ }
+ this.localTempDir = localTempDir;
+ }
+
+ public ShellAbstractTool() {
+ this((File)null);
+ }
+
+ protected static void warnOnDeprecated(Map<String, ?> props, String deprecatedKey, String correctKey) {
+ if (props.containsKey(deprecatedKey)) {
+ if (correctKey != null && props.containsKey(correctKey)) {
+ Object dv = props.get(deprecatedKey);
+ Object cv = props.get(correctKey);
+ if (!Objects.equal(cv, dv)) {
+ LOG.warn("SshTool detected deprecated key '"+deprecatedKey+"' with different value ("+dv+") "+
+ "than new key '"+correctKey+"' ("+cv+"); ambiguous which will be used");
+ } else {
+ // ignore, the deprecated key populated for legacy reasons
+ }
+ } else {
+ Object dv = props.get(deprecatedKey);
+ LOG.warn("SshTool detected deprecated key '"+deprecatedKey+"' used, with value ("+dv+")");
+ }
+ }
+ }
+
+ protected static Boolean hasVal(Map<String,?> map, ConfigKey<?> keyC) {
+ String key = keyC.getName();
+ return map.containsKey(key);
+ }
+
+ protected static <T> T getMandatoryVal(Map<String,?> map, ConfigKey<T> keyC) {
+ String key = keyC.getName();
+ checkArgument(map.containsKey(key), "must contain key '"+keyC+"'");
+ return TypeCoercions.coerce(map.get(key), keyC.getTypeToken());
+ }
+
+ public static <T> T getOptionalVal(Map<String,?> map, ConfigKey<T> keyC) {
+ if (keyC==null) return null;
+ String key = keyC.getName();
+ if (map!=null && map.containsKey(key) && map.get(key) != null) {
+ return TypeCoercions.coerce(map.get(key), keyC.getTypeToken());
+ } else {
+ return keyC.getDefaultValue();
+ }
+ }
+
+ /** returns the value of the key if specified, otherwise defaultValue */
+ protected static <T> T getOptionalVal(Map<String,?> map, ConfigKey<T> keyC, T defaultValue) {
+ String key = keyC.getName();
+ if (map!=null && map.containsKey(key) && map.get(key) != null) {
+ return TypeCoercions.coerce(map.get(key), keyC.getTypeToken());
+ } else {
+ return defaultValue;
+ }
+ }
+
+ protected void closeWhispering(Closeable closeable, Object context) {
+ closeWhispering(closeable, this, context);
+ }
+
+ /**
+ * Similar to Guava's Closeables.closeQuitely, except logs exception at debug with context in message.
+ */
+ protected static void closeWhispering(Closeable closeable, Object context1, Object context2) {
+ if (closeable != null) {
+ try {
+ closeable.close();
+ } catch (IOException e) {
+ if (LOG.isDebugEnabled()) {
+ String msg = String.format("<< exception during close, for %s -> %s (%s); continuing.",
+ context1, context2, closeable);
+ if (LOG.isTraceEnabled())
+ LOG.debug(msg + ": " + e);
+ else
+ LOG.trace(msg, e);
+ }
+ }
+ }
+ }
+
+ protected File writeTempFile(InputStream contents) {
+ File tempFile = Os.writeToTempFile(contents, localTempDir, "sshcopy", "data");
+ tempFile.setReadable(false, false);
+ tempFile.setReadable(true, true);
+ tempFile.setWritable(false);
+ tempFile.setExecutable(false);
+ return tempFile;
+ }
+
+ protected File writeTempFile(String contents) {
+ return writeTempFile(contents.getBytes());
+ }
+
+ protected File writeTempFile(byte[] contents) {
+ return writeTempFile(new ByteArrayInputStream(contents));
+ }
+
+ protected String toScript(Map<String,?> props, List<String> commands, Map<String,?> env) {
+ List<String> allcmds = toCommandSequence(commands, env);
+ StringBuilder result = new StringBuilder();
+ result.append(getOptionalVal(props, PROP_SCRIPT_HEADER)).append('\n');
+
+ for (String cmd : allcmds) {
+ result.append(cmd).append('\n');
+ }
+
+ return result.toString();
+ }
+
+ /**
+ * Merges the commands and env, into a single set of commands. Also escapes the commands as required.
+ *
+ * Not all ssh servers handle "env", so instead convert env into exported variables
+ */
+ protected List<String> toCommandSequence(List<String> commands, Map<String,?> env) {
+ List<String> result = new ArrayList<String>((env!=null ? env.size() : 0) + commands.size());
+
+ if (env!=null) {
+ for (Entry<String,?> entry : env.entrySet()) {
+ if (entry.getKey() == null || entry.getValue() == null) {
+ LOG.warn("env key-values must not be null; ignoring: key="+entry.getKey()+"; value="+entry.getValue());
+ continue;
+ }
+ String escapedVal = BashStringEscapes.escapeLiteralForDoubleQuotedBash(entry.getValue().toString());
+ result.add("export "+entry.getKey()+"=\""+escapedVal+"\"");
+ }
+ }
+ for (CharSequence cmd : commands) { // objects in commands can be groovy GString so can't treat as String here
+ result.add(cmd.toString());
+ }
+
+ return result;
+ }
+
+ @Override
+ public int execScript(Map<String,?> props, List<String> commands) {
+ return execScript(props, commands, Collections.<String,Object>emptyMap());
+ }
+
+ @Override
+ public int execCommands(Map<String,?> props, List<String> commands) {
+ return execCommands(props, commands, Collections.<String,Object>emptyMap());
+ }
+
+ protected static int asInt(Integer input, int valueIfInputNull) {
+ return input != null ? input : valueIfInputNull;
+ }
+
+ protected abstract class ToolAbstractExecScript {
+ protected final Map<String, ?> props;
+ protected final String separator;
+ protected final OutputStream out;
+ protected final OutputStream err;
+ protected final String scriptDir;
+ protected final Boolean runAsRoot;
+ protected final Boolean noExtraOutput;
+ protected final Boolean noDeleteAfterExec;
+ protected final String scriptNameWithoutExtension;
+ protected final String scriptPath;
+ protected final Duration execTimeout;
+
+ public ToolAbstractExecScript(Map<String,?> props) {
+ this.props = props;
+ this.separator = getOptionalVal(props, PROP_SEPARATOR);
+ this.out = getOptionalVal(props, PROP_OUT_STREAM);
+ this.err = getOptionalVal(props, PROP_ERR_STREAM);
+
+ this.scriptDir = getOptionalVal(props, PROP_SCRIPT_DIR);
+ this.runAsRoot = getOptionalVal(props, PROP_RUN_AS_ROOT);
+ this.noExtraOutput = getOptionalVal(props, PROP_NO_EXTRA_OUTPUT);
+ this.noDeleteAfterExec = getOptionalVal(props, PROP_NO_DELETE_SCRIPT);
+ this.execTimeout = getOptionalVal(props, PROP_EXEC_TIMEOUT);
+
+ String summary = getOptionalVal(props, PROP_SUMMARY);
+ if (summary!=null) {
+ summary = Strings.makeValidFilename(summary);
+ if (summary.length()>30)
+ summary = summary.substring(0,30);
+ }
+ this.scriptNameWithoutExtension = "brooklyn-"+
+ Time.makeDateStampString()+"-"+Identifiers.makeRandomId(4)+
+ (Strings.isBlank(summary) ? "" : "-"+summary);
+ this.scriptPath = Os.mergePathsUnix(scriptDir, scriptNameWithoutExtension+".sh");
+ }
+
+ /** builds the command to run the given script;
+ * note that some modes require \$RESULT passed in order to access a variable, whereas most just need $ */
+ protected List<String> buildRunScriptCommand() {
+ MutableList.Builder<String> cmds = MutableList.<String>builder()
+ .add((runAsRoot ? BashCommands.sudo(scriptPath) : scriptPath) + " < /dev/null")
+ .add("RESULT=$?");
+ if (noExtraOutput==null || !noExtraOutput)
+ cmds.add("echo Executed "+scriptPath+", result $RESULT");
+ if (noDeleteAfterExec!=Boolean.TRUE) {
+ // use "-f" because some systems have "rm" aliased to "rm -i"
+ // use "< /dev/null" to guarantee doesn't hang
+ cmds.add("rm -f "+scriptPath+" < /dev/null");
+ }
+ cmds.add("exit $RESULT");
+ return cmds.build();
+ }
+
+ protected String getSummary() {
+ String summary = getOptionalVal(props, PROP_SUMMARY);
+ return (summary != null) ? summary : scriptPath;
+ }
+
+ public abstract int run();
+ }
+
+ protected abstract class ToolAbstractAsyncExecScript extends ToolAbstractExecScript {
+ protected final String stdoutPath;
+ protected final String stderrPath;
+ protected final String exitStatusPath;
+ protected final String pidPath;
+
+ public ToolAbstractAsyncExecScript(Map<String,?> props) {
+ super(props);
+
+ stdoutPath = Os.mergePathsUnix(scriptDir, scriptNameWithoutExtension + ".stdout");
+ stderrPath = Os.mergePathsUnix(scriptDir, scriptNameWithoutExtension + ".stderr");
+ exitStatusPath = Os.mergePathsUnix(scriptDir, scriptNameWithoutExtension + ".exitstatus");
+ pidPath = Os.mergePathsUnix(scriptDir, scriptNameWithoutExtension + ".pid");
+ }
+
+ /**
+ * Builds the command to run the given script, asynchronously.
+ * The executed command will return immediately, but the output from the script
+ * will continue to be written
+ * note that some modes require \$RESULT passed in order to access a variable, whereas most just need $ */
+ @Override
+ protected List<String> buildRunScriptCommand() {
+ String touchCmd = String.format("touch %s %s %s %s", stdoutPath, stderrPath, exitStatusPath, pidPath);
+ String cmd = String.format("nohup sh -c \"( %s > %s 2> %s < /dev/null ) ; echo \\$? > %s \" > /dev/null 2>&1 < /dev/null &", scriptPath, stdoutPath, stderrPath, exitStatusPath);
+ MutableList.Builder<String> cmds = MutableList.<String>builder()
+ .add(runAsRoot ? BashCommands.sudo(touchCmd) : touchCmd)
+ .add(runAsRoot ? BashCommands.sudo(cmd) : cmd)
+ .add("echo $! > "+pidPath)
+ .add("RESULT=$?");
+ if (noExtraOutput==null || !noExtraOutput) {
+ cmds.add("echo Executing async "+scriptPath);
+ }
+ cmds.add("exit $RESULT");
+ return cmds.build();
+ }
+
+ /**
+ * Builds the command to retrieve the exit status of the command, written to stdout.
+ */
+ protected List<String> buildRetrieveStatusCommand() {
+ // Retrieve exit status from file (writtent to stdout), if populated;
+ // if not found and pid still running, then return empty string; else exit code 1.
+ List<String> cmdParts = ImmutableList.of(
+ "# Retrieve status", // comment is to aid testing - see SshjToolAsyncStubIntegrationTest
+ "if test -s "+exitStatusPath+"; then",
+ " cat "+exitStatusPath,
+ "elif test -s "+pidPath+"; then",
+ " pid=`cat "+pidPath+"`",
+ " if ! ps -p $pid > /dev/null < /dev/null; then",
+ " # no exit status, and not executing; give a few seconds grace in case just about to write exit status",
+ " sleep 3",
+ " if test -s "+exitStatusPath+"; then",
+ " cat "+exitStatusPath+"",
+ " else",
+ " echo \"No exit status in "+exitStatusPath+", and pid in "+pidPath+" ($pid) not executing\"",
+ " exit 1",
+ " fi",
+ " fi",
+ "else",
+ " echo \"No exit status in "+exitStatusPath+", and "+pidPath+" is empty\"",
+ " exit 1",
+ "fi"+"\n");
+ String cmd = Joiner.on("\n").join(cmdParts);
+
+ MutableList.Builder<String> cmds = MutableList.<String>builder()
+ .add((runAsRoot ? BashCommands.sudo(cmd) : cmd))
+ .add("RESULT=$?");
+ cmds.add("exit $RESULT");
+ return cmds.build();
+ }
+
+ /**
+ * Builds the command to retrieve the stdout and stderr of the async command.
+ * An offset can be given, to only retrieve data starting at a particular character (indexed from 0).
+ */
+ protected List<String> buildRetrieveStdoutAndStderrCommand(int stdoutPosition, int stderrPosition) {
+ // Note that `tail -c +1` means start at the *first* character (i.e. start counting from 1, not 0)
+ String catStdoutCmd = "tail -c +"+(stdoutPosition+1)+" "+stdoutPath+" 2> /dev/null";
+ String catStderrCmd = "tail -c +"+(stderrPosition+1)+" "+stderrPath+" 2>&1 > /dev/null";
+ MutableList.Builder<String> cmds = MutableList.<String>builder()
+ .add((runAsRoot ? BashCommands.sudo(catStdoutCmd) : catStdoutCmd))
+ .add((runAsRoot ? BashCommands.sudo(catStderrCmd) : catStderrCmd))
+ .add("RESULT=$?");
+ cmds.add("exit $RESULT");
+ return cmds.build();
+ }
+
+ /**
+ * Builds the command to retrieve the stdout and stderr of the async command.
+ * An offset can be given, to only retrieve data starting at a particular character (indexed from 0).
+ */
+ protected List<String> buildLongPollCommand(int stdoutPosition, int stderrPosition, Duration timeout) {
+ long maxTime = Math.max(1, timeout.toSeconds());
+
+ // Note that `tail -c +1` means start at the *first* character (i.e. start counting from 1, not 0)
+ List<String> waitForExitStatusParts = ImmutableList.of(
+ //Should be careful here because any output will be part of the stdout/stderr streams
+ "# Long poll", // comment is to aid testing - see SshjToolAsyncStubIntegrationTest
+ // disown to avoid Terminated message after killing the process
+ // redirect error output to avoid "file truncated" messages
+ "tail -c +"+(stdoutPosition+1)+" -f "+stdoutPath+" 2> /dev/null & export TAIL_STDOUT_PID=$!; disown",
+ "tail -c +"+(stderrPosition+1)+" -f "+stderrPath+" 1>&2 2> /dev/null & export TAIL_STDERR_PID=$!; disown",
+ "EXIT_STATUS_PATH="+exitStatusPath,
+ "PID_PATH="+pidPath,
+ "MAX_TIME="+maxTime,
+ "COUNTER=0",
+ "while [ \"$COUNTER\" -lt $MAX_TIME ]; do",
+ " if test -s $EXIT_STATUS_PATH; then",
+ " EXIT_STATUS=`cat $EXIT_STATUS_PATH`",
+ " kill ${TAIL_STDERR_PID} ${TAIL_STDOUT_PID} 2> /dev/null",
+ " exit $EXIT_STATUS",
+ " elif test -s $PID_PATH; then",
+ " PID=`cat $PID_PATH`",
+ " if ! ps -p $PID > /dev/null 2>&1 < /dev/null; then",
+ " # no exit status, and not executing; give a few seconds grace in case just about to write exit status",
+ " sleep 3",
+ " if test -s $EXIT_STATUS_PATH; then",
+ " EXIT_STATUS=`cat $EXIT_STATUS_PATH`",
+ " kill ${TAIL_STDERR_PID} ${TAIL_STDOUT_PID} 2> /dev/null",
+ " exit $EXIT_STATUS",
+ " else",
+ " echo \"No exit status in $EXIT_STATUS_PATH, and pid in $PID_PATH ($PID) not executing\"",
+ " kill ${TAIL_STDERR_PID} ${TAIL_STDOUT_PID} 2> /dev/null",
+ " exit 126",
+ " fi",
+ " fi",
+ " fi",
+ " # No exit status in $EXIT_STATUS_PATH; keep waiting",
+ " sleep 1",
+ " COUNTER+=1",
+ "done",
+ "kill ${TAIL_STDERR_PID} ${TAIL_STDOUT_PID} 2> /dev/null",
+ "exit 125"+"\n");
+ String waitForExitStatus = Joiner.on("\n").join(waitForExitStatusParts);
+
+ return ImmutableList.of(runAsRoot ? BashCommands.sudo(waitForExitStatus) : waitForExitStatus);
+ }
+
+ protected List<String> deleteTemporaryFilesCommand() {
+ ImmutableList.Builder<String> cmdParts = ImmutableList.builder();
+
+ if (!Boolean.TRUE.equals(noDeleteAfterExec)) {
+ // use "-f" because some systems have "rm" aliased to "rm -i"
+ // use "< /dev/null" to guarantee doesn't hang
+ cmdParts.add(
+ "rm -f "+scriptPath+" "+stdoutPath+" "+stderrPath+" "+exitStatusPath+" "+pidPath+" < /dev/null");
+ }
+
+ // If the buildLongPollCommand didn't complete properly then it might have left tail command running;
+ // ensure they are killed.
+ cmdParts.add(
+ //ignore error output for the case where there are no running processes and kill is called without arguments
+ "ps aux | grep \"tail -c\" | grep \""+stdoutPath+"\" | grep -v grep | awk '{ printf $2 }' | xargs kill 2> /dev/null",
+ "ps aux | grep \"tail -c\" | grep \""+stderrPath+"\" | grep -v grep | awk '{ printf $2 }' | xargs kill 2> /dev/null");
+
+ String cmd = Joiner.on("\n").join(cmdParts.build());
+
+ return ImmutableList.of(runAsRoot ? BashCommands.sudo(cmd) : cmd);
+ }
+
+ @Override
+ public abstract int run();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/ShellTool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/ShellTool.java b/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/ShellTool.java
new file mode 100644
index 0000000..13bfb62
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/ShellTool.java
@@ -0,0 +1,113 @@
+/*
+ * 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.util.internal.ssh;
+
+import static brooklyn.entity.basic.ConfigKeys.newConfigKey;
+import static brooklyn.entity.basic.ConfigKeys.newStringConfigKey;
+
+import java.io.OutputStream;
+import java.util.List;
+import java.util.Map;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.util.os.Os;
+import brooklyn.util.time.Duration;
+
+/** Methods for executing things in an environment (localhost process, or ssh) */
+public interface ShellTool {
+
+ // config which applies to sessions
+
+ public static final ConfigKey<String> PROP_LOCAL_TEMP_DIR = newStringConfigKey(
+ "localTempDir",
+ "The directory on the local machine (i.e. running brooklyn) for writing temp files",
+ Os.mergePaths(Os.tmp(), "brooklyn-"+Os.user()+"-ssh-tmp"));
+
+ // config which applies to calls:
+
+ public static final ConfigKey<Boolean> PROP_RUN_AS_ROOT = newConfigKey("runAsRoot", "When running a script, whether to run as root", Boolean.FALSE);
+
+ public static final ConfigKey<OutputStream> PROP_OUT_STREAM = newConfigKey(OutputStream.class, "out", "Stream to which to capture stdout");
+ public static final ConfigKey<OutputStream> PROP_ERR_STREAM = newConfigKey(OutputStream.class, "err", "Stream to which to capture stderr");
+
+ public static final ConfigKey<Boolean> PROP_NO_EXTRA_OUTPUT = newConfigKey("noExtraOutput", "Suppresses any decorative output such as result code which some tool commands insert", false);
+
+ public static final ConfigKey<String> PROP_SEPARATOR = newConfigKey("separator", "string to insert between caller-supplied commands being executed as commands", " ; ");
+
+ public static final ConfigKey<String> PROP_SCRIPT_DIR = newConfigKey("scriptDir", "directory where scripts should be copied", "/tmp");
+ public static final ConfigKey<String> PROP_SCRIPT_HEADER = newConfigKey("scriptHeader", "lines to insert at the start of scripts generated for caller-supplied commands for script execution", "#!/bin/bash -e\n");
+ public static final ConfigKey<String> PROP_DIRECT_HEADER = newConfigKey("directHeader", "commands to run at the target before any caller-supplied commands for direct execution", "exec bash -e");
+
+ ConfigKey<Boolean> PROP_NO_DELETE_SCRIPT = newConfigKey("noDeleteAfterExec", "Retains the generated script file after executing the commands instead of deleting it", false);
+
+ ConfigKey<String> PROP_SUMMARY = ConfigKeys.newStringConfigKey("summary", "Provides a human-readable summary, used in file generation etc");
+
+ ConfigKey<Duration> PROP_EXEC_TIMEOUT = newConfigKey("execTimeout", "Timeout when executing a script", Duration.PRACTICALLY_FOREVER);
+
+ ConfigKey<Boolean> PROP_EXEC_ASYNC = newConfigKey("execAsync", "Executes the script asynchronously, and then polls for the result (and for stdout/stderr)", false);
+
+ ConfigKey<Duration> PROP_EXEC_ASYNC_POLLING_TIMEOUT = newConfigKey("execAsyncPollTimeout", "Timeout per poll when executing a script asynchronously", Duration.ONE_MINUTE);
+
+ /**
+ * Executes the set of commands in a shell script. Blocks until completion.
+ * <p>
+ *
+ * Optional properties are the same common ones as for {@link #execCommands(Map, List, Map)} with the addition of:
+ * <ul>
+ * <li>{@link #PROP_RUN_AS_ROOT}
+ * <li>{@link #PROP_SCRIPT_DIR}
+ * </ul>
+ *
+ * @return exit status of script
+ */
+ public int execScript(Map<String,?> props, List<String> commands, Map<String,?> env);
+
+ /**
+ * @see #execScript(Map, List, Map)
+ */
+ public int execScript(Map<String,?> props, List<String> commands);
+
+ /**
+ * Executes the set of commands using ssh exec.
+ *
+ * This is generally more efficient than ssh shell mode (cf {@link #execScript(Map, List, Map)}),
+ * but is not suitable if you need env values which are only set on a fully-fledged shell,
+ * or if you want the entire block executed with root permission.
+ *
+ * Common optional properties (which also apply to {@link #execScript(Map, List, Map)}) are:
+ * <ul>
+ * <li>{@link #PROP_OUT_STREAM}
+ * <li>{@link #PROP_ERR_STREAM}
+ * <li>{@link #PROP_SEPARATOR} (for some modes)
+ * <li>{@link #PROP_NO_EXTRA_OUTPUT} (often there is no extra output here)
+ * </ul>
+ *
+ * Note that {@link #PROP_RUN_AS_ROOT} is <i>not</i> typically supported here. Prefer {@link #execScript(Map, List, Map)}).
+ *
+ * @return exit status of commands
+ */
+ public int execCommands(Map<String,?> properties, List<String> commands, Map<String,?> env);
+
+ /**
+ * @see #execCommands(Map, List, Map)
+ */
+ public int execCommands(Map<String,?> properties, List<String> commands);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/SshAbstractTool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/SshAbstractTool.java b/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/SshAbstractTool.java
new file mode 100644
index 0000000..ea7a71e
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/SshAbstractTool.java
@@ -0,0 +1,172 @@
+/*
+ * 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.util.internal.ssh;
+
+import static brooklyn.util.net.Networking.checkPortValid;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.File;
+import java.util.Map;
+import java.util.Set;
+
+import brooklyn.util.os.Os;
+
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
+
+public abstract class SshAbstractTool extends ShellAbstractTool implements SshTool {
+
+ protected final String toString;
+
+ protected final String host;
+ protected final String user;
+ protected final String password;
+ protected final int port;
+ protected String privateKeyPassphrase;
+ protected String privateKeyData;
+ protected File privateKeyFile;
+ protected boolean strictHostKeyChecking;
+ protected boolean allocatePTY;
+
+ public static interface SshAction<T> {
+ void clear() throws Exception;
+ T create() throws Exception;
+ }
+
+ public static abstract class AbstractSshToolBuilder<T extends SshTool, B extends AbstractSshToolBuilder<T,B>> {
+ protected String host;
+ protected int port = 22;
+ protected String user = System.getProperty("user.name");
+ protected String password;
+ protected String privateKeyData;
+ protected String privateKeyPassphrase;
+ protected Set<String> privateKeyFiles = Sets.newLinkedHashSet();
+ protected boolean strictHostKeyChecking = false;
+ protected boolean allocatePTY = false;
+ protected File localTempDir = null;
+
+ @SuppressWarnings("unchecked")
+ protected B self() {
+ return (B) this;
+ }
+
+ public B from(Map<String,?> props) {
+ host = getMandatoryVal(props, PROP_HOST);
+ port = getOptionalVal(props, PROP_PORT);
+ user = getOptionalVal(props, PROP_USER);
+
+ password = getOptionalVal(props, PROP_PASSWORD);
+
+ warnOnDeprecated(props, "privateKey", "privateKeyData");
+ privateKeyData = getOptionalVal(props, PROP_PRIVATE_KEY_DATA);
+ privateKeyPassphrase = getOptionalVal(props, PROP_PRIVATE_KEY_PASSPHRASE);
+
+ // for backwards compatibility accept keyFiles and privateKey
+ // but sshj accepts only a single privateKeyFile; leave blank to use defaults (i.e. ~/.ssh/id_rsa and id_dsa)
+ warnOnDeprecated(props, "keyFiles", null);
+ String privateKeyFile = getOptionalVal(props, PROP_PRIVATE_KEY_FILE);
+ if (privateKeyFile != null) privateKeyFiles.add(privateKeyFile);
+
+ strictHostKeyChecking = getOptionalVal(props, PROP_STRICT_HOST_KEY_CHECKING);
+ allocatePTY = getOptionalVal(props, PROP_ALLOCATE_PTY);
+
+ String localTempDirPath = getOptionalVal(props, PROP_LOCAL_TEMP_DIR);
+ localTempDir = (localTempDirPath == null) ? null : new File(Os.tidyPath(localTempDirPath));
+
+ return self();
+ }
+ public B host(String val) {
+ this.host = val; return self();
+ }
+ public B user(String val) {
+ this.user = val; return self();
+ }
+ public B password(String val) {
+ this.password = val; return self();
+ }
+ public B port(int val) {
+ this.port = val; return self();
+ }
+ public B privateKeyPassphrase(String val) {
+ this.privateKeyPassphrase = val; return self();
+ }
+ /** @deprecated 1.4.0, use privateKeyData */
+ public B privateKey(String val) {
+ this.privateKeyData = val; return self();
+ }
+ public B privateKeyData(String val) {
+ this.privateKeyData = val; return self();
+ }
+ public B privateKeyFile(String val) {
+ this.privateKeyFiles.add(val); return self();
+ }
+ public B localTempDir(File val) {
+ this.localTempDir = val; return self();
+ }
+ public abstract T build();
+ }
+
+ protected SshAbstractTool(AbstractSshToolBuilder<?,?> builder) {
+ super(builder.localTempDir);
+
+ host = checkNotNull(builder.host, "host");
+ port = builder.port;
+ user = builder.user;
+ password = builder.password;
+ strictHostKeyChecking = builder.strictHostKeyChecking;
+ allocatePTY = builder.allocatePTY;
+ privateKeyPassphrase = builder.privateKeyPassphrase;
+ privateKeyData = builder.privateKeyData;
+
+ if (builder.privateKeyFiles.size() > 1) {
+ throw new IllegalArgumentException("sshj supports only a single private key-file; " +
+ "for defaults of ~/.ssh/id_rsa and ~/.ssh/id_dsa leave blank");
+ } else if (builder.privateKeyFiles.size() == 1) {
+ String privateKeyFileStr = Iterables.get(builder.privateKeyFiles, 0);
+ String amendedKeyFile = privateKeyFileStr.startsWith("~") ? (System.getProperty("user.home")+privateKeyFileStr.substring(1)) : privateKeyFileStr;
+ privateKeyFile = new File(amendedKeyFile);
+ } else {
+ privateKeyFile = null;
+ }
+
+ checkArgument(host.length() > 0, "host value must not be an empty string");
+ checkPortValid(port, "ssh port");
+
+ toString = String.format("%s@%s:%d", user, host, port);
+ }
+
+ @Override
+ public String toString() {
+ return toString;
+ }
+
+ public String getHostAddress() {
+ return this.host;
+ }
+
+ public String getUsername() {
+ return this.user;
+ }
+
+ protected SshException propagate(Exception e, String message) throws SshException {
+ throw new SshException("(" + toString() + ") " + message + ": " + e.getMessage(), e);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/SshException.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/SshException.java b/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/SshException.java
new file mode 100644
index 0000000..c13aa42
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/SshException.java
@@ -0,0 +1,32 @@
+/*
+ * 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.util.internal.ssh;
+
+public class SshException extends RuntimeException {
+
+ private static final long serialVersionUID = -5690230838066860965L;
+
+ public SshException(String msg) {
+ super(msg);
+ }
+
+ public SshException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+}
[05/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/JavaWebAppSshDriver.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/JavaWebAppSshDriver.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/JavaWebAppSshDriver.java
index f7c3e04..b7cae85 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/JavaWebAppSshDriver.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/JavaWebAppSshDriver.java
@@ -26,10 +26,12 @@ import java.util.Set;
import brooklyn.entity.basic.Attributes;
import brooklyn.entity.java.JavaSoftwareProcessSshDriver;
+
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.core.util.task.ssh.SshTasks;
import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.task.ssh.SshTasks;
+
import brooklyn.util.text.Strings;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/WebAppServiceConstants.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/WebAppServiceConstants.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/WebAppServiceConstants.java
index 4320c9b..693b4c4 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/WebAppServiceConstants.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/WebAppServiceConstants.java
@@ -21,6 +21,7 @@ package org.apache.brooklyn.entity.webapp;
import java.util.Set;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import com.google.common.collect.ImmutableSet;
@@ -29,7 +30,6 @@ import brooklyn.entity.basic.Attributes;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
public interface WebAppServiceConstants extends WebAppServiceMetrics {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/jboss/JBoss6Server.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/jboss/JBoss6Server.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/jboss/JBoss6Server.java
index 6a558e7..0935690 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/jboss/JBoss6Server.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/jboss/JBoss6Server.java
@@ -20,6 +20,7 @@ package org.apache.brooklyn.entity.webapp.jboss;
import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.entity.webapp.JavaWebAppSoftwareProcess;
import brooklyn.config.ConfigKey;
@@ -27,7 +28,6 @@ import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.SoftwareProcess;
import brooklyn.entity.java.UsesJmx;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
-import brooklyn.util.flags.SetFromFlag;
@Catalog(name="JBoss Application Server 6", description="AS6: an open source Java application server from JBoss", iconUrl="classpath:///jboss-logo.png")
@ImplementedBy(JBoss6ServerImpl.class)
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/jboss/JBoss7Server.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/jboss/JBoss7Server.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/jboss/JBoss7Server.java
index 4872b68..dd5f2bd 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/jboss/JBoss7Server.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/jboss/JBoss7Server.java
@@ -22,6 +22,7 @@ import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.entity.trait.HasShortName;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.entity.webapp.JavaWebAppSoftwareProcess;
import brooklyn.config.ConfigKey;
@@ -31,7 +32,6 @@ import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey.StringAttributeSensorAndConfigKey;
import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.javalang.JavaClassNames;
@Catalog(name="JBoss Application Server 7", description="AS7: an open source Java application server from JBoss", iconUrl="classpath:///jboss-logo.png")
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/jetty/Jetty6Server.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/jetty/Jetty6Server.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/jetty/Jetty6Server.java
index bd5cfce..70baeee 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/jetty/Jetty6Server.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/jetty/Jetty6Server.java
@@ -22,6 +22,7 @@ import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.entity.trait.HasShortName;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.entity.webapp.JavaWebAppSoftwareProcess;
import brooklyn.config.ConfigKey;
@@ -30,7 +31,6 @@ import brooklyn.entity.basic.SoftwareProcess;
import brooklyn.entity.java.UsesJmx;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.time.Duration;
/**
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/nodejs/NodeJsWebAppService.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/nodejs/NodeJsWebAppService.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/nodejs/NodeJsWebAppService.java
index 166d2ad..9e34c57 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/nodejs/NodeJsWebAppService.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/nodejs/NodeJsWebAppService.java
@@ -23,6 +23,7 @@ import java.util.List;
import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.location.PortRange;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.entity.webapp.WebAppService;
import brooklyn.config.ConfigKey;
@@ -32,8 +33,6 @@ import brooklyn.entity.basic.SoftwareProcess;
import org.apache.brooklyn.location.basic.PortRanges;
-import brooklyn.util.flags.SetFromFlag;
-
import com.google.common.collect.ImmutableList;
import com.google.common.reflect.TypeToken;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/nodejs/NodeJsWebAppSshDriver.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/nodejs/NodeJsWebAppSshDriver.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/nodejs/NodeJsWebAppSshDriver.java
index e336a93..1735cb8 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/nodejs/NodeJsWebAppSshDriver.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/nodejs/NodeJsWebAppSshDriver.java
@@ -23,6 +23,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
+import org.apache.brooklyn.core.util.file.ArchiveUtils;
import org.apache.brooklyn.entity.webapp.WebAppService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -30,10 +31,11 @@ import org.slf4j.LoggerFactory;
import brooklyn.entity.basic.AbstractSoftwareProcessSshDriver;
import brooklyn.entity.basic.Attributes;
import brooklyn.entity.basic.SoftwareProcess;
+
import org.apache.brooklyn.location.basic.SshMachineLocation;
+
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.file.ArchiveUtils;
import brooklyn.util.net.Networking;
import brooklyn.util.os.Os;
import brooklyn.util.ssh.BashCommands;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/tomcat/Tomcat8Server.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/tomcat/Tomcat8Server.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/tomcat/Tomcat8Server.java
index 766c7a0..aef6ffd 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/tomcat/Tomcat8Server.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/tomcat/Tomcat8Server.java
@@ -20,12 +20,12 @@ package org.apache.brooklyn.entity.webapp.tomcat;
import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.SoftwareProcess;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.javalang.JavaClassNames;
/**
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/tomcat/TomcatServer.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/tomcat/TomcatServer.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/tomcat/TomcatServer.java
index d9327cd..95a8c31 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/tomcat/TomcatServer.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/tomcat/TomcatServer.java
@@ -22,6 +22,7 @@ import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.entity.trait.HasShortName;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.entity.webapp.JavaWebAppSoftwareProcess;
import brooklyn.config.ConfigKey;
@@ -31,8 +32,9 @@ import brooklyn.entity.java.UsesJmx;
import brooklyn.event.basic.BasicAttributeSensor;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
+
import org.apache.brooklyn.location.basic.PortRanges;
-import brooklyn.util.flags.SetFromFlag;
+
import brooklyn.util.javalang.JavaClassNames;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/test/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingScriptGeneratorTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingScriptGeneratorTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingScriptGeneratorTest.java
index f5c3f41..dc8dd41 100644
--- a/software/webapp/src/test/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingScriptGeneratorTest.java
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingScriptGeneratorTest.java
@@ -26,9 +26,8 @@ import java.util.LinkedHashSet;
import java.util.Set;
import org.testng.annotations.Test;
-
+import org.apache.brooklyn.core.util.ResourceUtils;
import org.apache.brooklyn.location.geo.HostGeoInfo;
-import brooklyn.util.ResourceUtils;
/**
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/test/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingWebClientTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingWebClientTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingWebClientTest.java
index 4602840..d068b48 100644
--- a/software/webapp/src/test/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingWebClientTest.java
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingWebClientTest.java
@@ -26,6 +26,7 @@ import static org.apache.brooklyn.entity.dns.geoscaling.GeoscalingWebClient.PROV
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
+import org.apache.brooklyn.core.util.http.HttpTool;
import org.apache.brooklyn.entity.dns.geoscaling.GeoscalingWebClient;
import org.apache.brooklyn.entity.dns.geoscaling.GeoscalingWebClient.Domain;
import org.apache.brooklyn.entity.dns.geoscaling.GeoscalingWebClient.SmartSubdomain;
@@ -34,7 +35,6 @@ import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
-import brooklyn.util.http.HttpTool;
import brooklyn.util.text.Strings;
/**
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/AbstractControllerTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/AbstractControllerTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/AbstractControllerTest.java
index facde8d..f3af752 100644
--- a/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/AbstractControllerTest.java
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/AbstractControllerTest.java
@@ -38,6 +38,7 @@ import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.location.MachineLocation;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
import org.apache.brooklyn.api.location.NoMachinesAvailableException;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.test.entity.TestEntity;
import org.apache.brooklyn.test.entity.TestEntityImpl;
import org.slf4j.Logger;
@@ -60,7 +61,6 @@ import brooklyn.test.Asserts;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/ProxySslConfigTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/ProxySslConfigTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/ProxySslConfigTest.java
index 218debf..37a8061 100644
--- a/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/ProxySslConfigTest.java
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/ProxySslConfigTest.java
@@ -18,12 +18,12 @@
*/
package org.apache.brooklyn.entity.proxy;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import org.apache.brooklyn.entity.proxy.ProxySslConfig;
import org.testng.Assert;
import org.testng.annotations.Test;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.flags.TypeCoercions;
@Test
public class ProxySslConfigTest {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/nginx/NginxRebindWithHaIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/nginx/NginxRebindWithHaIntegrationTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/nginx/NginxRebindWithHaIntegrationTest.java
index 57ea76d..9318fc9 100644
--- a/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/nginx/NginxRebindWithHaIntegrationTest.java
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/nginx/NginxRebindWithHaIntegrationTest.java
@@ -32,6 +32,8 @@ import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
+import org.apache.brooklyn.core.util.task.BasicExecutionManager;
import org.apache.brooklyn.entity.proxy.nginx.NginxController;
import org.apache.brooklyn.entity.webapp.tomcat.TomcatServer;
import org.apache.brooklyn.test.EntityTestUtils;
@@ -56,10 +58,8 @@ import brooklyn.entity.rebind.RebindTestUtils;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
import org.apache.brooklyn.location.basic.SshMachineLocationReuseIntegrationTest.RecordingSshjTool;
-import brooklyn.util.internal.ssh.SshTool;
import brooklyn.util.net.Networking;
import brooklyn.util.repeat.Repeater;
-import brooklyn.util.task.BasicExecutionManager;
import brooklyn.util.time.Duration;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/AbstractWebAppFixtureIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/AbstractWebAppFixtureIntegrationTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/AbstractWebAppFixtureIntegrationTest.java
index cf42c5e..b21cd38 100644
--- a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/AbstractWebAppFixtureIntegrationTest.java
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/AbstractWebAppFixtureIntegrationTest.java
@@ -68,6 +68,8 @@ import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.SubscriptionContext;
import org.apache.brooklyn.api.management.SubscriptionHandle;
+import org.apache.brooklyn.core.util.crypto.FluentKeySigner;
+import org.apache.brooklyn.core.util.crypto.SecureKeys;
import org.apache.brooklyn.entity.webapp.JavaWebAppService;
import org.apache.brooklyn.entity.webapp.JavaWebAppSoftwareProcess;
import org.apache.brooklyn.entity.webapp.WebAppService;
@@ -79,8 +81,6 @@ import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.test.entity.TestApplication;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.crypto.FluentKeySigner;
-import brooklyn.util.crypto.SecureKeys;
import brooklyn.util.net.Urls;
import brooklyn.util.stream.Streams;
import brooklyn.util.time.Time;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/HttpsSslConfigTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/HttpsSslConfigTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/HttpsSslConfigTest.java
index d21c0d9..830775c 100644
--- a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/HttpsSslConfigTest.java
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/HttpsSslConfigTest.java
@@ -18,12 +18,12 @@
*/
package org.apache.brooklyn.entity.webapp;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import org.apache.brooklyn.entity.webapp.HttpsSslConfig;
import org.testng.Assert;
import org.testng.annotations.Test;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.flags.TypeCoercions;
public class HttpsSslConfigTest {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/WebAppConcurrentDeployTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/WebAppConcurrentDeployTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/WebAppConcurrentDeployTest.java
index 9d0e1eb..28f331d 100644
--- a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/WebAppConcurrentDeployTest.java
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/WebAppConcurrentDeployTest.java
@@ -40,6 +40,8 @@ import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.http.HttpTool;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
import org.apache.brooklyn.entity.webapp.JavaWebAppSoftwareProcess;
import org.apache.brooklyn.entity.webapp.jboss.JBoss7Server;
import org.apache.brooklyn.entity.webapp.tomcat.TomcatServer;
@@ -48,8 +50,6 @@ import org.apache.brooklyn.test.TestResourceUnavailableException;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.http.HttpTool;
-import brooklyn.util.http.HttpToolResponse;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/test/java/org/apache/brooklyn/test/entity/TestJavaWebAppEntity.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/test/entity/TestJavaWebAppEntity.java b/software/webapp/src/test/java/org/apache/brooklyn/test/entity/TestJavaWebAppEntity.java
index c5967d0..b9d57ca 100644
--- a/software/webapp/src/test/java/org/apache/brooklyn/test/entity/TestJavaWebAppEntity.java
+++ b/software/webapp/src/test/java/org/apache/brooklyn/test/entity/TestJavaWebAppEntity.java
@@ -21,6 +21,7 @@ package org.apache.brooklyn.test.entity;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.entity.webapp.WebAppService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,7 +34,6 @@ import brooklyn.entity.basic.ServiceStateLogic;
import brooklyn.entity.basic.SoftwareProcess;
import brooklyn.entity.basic.SoftwareProcessDriverLifecycleEffectorTasks;
import brooklyn.entity.java.VanillaJavaApp;
-import brooklyn.util.config.ConfigBag;
/**
* Mock web application server entity for testing.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/test/java/org/apache/brooklyn/test/entity/TestJavaWebAppEntityImpl.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/test/entity/TestJavaWebAppEntityImpl.java b/software/webapp/src/test/java/org/apache/brooklyn/test/entity/TestJavaWebAppEntityImpl.java
index 7e909ab..04b8bd0 100644
--- a/software/webapp/src/test/java/org/apache/brooklyn/test/entity/TestJavaWebAppEntityImpl.java
+++ b/software/webapp/src/test/java/org/apache/brooklyn/test/entity/TestJavaWebAppEntityImpl.java
@@ -21,10 +21,10 @@ package org.apache.brooklyn.test.entity;
import java.util.Map;
import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.entity.webapp.WebAppServiceConstants;
import brooklyn.entity.java.VanillaJavaAppImpl;
-import brooklyn.util.flags.SetFromFlag;
public class TestJavaWebAppEntityImpl extends VanillaJavaAppImpl implements TestJavaWebAppEntity {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/archetypes/quickstart/src/brooklyn-sample/src/test/java/com/acme/sample/brooklyn/sample/app/SampleLocalhostIntegrationTest.java
----------------------------------------------------------------------
diff --git a/usage/archetypes/quickstart/src/brooklyn-sample/src/test/java/com/acme/sample/brooklyn/sample/app/SampleLocalhostIntegrationTest.java b/usage/archetypes/quickstart/src/brooklyn-sample/src/test/java/com/acme/sample/brooklyn/sample/app/SampleLocalhostIntegrationTest.java
index 471d5e3..f679425 100644
--- a/usage/archetypes/quickstart/src/brooklyn-sample/src/test/java/com/acme/sample/brooklyn/sample/app/SampleLocalhostIntegrationTest.java
+++ b/usage/archetypes/quickstart/src/brooklyn-sample/src/test/java/com/acme/sample/brooklyn/sample/app/SampleLocalhostIntegrationTest.java
@@ -17,7 +17,7 @@ import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.entity.webapp.JavaWebAppService;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
-import brooklyn.util.ResourceUtils;
+import org.apache.brooklyn.core.util.ResourceUtils;
import brooklyn.util.text.Strings;
/**
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/YamlLauncherAbstract.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/YamlLauncherAbstract.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/YamlLauncherAbstract.java
index 1ad7868..6296339 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/YamlLauncherAbstract.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/YamlLauncherAbstract.java
@@ -28,13 +28,13 @@ import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.ResourceUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.entity.basic.BrooklynShutdownHooks;
import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.entity.basic.Entities;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.stream.Streams;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
index 9241a73..3931a82 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
@@ -51,12 +51,12 @@ import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog.BrooklynLoaderTracker;
import org.apache.brooklyn.core.management.internal.EntityManagementUtils;
import org.apache.brooklyn.core.management.internal.EntityManagementUtils.CreationResult;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import brooklyn.config.BrooklynServerConfig;
import brooklyn.entity.basic.BasicApplicationImpl;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.net.Urls;
import com.google.common.collect.Iterables;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
index 33bb6a1..03e3920 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
@@ -50,6 +50,11 @@ import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.ManagementContextInjectable;
import org.apache.brooklyn.core.management.classloading.JavaBrooklynClassLoadingContext;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.FlagUtils;
+import org.apache.brooklyn.core.util.flags.FlagUtils.FlagConfigKeyAndValueRecord;
+import org.apache.brooklyn.core.util.task.Tasks;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.AbstractEntity;
@@ -57,15 +62,10 @@ import brooklyn.entity.basic.BrooklynTags;
import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.proxying.InternalEntityFactory;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableSet;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.flags.FlagUtils;
-import brooklyn.util.flags.FlagUtils.FlagConfigKeyAndValueRecord;
import brooklyn.util.guava.Maybe;
import brooklyn.util.javalang.Reflections;
-import brooklyn.util.task.Tasks;
import brooklyn.util.text.Strings;
import com.google.common.base.Function;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
index 527a44c..35c8b4c 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
@@ -33,9 +33,9 @@ import org.apache.brooklyn.api.policy.PolicySpec;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampReservedKeys;
import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynYamlTypeInstantiator.InstantiatorFromKey;
import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import brooklyn.util.collections.MutableList;
-import brooklyn.util.config.ConfigBag;
import com.google.common.annotations.Beta;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeInstantiator.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeInstantiator.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeInstantiator.java
index 2954ee7..87b1f01 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeInstantiator.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeInstantiator.java
@@ -25,11 +25,11 @@ import javax.annotation.Nullable;
import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampReservedKeys;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.guava.Maybe;
import brooklyn.util.javalang.Reflections;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslDeferredSupplier.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslDeferredSupplier.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslDeferredSupplier.java
index 3babd31..f8d03c9 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslDeferredSupplier.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslDeferredSupplier.java
@@ -27,6 +27,7 @@ import io.brooklyn.camp.spi.resolve.interpret.PlanInterpretationNode;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.management.TaskFactory;
+import org.apache.brooklyn.core.util.task.DeferredSupplier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -35,7 +36,6 @@ import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.effector.EffectorTasks;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.task.DeferredSupplier;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslUtils.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslUtils.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslUtils.java
index e5194bf..4eaf37d 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslUtils.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslUtils.java
@@ -18,7 +18,7 @@
*/
package org.apache.brooklyn.camp.brooklyn.spi.dsl;
-import brooklyn.util.task.DeferredSupplier;
+import org.apache.brooklyn.core.util.task.DeferredSupplier;
import com.google.common.collect.Iterables;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
index 71a72a5..5b1b1e8 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
@@ -34,18 +34,18 @@ import org.apache.brooklyn.camp.brooklyn.spi.creation.EntitySpecConfiguration;
import org.apache.brooklyn.camp.brooklyn.spi.dsl.BrooklynDslDeferredSupplier;
import org.apache.brooklyn.camp.brooklyn.spi.dsl.DslUtils;
import org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.DslComponent.Scope;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.ClassCoercionException;
+import org.apache.brooklyn.core.util.flags.FlagUtils;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
+import org.apache.brooklyn.core.util.task.DeferredSupplier;
import org.apache.commons.beanutils.BeanUtils;
import brooklyn.entity.basic.EntityDynamicType;
import brooklyn.event.basic.DependentConfiguration;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.ClassCoercionException;
-import brooklyn.util.flags.FlagUtils;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.javalang.Reflections;
-import brooklyn.util.task.DeferredSupplier;
import brooklyn.util.text.StringEscapes.JavaStringEscapes;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
index 601a46a..791c79f 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
@@ -29,6 +29,8 @@ import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampConstants;
import org.apache.brooklyn.camp.brooklyn.spi.dsl.BrooklynDslDeferredSupplier;
import org.apache.brooklyn.core.management.internal.EntityManagerInternal;
+import org.apache.brooklyn.core.util.task.TaskBuilder;
+import org.apache.brooklyn.core.util.task.Tasks;
import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.entity.basic.ConfigKeys;
@@ -38,8 +40,6 @@ import brooklyn.entity.basic.EntityPredicates;
import brooklyn.event.basic.DependentConfiguration;
import brooklyn.event.basic.Sensors;
import brooklyn.util.guava.Maybe;
-import brooklyn.util.task.TaskBuilder;
-import brooklyn.util.task.Tasks;
import brooklyn.util.text.StringEscapes.JavaStringEscapes;
import com.google.common.base.Optional;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlRebindTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlRebindTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlRebindTest.java
index c0b77f4..8922059 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlRebindTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlRebindTest.java
@@ -32,6 +32,8 @@ import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatform;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherNoServer;
import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.AfterMethod;
@@ -42,8 +44,6 @@ import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.StartableApplication;
import brooklyn.entity.rebind.RebindOptions;
import brooklyn.entity.rebind.RebindTestFixture;
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.config.ConfigBag;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java
index d96b132..0396009 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java
@@ -32,6 +32,8 @@ import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatform;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherNoServer;
import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -40,8 +42,6 @@ import org.testng.annotations.BeforeMethod;
import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.entity.basic.Entities;
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.config.ConfigBag;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/DslAndRebindYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/DslAndRebindYamlTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/DslAndRebindYamlTest.java
index 87d014b..110851a 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/DslAndRebindYamlTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/DslAndRebindYamlTest.java
@@ -27,6 +27,7 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.apache.brooklyn.test.entity.TestEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -42,7 +43,6 @@ import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.rebind.RebindTestUtils;
import brooklyn.event.basic.Sensors;
import brooklyn.util.collections.MutableSet;
-import brooklyn.util.task.Tasks;
import com.google.common.collect.Iterables;
import com.google.common.io.Files;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/EntitiesYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/EntitiesYamlTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/EntitiesYamlTest.java
index 06f596a..a0278b2 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/EntitiesYamlTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/EntitiesYamlTest.java
@@ -40,6 +40,7 @@ import org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.BrooklynDslCommon;
import org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.DslComponent;
import org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.DslComponent.Scope;
import org.apache.brooklyn.core.management.internal.EntityManagerInternal;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.apache.brooklyn.test.entity.TestEntity;
import org.apache.brooklyn.test.entity.TestEntityImpl;
import org.slf4j.Logger;
@@ -65,7 +66,6 @@ import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.guava.Functionals;
import brooklyn.util.guava.Maybe;
-import brooklyn.util.task.Tasks;
import brooklyn.util.time.Duration;
import com.google.common.base.Suppliers;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppWithDslYamlRebindIntegrationTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppWithDslYamlRebindIntegrationTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppWithDslYamlRebindIntegrationTest.java
index e558288..72b06e3 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppWithDslYamlRebindIntegrationTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppWithDslYamlRebindIntegrationTest.java
@@ -29,6 +29,7 @@ import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.util.ResourceUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
@@ -38,7 +39,6 @@ import org.testng.annotations.Test;
import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.rebind.RebindTestUtils;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableSet;
import brooklyn.util.stream.Streams;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppsIntegrationTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppsIntegrationTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppsIntegrationTest.java
index 94b3f66..7314e66 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppsIntegrationTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppsIntegrationTest.java
@@ -38,6 +38,7 @@ import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatform;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherNoServer;
+import org.apache.brooklyn.core.util.ResourceUtils;
import org.apache.brooklyn.entity.webapp.DynamicWebAppCluster;
import org.apache.brooklyn.entity.webapp.JavaWebAppService;
import org.apache.brooklyn.entity.webapp.WebAppService;
@@ -55,7 +56,6 @@ import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.Lifecycle;
import brooklyn.policy.autoscaling.AutoScalerPolicy;
import brooklyn.test.Asserts;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.net.Urls;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppsMatchingTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppsMatchingTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppsMatchingTest.java
index b4a647e..7e45019 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppsMatchingTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppsMatchingTest.java
@@ -32,6 +32,8 @@ import java.util.Map;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatform;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampReservedKeys;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.task.DeferredSupplier;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -41,10 +43,8 @@ import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import brooklyn.entity.basic.Entities;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.stream.Streams;
-import brooklyn.util.task.DeferredSupplier;
@Test
public class JavaWebAppsMatchingTest {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/MapReferenceYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/MapReferenceYamlTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/MapReferenceYamlTest.java
index f20af51..7a8ca3c 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/MapReferenceYamlTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/MapReferenceYamlTest.java
@@ -22,6 +22,7 @@ import java.util.Map;
import java.util.concurrent.Callable;
import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.apache.brooklyn.entity.proxy.ProxySslConfig;
import org.apache.brooklyn.test.entity.TestEntity;
import org.slf4j.Logger;
@@ -31,7 +32,6 @@ import org.testng.annotations.Test;
import brooklyn.entity.basic.BasicEntity;
import brooklyn.entity.basic.Entities;
-import brooklyn.util.task.Tasks;
import com.google.common.collect.Iterables;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java
index ba29051..6b19d3b 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java
@@ -26,6 +26,9 @@ import org.apache.brooklyn.api.entity.trait.Configurable;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.core.management.ManagementContextInjectable;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import org.apache.brooklyn.entity.proxy.ProxySslConfig;
import org.apache.brooklyn.test.entity.TestEntity;
import org.slf4j.Logger;
@@ -37,9 +40,6 @@ import brooklyn.config.ConfigKey;
import brooklyn.config.ConfigKey.HasConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.Entities;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.flags.SetFromFlag;
-import brooklyn.util.flags.TypeCoercions;
import com.google.common.collect.Lists;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ReloadBrooklynPropertiesTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ReloadBrooklynPropertiesTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ReloadBrooklynPropertiesTest.java
index 3774e7e..961e2fd 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ReloadBrooklynPropertiesTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ReloadBrooklynPropertiesTest.java
@@ -28,6 +28,7 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampConstants;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherNoServer;
+import org.apache.brooklyn.core.util.ResourceUtils;
import org.apache.brooklyn.test.EntityTestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -38,7 +39,6 @@ import org.testng.annotations.Test;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.trait.Startable;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.stream.Streams;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/TestSensorAndEffectorInitializer.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/TestSensorAndEffectorInitializer.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/TestSensorAndEffectorInitializer.java
index 55b9c27..c03a282 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/TestSensorAndEffectorInitializer.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/TestSensorAndEffectorInitializer.java
@@ -24,6 +24,7 @@ import org.apache.brooklyn.api.entity.Effector;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.entity.proxying.EntityInitializer;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.testng.Assert;
import com.google.common.base.Preconditions;
@@ -32,7 +33,6 @@ import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.effector.EffectorBody;
import brooklyn.entity.effector.Effectors;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.config.ConfigBag;
public class TestSensorAndEffectorInitializer implements EntityInitializer {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/AbstractCatalogXmlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/AbstractCatalogXmlTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/AbstractCatalogXmlTest.java
index 65bb7e0..5eab943 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/AbstractCatalogXmlTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/AbstractCatalogXmlTest.java
@@ -22,6 +22,7 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.core.management.osgi.OsgiTestResources;
+import org.apache.brooklyn.core.util.ResourceUtils;
import org.apache.brooklyn.test.TestResourceUnavailableException;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
@@ -33,7 +34,6 @@ import java.io.StringReader;
import brooklyn.config.BrooklynProperties;
import brooklyn.config.BrooklynServerConfig;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.os.Os;
import brooklyn.util.stream.ReaderInputStream;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
index 66fee85..d08cfed 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
@@ -39,9 +39,9 @@ import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynEntityMatcher;
import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.osgi.OsgiVersionMoreEntityTest;
+import org.apache.brooklyn.core.util.ResourceUtils;
import org.apache.brooklyn.test.TestResourceUnavailableException;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.text.Strings;
import com.google.common.collect.Iterables;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
index 3aa9b74..4cece0a 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
@@ -35,6 +35,7 @@ import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.osgi.OsgiStandaloneTest;
import org.apache.brooklyn.core.management.osgi.OsgiTestResources;
+import org.apache.brooklyn.core.util.ResourceUtils;
import brooklyn.entity.basic.BasicEntity;
@@ -42,7 +43,6 @@ import org.apache.brooklyn.test.TestResourceUnavailableException;
import org.apache.brooklyn.test.entity.TestEntity;
import org.apache.brooklyn.test.entity.TestEntityImpl;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableList;
import brooklyn.util.exceptions.Exceptions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/cli/src/main/java/org/apache/brooklyn/cli/ItemLister.java
----------------------------------------------------------------------
diff --git a/usage/cli/src/main/java/org/apache/brooklyn/cli/ItemLister.java b/usage/cli/src/main/java/org/apache/brooklyn/cli/ItemLister.java
index 88780aa..56f691c 100644
--- a/usage/cli/src/main/java/org/apache/brooklyn/cli/ItemLister.java
+++ b/usage/cli/src/main/java/org/apache/brooklyn/cli/ItemLister.java
@@ -42,13 +42,13 @@ import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.cli.lister.ClassFinder;
import org.apache.brooklyn.cli.lister.ItemDescriptors;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.text.TemplateProcessor;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableSet;
import brooklyn.util.net.Urls;
import brooklyn.util.os.Os;
import brooklyn.util.text.Strings;
-import brooklyn.util.text.TemplateProcessor;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/cli/src/main/java/org/apache/brooklyn/cli/Main.java
----------------------------------------------------------------------
diff --git a/usage/cli/src/main/java/org/apache/brooklyn/cli/Main.java b/usage/cli/src/main/java/org/apache/brooklyn/cli/Main.java
index 8d3ed07..95c10a1 100644
--- a/usage/cli/src/main/java/org/apache/brooklyn/cli/Main.java
+++ b/usage/cli/src/main/java/org/apache/brooklyn/cli/Main.java
@@ -78,6 +78,7 @@ import org.apache.brooklyn.cli.CloudExplorer.ComputeTerminateInstancesCommand;
import org.apache.brooklyn.cli.ItemLister.ListAllCommand;
import org.apache.brooklyn.core.catalog.internal.CatalogInitialization;
import org.apache.brooklyn.core.management.ha.OsgiManager;
+import org.apache.brooklyn.core.util.ResourceUtils;
import brooklyn.entity.basic.AbstractApplication;
import brooklyn.entity.basic.AbstractEntity;
@@ -95,7 +96,6 @@ import org.apache.brooklyn.launcher.config.StopWhichAppsOnShutdown;
import org.apache.brooklyn.rest.security.PasswordHasher;
import org.apache.brooklyn.rest.util.ShutdownHandler;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.exceptions.FatalConfigurationRuntimeException;
import brooklyn.util.exceptions.FatalRuntimeException;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/cli/src/main/java/org/apache/brooklyn/cli/lister/ClassFinder.java
----------------------------------------------------------------------
diff --git a/usage/cli/src/main/java/org/apache/brooklyn/cli/lister/ClassFinder.java b/usage/cli/src/main/java/org/apache/brooklyn/cli/lister/ClassFinder.java
index 63ad940..4d22b3f 100644
--- a/usage/cli/src/main/java/org/apache/brooklyn/cli/lister/ClassFinder.java
+++ b/usage/cli/src/main/java/org/apache/brooklyn/cli/lister/ClassFinder.java
@@ -31,6 +31,8 @@ import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.javalang.UrlClassLoader;
import org.reflections.Reflections;
import org.reflections.scanners.FieldAnnotationsScanner;
import org.reflections.scanners.SubTypesScanner;
@@ -44,8 +46,6 @@ import brooklyn.entity.basic.AbstractApplication;
import brooklyn.entity.basic.AbstractEntity;
import brooklyn.entity.basic.SoftwareProcessImpl;
import brooklyn.policy.basic.AbstractPolicy;
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.javalang.UrlClassLoader;
import brooklyn.util.net.Urls;
import brooklyn.util.os.Os;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/cli/src/test/java/org/apache/brooklyn/cli/CliTest.java
----------------------------------------------------------------------
diff --git a/usage/cli/src/test/java/org/apache/brooklyn/cli/CliTest.java b/usage/cli/src/test/java/org/apache/brooklyn/cli/CliTest.java
index ff6a5d3..44207c1 100644
--- a/usage/cli/src/test/java/org/apache/brooklyn/cli/CliTest.java
+++ b/usage/cli/src/test/java/org/apache/brooklyn/cli/CliTest.java
@@ -51,6 +51,7 @@ import org.apache.brooklyn.cli.AbstractMain.HelpCommand;
import org.apache.brooklyn.cli.Main.AppShutdownHandler;
import org.apache.brooklyn.cli.Main.GeneratePasswordCommand;
import org.apache.brooklyn.cli.Main.LaunchCommand;
+import org.apache.brooklyn.core.util.ResourceUtils;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -70,7 +71,6 @@ import brooklyn.entity.trait.Startable;
import org.apache.brooklyn.location.basic.SimulatedLocation;
import brooklyn.test.Asserts;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.exceptions.FatalConfigurationRuntimeException;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynWebServer.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynWebServer.java b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynWebServer.java
index 13ee15a..82c881f 100644
--- a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynWebServer.java
+++ b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynWebServer.java
@@ -68,6 +68,13 @@ import org.apache.brooklyn.api.location.PortRange;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.core.internal.BrooklynInitialization;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.util.BrooklynNetworkUtils;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.crypto.FluentKeySigner;
+import org.apache.brooklyn.core.util.crypto.SecureKeys;
+import org.apache.brooklyn.core.util.flags.FlagUtils;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import org.apache.brooklyn.launcher.config.CustomResourceLocator;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
import org.apache.brooklyn.location.basic.PortRanges;
@@ -83,15 +90,8 @@ import org.apache.brooklyn.rest.util.ManagementContextProvider;
import org.apache.brooklyn.rest.util.ShutdownHandler;
import org.apache.brooklyn.rest.util.ShutdownHandlerProvider;
-import brooklyn.util.BrooklynNetworkUtils;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.crypto.FluentKeySigner;
-import brooklyn.util.crypto.SecureKeys;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.FlagUtils;
-import brooklyn.util.flags.SetFromFlag;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.io.FileUtil;
import brooklyn.util.javalang.Threads;
import brooklyn.util.logging.LoggingSetup;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/launcher/src/main/java/org/apache/brooklyn/launcher/config/CustomResourceLocator.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/config/CustomResourceLocator.java b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/config/CustomResourceLocator.java
index 78ad7c6..eb1052d 100644
--- a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/config/CustomResourceLocator.java
+++ b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/config/CustomResourceLocator.java
@@ -23,12 +23,12 @@ import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
+import org.apache.brooklyn.core.util.ResourceUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.BrooklynVersion;
import brooklyn.config.ConfigMap;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.os.Os;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/launcher/src/test/java/org/apache/brooklyn/entity/basic/VanillaSoftwareYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/entity/basic/VanillaSoftwareYamlTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/entity/basic/VanillaSoftwareYamlTest.java
index a8c9f98..1d14d72 100644
--- a/usage/launcher/src/test/java/org/apache/brooklyn/entity/basic/VanillaSoftwareYamlTest.java
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/entity/basic/VanillaSoftwareYamlTest.java
@@ -28,11 +28,11 @@ import brooklyn.entity.trait.Startable;
import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.core.util.ResourceUtils;
import org.apache.brooklyn.launcher.SimpleYamlLauncherForTests;
import org.apache.brooklyn.launcher.camp.SimpleYamlLauncher;
import brooklyn.test.Asserts;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.os.Os;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/launcher/src/test/java/org/apache/brooklyn/entity/brooklynnode/BrooklynNodeRestTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/entity/brooklynnode/BrooklynNodeRestTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/entity/brooklynnode/BrooklynNodeRestTest.java
index a8d301e..933071c 100644
--- a/usage/launcher/src/test/java/org/apache/brooklyn/entity/brooklynnode/BrooklynNodeRestTest.java
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/entity/brooklynnode/BrooklynNodeRestTest.java
@@ -44,15 +44,15 @@ import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.http.HttpTool;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
import org.apache.brooklyn.launcher.SimpleYamlLauncherForTests;
import org.apache.brooklyn.launcher.camp.SimpleYamlLauncher;
import brooklyn.util.collections.Jsonya;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.http.HttpTool;
-import brooklyn.util.http.HttpToolResponse;
import brooklyn.util.net.Urls;
import brooklyn.util.repeat.Repeater;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/launcher/src/test/java/org/apache/brooklyn/entity/database/mssql/MssqlBlueprintLiveTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/entity/database/mssql/MssqlBlueprintLiveTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/entity/database/mssql/MssqlBlueprintLiveTest.java
index 9103792..6badab5 100644
--- a/usage/launcher/src/test/java/org/apache/brooklyn/entity/database/mssql/MssqlBlueprintLiveTest.java
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/entity/database/mssql/MssqlBlueprintLiveTest.java
@@ -22,10 +22,9 @@ import java.io.StringReader;
import java.util.Map;
import org.testng.annotations.Test;
-
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.text.TemplateProcessor;
import org.apache.brooklyn.launcher.blueprints.AbstractBlueprintTest;
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.text.TemplateProcessor;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindCatalogTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindCatalogTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindCatalogTest.java
index 49596d6..060aa8f 100644
--- a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindCatalogTest.java
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindCatalogTest.java
@@ -37,10 +37,10 @@ import com.google.common.io.Files;
import org.apache.brooklyn.api.catalog.BrooklynCatalog;
import org.apache.brooklyn.api.catalog.CatalogItem;
import org.apache.brooklyn.core.catalog.internal.CatalogInitialization;
+import org.apache.brooklyn.core.util.ResourceUtils;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import brooklyn.entity.rebind.persister.PersistMode;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.os.Os;
public class BrooklynLauncherRebindCatalogTest {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynWebServerTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynWebServerTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynWebServerTest.java
index 8ee48f4..f743aea 100644
--- a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynWebServerTest.java
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynWebServerTest.java
@@ -19,6 +19,8 @@
package org.apache.brooklyn.launcher;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.util.http.HttpTool;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
import org.apache.brooklyn.launcher.BrooklynWebServer;
import static org.testng.Assert.assertEquals;
@@ -55,8 +57,6 @@ import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.http.HttpTool;
-import brooklyn.util.http.HttpToolResponse;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/launcher/src/test/java/org/apache/brooklyn/launcher/blueprints/AbstractBlueprintTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/blueprints/AbstractBlueprintTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/blueprints/AbstractBlueprintTest.java
index 4fcc63d..707d9a7 100644
--- a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/blueprints/AbstractBlueprintTest.java
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/blueprints/AbstractBlueprintTest.java
@@ -30,6 +30,7 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherAbstract;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.util.ResourceUtils;
import org.apache.brooklyn.test.EntityTestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -49,7 +50,6 @@ import org.apache.brooklyn.launcher.SimpleYamlLauncherForTests;
import org.apache.brooklyn.launcher.camp.BrooklynCampPlatformLauncher;
import brooklyn.test.Asserts;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.os.Os;
public abstract class AbstractBlueprintTest {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/qa/src/main/java/org/apache/brooklyn/qa/load/SimulatedMySqlNodeImpl.java
----------------------------------------------------------------------
diff --git a/usage/qa/src/main/java/org/apache/brooklyn/qa/load/SimulatedMySqlNodeImpl.java b/usage/qa/src/main/java/org/apache/brooklyn/qa/load/SimulatedMySqlNodeImpl.java
index 7570cc5..b5f0cf4 100644
--- a/usage/qa/src/main/java/org/apache/brooklyn/qa/load/SimulatedMySqlNodeImpl.java
+++ b/usage/qa/src/main/java/org/apache/brooklyn/qa/load/SimulatedMySqlNodeImpl.java
@@ -30,10 +30,12 @@ import brooklyn.entity.database.mysql.MySqlSshDriver;
import brooklyn.entity.software.SshEffectorTasks;
import brooklyn.event.feed.function.FunctionFeed;
import brooklyn.event.feed.function.FunctionPollConfig;
+
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
import org.apache.brooklyn.location.basic.SshMachineLocation;
+
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.system.ProcessTaskWrapper;
import brooklyn.util.time.CountdownTimer;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/qa/src/main/java/org/apache/brooklyn/qa/longevity/MonitorUtils.java
----------------------------------------------------------------------
diff --git a/usage/qa/src/main/java/org/apache/brooklyn/qa/longevity/MonitorUtils.java b/usage/qa/src/main/java/org/apache/brooklyn/qa/longevity/MonitorUtils.java
index 54acb3b..9dbfe0a 100644
--- a/usage/qa/src/main/java/org/apache/brooklyn/qa/longevity/MonitorUtils.java
+++ b/usage/qa/src/main/java/org/apache/brooklyn/qa/longevity/MonitorUtils.java
@@ -35,11 +35,11 @@ import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
+import org.apache.brooklyn.core.util.http.HttpTool;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import brooklyn.util.http.HttpTool;
-import brooklyn.util.http.HttpToolResponse;
import brooklyn.util.stream.StreamGobbler;
import com.google.common.base.Objects;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/qa/src/test/java/org/apache/brooklyn/qa/brooklynnode/SoftlayerObtainPrivateLiveTest.java
----------------------------------------------------------------------
diff --git a/usage/qa/src/test/java/org/apache/brooklyn/qa/brooklynnode/SoftlayerObtainPrivateLiveTest.java b/usage/qa/src/test/java/org/apache/brooklyn/qa/brooklynnode/SoftlayerObtainPrivateLiveTest.java
index 59c5b0b..8a02698 100644
--- a/usage/qa/src/test/java/org/apache/brooklyn/qa/brooklynnode/SoftlayerObtainPrivateLiveTest.java
+++ b/usage/qa/src/test/java/org/apache/brooklyn/qa/brooklynnode/SoftlayerObtainPrivateLiveTest.java
@@ -44,10 +44,10 @@ import brooklyn.entity.brooklynnode.BrooklynNode.DeployBlueprintEffector;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.util.BrooklynMavenArtifacts;
import org.apache.brooklyn.launcher.BrooklynLauncher;
import org.apache.brooklyn.location.jclouds.JcloudsLocationConfig;
-import brooklyn.util.BrooklynMavenArtifacts;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.maven.MavenRetriever;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/AbstractBrooklynRestResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/AbstractBrooklynRestResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/AbstractBrooklynRestResource.java
index 9313987..830214e 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/AbstractBrooklynRestResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/AbstractBrooklynRestResource.java
@@ -34,12 +34,12 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.core.management.ManagementContextInjectable;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.apache.brooklyn.rest.util.BrooklynRestResourceUtils;
import org.apache.brooklyn.rest.util.WebResourceUtils;
import org.apache.brooklyn.rest.util.json.BrooklynJacksonJsonProvider;
import brooklyn.util.guava.Maybe;
-import brooklyn.util.task.Tasks;
import brooklyn.util.time.Duration;
public abstract class AbstractBrooklynRestResource implements ManagementContextInjectable {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
index 98d5648..d195af6 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
@@ -66,6 +66,7 @@ import org.apache.brooklyn.core.management.entitlement.Entitlements.EntityAndIte
import org.apache.brooklyn.core.management.entitlement.Entitlements.StringAndArgument;
import org.apache.brooklyn.core.management.internal.EntityManagementUtils;
import org.apache.brooklyn.core.management.internal.EntityManagementUtils.CreationResult;
+import org.apache.brooklyn.core.util.ResourceUtils;
import org.apache.brooklyn.rest.api.ApplicationApi;
import org.apache.brooklyn.rest.domain.ApplicationSpec;
import org.apache.brooklyn.rest.domain.ApplicationSummary;
@@ -79,7 +80,6 @@ import org.apache.brooklyn.rest.transform.TaskTransformer;
import org.apache.brooklyn.rest.util.BrooklynRestResourceUtils;
import org.apache.brooklyn.rest.util.WebResourceUtils;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
index 80dc2a3..08ed505 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
@@ -51,6 +51,7 @@ import org.apache.brooklyn.core.catalog.internal.CatalogItemComparator;
import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.entitlement.Entitlements;
import org.apache.brooklyn.core.management.entitlement.Entitlements.StringAndArgument;
+import org.apache.brooklyn.core.util.ResourceUtils;
import org.apache.brooklyn.rest.api.CatalogApi;
import org.apache.brooklyn.rest.domain.ApiError;
import org.apache.brooklyn.rest.domain.CatalogEntitySummary;
@@ -61,7 +62,6 @@ import org.apache.brooklyn.rest.filter.HaHotStateRequired;
import org.apache.brooklyn.rest.transform.CatalogTransformer;
import org.apache.brooklyn.rest.util.WebResourceUtils;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
import brooklyn.util.exceptions.Exceptions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityConfigResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityConfigResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityConfigResource.java
index 5353f50..f5f43ea 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityConfigResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityConfigResource.java
@@ -34,14 +34,14 @@ import brooklyn.event.basic.BasicConfigKey;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.core.management.entitlement.Entitlements;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
+import org.apache.brooklyn.core.util.task.ValueResolver;
import org.apache.brooklyn.rest.api.EntityConfigApi;
import org.apache.brooklyn.rest.domain.EntityConfigSummary;
import org.apache.brooklyn.rest.filter.HaHotStateRequired;
import org.apache.brooklyn.rest.transform.EntityTransformer;
import org.apache.brooklyn.rest.util.WebResourceUtils;
-import brooklyn.util.flags.TypeCoercions;
-import brooklyn.util.task.ValueResolver;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityResource.java
index a50a86e..eef52e9 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityResource.java
@@ -50,6 +50,7 @@ import org.apache.brooklyn.core.management.entitlement.EntitlementPredicates;
import org.apache.brooklyn.core.management.entitlement.Entitlements;
import org.apache.brooklyn.core.management.internal.EntityManagementUtils;
import org.apache.brooklyn.core.management.internal.EntityManagementUtils.CreationResult;
+import org.apache.brooklyn.core.util.ResourceUtils;
import org.apache.brooklyn.rest.api.EntityApi;
import org.apache.brooklyn.rest.domain.EntitySummary;
import org.apache.brooklyn.rest.domain.LocationSummary;
@@ -61,7 +62,6 @@ import org.apache.brooklyn.rest.transform.LocationTransformer.LocationDetailLeve
import org.apache.brooklyn.rest.transform.TaskTransformer;
import org.apache.brooklyn.rest.util.WebResourceUtils;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableList;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/PolicyConfigResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/PolicyConfigResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/PolicyConfigResource.java
index 655c20c..a6ca58b 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/PolicyConfigResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/PolicyConfigResource.java
@@ -30,6 +30,7 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.core.management.entitlement.Entitlements;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import org.apache.brooklyn.rest.api.PolicyConfigApi;
import org.apache.brooklyn.rest.domain.PolicyConfigSummary;
import org.apache.brooklyn.rest.filter.HaHotStateRequired;
@@ -37,8 +38,6 @@ import org.apache.brooklyn.rest.transform.PolicyTransformer;
import org.apache.brooklyn.rest.util.BrooklynRestResourceUtils;
import org.apache.brooklyn.rest.util.WebResourceUtils;
-import brooklyn.util.flags.TypeCoercions;
-
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/SensorResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/SensorResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/SensorResource.java
index e8b85ef..d8be210 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/SensorResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/SensorResource.java
@@ -34,13 +34,13 @@ import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.core.management.entitlement.Entitlements;
+import org.apache.brooklyn.core.util.task.ValueResolver;
import org.apache.brooklyn.rest.api.SensorApi;
import org.apache.brooklyn.rest.domain.SensorSummary;
import org.apache.brooklyn.rest.filter.HaHotStateRequired;
import org.apache.brooklyn.rest.transform.SensorTransformer;
import org.apache.brooklyn.rest.util.WebResourceUtils;
-import brooklyn.util.task.ValueResolver;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Duration;
[04/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ServerResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ServerResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ServerResource.java
index 9c48ddf..1fed7c6 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ServerResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ServerResource.java
@@ -63,6 +63,9 @@ import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecord;
import org.apache.brooklyn.api.management.ha.MementoCopyMode;
import org.apache.brooklyn.core.management.entitlement.Entitlements;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.file.ArchiveBuilder;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import org.apache.brooklyn.rest.api.ServerApi;
import org.apache.brooklyn.rest.domain.BrooklynFeatureSummary;
import org.apache.brooklyn.rest.domain.HighAvailabilitySummary;
@@ -72,11 +75,8 @@ import org.apache.brooklyn.rest.transform.HighAvailabilityTransformer;
import org.apache.brooklyn.rest.util.ShutdownHandler;
import org.apache.brooklyn.rest.util.WebResourceUtils;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.file.ArchiveBuilder;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.guava.Maybe;
import brooklyn.util.os.Os;
import brooklyn.util.text.Identifiers;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/EffectorTransformer.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/EffectorTransformer.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/EffectorTransformer.java
index f78df8b..32a8887 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/EffectorTransformer.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/EffectorTransformer.java
@@ -27,14 +27,14 @@ import org.apache.brooklyn.api.entity.Effector;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.ParameterType;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.core.util.task.ValueResolver;
import org.apache.brooklyn.rest.domain.EffectorSummary;
import org.apache.brooklyn.rest.domain.EffectorSummary.ParameterSummary;
import org.apache.brooklyn.rest.util.WebResourceUtils;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.guava.Maybe;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.task.ValueResolver;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/LocationTransformer.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/LocationTransformer.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/LocationTransformer.java
index 72d17db..f1b6959 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/LocationTransformer.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/LocationTransformer.java
@@ -32,11 +32,11 @@ import org.apache.brooklyn.location.basic.LocationInternal;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationDefinition;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.rest.domain.LocationSummary;
import org.apache.brooklyn.rest.util.WebResourceUtils;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.guava.Maybe;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/TaskTransformer.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/TaskTransformer.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/TaskTransformer.java
index 6b337a0..ead9ba5 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/TaskTransformer.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/TaskTransformer.java
@@ -36,13 +36,13 @@ import brooklyn.entity.basic.BrooklynTaskTags.WrappedStream;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.management.HasTaskChildren;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.task.TaskInternal;
import org.apache.brooklyn.rest.domain.LinkWithMetadata;
import org.apache.brooklyn.rest.domain.TaskSummary;
import org.apache.brooklyn.rest.util.WebResourceUtils;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.task.TaskInternal;
import brooklyn.util.text.Strings;
import com.google.common.base.Function;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
index d09d05b..d29b6e8 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
@@ -53,6 +53,7 @@ import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.entitlement.Entitlements;
import org.apache.brooklyn.core.management.entitlement.Entitlements.StringAndArgument;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import brooklyn.config.ConfigKey;
import brooklyn.enricher.Enrichers;
@@ -70,7 +71,6 @@ import org.apache.brooklyn.rest.domain.EntitySpec;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.javalang.Reflections;
import brooklyn.util.net.Urls;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/DefaultExceptionMapper.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/DefaultExceptionMapper.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/DefaultExceptionMapper.java
index 491c1a7..8d78462 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/DefaultExceptionMapper.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/DefaultExceptionMapper.java
@@ -31,13 +31,13 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yaml.snakeyaml.error.YAMLException;
import org.apache.brooklyn.core.management.entitlement.Entitlements;
+import org.apache.brooklyn.core.util.flags.ClassCoercionException;
import org.apache.brooklyn.rest.domain.ApiError;
import org.apache.brooklyn.rest.domain.ApiError.Builder;
import brooklyn.util.collections.MutableSet;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.exceptions.UserFacingException;
-import brooklyn.util.flags.ClassCoercionException;
import brooklyn.util.text.Strings;
@Provider
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/rest-server/src/test/java/org/apache/brooklyn/rest/BrooklynPropertiesSecurityFilterTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/BrooklynPropertiesSecurityFilterTest.java b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/BrooklynPropertiesSecurityFilterTest.java
index 6d8e15e..4320321 100644
--- a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/BrooklynPropertiesSecurityFilterTest.java
+++ b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/BrooklynPropertiesSecurityFilterTest.java
@@ -35,11 +35,11 @@ import org.eclipse.jetty.server.Server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.Test;
-
+import org.apache.brooklyn.core.util.http.HttpTool;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
import org.apache.brooklyn.rest.security.provider.AnyoneSecurityProvider;
+
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.http.HttpTool;
-import brooklyn.util.http.HttpToolResponse;
import brooklyn.util.time.Time;
import com.fasterxml.jackson.databind.ObjectMapper;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/rest-server/src/test/java/org/apache/brooklyn/rest/HaMasterCheckFilterTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/HaMasterCheckFilterTest.java b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/HaMasterCheckFilterTest.java
index f5ac071..3f529ca 100644
--- a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/HaMasterCheckFilterTest.java
+++ b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/HaMasterCheckFilterTest.java
@@ -32,6 +32,8 @@ import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
import org.apache.brooklyn.api.management.ha.ManagementNodeState;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherNoServer;
+import org.apache.brooklyn.core.util.http.HttpTool;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.eclipse.jetty.server.Server;
@@ -45,8 +47,6 @@ import brooklyn.entity.rebind.RebindTestUtils;
import org.apache.brooklyn.rest.security.provider.AnyoneSecurityProvider;
import brooklyn.test.Asserts;
-import brooklyn.util.http.HttpTool;
-import brooklyn.util.http.HttpToolResponse;
import brooklyn.util.os.Os;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/CatalogResetTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/CatalogResetTest.java b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/CatalogResetTest.java
index b073c2c..e9440e8 100644
--- a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/CatalogResetTest.java
+++ b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/CatalogResetTest.java
@@ -27,11 +27,11 @@ import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.apache.brooklyn.api.catalog.BrooklynCatalog;
+import org.apache.brooklyn.core.util.ResourceUtils;
import org.apache.brooklyn.rest.testing.BrooklynRestResourceTest;
import brooklyn.test.TestHttpRequestHandler;
import brooklyn.test.TestHttpServer;
-import brooklyn.util.ResourceUtils;
import com.sun.jersey.api.client.UniformInterfaceException;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/SensorResourceIntegrationTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/SensorResourceIntegrationTest.java b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/SensorResourceIntegrationTest.java
index 6af06cb..354f4ed 100644
--- a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/SensorResourceIntegrationTest.java
+++ b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/SensorResourceIntegrationTest.java
@@ -35,14 +35,14 @@ import brooklyn.entity.basic.EntityPredicates;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.util.http.HttpTool;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
import org.apache.brooklyn.rest.BrooklynRestApiLauncher;
import org.apache.brooklyn.rest.BrooklynRestApiLauncherTestFixture;
import org.apache.brooklyn.rest.testing.mocks.RestMockSimpleEntity;
import org.apache.brooklyn.test.HttpTestUtils;
import brooklyn.util.collections.MutableList;
-import brooklyn.util.http.HttpTool;
-import brooklyn.util.http.HttpToolResponse;
import brooklyn.util.net.Urls;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/ServerResourceIntegrationTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/ServerResourceIntegrationTest.java b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/ServerResourceIntegrationTest.java
index c228b95..0dcfd44 100644
--- a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/ServerResourceIntegrationTest.java
+++ b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/ServerResourceIntegrationTest.java
@@ -18,7 +18,7 @@
*/
package org.apache.brooklyn.rest.resources;
-import static brooklyn.util.http.HttpTool.httpClientBuilder;
+import static org.apache.brooklyn.core.util.http.HttpTool.httpClientBuilder;
import static org.testng.Assert.assertEquals;
import java.net.URI;
@@ -37,14 +37,13 @@ import brooklyn.config.BrooklynProperties;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.util.http.HttpTool;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
import org.apache.brooklyn.rest.BrooklynRestApiLauncher;
import org.apache.brooklyn.rest.BrooklynRestApiLauncherTestFixture;
import org.apache.brooklyn.rest.security.provider.TestSecurityProvider;
import org.apache.brooklyn.test.HttpTestUtils;
-import brooklyn.util.http.HttpTool;
-import brooklyn.util.http.HttpToolResponse;
-
import com.google.common.collect.ImmutableMap;
public class ServerResourceIntegrationTest extends BrooklynRestApiLauncherTestFixture {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/rest-server/src/test/java/org/apache/brooklyn/rest/testing/mocks/RestMockSimpleEntity.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/testing/mocks/RestMockSimpleEntity.java b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/testing/mocks/RestMockSimpleEntity.java
index 04baadf..1bb5677 100644
--- a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/testing/mocks/RestMockSimpleEntity.java
+++ b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/testing/mocks/RestMockSimpleEntity.java
@@ -23,6 +23,7 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -34,8 +35,8 @@ import brooklyn.entity.basic.MethodEffector;
import brooklyn.entity.basic.SoftwareProcessImpl;
import brooklyn.event.basic.BasicAttributeSensor;
import brooklyn.event.basic.BasicConfigKey;
+
import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.flags.SetFromFlag;
public class RestMockSimpleEntity extends SoftwareProcessImpl {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/rest-server/src/test/java/org/apache/brooklyn/rest/testing/mocks/RestMockSimplePolicy.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/testing/mocks/RestMockSimplePolicy.java b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/testing/mocks/RestMockSimplePolicy.java
index 92d488f..d6e2b77 100644
--- a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/testing/mocks/RestMockSimplePolicy.java
+++ b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/testing/mocks/RestMockSimplePolicy.java
@@ -20,13 +20,13 @@ package org.apache.brooklyn.rest.testing.mocks;
import java.util.Map;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.config.ConfigKey;
import brooklyn.event.basic.BasicConfigKey;
import brooklyn.policy.basic.AbstractPolicy;
-import brooklyn.util.flags.SetFromFlag;
public class RestMockSimplePolicy extends AbstractPolicy {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/usage/rest-server/src/test/java/org/apache/brooklyn/rest/util/json/BrooklynJacksonSerializerTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/util/json/BrooklynJacksonSerializerTest.java b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/util/json/BrooklynJacksonSerializerTest.java
index 642fc10..7968089 100644
--- a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/util/json/BrooklynJacksonSerializerTest.java
+++ b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/util/json/BrooklynJacksonSerializerTest.java
@@ -43,6 +43,7 @@ import brooklyn.entity.basic.Entities;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.util.http.HttpTool;
import org.apache.brooklyn.rest.BrooklynRestApiLauncher;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.test.entity.TestApplication;
@@ -51,7 +52,6 @@ import org.apache.brooklyn.test.entity.TestEntity;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.http.HttpTool;
import brooklyn.util.stream.Streams;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/utils/jmx/jmxmp-ssl-agent/src/test/java/brooklyn/util/jmx/jmxmp/JmxmpAgentSslTest.java
----------------------------------------------------------------------
diff --git a/utils/jmx/jmxmp-ssl-agent/src/test/java/brooklyn/util/jmx/jmxmp/JmxmpAgentSslTest.java b/utils/jmx/jmxmp-ssl-agent/src/test/java/brooklyn/util/jmx/jmxmp/JmxmpAgentSslTest.java
index c0f78ac..771ba6d 100644
--- a/utils/jmx/jmxmp-ssl-agent/src/test/java/brooklyn/util/jmx/jmxmp/JmxmpAgentSslTest.java
+++ b/utils/jmx/jmxmp-ssl-agent/src/test/java/brooklyn/util/jmx/jmxmp/JmxmpAgentSslTest.java
@@ -34,15 +34,14 @@ import java.util.Properties;
import javax.management.remote.JMXConnectorServer;
+import org.apache.brooklyn.core.util.crypto.FluentKeySigner;
+import org.apache.brooklyn.core.util.crypto.SecureKeys;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
-import brooklyn.util.crypto.FluentKeySigner;
-import brooklyn.util.crypto.SecureKeys;
-
public class JmxmpAgentSslTest {
KeyPair caRootKey;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/utils/jmx/jmxmp-ssl-agent/src/test/java/brooklyn/util/jmx/jmxmp/JmxmpClient.java
----------------------------------------------------------------------
diff --git a/utils/jmx/jmxmp-ssl-agent/src/test/java/brooklyn/util/jmx/jmxmp/JmxmpClient.java b/utils/jmx/jmxmp-ssl-agent/src/test/java/brooklyn/util/jmx/jmxmp/JmxmpClient.java
index d8fc178..3896631 100644
--- a/utils/jmx/jmxmp-ssl-agent/src/test/java/brooklyn/util/jmx/jmxmp/JmxmpClient.java
+++ b/utils/jmx/jmxmp-ssl-agent/src/test/java/brooklyn/util/jmx/jmxmp/JmxmpClient.java
@@ -40,7 +40,8 @@ import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
-import brooklyn.util.crypto.SecureKeys;
+import org.apache.brooklyn.core.util.crypto.SecureKeys;
+
import brooklyn.util.crypto.SslTrustUtils;
@SuppressWarnings({"rawtypes","unchecked"})
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/utils/test-bundles/entities/src/main/java/brooklyn/osgi/tests/SimpleLocation.java
----------------------------------------------------------------------
diff --git a/utils/test-bundles/entities/src/main/java/brooklyn/osgi/tests/SimpleLocation.java b/utils/test-bundles/entities/src/main/java/brooklyn/osgi/tests/SimpleLocation.java
index bf64795..9817017 100644
--- a/utils/test-bundles/entities/src/main/java/brooklyn/osgi/tests/SimpleLocation.java
+++ b/utils/test-bundles/entities/src/main/java/brooklyn/osgi/tests/SimpleLocation.java
@@ -20,8 +20,9 @@ package brooklyn.osgi.tests;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
+
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.location.basic.AbstractLocation;
-import brooklyn.util.flags.SetFromFlag;
public class SimpleLocation extends AbstractLocation {
@SetFromFlag("config1")
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/utils/test-bundles/entities/src/main/java/brooklyn/osgi/tests/SimplePolicy.java
----------------------------------------------------------------------
diff --git a/utils/test-bundles/entities/src/main/java/brooklyn/osgi/tests/SimplePolicy.java b/utils/test-bundles/entities/src/main/java/brooklyn/osgi/tests/SimplePolicy.java
index 10a0094..f70b60b 100644
--- a/utils/test-bundles/entities/src/main/java/brooklyn/osgi/tests/SimplePolicy.java
+++ b/utils/test-bundles/entities/src/main/java/brooklyn/osgi/tests/SimplePolicy.java
@@ -19,10 +19,11 @@
package brooklyn.osgi.tests;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
+
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.config.ConfigKey;
import brooklyn.policy.basic.AbstractPolicy;
-import brooklyn.util.flags.SetFromFlag;
public class SimplePolicy extends AbstractPolicy {
@SetFromFlag("config1")
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/utils/test-bundles/more-entities-v1/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
----------------------------------------------------------------------
diff --git a/utils/test-bundles/more-entities-v1/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java b/utils/test-bundles/more-entities-v1/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
index 80d6b97..ece1b1e 100644
--- a/utils/test-bundles/more-entities-v1/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
+++ b/utils/test-bundles/more-entities-v1/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
@@ -18,9 +18,10 @@
*/
package brooklyn.osgi.tests.more;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+
import brooklyn.entity.basic.AbstractEntity;
import brooklyn.entity.effector.EffectorBody;
-import brooklyn.util.config.ConfigBag;
public class MoreEntityImpl extends AbstractEntity implements MoreEntity {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/utils/test-bundles/more-entities-v2-evil-twin/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
----------------------------------------------------------------------
diff --git a/utils/test-bundles/more-entities-v2-evil-twin/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java b/utils/test-bundles/more-entities-v2-evil-twin/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
index 238d743..3dd4059 100644
--- a/utils/test-bundles/more-entities-v2-evil-twin/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
+++ b/utils/test-bundles/more-entities-v2-evil-twin/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
@@ -21,7 +21,7 @@ package brooklyn.osgi.tests.more;
import brooklyn.entity.basic.AbstractEntity;
import brooklyn.entity.effector.EffectorBody;
import org.apache.brooklyn.api.policy.PolicySpec;
-import brooklyn.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.config.ConfigBag;
public class MoreEntityImpl extends AbstractEntity implements MoreEntity {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/utils/test-bundles/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
----------------------------------------------------------------------
diff --git a/utils/test-bundles/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java b/utils/test-bundles/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
index 327fd23..e560b54 100644
--- a/utils/test-bundles/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
+++ b/utils/test-bundles/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
@@ -21,7 +21,7 @@ package brooklyn.osgi.tests.more;
import brooklyn.entity.basic.AbstractEntity;
import brooklyn.entity.effector.EffectorBody;
import org.apache.brooklyn.api.policy.PolicySpec;
-import brooklyn.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.config.ConfigBag;
public class MoreEntityImpl extends AbstractEntity implements MoreEntity {
[11/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/osgi/OsgisTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/osgi/OsgisTest.java b/core/src/test/java/org/apache/brooklyn/core/util/osgi/OsgisTest.java
new file mode 100644
index 0000000..cdaf433
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/osgi/OsgisTest.java
@@ -0,0 +1,41 @@
+/*
+ * 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.util.osgi;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+
+import org.apache.brooklyn.core.util.osgi.Osgis;
+import org.apache.brooklyn.core.util.osgi.Osgis.VersionedName;
+import org.osgi.framework.Version;
+import org.testng.annotations.Test;
+
+public class OsgisTest {
+
+ @Test
+ public void testParseOsgiIdentifier() throws Exception {
+ assertEquals(Osgis.parseOsgiIdentifier("a.b").get(), new VersionedName("a.b", null));
+ assertEquals(Osgis.parseOsgiIdentifier("a.b:0.1.2").get(), new VersionedName("a.b", Version.parseVersion("0.1.2")));
+ assertEquals(Osgis.parseOsgiIdentifier("a.b:0.0.0.SNAPSHOT").get(), new VersionedName("a.b", Version.parseVersion("0.0.0.SNAPSHOT")));
+ assertFalse(Osgis.parseOsgiIdentifier("a.b:0.notanumber.2").isPresent()); // invalid version
+ assertFalse(Osgis.parseOsgiIdentifier("a.b:0.1.2:3.4.5").isPresent()); // too many colons
+ assertFalse(Osgis.parseOsgiIdentifier("a.b:0.0.0_SNAPSHOT").isPresent()); // invalid version
+ assertFalse(Osgis.parseOsgiIdentifier("").isPresent());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/ssh/BashCommandsIntegrationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/ssh/BashCommandsIntegrationTest.java b/core/src/test/java/org/apache/brooklyn/core/util/ssh/BashCommandsIntegrationTest.java
new file mode 100644
index 0000000..77f91f6
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/ssh/BashCommandsIntegrationTest.java
@@ -0,0 +1,504 @@
+/*
+ * 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.util.ssh;
+
+import static brooklyn.util.ssh.BashCommands.sudo;
+import static java.lang.String.format;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.util.task.BasicExecutionContext;
+import org.apache.brooklyn.core.util.task.ssh.SshTasks;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
+import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
+import org.apache.commons.io.FileUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.basic.Entities;
+
+import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
+import org.apache.brooklyn.location.basic.SshMachineLocation;
+
+import brooklyn.util.javalang.JavaClassNames;
+import brooklyn.util.net.Networking;
+import brooklyn.util.os.Os;
+import brooklyn.util.ssh.BashCommands;
+import brooklyn.util.text.Identifiers;
+import brooklyn.util.text.Strings;
+import brooklyn.util.time.Duration;
+
+import com.google.common.base.Charsets;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.io.Files;
+
+public class BashCommandsIntegrationTest {
+
+ private static final Logger log = LoggerFactory.getLogger(BashCommandsIntegrationTest.class);
+
+ private ManagementContext mgmt;
+ private BasicExecutionContext exec;
+
+ private File destFile;
+ private File sourceNonExistantFile;
+ private File sourceFile1;
+ private File sourceFile2;
+ private String sourceNonExistantFileUrl;
+ private String sourceFileUrl1;
+ private String sourceFileUrl2;
+ private SshMachineLocation loc;
+
+ private String localRepoFilename = "localrepofile.txt";
+ private File localRepoBasePath;
+ private File localRepoEntityBasePath;
+ private String localRepoEntityVersionPath;
+ private File localRepoEntityFile;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ mgmt = new LocalManagementContextForTests();
+ exec = new BasicExecutionContext(mgmt.getExecutionManager());
+
+ destFile = Os.newTempFile(getClass(), "commoncommands-test-dest.txt");
+
+ sourceNonExistantFile = new File("/this/does/not/exist/ERQBETJJIG1234");
+ sourceNonExistantFileUrl = sourceNonExistantFile.toURI().toString();
+
+ sourceFile1 = Os.newTempFile(getClass(), "commoncommands-test.txt");
+ sourceFileUrl1 = sourceFile1.toURI().toString();
+ Files.write("mysource1".getBytes(), sourceFile1);
+
+ sourceFile2 = Os.newTempFile(getClass(), "commoncommands-test2.txt");
+ sourceFileUrl2 = sourceFile2.toURI().toString();
+ Files.write("mysource2".getBytes(), sourceFile2);
+
+ localRepoEntityVersionPath = JavaClassNames.simpleClassName(this)+"-test-dest-"+Identifiers.makeRandomId(8);
+ localRepoBasePath = new File(format("%s/.brooklyn/repository", System.getProperty("user.home")));
+ localRepoEntityBasePath = new File(localRepoBasePath, localRepoEntityVersionPath);
+ localRepoEntityFile = new File(localRepoEntityBasePath, localRepoFilename);
+ localRepoEntityBasePath.mkdirs();
+ Files.write("mylocal1".getBytes(), localRepoEntityFile);
+
+ loc = mgmt.getLocationManager().createLocation(LocalhostMachineProvisioningLocation.spec()).obtain();
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ if (sourceFile1 != null) sourceFile1.delete();
+ if (sourceFile2 != null) sourceFile2.delete();
+ if (destFile != null) destFile.delete();
+ if (localRepoEntityFile != null) localRepoEntityFile.delete();
+ if (localRepoEntityBasePath != null) FileUtils.deleteDirectory(localRepoEntityBasePath);
+ if (loc != null) loc.close();
+ if (mgmt != null) Entities.destroyAll(mgmt);
+ }
+
+ @Test(groups="Integration")
+ public void testSudo() throws Exception {
+ ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+ ByteArrayOutputStream errStream = new ByteArrayOutputStream();
+ String cmd = sudo("whoami");
+ int exitcode = loc.execCommands(ImmutableMap.of("out", outStream, "err", errStream), "test", ImmutableList.of(cmd));
+ String outstr = new String(outStream.toByteArray());
+ String errstr = new String(errStream.toByteArray());
+
+ assertEquals(exitcode, 0, "out="+outstr+"; err="+errstr);
+ assertTrue(outstr.contains("root"), "out="+outstr+"; err="+errstr);
+ }
+
+ public void testDownloadUrl() throws Exception {
+ List<String> cmds = BashCommands.commandsToDownloadUrlsAs(
+ ImmutableList.of(sourceFileUrl1),
+ destFile.getAbsolutePath());
+ int exitcode = loc.execCommands("test", cmds);
+
+ assertEquals(0, exitcode);
+ assertEquals(Files.readLines(destFile, Charsets.UTF_8), ImmutableList.of("mysource1"));
+ }
+
+ @Test(groups="Integration")
+ public void testDownloadFirstSuccessfulFile() throws Exception {
+ List<String> cmds = BashCommands.commandsToDownloadUrlsAs(
+ ImmutableList.of(sourceNonExistantFileUrl, sourceFileUrl1, sourceFileUrl2),
+ destFile.getAbsolutePath());
+ int exitcode = loc.execCommands("test", cmds);
+
+ assertEquals(0, exitcode);
+ assertEquals(Files.readLines(destFile, Charsets.UTF_8), ImmutableList.of("mysource1"));
+ }
+
+ @Test(groups="Integration")
+ public void testDownloadToStdout() throws Exception {
+ ProcessTaskWrapper<String> t = SshTasks.newSshExecTaskFactory(loc,
+ "cd "+destFile.getParentFile().getAbsolutePath(),
+ BashCommands.downloadToStdout(Arrays.asList(sourceFileUrl1))+" | sed s/my/your/")
+ .requiringZeroAndReturningStdout().newTask();
+
+ String result = exec.submit(t).get();
+ assertTrue(result.trim().equals("yoursource1"), "Wrong contents of stdout download: "+result);
+ }
+
+ @Test(groups="Integration")
+ public void testAlternativesWhereFirstSucceeds() throws Exception {
+ ProcessTaskWrapper<Integer> t = SshTasks.newSshExecTaskFactory(loc)
+ .add(BashCommands.alternatives(Arrays.asList("echo first", "exit 88")))
+ .newTask();
+
+ Integer returnCode = exec.submit(t).get();
+ String stdout = t.getStdout();
+ String stderr = t.getStderr();
+ log.info("alternatives for good first command gave: "+returnCode+"; err="+stderr+"; out="+stdout);
+ assertTrue(stdout.contains("first"), "errcode="+returnCode+"; stdout="+stdout+"; stderr="+stderr);
+ assertEquals(returnCode, (Integer)0);
+ }
+
+ @Test(groups="Integration")
+ public void testAlternatives() throws Exception {
+ ProcessTaskWrapper<Integer> t = SshTasks.newSshExecTaskFactory(loc)
+ .add(BashCommands.alternatives(Arrays.asList("asdfj_no_such_command_1", "exit 88")))
+ .newTask();
+
+ Integer returnCode = exec.submit(t).get();
+ log.info("alternatives for bad commands gave: "+returnCode+"; err="+new String(t.getStderr())+"; out="+new String(t.getStdout()));
+ assertEquals(returnCode, (Integer)88);
+ }
+
+ @Test(groups="Integration")
+ public void testRequireTestHandlesFailure() throws Exception {
+ ProcessTaskWrapper<?> t = SshTasks.newSshExecTaskFactory(loc)
+ .add(BashCommands.requireTest("-f "+sourceNonExistantFile.getPath(),
+ "The requested file does not exist")).newTask();
+
+ exec.submit(t).get();
+ assertNotEquals(t.getExitCode(), (Integer)0);
+ assertTrue(t.getStderr().contains("The requested file"), "Expected message in: "+t.getStderr());
+ assertTrue(t.getStdout().contains("The requested file"), "Expected message in: "+t.getStdout());
+ }
+
+ @Test(groups="Integration")
+ public void testRequireTestHandlesSuccess() throws Exception {
+ ProcessTaskWrapper<?> t = SshTasks.newSshExecTaskFactory(loc)
+ .add(BashCommands.requireTest("-f "+sourceFile1.getPath(),
+ "The requested file does not exist")).newTask();
+
+ exec.submit(t).get();
+ assertEquals(t.getExitCode(), (Integer)0);
+ assertTrue(t.getStderr().equals(""), "Expected no stderr messages, but got: "+t.getStderr());
+ }
+
+ @Test(groups="Integration")
+ public void testRequireFileHandlesFailure() throws Exception {
+ ProcessTaskWrapper<?> t = SshTasks.newSshExecTaskFactory(loc)
+ .add(BashCommands.requireFile(sourceNonExistantFile.getPath())).newTask();
+
+ exec.submit(t).get();
+ assertNotEquals(t.getExitCode(), (Integer)0);
+ assertTrue(t.getStderr().contains("required file"), "Expected message in: "+t.getStderr());
+ assertTrue(t.getStderr().contains(sourceNonExistantFile.getPath()), "Expected message in: "+t.getStderr());
+ assertTrue(t.getStdout().contains("required file"), "Expected message in: "+t.getStdout());
+ assertTrue(t.getStdout().contains(sourceNonExistantFile.getPath()), "Expected message in: "+t.getStdout());
+ }
+
+ @Test(groups="Integration")
+ public void testRequireFileHandlesSuccess() throws Exception {
+ ProcessTaskWrapper<?> t = SshTasks.newSshExecTaskFactory(loc)
+ .add(BashCommands.requireFile(sourceFile1.getPath())).newTask();
+
+ exec.submit(t).get();
+ assertEquals(t.getExitCode(), (Integer)0);
+ assertTrue(t.getStderr().equals(""), "Expected no stderr messages, but got: "+t.getStderr());
+ }
+
+ @Test(groups="Integration")
+ public void testRequireFailureExitsImmediately() throws Exception {
+ ProcessTaskWrapper<?> t = SshTasks.newSshExecTaskFactory(loc)
+ .add(BashCommands.requireTest("-f "+sourceNonExistantFile.getPath(),
+ "The requested file does not exist"))
+ .add("echo shouldnae come here").newTask();
+
+ exec.submit(t).get();
+ assertNotEquals(t.getExitCode(), (Integer)0);
+ assertTrue(t.getStderr().contains("The requested file"), "Expected message in: "+t.getStderr());
+ assertTrue(t.getStdout().contains("The requested file"), "Expected message in: "+t.getStdout());
+ Assert.assertFalse(t.getStdout().contains("shouldnae"), "Expected message in: "+t.getStdout());
+ }
+
+ @Test(groups="Integration")
+ public void testPipeMultiline() throws Exception {
+ String output = execRequiringZeroAndReturningStdout(loc,
+ BashCommands.pipeTextTo("hello world\n"+"and goodbye\n", "wc")).get();
+
+ assertEquals(Strings.replaceAllRegex(output, "\\s+", " ").trim(), "3 4 25");
+ }
+
+ @Test(groups="Integration")
+ public void testWaitForFileContentsWhenAbortingOnFail() throws Exception {
+ String fileContent = "mycontents";
+ String cmd = BashCommands.waitForFileContents(destFile.getAbsolutePath(), fileContent, Duration.ONE_SECOND, true);
+
+ int exitcode = loc.execCommands("test", ImmutableList.of(cmd));
+ assertEquals(exitcode, 1);
+
+ Files.write(fileContent, destFile, Charsets.UTF_8);
+ int exitcode2 = loc.execCommands("test", ImmutableList.of(cmd));
+ assertEquals(exitcode2, 0);
+ }
+
+ @Test(groups="Integration")
+ public void testWaitForFileContentsWhenNotAbortingOnFail() throws Exception {
+ String fileContent = "mycontents";
+ String cmd = BashCommands.waitForFileContents(destFile.getAbsolutePath(), fileContent, Duration.ONE_SECOND, false);
+
+ String output = execRequiringZeroAndReturningStdout(loc, cmd).get();
+ assertTrue(output.contains("Couldn't find"), "output="+output);
+
+ Files.write(fileContent, destFile, Charsets.UTF_8);
+ String output2 = execRequiringZeroAndReturningStdout(loc, cmd).get();
+ assertFalse(output2.contains("Couldn't find"), "output="+output2);
+ }
+
+ @Test(groups="Integration")
+ public void testWaitForFileContentsWhenContentsAppearAfterStart() throws Exception {
+ String fileContent = "mycontents";
+
+ String cmd = BashCommands.waitForFileContents(destFile.getAbsolutePath(), fileContent, Duration.THIRTY_SECONDS, false);
+ ProcessTaskWrapper<String> t = execRequiringZeroAndReturningStdout(loc, cmd);
+ exec.submit(t);
+
+ // sleep for long enough to ensure the ssh command is definitely executing
+ Thread.sleep(5*1000);
+ assertFalse(t.isDone());
+
+ Files.write(fileContent, destFile, Charsets.UTF_8);
+ String output = t.get();
+ assertFalse(output.contains("Couldn't find"), "output="+output);
+ }
+
+ @Test(groups="Integration", dependsOnMethods="testSudo")
+ public void testWaitForPortFreeWhenAbortingOnTimeout() throws Exception {
+ ServerSocket serverSocket = openServerSocket();
+ try {
+ int port = serverSocket.getLocalPort();
+ String cmd = BashCommands.waitForPortFree(port, Duration.ONE_SECOND, true);
+
+ int exitcode = loc.execCommands("test", ImmutableList.of(cmd));
+ assertEquals(exitcode, 1);
+
+ serverSocket.close();
+ assertTrue(Networking.isPortAvailable(port));
+ int exitcode2 = loc.execCommands("test", ImmutableList.of(cmd));
+ assertEquals(exitcode2, 0);
+ } finally {
+ serverSocket.close();
+ }
+ }
+
+ @Test(groups="Integration", dependsOnMethods="testSudo")
+ public void testWaitForPortFreeWhenNotAbortingOnTimeout() throws Exception {
+ ServerSocket serverSocket = openServerSocket();
+ try {
+ int port = serverSocket.getLocalPort();
+ String cmd = BashCommands.waitForPortFree(port, Duration.ONE_SECOND, false);
+
+ String output = execRequiringZeroAndReturningStdout(loc, cmd).get();
+ assertTrue(output.contains(port+" still in use"), "output="+output);
+
+ serverSocket.close();
+ assertTrue(Networking.isPortAvailable(port));
+ String output2 = execRequiringZeroAndReturningStdout(loc, cmd).get();
+ assertFalse(output2.contains("still in use"), "output="+output2);
+ } finally {
+ serverSocket.close();
+ }
+ }
+
+ @Test(groups="Integration", dependsOnMethods="testSudo")
+ public void testWaitForPortFreeWhenFreedAfterStart() throws Exception {
+ ServerSocket serverSocket = openServerSocket();
+ try {
+ int port = serverSocket.getLocalPort();
+
+ String cmd = BashCommands.waitForPortFree(port, Duration.THIRTY_SECONDS, false);
+ ProcessTaskWrapper<String> t = execRequiringZeroAndReturningStdout(loc, cmd);
+ exec.submit(t);
+
+ // sleep for long enough to ensure the ssh command is definitely executing
+ Thread.sleep(5*1000);
+ assertFalse(t.isDone());
+
+ serverSocket.close();
+ assertTrue(Networking.isPortAvailable(port));
+ String output = t.get();
+ assertFalse(output.contains("still in use"), "output="+output);
+ } finally {
+ serverSocket.close();
+ }
+ }
+
+
+ // Disabled by default because of risk of overriding /etc/hosts in really bad way if doesn't work properly!
+ // As a manual visual inspection test, consider first manually creating /etc/hostname and /etc/sysconfig/network
+ // so that it looks like debian+ubuntu / CentOS/RHEL.
+ @Test(groups={"Integration"}, enabled=false)
+ public void testSetHostnameUnqualified() throws Exception {
+ runSetHostname("br-"+Identifiers.makeRandomId(8).toLowerCase(), null, false);
+ }
+
+ @Test(groups={"Integration"}, enabled=false)
+ public void testSetHostnameQualified() throws Exception {
+ runSetHostname("br-"+Identifiers.makeRandomId(8).toLowerCase()+".brooklyn.incubator.apache.org", null, false);
+ }
+
+ @Test(groups={"Integration"}, enabled=false)
+ public void testSetHostnameNullDomain() throws Exception {
+ runSetHostname("br-"+Identifiers.makeRandomId(8).toLowerCase(), null, true);
+ }
+
+ @Test(groups={"Integration"}, enabled=false)
+ public void testSetHostnameNonNullDomain() throws Exception {
+ runSetHostname("br-"+Identifiers.makeRandomId(8).toLowerCase(), "brooklyn.incubator.apache.org", true);
+ }
+
+ protected void runSetHostname(String newHostname, String newDomain, boolean includeDomain) throws Exception {
+ String fqdn = (includeDomain && Strings.isNonBlank(newDomain)) ? newHostname + "." + newDomain : newHostname;
+
+ LocalManagementContextForTests mgmt = new LocalManagementContextForTests();
+ SshMachineLocation loc = mgmt.getLocationManager().createLocation(LocalhostMachineProvisioningLocation.spec()).obtain();
+
+ execRequiringZeroAndReturningStdout(loc, sudo("cp /etc/hosts /etc/hosts-orig-testSetHostname")).get();
+ execRequiringZeroAndReturningStdout(loc, BashCommands.ifFileExistsElse0("/etc/hostname", sudo("cp /etc/hostname /etc/hostname-orig-testSetHostname"))).get();
+ execRequiringZeroAndReturningStdout(loc, BashCommands.ifFileExistsElse0("/etc/sysconfig/network", sudo("cp /etc/sysconfig/network /etc/sysconfig/network-orig-testSetHostname"))).get();
+
+ String origHostname = getHostnameNoArgs(loc);
+ assertTrue(Strings.isNonBlank(origHostname));
+
+ try {
+ List<String> cmd = (includeDomain) ? BashCommands.setHostname(newHostname, newDomain) : BashCommands.setHostname(newHostname);
+ execRequiringZeroAndReturningStdout(loc, cmd).get();
+
+ String actualHostnameUnqualified = getHostnameUnqualified(loc);
+ String actualHostnameFullyQualified = getHostnameFullyQualified(loc);
+
+ // TODO On OS X at least, we aren't actually setting the domain name; we're just letting
+ // the user pass in what the domain name is. We do add this properly to /etc/hosts
+ // (e.g. first line is "127.0.0.1 br-g4x5wgx8.brooklyn.incubator.apache.org br-g4x5wgx8 localhost")
+ // but subsequent calls to `hostname -f` returns the unqualified. Similarly, `domainname`
+ // returns blank. Therefore we can't assert that it equals our expected val (because we just made
+ // it up - "brooklyn.incubator.apache.org").
+ // assertEquals(actualHostnameFullyQualified, fqdn);
+ assertEquals(actualHostnameUnqualified, Strings.getFragmentBetween(newHostname, null, "."));
+ execRequiringZeroAndReturningStdout(loc, "ping -c1 -n -q "+actualHostnameUnqualified).get();
+ execRequiringZeroAndReturningStdout(loc, "ping -c1 -n -q "+actualHostnameFullyQualified).get();
+
+ String result = execRequiringZeroAndReturningStdout(loc, "grep -n "+fqdn+" /etc/hosts").get();
+ assertTrue(result.contains("localhost"), "line="+result);
+ log.info("result="+result);
+
+ } finally {
+ execRequiringZeroAndReturningStdout(loc, sudo("cp /etc/hosts-orig-testSetHostname /etc/hosts")).get();
+ execRequiringZeroAndReturningStdout(loc, BashCommands.ifFileExistsElse0("/etc/hostname-orig-testSetHostname", sudo("cp /etc/hostname-orig-testSetHostname /etc/hostname"))).get();
+ execRequiringZeroAndReturningStdout(loc, BashCommands.ifFileExistsElse0("/etc/sysconfig/network-orig-testSetHostname", sudo("cp /etc/sysconfig/network-orig-testSetHostname /etc/sysconfig/network"))).get();
+ execRequiringZeroAndReturningStdout(loc, sudo("hostname "+origHostname)).get();
+ }
+ }
+
+ // Marked disabled because not safe to run on your normal machine! It modifies /etc/hosts, which is dangerous if things go wrong!
+ @Test(groups={"Integration"}, enabled=false)
+ public void testModifyEtcHosts() throws Exception {
+ LocalManagementContextForTests mgmt = new LocalManagementContextForTests();
+ SshMachineLocation loc = mgmt.getLocationManager().createLocation(LocalhostMachineProvisioningLocation.spec()).obtain();
+
+ execRequiringZeroAndReturningStdout(loc, sudo("cp /etc/hosts /etc/hosts-orig-testModifyEtcHosts")).get();
+ int numLinesOrig = Integer.parseInt(execRequiringZeroAndReturningStdout(loc, "wc -l /etc/hosts").get().trim().split("\\s")[0]);
+
+ try {
+ String cmd = BashCommands.prependToEtcHosts("1.2.3.4", "myhostnamefor1234.at.start", "myhostnamefor1234b");
+ execRequiringZeroAndReturningStdout(loc, cmd).get();
+
+ String cmd2 = BashCommands.appendToEtcHosts("5.6.7.8", "myhostnamefor5678.at.end", "myhostnamefor5678");
+ execRequiringZeroAndReturningStdout(loc, cmd2).get();
+
+ String grepFirst = execRequiringZeroAndReturningStdout(loc, "grep -n myhostnamefor1234 /etc/hosts").get();
+ String grepLast = execRequiringZeroAndReturningStdout(loc, "grep -n myhostnamefor5678 /etc/hosts").get();
+ int numLinesAfter = Integer.parseInt(execRequiringZeroAndReturningStdout(loc, "wc -l /etc/hosts").get().trim().split("\\s")[0]);
+ log.info("result: numLinesBefore="+numLinesOrig+"; numLinesAfter="+numLinesAfter+"; first="+grepFirst+"; last="+grepLast);
+
+ assertTrue(grepFirst.startsWith("1:") && grepFirst.contains("1.2.3.4 myhostnamefor1234.at.start myhostnamefor1234"), "first="+grepFirst);
+ assertTrue(grepLast.startsWith((numLinesOrig+2)+":") && grepLast.contains("5.6.7.8 myhostnamefor5678.at.end myhostnamefor5678"), "last="+grepLast);
+ assertEquals(numLinesOrig + 2, numLinesAfter, "lines orig="+numLinesOrig+", after="+numLinesAfter);
+ } finally {
+ execRequiringZeroAndReturningStdout(loc, sudo("cp /etc/hosts-orig-testModifyEtcHosts /etc/hosts")).get();
+ }
+ }
+
+ private String getHostnameNoArgs(SshMachineLocation machine) {
+ String hostnameStdout = execRequiringZeroAndReturningStdout(machine, "echo FOREMARKER; hostname; echo AFTMARKER").get();
+ return Strings.getFragmentBetween(hostnameStdout, "FOREMARKER", "AFTMARKER").trim();
+ }
+
+ private String getHostnameUnqualified(SshMachineLocation machine) {
+ String hostnameStdout = execRequiringZeroAndReturningStdout(machine, "echo FOREMARKER; hostname -s 2> /dev/null || hostname; echo AFTMARKER").get();
+ return Strings.getFragmentBetween(hostnameStdout, "FOREMARKER", "AFTMARKER").trim();
+ }
+
+ private String getHostnameFullyQualified(SshMachineLocation machine) {
+ String hostnameStdout = execRequiringZeroAndReturningStdout(machine, "echo FOREMARKER; hostname --fqdn 2> /dev/null || hostname -f; echo AFTMARKER").get();
+ return Strings.getFragmentBetween(hostnameStdout, "FOREMARKER", "AFTMARKER").trim();
+ }
+
+ private ProcessTaskWrapper<String> execRequiringZeroAndReturningStdout(SshMachineLocation loc, Collection<String> cmds) {
+ return execRequiringZeroAndReturningStdout(loc, cmds.toArray(new String[cmds.size()]));
+ }
+
+ private ProcessTaskWrapper<String> execRequiringZeroAndReturningStdout(SshMachineLocation loc, String... cmds) {
+ ProcessTaskWrapper<String> t = SshTasks.newSshExecTaskFactory(loc, cmds)
+ .requiringZeroAndReturningStdout().newTask();
+ exec.submit(t);
+ return t;
+ }
+
+ private ServerSocket openServerSocket() {
+ int lowerBound = 40000;
+ int upperBound = 40100;
+ for (int i = lowerBound; i < upperBound; i++) {
+ try {
+ return new ServerSocket(i);
+ } catch (IOException e) {
+ // try next number
+ }
+ }
+ throw new IllegalStateException("No ports available in range "+lowerBound+" to "+upperBound);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/task/BasicTaskExecutionPerformanceTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/task/BasicTaskExecutionPerformanceTest.java b/core/src/test/java/org/apache/brooklyn/core/util/task/BasicTaskExecutionPerformanceTest.java
new file mode 100644
index 0000000..71d2586
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/task/BasicTaskExecutionPerformanceTest.java
@@ -0,0 +1,209 @@
+/*
+ * 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.util.task;
+
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.task.BasicExecutionManager;
+import org.apache.brooklyn.core.util.task.BasicTask;
+import org.apache.brooklyn.core.util.task.ScheduledTask;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.util.collections.MutableMap;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Stopwatch;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.Callables;
+
+/**
+ * Test the operation of the {@link BasicTask} class.
+ *
+ * TODO clarify test purpose
+ */
+public class BasicTaskExecutionPerformanceTest {
+ private static final Logger log = LoggerFactory.getLogger(BasicTaskExecutionPerformanceTest.class);
+
+ private static final int TIMEOUT_MS = 10*1000;
+
+ private BasicExecutionManager em;
+
+ public static final int MAX_OVERHEAD_MS = 1500; // was 750ms but saw 1.3s on buildhive
+ public static final int EARLY_RETURN_GRACE = 25; // saw 13ms early return on jenkins!
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ em = new BasicExecutionManager("mycontext");
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ if (em != null) em.shutdownNow();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testScheduledTaskExecutedAfterDelay() throws Exception {
+ int delay = 100;
+ final CountDownLatch latch = new CountDownLatch(1);
+
+ Callable<Task<?>> taskFactory = new Callable<Task<?>>() {
+ @Override public Task<?> call() {
+ return new BasicTask<Void>(new Runnable() {
+ @Override public void run() {
+ latch.countDown();
+ }});
+ }};
+ ScheduledTask t = new ScheduledTask(taskFactory).delay(delay);
+
+ Stopwatch stopwatch = Stopwatch.createStarted();
+ em.submit(t);
+
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ long actualDelay = stopwatch.elapsed(TimeUnit.MILLISECONDS);
+
+ assertTrue(actualDelay > (delay-EARLY_RETURN_GRACE), "actualDelay="+actualDelay+"; delay="+delay);
+ assertTrue(actualDelay < (delay+MAX_OVERHEAD_MS), "actualDelay="+actualDelay+"; delay="+delay);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testScheduledTaskExecutedAtRegularPeriod() throws Exception {
+ final int period = 100;
+ final int numTimestamps = 4;
+ final CountDownLatch latch = new CountDownLatch(1);
+ final List<Long> timestamps = Collections.synchronizedList(Lists.<Long>newArrayList());
+ final Stopwatch stopwatch = Stopwatch.createStarted();
+
+ Callable<Task<?>> taskFactory = new Callable<Task<?>>() {
+ @Override public Task<?> call() {
+ return new BasicTask<Void>(new Runnable() {
+ @Override public void run() {
+ timestamps.add(stopwatch.elapsed(TimeUnit.MILLISECONDS));
+ if (timestamps.size() >= numTimestamps) latch.countDown();
+ }});
+ }};
+ ScheduledTask t = new ScheduledTask(taskFactory).delay(1).period(period);
+ em.submit(t);
+
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ synchronized (timestamps) {
+ long prev = timestamps.get(0);
+ for (long timestamp : timestamps.subList(1, timestamps.size())) {
+ assertTrue(timestamp > prev+period-EARLY_RETURN_GRACE, "timestamps="+timestamps);
+ assertTrue(timestamp < prev+period+MAX_OVERHEAD_MS, "timestamps="+timestamps);
+ prev = timestamp;
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testCanCancelScheduledTask() throws Exception {
+ final int period = 1;
+ final long checkPeriod = 250;
+ final List<Long> timestamps = Collections.synchronizedList(Lists.<Long>newArrayList());
+
+ Callable<Task<?>> taskFactory = new Callable<Task<?>>() {
+ @Override public Task<?> call() {
+ return new BasicTask<Void>(new Runnable() {
+ @Override public void run() {
+ timestamps.add(System.currentTimeMillis());
+ }});
+ }};
+ ScheduledTask t = new ScheduledTask(taskFactory).period(period);
+ em.submit(t);
+
+ t.cancel();
+ long cancelTime = System.currentTimeMillis();
+ int countImmediatelyAfterCancel = timestamps.size();
+ Thread.sleep(checkPeriod);
+ int countWellAfterCancel = timestamps.size();
+
+ // should have at most 1 more execution after cancel
+ log.info("testCanCancelScheduledTask saw "+countImmediatelyAfterCancel+" then cancel then "+countWellAfterCancel+" total");
+ assertTrue(countWellAfterCancel - countImmediatelyAfterCancel <= 2, "timestamps="+timestamps+"; cancelTime="+cancelTime);
+ }
+
+ // Previously, when we used a CopyOnWriteArraySet, performance for submitting new tasks was
+ // terrible, and it degraded significantly as the number of previously executed tasks increased
+ // (e.g. 9s for first 1000; 26s for next 1000; 42s for next 1000).
+ @Test
+ public void testExecutionManagerPerformance() throws Exception {
+ // Was fixed at 1000 tasks, but was running out of virtual memory due to excessive thread creation
+ // on machines which were not able to execute the threads quickly.
+ final int NUM_TASKS = Math.min(500 * Runtime.getRuntime().availableProcessors(), 1000);
+ final int NUM_TIMES = 10;
+ final int MAX_ACCEPTABLE_TIME = 7500; // saw 5601ms on buildhive
+
+ long tWarmup = execTasksAndWaitForDone(NUM_TASKS, ImmutableList.of("A"));
+
+ List<Long> times = Lists.newArrayList();
+ for (int i = 1; i <= NUM_TIMES; i++) {
+ times.add(execTasksAndWaitForDone(NUM_TASKS, ImmutableList.of("A")));
+ }
+
+ Long toobig = Iterables.find(
+ times,
+ new Predicate<Long>() {
+ public boolean apply(Long input) {
+ return input > MAX_ACCEPTABLE_TIME;
+ }},
+ null);
+ assertNull(toobig, "warmup="+tWarmup+"; times="+times);
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ private long execTasksAndWaitForDone(int numTasks, List<?> tags) throws Exception {
+ List<Task<?>> tasks = Lists.newArrayList();
+ long startTimestamp = System.currentTimeMillis();
+ for (int i = 1; i < numTasks; i++) {
+ Task<?> t = new BasicTask(Callables.returning(null)); // no-op
+ em.submit(MutableMap.of("tags", tags), t);
+ tasks.add(t);
+ }
+ long submittedTimestamp = System.currentTimeMillis();
+
+ for (Task t : tasks) {
+ t.get();
+ }
+ long endTimestamp = System.currentTimeMillis();
+ long submitTime = submittedTimestamp - startTimestamp;
+ long totalTime = endTimestamp - startTimestamp;
+
+ log.info("Executed {} tasks; {}ms total; {}ms to submit", new Object[] {numTasks, totalTime, submitTime});
+
+ return totalTime;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/task/BasicTaskExecutionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/task/BasicTaskExecutionTest.java b/core/src/test/java/org/apache/brooklyn/core/util/task/BasicTaskExecutionTest.java
new file mode 100644
index 0000000..c730738
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/task/BasicTaskExecutionTest.java
@@ -0,0 +1,462 @@
+/*
+ * 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.util.task;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.task.BasicExecutionManager;
+import org.apache.brooklyn.core.util.task.BasicTask;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.test.Asserts;
+import brooklyn.util.collections.MutableMap;
+
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.Callables;
+
+/**
+ * Test the operation of the {@link BasicTask} class.
+ *
+ * TODO clarify test purpose
+ */
+public class BasicTaskExecutionTest {
+ private static final Logger log = LoggerFactory.getLogger(BasicTaskExecutionTest.class);
+
+ private static final int TIMEOUT_MS = 10*1000;
+
+ private BasicExecutionManager em;
+ private Map<Object, Object> data;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() {
+ em = new BasicExecutionManager("mycontext");
+ data = Collections.synchronizedMap(new HashMap<Object, Object>());
+ data.clear();
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ if (em != null) em.shutdownNow();
+ if (data != null) data.clear();
+ }
+
+ @Test
+ public void runSimpleBasicTask() throws Exception {
+ BasicTask<Object> t = new BasicTask<Object>(newPutCallable(1, "b"));
+ data.put(1, "a");
+ Task<Object> t2 = em.submit(MutableMap.of("tag", "A"), t);
+ assertEquals("a", t.get());
+ assertEquals("a", t2.get());
+ assertEquals("b", data.get(1));
+ }
+
+ @Test
+ public void runSimpleRunnable() throws Exception {
+ data.put(1, "a");
+ Task<?> t = em.submit(MutableMap.of("tag", "A"), newPutRunnable(1, "b"));
+ assertEquals(null, t.get());
+ assertEquals("b", data.get(1));
+ }
+
+ @Test
+ public void runSimpleCallable() throws Exception {
+ data.put(1, "a");
+ Task<?> t = em.submit(MutableMap.of("tag", "A"), newPutCallable(1, "b"));
+ assertEquals("a", t.get());
+ assertEquals("b", data.get(1));
+ }
+
+ @Test
+ public void runBasicTaskWithWaits() throws Exception {
+ final CountDownLatch signalStarted = new CountDownLatch(1);
+ final CountDownLatch allowCompletion = new CountDownLatch(1);
+ final BasicTask<Object> t = new BasicTask<Object>(new Callable<Object>() {
+ public Object call() throws Exception {
+ Object result = data.put(1, "b");
+ signalStarted.countDown();
+ assertTrue(allowCompletion.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ return result;
+ }});
+ data.put(1, "a");
+
+ Task<?> t2 = em.submit(MutableMap.of("tag", "A"), t);
+ assertEquals(t, t2);
+ assertFalse(t.isDone());
+
+ assertTrue(signalStarted.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertEquals("b", data.get(1));
+ assertFalse(t.isDone());
+
+ log.debug("runBasicTaskWithWaits, BasicTask status: {}", t.getStatusDetail(false));
+
+ Asserts.succeedsEventually(new Runnable() {
+ public void run() {
+ String status = t.getStatusDetail(false);
+ assertTrue(status != null && status.toLowerCase().contains("waiting"), "status="+status);
+ }});
+
+ allowCompletion.countDown();
+ assertEquals("a", t.get());
+ }
+
+ @Test
+ public void runMultipleBasicTasks() throws Exception {
+ data.put(1, 1);
+ BasicExecutionManager em = new BasicExecutionManager("mycontext");
+ for (int i = 0; i < 2; i++) {
+ em.submit(MutableMap.of("tag", "A"), new BasicTask<Integer>(newIncrementCallable(1)));
+ em.submit(MutableMap.of("tag", "B"), new BasicTask<Integer>(newIncrementCallable((1))));
+ }
+ int total = 0;
+ for (Object tag : em.getTaskTags()) {
+ log.debug("tag {}", tag);
+ for (Task<?> task : em.getTasksWithTag(tag)) {
+ log.debug("BasicTask {}, has {}", task, task.get());
+ total += (Integer)task.get();
+ }
+ }
+ assertEquals(10, total);
+ //now that all have completed:
+ assertEquals(5, data.get(1));
+ }
+
+ @Test
+ public void runMultipleBasicTasksMultipleTags() throws Exception {
+ data.put(1, 1);
+ Collection<Task<Integer>> tasks = Lists.newArrayList();
+ tasks.add(em.submit(MutableMap.of("tag", "A"), new BasicTask<Integer>(newIncrementCallable(1))));
+ tasks.add(em.submit(MutableMap.of("tags", ImmutableList.of("A","B")), new BasicTask<Integer>(newIncrementCallable(1))));
+ tasks.add(em.submit(MutableMap.of("tags", ImmutableList.of("B","C")), new BasicTask<Integer>(newIncrementCallable(1))));
+ tasks.add(em.submit(MutableMap.of("tags", ImmutableList.of("D")), new BasicTask<Integer>(newIncrementCallable(1))));
+ int total = 0;
+
+ for (Task<Integer> t : tasks) {
+ log.debug("BasicTask {}, has {}", t, t.get());
+ total += t.get();
+ }
+ assertEquals(10, total);
+
+ //now that all have completed:
+ assertEquals(data.get(1), 5);
+ assertEquals(em.getTasksWithTag("A").size(), 2);
+ assertEquals(em.getTasksWithAnyTag(ImmutableList.of("A")).size(), 2);
+ assertEquals(em.getTasksWithAllTags(ImmutableList.of("A")).size(), 2);
+
+ assertEquals(em.getTasksWithAnyTag(ImmutableList.of("A", "B")).size(), 3);
+ assertEquals(em.getTasksWithAllTags(ImmutableList.of("A", "B")).size(), 1);
+ assertEquals(em.getTasksWithAllTags(ImmutableList.of("B", "C")).size(), 1);
+ assertEquals(em.getTasksWithAnyTag(ImmutableList.of("A", "D")).size(), 3);
+ }
+
+ @Test
+ public void testGetTaskById() throws Exception {
+ Task<?> t = new BasicTask<Void>(newNoop());
+ em.submit(MutableMap.of("tag", "A"), t);
+ assertEquals(em.getTask(t.getId()), t);
+ }
+
+ @Test
+ public void testRetrievingTasksWithTagsReturnsExpectedTask() throws Exception {
+ Task<?> t = new BasicTask<Void>(newNoop());
+ em.submit(MutableMap.of("tag", "A"), t);
+ t.get();
+
+ assertEquals(em.getTasksWithTag("A"), ImmutableList.of(t));
+ assertEquals(em.getTasksWithAnyTag(ImmutableList.of("A")), ImmutableList.of(t));
+ assertEquals(em.getTasksWithAnyTag(ImmutableList.of("A", "B")), ImmutableList.of(t));
+ assertEquals(em.getTasksWithAllTags(ImmutableList.of("A")), ImmutableList.of(t));
+ }
+
+ @Test
+ public void testRetrievingTasksWithTagsExcludesNonMatchingTasks() throws Exception {
+ Task<?> t = new BasicTask<Void>(newNoop());
+ em.submit(MutableMap.of("tag", "A"), t);
+ t.get();
+
+ assertEquals(em.getTasksWithTag("B"), ImmutableSet.of());
+ assertEquals(em.getTasksWithAnyTag(ImmutableList.of("B")), ImmutableSet.of());
+ assertEquals(em.getTasksWithAllTags(ImmutableList.of("A", "B")), ImmutableSet.of());
+ }
+
+ @Test
+ public void testRetrievingTasksWithMultipleTags() throws Exception {
+ Task<?> t = new BasicTask<Void>(newNoop());
+ em.submit(MutableMap.of("tags", ImmutableList.of("A", "B")), t);
+ t.get();
+
+ assertEquals(em.getTasksWithTag("A"), ImmutableList.of(t));
+ assertEquals(em.getTasksWithTag("B"), ImmutableList.of(t));
+ assertEquals(em.getTasksWithAnyTag(ImmutableList.of("A")), ImmutableList.of(t));
+ assertEquals(em.getTasksWithAnyTag(ImmutableList.of("B")), ImmutableList.of(t));
+ assertEquals(em.getTasksWithAnyTag(ImmutableList.of("A", "B")), ImmutableList.of(t));
+ assertEquals(em.getTasksWithAllTags(ImmutableList.of("A", "B")), ImmutableList.of(t));
+ assertEquals(em.getTasksWithAllTags(ImmutableList.of("A")), ImmutableList.of(t));
+ assertEquals(em.getTasksWithAllTags(ImmutableList.of("B")), ImmutableList.of(t));
+ }
+
+ // ENGR-1796: if nothing matched first tag, then returned whatever matched second tag!
+ @Test
+ public void testRetrievingTasksWithAllTagsWhenFirstNotMatched() throws Exception {
+ Task<?> t = new BasicTask<Void>(newNoop());
+ em.submit(MutableMap.of("tags", ImmutableList.of("A")), t);
+ t.get();
+
+ assertEquals(em.getTasksWithAllTags(ImmutableList.of("not_there","A")), ImmutableSet.of());
+ }
+
+ @Test
+ public void testRetrievedTasksIncludesTasksInProgress() throws Exception {
+ final CountDownLatch runningLatch = new CountDownLatch(1);
+ final CountDownLatch finishLatch = new CountDownLatch(1);
+ Task<Void> t = new BasicTask<Void>(new Callable<Void>() {
+ public Void call() throws Exception {
+ runningLatch.countDown();
+ finishLatch.await();
+ return null;
+ }});
+ em.submit(MutableMap.of("tags", ImmutableList.of("A")), t);
+
+ try {
+ runningLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+
+ assertEquals(em.getTasksWithTag("A"), ImmutableList.of(t));
+ } finally {
+ finishLatch.countDown();
+ }
+ }
+
+ @Test
+ public void cancelBeforeRun() throws Exception {
+ final CountDownLatch blockForever = new CountDownLatch(1);
+
+ BasicTask<Integer> t = new BasicTask<Integer>(new Callable<Integer>() {
+ public Integer call() throws Exception {
+ blockForever.await(); return 42;
+ }});
+ t.cancel(true);
+ assertTrue(t.isCancelled());
+ assertTrue(t.isDone());
+ assertTrue(t.isError());
+ em.submit(MutableMap.of("tag", "A"), t);
+ try {
+ t.get();
+ fail("get should have failed due to cancel");
+ } catch (CancellationException e) {
+ // expected
+ }
+ assertTrue(t.isCancelled());
+ assertTrue(t.isDone());
+ assertTrue(t.isError());
+
+ log.debug("cancelBeforeRun status: {}", t.getStatusDetail(false));
+ assertTrue(t.getStatusDetail(false).toLowerCase().contains("cancel"));
+ }
+
+ @Test
+ public void cancelDuringRun() throws Exception {
+ final CountDownLatch signalStarted = new CountDownLatch(1);
+ final CountDownLatch blockForever = new CountDownLatch(1);
+
+ BasicTask<Integer> t = new BasicTask<Integer>(new Callable<Integer>() {
+ public Integer call() throws Exception {
+ synchronized (data) {
+ signalStarted.countDown();
+ blockForever.await();
+ }
+ return 42;
+ }});
+ em.submit(MutableMap.of("tag", "A"), t);
+ assertFalse(t.isCancelled());
+ assertFalse(t.isDone());
+ assertFalse(t.isError());
+
+ assertTrue(signalStarted.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ t.cancel(true);
+
+ assertTrue(t.isCancelled());
+ assertTrue(t.isError());
+ try {
+ t.get();
+ fail("get should have failed due to cancel");
+ } catch (CancellationException e) {
+ // expected
+ }
+ assertTrue(t.isCancelled());
+ assertTrue(t.isDone());
+ assertTrue(t.isError());
+ }
+
+ @Test
+ public void cancelAfterRun() throws Exception {
+ BasicTask<Integer> t = new BasicTask<Integer>(Callables.returning(42));
+ em.submit(MutableMap.of("tag", "A"), t);
+
+ assertEquals(t.get(), (Integer)42);
+ t.cancel(true);
+ assertFalse(t.isCancelled());
+ assertFalse(t.isError());
+ assertTrue(t.isDone());
+ }
+
+ @Test
+ public void errorDuringRun() throws Exception {
+ BasicTask<Void> t = new BasicTask<Void>(new Callable<Void>() {
+ public Void call() throws Exception {
+ throw new IllegalStateException("Simulating failure in errorDuringRun");
+ }});
+
+ em.submit(MutableMap.of("tag", "A"), t);
+
+ try {
+ t.get();
+ fail("get should have failed due to error");
+ } catch (Exception eo) {
+ Throwable e = Throwables.getRootCause(eo);
+ assertEquals("Simulating failure in errorDuringRun", e.getMessage());
+ }
+
+ assertFalse(t.isCancelled());
+ assertTrue(t.isError());
+ assertTrue(t.isDone());
+
+ log.debug("errorDuringRun status: {}", t.getStatusDetail(false));
+ assertTrue(t.getStatusDetail(false).contains("Simulating failure in errorDuringRun"), "details="+t.getStatusDetail(false));
+ }
+
+ @Test
+ public void fieldsSetForSimpleBasicTask() throws Exception {
+ final CountDownLatch signalStarted = new CountDownLatch(1);
+ final CountDownLatch allowCompletion = new CountDownLatch(1);
+
+ BasicTask<Integer> t = new BasicTask<Integer>(new Callable<Integer>() {
+ public Integer call() throws Exception {
+ signalStarted.countDown();
+ allowCompletion.await();
+ return 42;
+ }});
+ assertEquals(null, t.getSubmittedByTask());
+ assertEquals(-1, t.submitTimeUtc);
+ assertNull(t.getInternalFuture());
+
+ em.submit(MutableMap.of("tag", "A"), t);
+ assertTrue(signalStarted.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ assertTrue(t.submitTimeUtc > 0);
+ assertTrue(t.startTimeUtc >= t.submitTimeUtc);
+ assertNotNull(t.getInternalFuture());
+ assertEquals(-1, t.endTimeUtc);
+ assertEquals(false, t.isCancelled());
+
+ allowCompletion.countDown();
+ assertEquals(t.get(), (Integer)42);
+ assertTrue(t.endTimeUtc >= t.startTimeUtc);
+
+ log.debug("BasicTask duration (millis): {}", (t.endTimeUtc - t.submitTimeUtc));
+ }
+
+ @Test
+ public void fieldsSetForBasicTaskSubmittedBasicTask() throws Exception {
+ //submitted BasicTask B is started by A, and waits for A to complete
+ BasicTask<Integer> t = new BasicTask<Integer>(MutableMap.of("displayName", "sample", "description", "some descr"), new Callable<Integer>() {
+ public Integer call() throws Exception {
+ em.submit(MutableMap.of("tag", "B"), new Callable<Integer>() {
+ public Integer call() throws Exception {
+ assertEquals(45, em.getTasksWithTag("A").iterator().next().get());
+ return 46;
+ }});
+ return 45;
+ }});
+ em.submit(MutableMap.of("tag", "A"), t);
+
+ t.blockUntilEnded();
+
+// assertEquals(em.getAllTasks().size(), 2
+
+ BasicTask<?> tb = (BasicTask<?>) em.getTasksWithTag("B").iterator().next();
+ assertEquals( 46, tb.get() );
+ assertEquals( t, em.getTasksWithTag("A").iterator().next() );
+ assertNull( t.getSubmittedByTask() );
+
+ BasicTask<?> submitter = (BasicTask<?>) tb.getSubmittedByTask();
+ assertNotNull(submitter);
+ assertEquals("sample", submitter.displayName);
+ assertEquals("some descr", submitter.description);
+ assertEquals(t, submitter);
+
+ assertTrue(submitter.submitTimeUtc <= tb.submitTimeUtc);
+ assertTrue(submitter.endTimeUtc <= tb.endTimeUtc);
+
+ log.debug("BasicTask {} was submitted by {}", tb, submitter);
+ }
+
+ private Callable<Object> newPutCallable(final Object key, final Object val) {
+ return new Callable<Object>() {
+ public Object call() {
+ return data.put(key, val);
+ }
+ };
+ }
+
+ private Callable<Integer> newIncrementCallable(final Object key) {
+ return new Callable<Integer>() {
+ public Integer call() {
+ synchronized (data) {
+ return (Integer) data.put(key, (Integer)data.get(key) + 1);
+ }
+ }
+ };
+ }
+
+ private Runnable newPutRunnable(final Object key, final Object val) {
+ return new Runnable() {
+ public void run() {
+ data.put(key, val);
+ }
+ };
+ }
+
+ private Runnable newNoop() {
+ return new Runnable() {
+ public void run() {
+ }
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/task/BasicTasksFutureTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/task/BasicTasksFutureTest.java b/core/src/test/java/org/apache/brooklyn/core/util/task/BasicTasksFutureTest.java
new file mode 100644
index 0000000..020a98c
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/task/BasicTasksFutureTest.java
@@ -0,0 +1,227 @@
+/*
+ * 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.util.task;
+
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.task.BasicExecutionContext;
+import org.apache.brooklyn.core.util.task.BasicExecutionManager;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Time;
+
+import com.google.common.base.Stopwatch;
+
+public class BasicTasksFutureTest {
+
+ private static final Logger log = LoggerFactory.getLogger(BasicTasksFutureTest.class);
+
+ private BasicExecutionManager em;
+ private BasicExecutionContext ec;
+ private Map<Object,Object> data;
+ private ExecutorService ex;
+ private Semaphore started;
+ private Semaphore waitInTask;
+ private Semaphore cancelledWhileSleeping;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() {
+ em = new BasicExecutionManager("mycontext");
+ ec = new BasicExecutionContext(em);
+ ex = Executors.newCachedThreadPool();
+ data = Collections.synchronizedMap(new LinkedHashMap<Object,Object>());
+ started = new Semaphore(0);
+ waitInTask = new Semaphore(0);
+ cancelledWhileSleeping = new Semaphore(0);
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ if (em != null) em.shutdownNow();
+ if (ex != null) ex.shutdownNow();
+ }
+
+ @Test
+ public void testBlockAndGetWithTimeoutsAndListenableFuture() throws InterruptedException {
+ Task<String> t = waitForSemaphore(Duration.FIVE_SECONDS, true, "x");
+
+ Assert.assertFalse(t.blockUntilEnded(Duration.millis(1)));
+ Assert.assertFalse(t.blockUntilEnded(Duration.ZERO));
+ boolean didNotThrow = false;
+
+ try { t.getUnchecked(Duration.millis(1)); didNotThrow = true; }
+ catch (Exception e) { /* expected */ }
+ Assert.assertFalse(didNotThrow);
+
+ try { t.getUnchecked(Duration.ZERO); didNotThrow = true; }
+ catch (Exception e) { /* expected */ }
+ Assert.assertFalse(didNotThrow);
+
+ addFutureListener(t, "before");
+ ec.submit(t);
+
+ Assert.assertFalse(t.blockUntilEnded(Duration.millis(1)));
+ Assert.assertFalse(t.blockUntilEnded(Duration.ZERO));
+
+ try { t.getUnchecked(Duration.millis(1)); didNotThrow = true; }
+ catch (Exception e) { /* expected */ }
+ Assert.assertFalse(didNotThrow);
+
+ try { t.getUnchecked(Duration.ZERO); didNotThrow = true; }
+ catch (Exception e) { /* expected */ }
+ Assert.assertFalse(didNotThrow);
+
+ addFutureListener(t, "during");
+
+ synchronized (data) {
+ // now let it finish
+ waitInTask.release();
+ Assert.assertTrue(t.blockUntilEnded(Duration.TEN_SECONDS));
+
+ Assert.assertEquals(t.getUnchecked(Duration.millis(1)), "x");
+ Assert.assertEquals(t.getUnchecked(Duration.ZERO), "x");
+
+ Assert.assertNull(data.get("before"));
+ Assert.assertNull(data.get("during"));
+ // can't set the data(above) until we release the lock (in assert call below)
+ assertSoonGetsData("before");
+ assertSoonGetsData("during");
+ }
+
+ // and see that a listener added late also runs
+ synchronized (data) {
+ addFutureListener(t, "after");
+ Assert.assertNull(data.get("after"));
+ assertSoonGetsData("after");
+ }
+ }
+
+ private void addFutureListener(Task<String> t, final String key) {
+ t.addListener(new Runnable() { public void run() {
+ synchronized (data) {
+ log.info("notifying for "+key);
+ data.notifyAll();
+ data.put(key, true);
+ }
+ }}, ex);
+ }
+
+ private void assertSoonGetsData(String key) throws InterruptedException {
+ for (int i=0; i<10; i++) {
+ if (Boolean.TRUE.equals(data.get(key))) {
+ log.info("got data for "+key);
+ return;
+ }
+ data.wait(Duration.ONE_SECOND.toMilliseconds());
+ }
+ Assert.fail("did not get data for '"+key+"' in time");
+ }
+
+ private <T> Task<T> waitForSemaphore(final Duration time, final boolean requireSemaphore, final T result) {
+ return Tasks.<T>builder().body(new Callable<T>() {
+ public T call() {
+ try {
+ started.release();
+ log.info("waiting up to "+time+" to acquire before returning "+result);
+ if (!waitInTask.tryAcquire(time.toMilliseconds(), TimeUnit.MILLISECONDS)) {
+ log.info("did not get semaphore");
+ if (requireSemaphore) Assert.fail("task did not get semaphore");
+ } else {
+ log.info("got semaphore");
+ }
+ } catch (Exception e) {
+ log.info("cancelled before returning "+result);
+ cancelledWhileSleeping.release();
+ throw Exceptions.propagate(e);
+ }
+ log.info("task returning "+result);
+ return result;
+ }
+ }).build();
+ }
+
+ @Test
+ public void testCancelAfterStartTriggersListenableFuture() throws Exception {
+ doTestCancelTriggersListenableFuture(Duration.millis(50));
+ }
+ @Test
+ public void testCancelImmediateTriggersListenableFuture() throws Exception {
+ // if cancel fires after submit but before it passes to the executor,
+ // that needs handling separately; this doesn't guarantee this code path,
+ // but it happens sometimes (and it should be handled)
+ doTestCancelTriggersListenableFuture(Duration.ZERO);
+ }
+ public void doTestCancelTriggersListenableFuture(Duration delay) throws Exception {
+ Task<String> t = waitForSemaphore(Duration.TEN_SECONDS, true, "x");
+ addFutureListener(t, "before");
+
+ Stopwatch watch = Stopwatch.createStarted();
+ ec.submit(t);
+
+ addFutureListener(t, "during");
+
+ log.info("test cancelling "+t+" ("+t.getClass()+") after "+delay);
+ // NB: two different code paths (callers to this method) for notifying futures
+ // depending whether task is started
+ Time.sleep(delay);
+
+ synchronized (data) {
+ t.cancel(true);
+
+ assertSoonGetsData("before");
+ assertSoonGetsData("during");
+
+ addFutureListener(t, "after");
+ Assert.assertNull(data.get("after"));
+ assertSoonGetsData("after");
+ }
+
+ Assert.assertTrue(t.isDone());
+ Assert.assertTrue(t.isCancelled());
+ try {
+ t.get();
+ Assert.fail("should have thrown CancellationException");
+ } catch (CancellationException e) { /* expected */ }
+
+ Assert.assertTrue(watch.elapsed(TimeUnit.MILLISECONDS) < Duration.FIVE_SECONDS.toMilliseconds(),
+ Time.makeTimeStringRounded(watch.elapsed(TimeUnit.MILLISECONDS))+" is too long; should have cancelled very quickly");
+
+ if (started.tryAcquire())
+ // if the task is begun, this should get released
+ Assert.assertTrue(cancelledWhileSleeping.tryAcquire(5, TimeUnit.SECONDS));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/task/CompoundTaskExecutionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/task/CompoundTaskExecutionTest.java b/core/src/test/java/org/apache/brooklyn/core/util/task/CompoundTaskExecutionTest.java
new file mode 100644
index 0000000..89bde95
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/task/CompoundTaskExecutionTest.java
@@ -0,0 +1,258 @@
+/*
+ * 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.util.task;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Semaphore;
+
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.task.BasicExecutionContext;
+import org.apache.brooklyn.core.util.task.BasicExecutionManager;
+import org.apache.brooklyn.core.util.task.BasicTask;
+import org.apache.brooklyn.core.util.task.CompoundTask;
+import org.apache.brooklyn.core.util.task.ParallelTask;
+import org.apache.brooklyn.core.util.task.SequentialTask;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.testng.collections.Lists;
+
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Time;
+
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Test the operation of the {@link CompoundTask} class.
+ */
+public class CompoundTaskExecutionTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(CompoundTaskExecutionTest.class);
+
+ BasicExecutionManager em;
+ BasicExecutionContext ec;
+
+ @BeforeClass
+ public void setup() {
+ em = new BasicExecutionManager("mycontext");
+ ec = new BasicExecutionContext(em);
+ }
+
+ @AfterClass
+ public void teardown() {
+ if (em != null) em.shutdownNow();
+ em = null;
+ }
+
+ private BasicTask<String> taskReturning(final String val) {
+ return new BasicTask<String>(new Callable<String>() {
+ @Override public String call() {
+ return val;
+ }
+ });
+ }
+
+ private BasicTask<String> slowTaskReturning(final String val, final Duration pauseTime) {
+ return new BasicTask<String>(new Callable<String>() {
+ @Override public String call() {
+ Time.sleep(pauseTime);
+ return val;
+ }
+ });
+ }
+
+
+ @Test
+ public void runSequenceTask() throws Exception {
+ BasicTask<String> t1 = taskReturning("a");
+ BasicTask<String> t2 = taskReturning("b");
+ BasicTask<String> t3 = taskReturning("c");
+ BasicTask<String> t4 = taskReturning("d");
+ Task<List<String>> tSequence = ec.submit(new SequentialTask<String>(t1, t2, t3, t4));
+ assertEquals(tSequence.get(), ImmutableList.of("a", "b", "c", "d"));
+ }
+
+ @Test
+ public void testSequentialTaskFailsWhenIntermediateTaskThrowsException() throws Exception {
+ BasicTask<String> t1 = taskReturning("a");
+ BasicTask<String> t2 = new BasicTask<String>(new Callable<String>() {
+ @Override public String call() throws Exception {
+ throw new IllegalArgumentException("forced exception");
+ }
+ });
+ BasicTask<String> t3 = taskReturning("c");
+ SequentialTask<String> task = new SequentialTask<String>(t1, t2, t3);
+ Task<List<String>> tSequence = ec.submit(task);
+
+ try {
+ tSequence.get();
+ fail("t2 should have thrown an exception");
+ } catch (Exception e) {}
+
+ assertTrue(task.isDone());
+ assertTrue(task.isError());
+ assertTrue(t1.isDone());
+ assertFalse(t1.isError());
+ assertTrue(t2.isDone());
+ assertTrue(t2.isError());
+ // t3 not run because of t2 exception
+ assertFalse(t3.isDone());
+ assertFalse(t3.isBegun());
+ }
+
+ @Test
+ public void testParallelTaskFailsWhenIntermediateTaskThrowsException() throws Exception {
+ // differs from test above of SequentialTask in that expect t3 to be executed,
+ // despite t2 failing.
+ // TODO Do we expect tSequence.get() to block for everything to either fail or complete,
+ // and then to throw exception? Currently it does *not* do that so test was previously failing.
+
+ BasicTask<String> t1 = taskReturning("a");
+ BasicTask<String> t2 = new BasicTask<String>(new Callable<String>() {
+ @Override public String call() throws Exception {
+ throw new IllegalArgumentException("forced exception");
+ }
+ });
+ BasicTask<String> t3 = slowTaskReturning("c", Duration.millis(100));
+ ParallelTask<String> task = new ParallelTask<String>(t1, t2, t3);
+ Task<List<String>> tSequence = ec.submit(task);
+
+ try {
+ tSequence.get();
+ fail("t2 should have thrown an exception");
+ } catch (Exception e) {}
+
+ assertTrue(task.isDone());
+ assertTrue(task.isError());
+ assertTrue(t1.isDone());
+ assertFalse(t1.isError());
+ assertTrue(t2.isDone());
+ assertTrue(t2.isError());
+ assertTrue(t3.isBegun());
+ assertTrue(t3.isDone());
+ assertFalse(t3.isError());
+ }
+
+ @Test
+ public void runParallelTask() throws Exception {
+ BasicTask<String> t1 = taskReturning("a");
+ BasicTask<String> t2 = taskReturning("b");
+ BasicTask<String> t3 = taskReturning("c");
+ BasicTask<String> t4 = taskReturning("d");
+ Task<List<String>> tSequence = ec.submit(new ParallelTask<String>(t4, t2, t1, t3));
+ assertEquals(new HashSet<String>(tSequence.get()), ImmutableSet.of("a", "b", "c", "d"));
+ }
+
+ @Test
+ public void runParallelTaskWithDelay() throws Exception {
+ final Semaphore locker = new Semaphore(0);
+ BasicTask<String> t1 = new BasicTask<String>(new Callable<String>() {
+ @Override public String call() {
+ try {
+ locker.acquire();
+ } catch (InterruptedException e) {
+ throw Throwables.propagate(e);
+ }
+ return "a";
+ }
+ });
+ BasicTask<String> t2 = taskReturning("b");
+ BasicTask<String> t3 = taskReturning("c");
+ BasicTask<String> t4 = taskReturning("d");
+ final Task<List<String>> tSequence = ec.submit(new ParallelTask<String>(t4, t2, t1, t3));
+
+ assertEquals(ImmutableSet.of(t2.get(), t3.get(), t4.get()), ImmutableSet.of("b", "c", "d"));
+ assertFalse(t1.isDone());
+ assertFalse(tSequence.isDone());
+
+ // get blocks until tasks have completed
+ Thread t = new Thread() {
+ @Override public void run() {
+ try {
+ tSequence.get();
+ } catch (Exception e) {
+ throw Throwables.propagate(e);
+ }
+ locker.release();
+ }
+ };
+ t.start();
+ Thread.sleep(30);
+ assertTrue(t.isAlive());
+
+ locker.release();
+
+ assertEquals(new HashSet<String>(tSequence.get()), ImmutableSet.of("a", "b", "c", "d"));
+ assertTrue(t1.isDone());
+ assertTrue(tSequence.isDone());
+
+ locker.acquire();
+ }
+
+ @Test
+ public void testComplexOrdering() throws Exception {
+ List<String> data = new CopyOnWriteArrayList<String>();
+ SequentialTask<String> taskA = new SequentialTask<String>(
+ appendAfterDelay(data, "a1"), appendAfterDelay(data, "a2"), appendAfterDelay(data, "a3"), appendAfterDelay(data, "a4"));
+ SequentialTask<String> taskB = new SequentialTask<String>(
+ appendAfterDelay(data, "b1"), appendAfterDelay(data, "b2"), appendAfterDelay(data, "b3"), appendAfterDelay(data, "b4"));
+ Task<List<String>> t = ec.submit(new ParallelTask<String>(taskA, taskB));
+ t.get();
+
+ LOG.debug("Tasks happened in order: {}", data);
+ assertEquals(data.size(), 8);
+ assertEquals(new HashSet<String>(data), ImmutableSet.of("a1", "a2", "a3", "a4", "b1", "b2", "b3", "b4"));
+
+ // a1, ..., a4 should be in order
+ List<String> as = Lists.newArrayList(), bs = Lists.newArrayList();
+ for (String value : data) {
+ ((value.charAt(0) == 'a') ? as : bs).add(value);
+ }
+ assertEquals(as, ImmutableList.of("a1", "a2", "a3", "a4"));
+ assertEquals(bs, ImmutableList.of("b1", "b2", "b3", "b4"));
+ }
+
+ private BasicTask<String> appendAfterDelay(final List<String> list, final String value) {
+ return new BasicTask<String>(new Callable<String>() {
+ @Override public String call() {
+ try {
+ Thread.sleep((int) (100 * Math.random()));
+ } catch (InterruptedException e) {
+ throw Throwables.propagate(e);
+ }
+ LOG.debug("running {}", value);
+ list.add(value);
+ return value;
+ }
+ });
+ }
+
+}
[30/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/xstream/XmlUtil.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/xstream/XmlUtil.java b/core/src/main/java/brooklyn/util/xstream/XmlUtil.java
deleted file mode 100644
index 1ab1293..0000000
--- a/core/src/main/java/brooklyn/util/xstream/XmlUtil.java
+++ /dev/null
@@ -1,59 +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 brooklyn.util.xstream;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.xpath.XPathExpression;
-import javax.xml.xpath.XPathExpressionException;
-import javax.xml.xpath.XPathFactory;
-
-import org.w3c.dom.Document;
-import org.xml.sax.SAXException;
-
-import brooklyn.util.exceptions.Exceptions;
-
-public class XmlUtil {
-
- public static Object xpath(String xml, String xpath) {
- // TODO Could share factory/doc in thread-local storage; see http://stackoverflow.com/questions/9828254/is-documentbuilderfactory-thread-safe-in-java-5
- try {
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- DocumentBuilder builder = factory.newDocumentBuilder();
- Document doc = builder.parse(new ByteArrayInputStream(xml.getBytes()));
- XPathFactory xPathfactory = XPathFactory.newInstance();
- XPathExpression expr = xPathfactory.newXPath().compile(xpath);
-
- return expr.evaluate(doc);
-
- } catch (ParserConfigurationException e) {
- throw Exceptions.propagate(e);
- } catch (SAXException e) {
- throw Exceptions.propagate(e);
- } catch (IOException e) {
- throw Exceptions.propagate(e);
- } catch (XPathExpressionException e) {
- throw Exceptions.propagate(e);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
index 0e8ec80..ae3f39f 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
@@ -55,6 +55,7 @@ import org.apache.brooklyn.api.policy.PolicySpec;
import org.apache.brooklyn.core.catalog.CatalogPredicates;
import org.apache.brooklyn.core.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import brooklyn.config.BrooklynServerConfig;
@@ -64,7 +65,6 @@ import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.guava.Maybe;
import brooklyn.util.javalang.AggregateClassLoader;
import brooklyn.util.javalang.LoadedClassLoader;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogClasspathDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogClasspathDo.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogClasspathDo.java
index 2bf9cca..822a8d2 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogClasspathDo.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogClasspathDo.java
@@ -39,13 +39,13 @@ import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.javalang.ReflectionScanner;
+import org.apache.brooklyn.core.util.javalang.UrlClassLoader;
import brooklyn.entity.basic.ApplicationBuilder;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.javalang.AggregateClassLoader;
-import brooklyn.util.javalang.ReflectionScanner;
-import brooklyn.util.javalang.UrlClassLoader;
import brooklyn.util.os.Os;
import brooklyn.util.stream.Streams;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogDto.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogDto.java
index 847f114..aefb635 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogDto.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogDto.java
@@ -27,8 +27,8 @@ import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.brooklyn.api.catalog.CatalogItem;
+import org.apache.brooklyn.core.util.ResourceUtils;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogDtoUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogDtoUtils.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogDtoUtils.java
index e2df123..6a27393 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogDtoUtils.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogDtoUtils.java
@@ -22,10 +22,10 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.brooklyn.core.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
+import org.apache.brooklyn.core.util.ResourceUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.exceptions.Exceptions;
public class CatalogDtoUtils {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java
index 047a168..e00211c 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java
@@ -29,14 +29,14 @@ import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.ha.ManagementNodeState;
import org.apache.brooklyn.core.management.ManagementContextInjectable;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import brooklyn.config.BrooklynServerConfig;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableList;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.exceptions.FatalRuntimeException;
import brooklyn.util.exceptions.RuntimeInterruptedException;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.guava.Maybe;
import brooklyn.util.javalang.JavaClassNames;
import brooklyn.util.os.Os;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java
index 5aa073b..a7e52ee 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java
@@ -34,12 +34,12 @@ import brooklyn.basic.AbstractBrooklynObject;
import org.apache.brooklyn.api.catalog.CatalogItem;
import org.apache.brooklyn.api.entity.rebind.RebindSupport;
import org.apache.brooklyn.api.mementos.CatalogItemMemento;
+import org.apache.brooklyn.core.util.flags.FlagUtils;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.rebind.BasicCatalogItemRebindSupport;
import brooklyn.util.collections.MutableList;
-import brooklyn.util.flags.FlagUtils;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogXmlSerializer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogXmlSerializer.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogXmlSerializer.java
index 462e00e..836cac3 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogXmlSerializer.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogXmlSerializer.java
@@ -24,10 +24,10 @@ import java.util.List;
import java.util.Map;
import org.apache.brooklyn.core.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
+import org.apache.brooklyn.core.util.xstream.EnumCaseForgivingSingleValueConverter;
+import org.apache.brooklyn.core.util.xstream.XmlSerializer;
import brooklyn.basic.AbstractBrooklynObject;
-import brooklyn.util.xstream.EnumCaseForgivingSingleValueConverter;
-import brooklyn.util.xstream.XmlSerializer;
public class CatalogXmlSerializer extends XmlSerializer<Object> {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynFeatureEnablement.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynFeatureEnablement.java b/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynFeatureEnablement.java
index 24d138b..686fd35 100644
--- a/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynFeatureEnablement.java
+++ b/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynFeatureEnablement.java
@@ -21,12 +21,12 @@ package org.apache.brooklyn.core.internal;
import java.util.Map;
import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
+import org.apache.brooklyn.core.util.internal.ssh.ShellTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.config.BrooklynProperties;
import brooklyn.internal.storage.BrooklynStorage;
-import brooklyn.util.internal.ssh.ShellTool;
import com.google.common.annotations.Beta;
import com.google.common.collect.Maps;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynInitialization.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynInitialization.java b/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynInitialization.java
index 1858306..d1104af 100644
--- a/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynInitialization.java
+++ b/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynInitialization.java
@@ -20,9 +20,10 @@ package org.apache.brooklyn.core.internal;
import java.util.concurrent.atomic.AtomicBoolean;
+import org.apache.brooklyn.core.util.crypto.SecureKeys;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import org.apache.brooklyn.location.basic.PortRanges;
-import brooklyn.util.crypto.SecureKeys;
-import brooklyn.util.flags.TypeCoercions;
+
import brooklyn.util.net.Networking;
import com.google.common.annotations.Beta;
@@ -52,7 +53,7 @@ public class BrooklynInitialization {
@SuppressWarnings("deprecation")
public static void initLegacyLanguageExtensions() {
- brooklyn.util.BrooklynLanguageExtensions.init();
+ org.apache.brooklyn.core.util.BrooklynLanguageExtensions.init();
}
/* other things:
@@ -74,7 +75,7 @@ public class BrooklynInitialization {
@SuppressWarnings("deprecation")
public synchronized static void reinitAll() {
done.set(false);
- brooklyn.util.BrooklynLanguageExtensions.reinit();
+ org.apache.brooklyn.core.util.BrooklynLanguageExtensions.reinit();
initAll();
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/management/entitlement/Entitlements.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/entitlement/Entitlements.java b/core/src/main/java/org/apache/brooklyn/core/management/entitlement/Entitlements.java
index 6bf9329..dc49053 100644
--- a/core/src/main/java/org/apache/brooklyn/core/management/entitlement/Entitlements.java
+++ b/core/src/main/java/org/apache/brooklyn/core/management/entitlement/Entitlements.java
@@ -30,6 +30,7 @@ import org.apache.brooklyn.api.management.entitlement.EntitlementClass;
import org.apache.brooklyn.api.management.entitlement.EntitlementContext;
import org.apache.brooklyn.api.management.entitlement.EntitlementManager;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -49,7 +50,6 @@ import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.Entities;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.javalang.Reflections;
-import brooklyn.util.task.Tasks;
import brooklyn.util.text.Strings;
/** @since 0.7.0 */
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerImpl.java b/core/src/main/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerImpl.java
index bda7f6f..f369124 100644
--- a/core/src/main/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerImpl.java
+++ b/core/src/main/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerImpl.java
@@ -51,6 +51,8 @@ import org.apache.brooklyn.core.management.internal.LocalEntityManager;
import org.apache.brooklyn.core.management.internal.LocationManagerInternal;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.core.management.internal.ManagementTransitionMode;
+import org.apache.brooklyn.core.util.task.ScheduledTask;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -71,8 +73,6 @@ import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.exceptions.ReferenceWithError;
-import brooklyn.util.task.ScheduledTask;
-import brooklyn.util.task.Tasks;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Duration;
import brooklyn.util.time.Time;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/management/ha/OsgiManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/ha/OsgiManager.java b/core/src/main/java/org/apache/brooklyn/core/management/ha/OsgiManager.java
index 6a133fc..8241479 100644
--- a/core/src/main/java/org/apache/brooklyn/core/management/ha/OsgiManager.java
+++ b/core/src/main/java/org/apache/brooklyn/core/management/ha/OsgiManager.java
@@ -39,6 +39,8 @@ import brooklyn.BrooklynVersion;
import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.util.osgi.Osgis;
+import org.apache.brooklyn.core.util.osgi.Osgis.BundleFinder;
import brooklyn.config.BrooklynServerConfig;
import brooklyn.config.BrooklynServerPaths;
@@ -49,8 +51,6 @@ import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.guava.Maybe;
import brooklyn.util.os.Os;
import brooklyn.util.os.Os.DeletionResult;
-import brooklyn.util.osgi.Osgis;
-import brooklyn.util.osgi.Osgis.BundleFinder;
import brooklyn.util.repeat.Repeater;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/management/internal/AbstractManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/AbstractManagementContext.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/AbstractManagementContext.java
index 58e2f60..7c1e473 100644
--- a/core/src/main/java/org/apache/brooklyn/core/management/internal/AbstractManagementContext.java
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/AbstractManagementContext.java
@@ -56,6 +56,10 @@ import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.classloading.JavaBrooklynClassLoadingContext;
import org.apache.brooklyn.core.management.entitlement.Entitlements;
import org.apache.brooklyn.core.management.ha.HighAvailabilityManagerImpl;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.task.BasicExecutionContext;
+import org.apache.brooklyn.core.util.task.Tasks;
import brooklyn.config.BrooklynProperties;
import brooklyn.config.StringConfigMap;
@@ -74,13 +78,9 @@ import brooklyn.internal.storage.impl.inmemory.InMemoryDataGridFactory;
import org.apache.brooklyn.location.basic.BasicLocationRegistry;
import brooklyn.util.GroovyJavaMethods;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.guava.Maybe;
-import brooklyn.util.task.BasicExecutionContext;
-import brooklyn.util.task.Tasks;
import com.google.common.base.Function;
import com.google.common.base.Objects;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/management/internal/AsyncCollectionChangeAdapter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/AsyncCollectionChangeAdapter.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/AsyncCollectionChangeAdapter.java
index 038ec90..1fc1060 100644
--- a/core/src/main/java/org/apache/brooklyn/core/management/internal/AsyncCollectionChangeAdapter.java
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/AsyncCollectionChangeAdapter.java
@@ -21,13 +21,13 @@ package org.apache.brooklyn.core.management.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import org.apache.brooklyn.api.management.ExecutionManager;
+import org.apache.brooklyn.core.util.task.BasicExecutionManager;
+import org.apache.brooklyn.core.util.task.SingleThreadedScheduler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.task.BasicExecutionManager;
-import brooklyn.util.task.SingleThreadedScheduler;
public class AsyncCollectionChangeAdapter<Item> implements CollectionChangeListener<Item> {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/management/internal/BrooklynGarbageCollector.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/BrooklynGarbageCollector.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/BrooklynGarbageCollector.java
index c02ff81..45876c5 100644
--- a/core/src/main/java/org/apache/brooklyn/core/management/internal/BrooklynGarbageCollector.java
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/BrooklynGarbageCollector.java
@@ -39,6 +39,9 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.management.HasTaskChildren;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.task.BasicExecutionManager;
+import org.apache.brooklyn.core.util.task.ExecutionListener;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -55,9 +58,6 @@ import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.javalang.MemoryUsageTracker;
-import brooklyn.util.task.BasicExecutionManager;
-import brooklyn.util.task.ExecutionListener;
-import brooklyn.util.task.Tasks;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/management/internal/EffectorUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/EffectorUtils.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/EffectorUtils.java
index 028f2d2..0f3ab99 100644
--- a/core/src/main/java/org/apache/brooklyn/core/management/internal/EffectorUtils.java
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/EffectorUtils.java
@@ -33,6 +33,8 @@ import org.apache.brooklyn.api.entity.Effector;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.ParameterType;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -41,10 +43,8 @@ import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.exceptions.PropagatedRuntimeException;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.guava.Maybe;
import com.google.common.collect.Lists;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/management/internal/EntityManagementUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/EntityManagementUtils.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/EntityManagementUtils.java
index 3f59774..b243cda 100644
--- a/core/src/main/java/org/apache/brooklyn/core/management/internal/EntityManagementUtils.java
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/EntityManagementUtils.java
@@ -38,6 +38,8 @@ import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
import org.apache.brooklyn.core.management.classloading.JavaBrooklynClassLoadingContext;
+import org.apache.brooklyn.core.util.task.TaskBuilder;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -54,8 +56,6 @@ import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.guava.Maybe;
-import brooklyn.util.task.TaskBuilder;
-import brooklyn.util.task.Tasks;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalEntityManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalEntityManager.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalEntityManager.java
index 53d31eb..23039ba 100644
--- a/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalEntityManager.java
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalEntityManager.java
@@ -43,6 +43,7 @@ import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.EnricherSpec;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -62,7 +63,6 @@ import brooklyn.internal.storage.BrooklynStorage;
import brooklyn.util.collections.MutableSet;
import brooklyn.util.collections.SetFromLiveMap;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.task.Tasks;
import brooklyn.util.time.CountdownTimer;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalLocationManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalLocationManager.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalLocationManager.java
index 54708f5..f3e6aef 100644
--- a/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalLocationManager.java
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalLocationManager.java
@@ -30,6 +30,8 @@ import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.location.ProvisioningLocation;
import org.apache.brooklyn.api.management.AccessController;
import org.apache.brooklyn.core.management.entitlement.Entitlements;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -44,11 +46,9 @@ import brooklyn.internal.storage.BrooklynStorage;
import org.apache.brooklyn.location.basic.AbstractLocation;
import org.apache.brooklyn.location.basic.LocationInternal;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.exceptions.RuntimeInterruptedException;
import brooklyn.util.stream.Streams;
-import brooklyn.util.task.Tasks;
import com.google.common.annotations.Beta;
import com.google.common.base.Preconditions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalManagementContext.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalManagementContext.java
index 3c353e2..b29c178 100644
--- a/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalManagementContext.java
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalManagementContext.java
@@ -45,6 +45,11 @@ import org.apache.brooklyn.api.management.TaskAdaptable;
import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
import org.apache.brooklyn.core.management.entitlement.Entitlements;
import org.apache.brooklyn.core.management.ha.OsgiManager;
+import org.apache.brooklyn.core.util.task.BasicExecutionContext;
+import org.apache.brooklyn.core.util.task.BasicExecutionManager;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.TaskTags;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -58,11 +63,6 @@ import brooklyn.entity.proxying.InternalPolicyFactory;
import brooklyn.internal.storage.DataGridFactory;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.guava.Maybe;
-import brooklyn.util.task.BasicExecutionContext;
-import brooklyn.util.task.BasicExecutionManager;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.TaskTags;
-import brooklyn.util.task.Tasks;
import brooklyn.util.text.Strings;
import com.google.common.annotations.Beta;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalSubscriptionManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalSubscriptionManager.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalSubscriptionManager.java
index 99b79ec..9a75621 100644
--- a/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalSubscriptionManager.java
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalSubscriptionManager.java
@@ -40,12 +40,12 @@ import org.apache.brooklyn.api.event.SensorEventListener;
import org.apache.brooklyn.api.management.ExecutionManager;
import org.apache.brooklyn.api.management.SubscriptionHandle;
import org.apache.brooklyn.api.management.SubscriptionManager;
+import org.apache.brooklyn.core.util.task.BasicExecutionManager;
+import org.apache.brooklyn.core.util.task.SingleThreadedScheduler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.entity.basic.Entities;
-import brooklyn.util.task.BasicExecutionManager;
-import brooklyn.util.task.SingleThreadedScheduler;
import brooklyn.util.text.Identifiers;
import com.google.common.base.Predicate;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalUsageManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalUsageManager.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalUsageManager.java
index dc95d11..991f930 100644
--- a/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalUsageManager.java
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalUsageManager.java
@@ -39,6 +39,7 @@ import org.apache.brooklyn.core.management.ManagementContextInjectable;
import org.apache.brooklyn.core.management.entitlement.Entitlements;
import org.apache.brooklyn.core.management.usage.ApplicationUsage;
import org.apache.brooklyn.core.management.usage.LocationUsage;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -52,7 +53,6 @@ import org.apache.brooklyn.location.basic.LocationConfigKeys;
import org.apache.brooklyn.location.basic.LocationInternal;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.javalang.Reflections;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/management/internal/ManagementContextInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/ManagementContextInternal.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/ManagementContextInternal.java
index 6c993d8..3fc0677 100644
--- a/core/src/main/java/org/apache/brooklyn/core/management/internal/ManagementContextInternal.java
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/ManagementContextInternal.java
@@ -31,6 +31,7 @@ import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.core.catalog.internal.CatalogInitialization;
import org.apache.brooklyn.core.management.ha.OsgiManager;
+import org.apache.brooklyn.core.util.task.TaskTags;
import brooklyn.config.BrooklynProperties;
import brooklyn.entity.basic.BrooklynTaskTags;
@@ -39,7 +40,6 @@ import brooklyn.entity.proxying.InternalLocationFactory;
import brooklyn.entity.proxying.InternalPolicyFactory;
import brooklyn.internal.storage.BrooklynStorage;
import brooklyn.util.guava.Maybe;
-import brooklyn.util.task.TaskTags;
import com.google.common.annotations.Beta;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/BrooklynLanguageExtensions.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/BrooklynLanguageExtensions.java b/core/src/main/java/org/apache/brooklyn/core/util/BrooklynLanguageExtensions.java
new file mode 100644
index 0000000..9e1b80e
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/BrooklynLanguageExtensions.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.util;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.brooklyn.core.internal.BrooklynInitialization;
+
+import brooklyn.util.internal.TimeExtras;
+
+/** @deprecated since 0.7.0 use {@link BrooklynInitialization} */
+public class BrooklynLanguageExtensions {
+
+ private BrooklynLanguageExtensions() {}
+
+ private static AtomicBoolean done = new AtomicBoolean(false);
+
+ public synchronized static void reinit() {
+ done.set(false);
+ init();
+ }
+
+ /** performs the language extensions required for this project */
+ public synchronized static void init() {
+ if (done.getAndSet(true)) return;
+ TimeExtras.init();
+ BrooklynInitialization.initPortRanges();
+ }
+
+ static { BrooklynInitialization.initLegacyLanguageExtensions(); }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/BrooklynMavenArtifacts.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/BrooklynMavenArtifacts.java b/core/src/main/java/org/apache/brooklyn/core/util/BrooklynMavenArtifacts.java
new file mode 100644
index 0000000..c00fec0
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/BrooklynMavenArtifacts.java
@@ -0,0 +1,58 @@
+/*
+ * 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.util;
+
+import brooklyn.BrooklynVersion;
+import brooklyn.util.maven.MavenArtifact;
+import brooklyn.util.maven.MavenRetriever;
+import brooklyn.util.text.Strings;
+
+public class BrooklynMavenArtifacts {
+
+ public static MavenArtifact jar(String artifactId) {
+ return artifact(null, artifactId, "jar");
+ }
+
+ public static MavenArtifact artifact(String subgroupUnderIoBrooklyn, String artifactId, String packaging) {
+ return artifact(subgroupUnderIoBrooklyn, artifactId, packaging, null);
+ }
+
+ public static MavenArtifact artifact(String subgroupUnderIoBrooklyn, String artifactId, String packaging, String classifier) {
+ return new MavenArtifact(
+ Strings.isEmpty(subgroupUnderIoBrooklyn) ? "org.apache.brooklyn" : "org.apache.brooklyn."+subgroupUnderIoBrooklyn,
+ artifactId, packaging, classifier, BrooklynVersion.get());
+ }
+
+ public static String localUrlForJar(String artifactId) {
+ return MavenRetriever.localUrl(jar(artifactId));
+ }
+
+ public static String localUrl(String subgroupUnderIoBrooklyn, String artifactId, String packaging) {
+ return MavenRetriever.localUrl(artifact(subgroupUnderIoBrooklyn, artifactId, packaging));
+ }
+
+ public static String hostedUrlForJar(String artifactId) {
+ return MavenRetriever.hostedUrl(jar(artifactId));
+ }
+
+ public static String hostedUrl(String subgroupUnderIoBrooklyn, String artifactId, String packaging) {
+ return MavenRetriever.hostedUrl(artifact(subgroupUnderIoBrooklyn, artifactId, packaging));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/BrooklynNetworkUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/BrooklynNetworkUtils.java b/core/src/main/java/org/apache/brooklyn/core/util/BrooklynNetworkUtils.java
new file mode 100644
index 0000000..7240425
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/BrooklynNetworkUtils.java
@@ -0,0 +1,44 @@
+/*
+ * 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.util;
+
+import java.net.InetAddress;
+
+import brooklyn.config.BrooklynServiceAttributes;
+
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
+import org.apache.brooklyn.location.geo.LocalhostExternalIpLoader;
+
+import brooklyn.util.JavaGroovyEquivalents;
+import brooklyn.util.net.Networking;
+
+public class BrooklynNetworkUtils {
+
+ /** returns the externally-facing IP address from which this host comes, or 127.0.0.1 if not resolvable */
+ public static String getLocalhostExternalIp() {
+ return LocalhostExternalIpLoader.getLocalhostIpQuicklyOrDefault();
+ }
+
+ /** returns a IP address for localhost paying attention to a system property to prevent lookup in some cases */
+ public static InetAddress getLocalhostInetAddress() {
+ return TypeCoercions.coerce(JavaGroovyEquivalents.elvis(BrooklynServiceAttributes.LOCALHOST_IP_ADDRESS.getValue(),
+ Networking.getLocalHost()), InetAddress.class);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/ResourceUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/ResourceUtils.java b/core/src/main/java/org/apache/brooklyn/core/util/ResourceUtils.java
new file mode 100644
index 0000000..bbd88d5
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/ResourceUtils.java
@@ -0,0 +1,639 @@
+/*
+ * 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.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.InetAddress;
+import java.net.JarURLConnection;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
+import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog.BrooklynLoaderTracker;
+import org.apache.brooklyn.core.internal.BrooklynInitialization;
+import org.apache.brooklyn.core.management.classloading.JavaBrooklynClassLoadingContext;
+import org.apache.brooklyn.core.util.http.HttpTool;
+import org.apache.brooklyn.core.util.http.HttpTool.HttpClientBuilder;
+import org.apache.brooklyn.core.util.text.DataUriSchemeParser;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.auth.Credentials;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.util.EntityUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.brooklyn.location.basic.SshMachineLocation;
+
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.javalang.Threads;
+import brooklyn.util.net.Urls;
+import brooklyn.util.os.Os;
+import brooklyn.util.stream.Streams;
+import brooklyn.util.text.Strings;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Throwables;
+import com.google.common.collect.Lists;
+
+public class ResourceUtils {
+
+ private static final Logger log = LoggerFactory.getLogger(ResourceUtils.class);
+ private static final List<Function<Object,BrooklynClassLoadingContext>> classLoaderProviders = Lists.newCopyOnWriteArrayList();
+
+ private BrooklynClassLoadingContext loader = null;
+ private String context = null;
+ private Object contextObject = null;
+
+ static { BrooklynInitialization.initNetworking(); }
+
+ /**
+ * Creates a {@link ResourceUtils} object with a specific class loader and context.
+ * <p>
+ * Use the provided {@link ClassLoader} object for class loading with the
+ * {@code contextObject} for context and the {@code contextMessage} string for
+ * error messages.
+ *
+ * @see ResourceUtils#create(Object, String)
+ * @see ResourceUtils#create(Object)
+ */
+ public static final ResourceUtils create(ClassLoader loader, Object contextObject, String contextMessage) {
+ return new ResourceUtils(loader, contextObject, contextMessage);
+ }
+
+ /**
+ * Creates a {@link ResourceUtils} object with a specific class loader and context.
+ * <p>
+ * Use the provided {@link BrooklynClassLoadingContext} object for class loading with the
+ * {@code contextObject} for context and the {@code contextMessage} string for
+ * error messages.
+ *
+ * @see ResourceUtils#create(Object, String)
+ * @see ResourceUtils#create(Object)
+ */
+ public static final ResourceUtils create(BrooklynClassLoadingContext loader, Object contextObject, String contextMessage) {
+ return new ResourceUtils(loader, contextObject, contextMessage);
+ }
+
+ /**
+ * Creates a {@link ResourceUtils} object with the given context.
+ * <p>
+ * Uses the {@link ClassLoader} of the given {@code contextObject} for class
+ * loading and the {@code contextMessage} string for error messages.
+ *
+ * @see ResourceUtils#create(ClassLoader, Object, String)
+ * @see ResourceUtils#create(Object)
+ */
+ public static final ResourceUtils create(Object contextObject, String contextMessage) {
+ return new ResourceUtils(contextObject, contextMessage);
+ }
+
+ /**
+ * Creates a {@link ResourceUtils} object with the given context.
+ * <p>
+ * Uses the {@link ClassLoader} of the given {@code contextObject} for class
+ * loading and its {@link Object#toString()} (preceded by the word 'for') as
+ * the string used in error messages.
+ *
+ * @see ResourceUtils#create(ClassLoader, Object, String)
+ * @see ResourceUtils#create(Object)
+ */
+ public static final ResourceUtils create(Object contextObject) {
+ return new ResourceUtils(contextObject);
+ }
+
+ /**
+ * Creates a {@link ResourceUtils} object with itself as the context.
+ *
+ * @see ResourceUtils#create(Object)
+ */
+ public static final ResourceUtils create() {
+ return new ResourceUtils(null);
+ }
+
+ public ResourceUtils(ClassLoader loader, Object contextObject, String contextMessage) {
+ this(getClassLoadingContextInternal(loader, contextObject), contextObject, contextMessage);
+ }
+
+ public ResourceUtils(BrooklynClassLoadingContext loader, Object contextObject, String contextMessage) {
+ this.loader = loader;
+ this.contextObject = contextObject;
+ this.context = contextMessage;
+ }
+
+ public ResourceUtils(Object contextObject, String contextMessage) {
+ this(contextObject==null ? null : getClassLoadingContextInternal(null, contextObject), contextObject, contextMessage);
+ }
+
+ public ResourceUtils(Object contextObject) {
+ this(contextObject, Strings.toString(contextObject));
+ }
+
+ /** used to register custom mechanisms for getting classloaders given an object */
+ public static void addClassLoaderProvider(Function<Object,BrooklynClassLoadingContext> provider) {
+ classLoaderProviders.add(provider);
+ }
+
+ // TODO rework this class so it accepts but does not require a BCLC ?
+ @SuppressWarnings("deprecation")
+ protected static BrooklynClassLoadingContext getClassLoadingContextInternal(ClassLoader loader, Object contextObject) {
+ if (contextObject instanceof BrooklynClassLoadingContext)
+ return (BrooklynClassLoadingContext) contextObject;
+
+ for (Function<Object,BrooklynClassLoadingContext> provider: classLoaderProviders) {
+ BrooklynClassLoadingContext result = provider.apply(contextObject);
+ if (result!=null) return result;
+ }
+
+ BrooklynClassLoadingContext bl = BrooklynLoaderTracker.getLoader();
+ ManagementContext mgmt = (bl!=null ? bl.getManagementContext() : null);
+
+ ClassLoader cl = loader;
+ if (cl==null) cl = contextObject instanceof Class ? ((Class<?>)contextObject).getClassLoader() :
+ contextObject instanceof ClassLoader ? ((ClassLoader)contextObject) :
+ contextObject.getClass().getClassLoader();
+
+ return JavaBrooklynClassLoadingContext.create(mgmt, cl);
+ }
+
+ /** This should not be exposed as it risks it leaking into places where it would be serialized.
+ * Better for callers use {@link CatalogUtils#getClassLoadingContext(org.apache.brooklyn.api.entity.Entity)} or similar. }.
+ */
+ private BrooklynClassLoadingContext getLoader() {
+ return (loader!=null ? loader : getClassLoadingContextInternal(null, contextObject!=null ? contextObject : this));
+ }
+
+ /**
+ * @return all resources in Brooklyn's {@link BrooklynClassLoadingContext} with the given name.
+ */
+ public Iterable<URL> getResources(String name) {
+ return getLoader().getResources(name);
+ }
+
+ /**
+ * Takes a string which is treated as a URL (with some extended "schemes" also expected),
+ * or as a path to something either on the classpath (absolute only) or the local filesystem (relative or absolute, depending on leading slash)
+ * <p>
+ * URLs can be of the form <b>classpath://com/acme/Foo.properties</b>
+ * as well as <b>file:///home/...</b> and <b>http://acme.com/...</b>.
+ * <p>
+ * Throws exception if not found, using the context parameter passed into the constructor.
+ * <p>
+ * TODO may want OSGi, or typed object; should consider pax url
+ *
+ * @return a stream, or throws exception (never returns null)
+ */
+ public InputStream getResourceFromUrl(String url) {
+ try {
+ if (url==null) throw new NullPointerException("Cannot read from null");
+ if (url=="") throw new NullPointerException("Cannot read from empty string");
+ String orig = url;
+ String protocol = Urls.getProtocol(url);
+ if (protocol!=null) {
+ if ("classpath".equals(protocol)) {
+ try {
+ return getResourceViaClasspath(url);
+ } catch (IOException e) {
+ //catch the above because both orig and modified url may be interesting
+ throw new IOException("Error accessing "+orig+": "+e, e);
+ }
+ }
+ if ("sftp".equals(protocol)) {
+ try {
+ return getResourceViaSftp(url);
+ } catch (IOException e) {
+ throw new IOException("Error accessing "+orig+": "+e, e);
+ }
+ }
+
+ if ("file".equals(protocol))
+ url = tidyFileUrl(url);
+
+ if ("data".equals(protocol)) {
+ return new DataUriSchemeParser(url).lax().parse().getDataAsInputStream();
+ }
+
+ if ("http".equals(protocol) || "https".equals(protocol)) {
+ return getResourceViaHttp(url);
+ }
+
+ return new URL(url).openStream();
+ }
+
+ try {
+ //try as classpath reference, then as file
+ try {
+ URL u = getLoader().getResource(url);
+ if (u!=null) return u.openStream();
+ } catch (IllegalArgumentException e) {
+ //Felix installs an additional URL to the system classloader
+ //which throws an IllegalArgumentException when passed a
+ //windows path. See ExtensionManager.java static initializer.
+
+ //ignore, not a classpath resource
+ }
+ if (url.startsWith("/")) {
+ //some getResource calls fail if argument starts with /
+ String urlNoSlash = url;
+ while (urlNoSlash.startsWith("/")) urlNoSlash = urlNoSlash.substring(1);
+ URL u = getLoader().getResource(urlNoSlash);
+ if (u!=null) return u.openStream();
+// //Class.getResource can require a / (else it attempts to be relative) but Class.getClassLoader doesn't
+// u = getLoader().getResource("/"+urlNoSlash);
+// if (u!=null) return u.openStream();
+ }
+ File f;
+ // but first, if it starts with tilde, treat specially
+ if (url.startsWith("~/")) {
+ f = new File(Os.home(), url.substring(2));
+ } else if (url.startsWith("~\\")) {
+ f = new File(Os.home(), url.substring(2));
+ } else {
+ f = new File(url);
+ }
+ if (f.exists()) return new FileInputStream(f);
+ } catch (IOException e) {
+ //catch the above because both u and modified url will be interesting
+ throw new IOException("Error accessing "+orig+": "+e, e);
+ }
+ throw new IOException("'"+orig+"' not found on classpath or filesystem");
+ } catch (Exception e) {
+ if (context!=null) {
+ throw new RuntimeException("Error getting resource '"+url+"' for "+context+": "+e, e);
+ } else {
+ throw Exceptions.propagate(e);
+ }
+ }
+ }
+
+ private final static Pattern pattern = Pattern.compile("^file:/*~/+(.*)$");
+
+ public static URL tidy(URL url) {
+ // File class has helpful methods for URIs but not URLs. So we convert.
+ URI in;
+ try {
+ in = url.toURI();
+ } catch (URISyntaxException e) {
+ throw Exceptions.propagate(e);
+ }
+ URI out;
+
+ Matcher matcher = pattern.matcher(in.toString());
+ if (matcher.matches()) {
+ // home-relative
+ File home = new File(Os.home());
+ File file = new File(home, matcher.group(1));
+ out = file.toURI();
+ } else if (in.getScheme().equals("file:")) {
+ // some other file, so canonicalize
+ File file = new File(in);
+ out = file.toURI();
+ } else {
+ // some other scheme, so no-op
+ out = in;
+ }
+
+ URL urlOut;
+ try {
+ urlOut = out.toURL();
+ } catch (MalformedURLException e) {
+ throw Exceptions.propagate(e);
+ }
+ if (!urlOut.equals(url) && log.isDebugEnabled()) {
+ log.debug("quietly changing " + url + " to " + urlOut);
+ }
+ return urlOut;
+ }
+
+ public static String tidyFileUrl(String url) {
+ try {
+ return tidy(new URL(url)).toString();
+ } catch (MalformedURLException e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ /** @deprecated since 0.7.0; use method {@link Os#mergePaths(String...)} */ @Deprecated
+ public static String mergeFilePaths(String... items) {
+ return Os.mergePaths(items);
+ }
+
+ /** @deprecated since 0.7.0; use method {@link Os#tidyPath(String)} */ @Deprecated
+ public static String tidyFilePath(String path) {
+ return Os.tidyPath(path);
+ }
+
+ /** @deprecated since 0.7.0; use method {@link Urls#getProtocol(String)} */ @Deprecated
+ public static String getProtocol(String url) {
+ return Urls.getProtocol(url);
+ }
+
+ private InputStream getResourceViaClasspath(String url) throws IOException {
+ assert url.startsWith("classpath:");
+ String subUrl = url.substring("classpath:".length());
+ while (subUrl.startsWith("/")) subUrl = subUrl.substring(1);
+ URL u = getLoader().getResource(subUrl);
+ if (u!=null) return u.openStream();
+ else throw new IOException(subUrl+" not found on classpath");
+ }
+
+ private InputStream getResourceViaSftp(String url) throws IOException {
+ assert url.startsWith("sftp://");
+ String subUrl = url.substring("sftp://".length());
+ String user;
+ String address;
+ String path;
+ int atIndex = subUrl.indexOf("@");
+ int colonIndex = subUrl.indexOf(":", (atIndex > 0 ? atIndex : 0));
+ if (colonIndex <= 0 || colonIndex <= atIndex) {
+ throw new IllegalArgumentException("Invalid sftp url ("+url+"); IP or hostname must be specified, such as sftp://localhost:/path/to/file");
+ }
+ if (subUrl.length() <= (colonIndex+1)) {
+ throw new IllegalArgumentException("Invalid sftp url ("+url+"); must specify path of remote file, such as sftp://localhost:/path/to/file");
+ }
+ if (atIndex >= 0) {
+ user = subUrl.substring(0, atIndex);
+ } else {
+ user = null;
+ }
+ address = subUrl.substring(atIndex + 1, colonIndex);
+ path = subUrl.substring(colonIndex+1);
+
+ // TODO messy way to get an SCP session
+ SshMachineLocation machine = new SshMachineLocation(MutableMap.builder()
+ .putIfNotNull("user", user)
+ .put("address", InetAddress.getByName(address))
+ .build());
+ try {
+ final File tempFile = Os.newTempFile("brooklyn-sftp", "tmp");
+ tempFile.setReadable(true, true);
+ machine.copyFrom(path, tempFile.getAbsolutePath());
+ return new FileInputStream(tempFile) {
+ @Override
+ public void close() throws IOException {
+ super.close();
+ tempFile.delete();
+ }
+ };
+ } finally {
+ Streams.closeQuietly(machine);
+ }
+ }
+
+ //For HTTP(S) targets use HttpClient so
+ //we can do authentication
+ private InputStream getResourceViaHttp(String resource) throws IOException {
+ URI uri = URI.create(resource);
+ HttpClientBuilder builder = HttpTool.httpClientBuilder()
+ .laxRedirect(true)
+ .uri(uri);
+ Credentials credentials = getUrlCredentials(uri.getRawUserInfo());
+ if (credentials != null) {
+ builder.credentials(credentials);
+ }
+ HttpClient client = builder.build();
+ HttpResponse result = client.execute(new HttpGet(resource));
+ int statusCode = result.getStatusLine().getStatusCode();
+ if (HttpTool.isStatusCodeHealthy(statusCode)) {
+ HttpEntity entity = result.getEntity();
+ if (entity != null) {
+ return entity.getContent();
+ } else {
+ return new ByteArrayInputStream(new byte[0]);
+ }
+ } else {
+ EntityUtils.consume(result.getEntity());
+ throw new IllegalStateException("Invalid response invoking " + resource + ": response code " + statusCode);
+ }
+ }
+
+ private Credentials getUrlCredentials(String userInfo) {
+ if (userInfo != null) {
+ String[] arr = userInfo.split(":");
+ String username;
+ String password = null;
+ if (arr.length == 1) {
+ username = urlDecode(arr[0]);
+ } else if (arr.length == 2) {
+ username = urlDecode(arr[0]);
+ password = urlDecode(arr[1]);
+ } else {
+ return null;
+ }
+ return new UsernamePasswordCredentials(username, password);
+ } else {
+ return null;
+ }
+ }
+
+ private String urlDecode(String str) {
+ try {
+ return URLDecoder.decode(str, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ /** takes {@link #getResourceFromUrl(String)} and reads fully, into a string */
+ public String getResourceAsString(String url) {
+ try {
+ return readFullyString(getResourceFromUrl(url));
+ } catch (Exception e) {
+ log.debug("ResourceUtils got error reading "+url+(context==null?"":" "+context)+" (rethrowing): "+e);
+ throw Throwables.propagate(e);
+ }
+ }
+
+ /** allows failing-fast if URL cannot be read */
+ public String checkUrlExists(String url) {
+ return checkUrlExists(url, null);
+ }
+
+ public String checkUrlExists(String url, String message) {
+ if (url==null) throw new NullPointerException("URL "+(message!=null ? message+" " : "")+"must not be null");
+ InputStream s;
+ try {
+ s = getResourceFromUrl(url);
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ throw new IllegalArgumentException("Unable to access URL "+(message!=null ? message : "")+": "+url, e);
+ }
+ Streams.closeQuietly(s);
+ return url;
+ }
+
+ /** tests whether the url exists, returning true or false */
+ public boolean doesUrlExist(String url) {
+ InputStream s = null;
+ try {
+ s = getResourceFromUrl(url);
+ return true;
+ } catch (Exception e) {
+ return false;
+ } finally {
+ Streams.closeQuietly(s);
+ }
+ }
+
+ /** returns the first available URL */
+ public Optional<String> firstAvailableUrl(String ...urls) {
+ for (String url: urls) {
+ if (doesUrlExist(url)) return Optional.of(url);
+ }
+ return Optional.absent();
+ }
+
+ /** returns the base directory or JAR from which the context is class-loaded, if possible;
+ * throws exception if not found */
+ public String getClassLoaderDir() {
+ if (contextObject==null) throw new IllegalArgumentException("No suitable context ("+context+") to auto-detect classloader dir");
+ Class<?> cc = contextObject instanceof Class ? (Class<?>)contextObject : contextObject.getClass();
+ return getClassLoaderDir(cc.getCanonicalName().replace('.', '/')+".class");
+ }
+
+ public String getClassLoaderDir(String resourceInThatDir) {
+ resourceInThatDir = Strings.removeFromStart(resourceInThatDir, "/");
+ URL resourceUrl = getLoader().getResource(resourceInThatDir);
+ if (resourceUrl==null) throw new NoSuchElementException("Resource ("+resourceInThatDir+") not found");
+
+ URL containerUrl = getContainerUrl(resourceUrl, resourceInThatDir);
+
+ if (!"file".equals(containerUrl.getProtocol())) throw new IllegalStateException("Resource ("+resourceInThatDir+") not on file system (at "+containerUrl+")");
+
+ //convert from file: URL to File
+ File file;
+ try {
+ file = new File(containerUrl.toURI());
+ } catch (URISyntaxException e) {
+ throw new IllegalStateException("Resource ("+resourceInThatDir+") found at invalid URI (" + containerUrl + ")", e);
+ }
+
+ if (!file.exists()) throw new IllegalStateException("Context class url substring ("+containerUrl+") not found on filesystem");
+ return file.getPath();
+
+ }
+
+ public static URL getContainerUrl(URL url, String resourceInThatDir) {
+ //Switching from manual parsing of jar: and file: URLs to java provided functionality.
+ //The old code was breaking on any Windows path and instead of fixing it, using
+ //the provided Java APIs seemed like the better option since they are already tested
+ //on multiple platforms.
+ boolean isJar = "jar".equals(url.getProtocol());
+ if(isJar) {
+ try {
+ //let java handle the parsing of jar URL, no network connection is established.
+ //Strips the jar protocol:
+ // jar:file:/<path to jar>!<resourceInThatDir>
+ // becomes
+ // file:/<path to jar>
+ JarURLConnection connection = (JarURLConnection) url.openConnection();
+ url = connection.getJarFileURL();
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ } else {
+ //Remove the trailing resouceInThatDir path from the URL, thus getting the parent folder.
+ String path = url.toString();
+ int i = path.indexOf(resourceInThatDir);
+ if (i==-1) throw new IllegalStateException("Resource path ("+resourceInThatDir+") not in url substring ("+url+")");
+ String parent = path.substring(0, i);
+ try {
+ url = new URL(parent);
+ } catch (MalformedURLException e) {
+ throw new IllegalStateException("Resource ("+resourceInThatDir+") found at invalid URL parent (" + parent + ")", e);
+ }
+ }
+ return url;
+ }
+
+ /** @deprecated since 0.7.0 use {@link Streams#readFullyString(InputStream) */ @Deprecated
+ public static String readFullyString(InputStream is) throws IOException {
+ return Streams.readFullyString(is);
+ }
+
+ /** @deprecated since 0.7.0 use {@link Streams#readFully(InputStream) */ @Deprecated
+ public static byte[] readFullyBytes(InputStream is) throws IOException {
+ return Streams.readFully(is);
+ }
+
+ /** @deprecated since 0.7.0 use {@link Streams#copy(InputStream, OutputStream)} */ @Deprecated
+ public static void copy(InputStream input, OutputStream output) throws IOException {
+ Streams.copy(input, output);
+ }
+
+ /** @deprecated since 0.7.0; use same method in {@link Os} */ @Deprecated
+ public static File mkdirs(File dir) {
+ return Os.mkdirs(dir);
+ }
+
+ /** @deprecated since 0.7.0; use same method in {@link Os} */ @Deprecated
+ public static File writeToTempFile(InputStream is, String prefix, String suffix) {
+ return Os.writeToTempFile(is, prefix, suffix);
+ }
+
+ /** @deprecated since 0.7.0; use same method in {@link Os} */ @Deprecated
+ public static File writeToTempFile(InputStream is, File tempDir, String prefix, String suffix) {
+ return Os.writeToTempFile(is, tempDir, prefix, suffix);
+ }
+
+ /** @deprecated since 0.7.0; use method {@link Os#writePropertiesToTempFile(Properties, String, String)} */ @Deprecated
+ public static File writeToTempFile(Properties props, String prefix, String suffix) {
+ return Os.writePropertiesToTempFile(props, prefix, suffix);
+ }
+
+ /** @deprecated since 0.7.0; use method {@link Os#writePropertiesToTempFile(Properties, File, String, String)} */ @Deprecated
+ public static File writeToTempFile(Properties props, File tempDir, String prefix, String suffix) {
+ return Os.writePropertiesToTempFile(props, tempDir, prefix, suffix);
+ }
+
+ /** @deprecated since 0.7.0; use method {@link Threads#addShutdownHook(Runnable)} */ @Deprecated
+ public static Thread addShutdownHook(final Runnable task) {
+ return Threads.addShutdownHook(task);
+ }
+ /** @deprecated since 0.7.0; use method {@link Threads#removeShutdownHook(Thread)} */ @Deprecated
+ public static boolean removeShutdownHook(Thread hook) {
+ return Threads.removeShutdownHook(hook);
+ }
+
+ /** returns the items with exactly one "/" between items (whether or not the individual items start or end with /),
+ * except where character before the / is a : (url syntax) in which case it will permit multiple (will not remove any)
+ * @deprecated since 0.7.0 use either {@link Os#mergePathsUnix(String...)} {@link Urls#mergePaths(String...) */ @Deprecated
+ public static String mergePaths(String ...items) {
+ return Urls.mergePaths(items);
+ }
+}
[24/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/osgi/Osgis.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/osgi/Osgis.java b/core/src/main/java/org/apache/brooklyn/core/util/osgi/Osgis.java
new file mode 100644
index 0000000..849a33b
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/osgi/Osgis.java
@@ -0,0 +1,720 @@
+/*
+ * 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.util.osgi;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.jar.Attributes;
+import java.util.jar.JarInputStream;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+
+import javax.annotation.Nullable;
+
+import org.apache.felix.framework.FrameworkFactory;
+import org.apache.felix.framework.util.StringMap;
+import org.apache.felix.framework.util.manifestparser.ManifestParser;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Version;
+import org.osgi.framework.launch.Framework;
+import org.osgi.framework.namespace.PackageNamespace;
+import org.osgi.framework.wiring.BundleCapability;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.osgi.Osgis;
+
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.collections.MutableSet;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.exceptions.ReferenceWithError;
+import brooklyn.util.guava.Maybe;
+import brooklyn.util.net.Urls;
+import brooklyn.util.os.Os;
+import brooklyn.util.stream.Streams;
+import brooklyn.util.text.Strings;
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Time;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Joiner;
+import com.google.common.base.Objects;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.base.Stopwatch;
+
+/**
+ * utilities for working with osgi.
+ * osgi support is in early days (June 2014) so this class is beta, subject to change,
+ * particularly in how framework is started and bundles installed.
+ *
+ * @since 0.7.0 */
+@Beta
+public class Osgis {
+ private static final Logger LOG = LoggerFactory.getLogger(Osgis.class);
+
+ private static final String EXTENSION_PROTOCOL = "system";
+ private static final String MANIFEST_PATH = "META-INF/MANIFEST.MF";
+ private static final Set<String> SYSTEM_BUNDLES = MutableSet.of();
+
+ public static class VersionedName {
+ private final String symbolicName;
+ private final Version version;
+ public VersionedName(Bundle b) {
+ this.symbolicName = b.getSymbolicName();
+ this.version = b.getVersion();
+ }
+ public VersionedName(String symbolicName, Version version) {
+ this.symbolicName = symbolicName;
+ this.version = version;
+ }
+ @Override public String toString() {
+ return symbolicName + ":" + Strings.toString(version);
+ }
+ public boolean equals(String sn, String v) {
+ return symbolicName.equals(sn) && (version == null && v == null || version != null && version.toString().equals(v));
+ }
+ public boolean equals(String sn, Version v) {
+ return symbolicName.equals(sn) && (version == null && v == null || version != null && version.equals(v));
+ }
+ public String getSymbolicName() {
+ return symbolicName;
+ }
+ public Version getVersion() {
+ return version;
+ }
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(symbolicName, version);
+ }
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof VersionedName)) return false;
+ VersionedName o = (VersionedName) other;
+ return Objects.equal(symbolicName, o.symbolicName) && Objects.equal(version, o.version);
+ }
+ }
+
+ public static class BundleFinder {
+ protected final Framework framework;
+ protected String symbolicName;
+ protected String version;
+ protected String url;
+ protected boolean urlMandatory = false;
+ protected final List<Predicate<? super Bundle>> predicates = MutableList.of();
+
+ protected BundleFinder(Framework framework) {
+ this.framework = framework;
+ }
+
+ public BundleFinder symbolicName(String symbolicName) {
+ this.symbolicName = symbolicName;
+ return this;
+ }
+
+ public BundleFinder version(String version) {
+ this.version = version;
+ return this;
+ }
+
+ public BundleFinder id(String symbolicNameOptionallyWithVersion) {
+ if (Strings.isBlank(symbolicNameOptionallyWithVersion))
+ return this;
+
+ Maybe<VersionedName> nv = parseOsgiIdentifier(symbolicNameOptionallyWithVersion);
+ if (nv.isAbsent())
+ throw new IllegalArgumentException("Cannot parse symbolic-name:version string '"+symbolicNameOptionallyWithVersion+"'");
+
+ return id(nv.get());
+ }
+
+ private BundleFinder id(VersionedName nv) {
+ symbolicName(nv.getSymbolicName());
+ if (nv.getVersion() != null) {
+ version(nv.getVersion().toString());
+ }
+ return this;
+ }
+
+ public BundleFinder bundle(CatalogBundle bundle) {
+ if (bundle.isNamed()) {
+ symbolicName(bundle.getSymbolicName());
+ version(bundle.getVersion());
+ }
+ if (bundle.getUrl() != null) {
+ requiringFromUrl(bundle.getUrl());
+ }
+ return this;
+ }
+
+ /** Looks for a bundle matching the given URL;
+ * unlike {@link #requiringFromUrl(String)} however, if the URL does not match any bundles
+ * it will return other matching bundles <i>if</if> a {@link #symbolicName(String)} is specified.
+ */
+ public BundleFinder preferringFromUrl(String url) {
+ this.url = url;
+ urlMandatory = false;
+ return this;
+ }
+
+ /** Requires the bundle to have the given URL set as its location. */
+ public BundleFinder requiringFromUrl(String url) {
+ this.url = url;
+ urlMandatory = true;
+ return this;
+ }
+
+ /** Finds the best matching bundle. */
+ public Maybe<Bundle> find() {
+ return findOne(false);
+ }
+
+ /** Finds the matching bundle, requiring it to be unique. */
+ public Maybe<Bundle> findUnique() {
+ return findOne(true);
+ }
+
+ protected Maybe<Bundle> findOne(boolean requireExactlyOne) {
+ if (symbolicName==null && url==null)
+ throw new IllegalStateException(this+" must be given either a symbolic name or a URL");
+
+ List<Bundle> result = findAll();
+ if (result.isEmpty())
+ return Maybe.absent("No bundle matching "+getConstraintsDescription());
+ if (requireExactlyOne && result.size()>1)
+ return Maybe.absent("Multiple bundles ("+result.size()+") matching "+getConstraintsDescription());
+
+ return Maybe.of(result.get(0));
+ }
+
+ /** Finds all matching bundles, in decreasing version order. */
+ public List<Bundle> findAll() {
+ boolean urlMatched = false;
+ List<Bundle> result = MutableList.of();
+ for (Bundle b: framework.getBundleContext().getBundles()) {
+ if (symbolicName!=null && !symbolicName.equals(b.getSymbolicName())) continue;
+ if (version!=null && !Version.parseVersion(version).equals(b.getVersion())) continue;
+ for (Predicate<? super Bundle> predicate: predicates) {
+ if (!predicate.apply(b)) continue;
+ }
+
+ // check url last, because if it isn't mandatory we should only clear if we find a url
+ // for which the other items also match
+ if (url!=null) {
+ boolean matches = url.equals(b.getLocation());
+ if (urlMandatory) {
+ if (!matches) continue;
+ else urlMatched = true;
+ } else {
+ if (matches) {
+ if (!urlMatched) {
+ result.clear();
+ urlMatched = true;
+ }
+ } else {
+ if (urlMatched) {
+ // can't use this bundle as we have previously found a preferred bundle, with a matching url
+ continue;
+ }
+ }
+ }
+ }
+
+ result.add(b);
+ }
+
+ if (symbolicName==null && url!=null && !urlMatched) {
+ // if we only "preferred" the url, and we did not match it, and we did not have a symbolic name,
+ // then clear the results list!
+ result.clear();
+ }
+
+ Collections.sort(result, new Comparator<Bundle>() {
+ @Override
+ public int compare(Bundle o1, Bundle o2) {
+ return o2.getVersion().compareTo(o1.getVersion());
+ }
+ });
+
+ return result;
+ }
+
+ public String getConstraintsDescription() {
+ List<String> parts = MutableList.of();
+ if (symbolicName!=null) parts.add("symbolicName="+symbolicName);
+ if (version!=null) parts.add("version="+version);
+ if (url!=null)
+ parts.add("url["+(urlMandatory ? "required" : "preferred")+"]="+url);
+ if (!predicates.isEmpty())
+ parts.add("predicates="+predicates);
+ return Joiner.on(";").join(parts);
+ }
+
+ public String toString() {
+ return getClass().getCanonicalName()+"["+getConstraintsDescription()+"]";
+ }
+
+ public BundleFinder version(final Predicate<Version> versionPredicate) {
+ return satisfying(new Predicate<Bundle>() {
+ @Override
+ public boolean apply(Bundle input) {
+ return versionPredicate.apply(input.getVersion());
+ }
+ });
+ }
+
+ public BundleFinder satisfying(Predicate<? super Bundle> predicate) {
+ predicates.add(predicate);
+ return this;
+ }
+ }
+
+ public static BundleFinder bundleFinder(Framework framework) {
+ return new BundleFinder(framework);
+ }
+
+ /** @deprecated since 0.7.0 use {@link #bundleFinder(Framework)} */ @Deprecated
+ public static List<Bundle> getBundlesByName(Framework framework, String symbolicName, Predicate<Version> versionMatcher) {
+ return bundleFinder(framework).symbolicName(symbolicName).version(versionMatcher).findAll();
+ }
+
+ /** @deprecated since 0.7.0 use {@link #bundleFinder(Framework)} */ @Deprecated
+ public static List<Bundle> getBundlesByName(Framework framework, String symbolicName) {
+ return bundleFinder(framework).symbolicName(symbolicName).findAll();
+ }
+
+ /**
+ * Tries to find a bundle in the given framework with name matching either `name' or `name:version'.
+ * @deprecated since 0.7.0 use {@link #bundleFinder(Framework)} */ @Deprecated
+ public static Maybe<Bundle> getBundle(Framework framework, String symbolicNameOptionallyWithVersion) {
+ return bundleFinder(framework).id(symbolicNameOptionallyWithVersion).find();
+ }
+
+ /** @deprecated since 0.7.0 use {@link #bundleFinder(Framework)} */ @Deprecated
+ public static Maybe<Bundle> getBundle(Framework framework, String symbolicName, String version) {
+ return bundleFinder(framework).symbolicName(symbolicName).version(version).find();
+ }
+
+ /** @deprecated since 0.7.0 use {@link #bundleFinder(Framework)} */ @Deprecated
+ public static Maybe<Bundle> getBundle(Framework framework, String symbolicName, Version version) {
+ return bundleFinder(framework).symbolicName(symbolicName).version(Predicates.equalTo(version)).findUnique();
+ }
+
+ // -------- creating
+
+ /*
+ * loading framework factory and starting framework based on:
+ * http://felix.apache.org/documentation/subprojects/apache-felix-framework/apache-felix-framework-launching-and-embedding.html
+ */
+
+ public static FrameworkFactory newFrameworkFactory() {
+ URL url = Osgis.class.getClassLoader().getResource(
+ "META-INF/services/org.osgi.framework.launch.FrameworkFactory");
+ if (url != null) {
+ try {
+ BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
+ try {
+ for (String s = br.readLine(); s != null; s = br.readLine()) {
+ s = s.trim();
+ // load the first non-empty, non-commented line
+ if ((s.length() > 0) && (s.charAt(0) != '#')) {
+ return (FrameworkFactory) Class.forName(s).newInstance();
+ }
+ }
+ } finally {
+ if (br != null) br.close();
+ }
+ } catch (Exception e) {
+ // class creation exceptions are not interesting to caller...
+ throw Exceptions.propagate(e);
+ }
+ }
+ throw new IllegalStateException("Could not find framework factory.");
+ }
+
+ public static Framework newFrameworkStarted(String felixCacheDir, boolean clean, Map<?,?> extraStartupConfig) {
+ Map<Object,Object> cfg = MutableMap.copyOf(extraStartupConfig);
+ if (clean) cfg.put(Constants.FRAMEWORK_STORAGE_CLEAN, "onFirstInit");
+ if (felixCacheDir!=null) cfg.put(Constants.FRAMEWORK_STORAGE, felixCacheDir);
+ cfg.put(Constants.FRAMEWORK_BSNVERSION, Constants.FRAMEWORK_BSNVERSION_MULTIPLE);
+ FrameworkFactory factory = newFrameworkFactory();
+
+ Stopwatch timer = Stopwatch.createStarted();
+ Framework framework = factory.newFramework(cfg);
+ try {
+ framework.init();
+ installBootBundles(framework);
+ framework.start();
+ } catch (Exception e) {
+ // framework bundle start exceptions are not interesting to caller...
+ throw Exceptions.propagate(e);
+ }
+ LOG.debug("System bundles are: "+SYSTEM_BUNDLES);
+ LOG.debug("OSGi framework started in " + Duration.of(timer));
+ return framework;
+ }
+
+ private static void installBootBundles(Framework framework) {
+ Stopwatch timer = Stopwatch.createStarted();
+ LOG.debug("Installing OSGi boot bundles from "+Osgis.class.getClassLoader()+"...");
+ Enumeration<URL> resources;
+ try {
+ resources = Osgis.class.getClassLoader().getResources(MANIFEST_PATH);
+ } catch (IOException e) {
+ throw Exceptions.propagate(e);
+ }
+ BundleContext bundleContext = framework.getBundleContext();
+ Map<String, Bundle> installedBundles = getInstalledBundlesById(bundleContext);
+ while(resources.hasMoreElements()) {
+ URL url = resources.nextElement();
+ ReferenceWithError<?> installResult = installExtensionBundle(bundleContext, url, installedBundles, getVersionedId(framework));
+ if (installResult.hasError() && !installResult.masksErrorIfPresent()) {
+ // it's reported as a critical error, so warn here
+ LOG.warn("Unable to install manifest from "+url+": "+installResult.getError(), installResult.getError());
+ } else {
+ Object result = installResult.getWithoutError();
+ if (result instanceof Bundle) {
+ String v = getVersionedId( (Bundle)result );
+ SYSTEM_BUNDLES.add(v);
+ if (installResult.hasError()) {
+ LOG.debug(installResult.getError().getMessage()+(result!=null ? " ("+result+"/"+v+")" : ""));
+ } else {
+ LOG.debug("Installed "+v+" from "+url);
+ }
+ } else if (installResult.hasError()) {
+ LOG.debug(installResult.getError().getMessage());
+ }
+ }
+ }
+ LOG.debug("Installed OSGi boot bundles in "+Time.makeTimeStringRounded(timer)+": "+Arrays.asList(framework.getBundleContext().getBundles()));
+ }
+
+ private static Map<String, Bundle> getInstalledBundlesById(BundleContext bundleContext) {
+ Map<String, Bundle> installedBundles = new HashMap<String, Bundle>();
+ Bundle[] bundles = bundleContext.getBundles();
+ for (Bundle b : bundles) {
+ installedBundles.put(getVersionedId(b), b);
+ }
+ return installedBundles;
+ }
+
+ /** Wraps the bundle if successful or already installed, wraps TRUE if it's the system entry,
+ * wraps null if the bundle is already installed from somewhere else;
+ * in all these cases <i>masking</i> an explanatory error if already installed or it's the system entry.
+ * <p>
+ * Returns an instance wrapping null and <i>throwing</i> an error if the bundle could not be installed.
+ */
+ private static ReferenceWithError<?> installExtensionBundle(BundleContext bundleContext, URL manifestUrl, Map<String, Bundle> installedBundles, String frameworkVersionedId) {
+ //ignore http://felix.extensions:9/ system entry
+ if("felix.extensions".equals(manifestUrl.getHost()))
+ return ReferenceWithError.newInstanceMaskingError(null, new IllegalArgumentException("Skipping install of internal extension bundle from "+manifestUrl));
+
+ try {
+ Manifest manifest = readManifest(manifestUrl);
+ if (!isValidBundle(manifest))
+ return ReferenceWithError.newInstanceMaskingError(null, new IllegalArgumentException("Resource at "+manifestUrl+" is not an OSGi bundle: no valid manifest"));
+
+ String versionedId = getVersionedId(manifest);
+ URL bundleUrl = ResourceUtils.getContainerUrl(manifestUrl, MANIFEST_PATH);
+
+ Bundle existingBundle = installedBundles.get(versionedId);
+ if (existingBundle != null) {
+ if (!bundleUrl.equals(existingBundle.getLocation()) &&
+ //the framework bundle is always pre-installed, don't display duplicate info
+ !versionedId.equals(frameworkVersionedId)) {
+ return ReferenceWithError.newInstanceMaskingError(null, new IllegalArgumentException("Bundle "+versionedId+" (from manifest " + manifestUrl + ") is already installed, from " + existingBundle.getLocation()));
+ }
+ return ReferenceWithError.newInstanceMaskingError(existingBundle, new IllegalArgumentException("Bundle "+versionedId+" from manifest " + manifestUrl + " is already installed"));
+ }
+
+ byte[] jar = buildExtensionBundle(manifest);
+ LOG.debug("Installing boot bundle " + bundleUrl);
+ //mark the bundle as extension so we can detect it later using the "system:" protocol
+ //(since we cannot access BundleImpl.isExtension)
+ Bundle newBundle = bundleContext.installBundle(EXTENSION_PROTOCOL + ":" + bundleUrl.toString(), new ByteArrayInputStream(jar));
+ installedBundles.put(versionedId, newBundle);
+ return ReferenceWithError.newInstanceWithoutError(newBundle);
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ return ReferenceWithError.newInstanceThrowingError(null,
+ new IllegalStateException("Problem installing extension bundle " + manifestUrl + ": "+e, e));
+ }
+ }
+
+ private static Manifest readManifest(URL manifestUrl) throws IOException {
+ Manifest manifest;
+ InputStream in = null;
+ try {
+ in = manifestUrl.openStream();
+ manifest = new Manifest(in);
+ } finally {
+ if (in != null) {
+ try {in.close();}
+ catch (Exception e) {};
+ }
+ }
+ return manifest;
+ }
+
+ private static byte[] buildExtensionBundle(Manifest manifest) throws IOException {
+ Attributes atts = manifest.getMainAttributes();
+
+ //the following properties are invalid in extension bundles
+ atts.remove(new Attributes.Name(Constants.IMPORT_PACKAGE));
+ atts.remove(new Attributes.Name(Constants.REQUIRE_BUNDLE));
+ atts.remove(new Attributes.Name(Constants.BUNDLE_NATIVECODE));
+ atts.remove(new Attributes.Name(Constants.DYNAMICIMPORT_PACKAGE));
+ atts.remove(new Attributes.Name(Constants.BUNDLE_ACTIVATOR));
+
+ //mark as extension bundle
+ atts.putValue(Constants.FRAGMENT_HOST, "system.bundle; extension:=framework");
+
+ //create the jar containing the manifest
+ ByteArrayOutputStream jar = new ByteArrayOutputStream();
+ JarOutputStream out = new JarOutputStream(jar, manifest);
+ out.close();
+ return jar.toByteArray();
+ }
+
+ private static boolean isValidBundle(Manifest manifest) {
+ Attributes atts = manifest.getMainAttributes();
+ return atts.containsKey(new Attributes.Name(Constants.BUNDLE_MANIFESTVERSION));
+ }
+
+ private static String getVersionedId(Bundle b) {
+ return b.getSymbolicName() + ":" + b.getVersion();
+ }
+
+ private static String getVersionedId(Manifest manifest) {
+ Attributes atts = manifest.getMainAttributes();
+ return atts.getValue(Constants.BUNDLE_SYMBOLICNAME) + ":" +
+ atts.getValue(Constants.BUNDLE_VERSION);
+ }
+
+ /**
+ * Installs a bundle from the given URL, doing a check if already installed, and
+ * using the {@link ResourceUtils} loader for this project (brooklyn core)
+ */
+ public static Bundle install(Framework framework, String url) throws BundleException {
+ boolean isLocal = isLocalUrl(url);
+ String localUrl = url;
+ if (!isLocal) {
+ localUrl = cacheFile(url);
+ }
+
+ try {
+ Bundle bundle = getInstalledBundle(framework, localUrl);
+ if (bundle != null) {
+ return bundle;
+ }
+
+ // use our URL resolution so we get classpath items
+ LOG.debug("Installing bundle into {} from url: {}", framework, url);
+ InputStream stream = getUrlStream(localUrl);
+ Bundle installedBundle = framework.getBundleContext().installBundle(url, stream);
+
+ return installedBundle;
+ } finally {
+ if (!isLocal) {
+ try {
+ new File(new URI(localUrl)).delete();
+ } catch (URISyntaxException e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+ }
+ }
+
+ private static String cacheFile(String url) {
+ InputStream in = getUrlStream(url);
+ File cache = Os.writeToTempFile(in, "bundle-cache", "jar");
+ return cache.toURI().toString();
+ }
+
+ private static boolean isLocalUrl(String url) {
+ String protocol = Urls.getProtocol(url);
+ return "file".equals(protocol) ||
+ "classpath".equals(protocol) ||
+ "jar".equals(protocol);
+ }
+
+ private static Bundle getInstalledBundle(Framework framework, String url) {
+ Bundle bundle = framework.getBundleContext().getBundle(url);
+ if (bundle != null) {
+ return bundle;
+ }
+
+ // We now support same version installed multiple times (avail since OSGi 4.3+).
+ // However we do not support overriding *system* bundles, ie anything already on the classpath.
+ // If we wanted to disable multiple versions, see comments below, and reference to FRAMEWORK_BSNVERSION_MULTIPLE above.
+
+ // Felix already assumes the stream is pointing to a JAR
+ JarInputStream stream;
+ try {
+ stream = new JarInputStream(getUrlStream(url));
+ } catch (IOException e) {
+ throw Exceptions.propagate(e);
+ }
+ Manifest manifest = stream.getManifest();
+ Streams.closeQuietly(stream);
+ if (manifest == null) {
+ throw new IllegalStateException("Missing manifest file in bundle or not a jar file.");
+ }
+ String versionedId = getVersionedId(manifest);
+ for (Bundle installedBundle : framework.getBundleContext().getBundles()) {
+ if (versionedId.equals(getVersionedId(installedBundle))) {
+ if (SYSTEM_BUNDLES.contains(versionedId)) {
+ LOG.debug("Already have system bundle "+versionedId+" from "+installedBundle+"/"+installedBundle.getLocation()+" when requested "+url+"; not installing");
+ // "System bundles" (ie things on the classpath) cannot be overridden
+ return installedBundle;
+ } else {
+ LOG.debug("Already have bundle "+versionedId+" from "+installedBundle+"/"+installedBundle.getLocation()+" when requested "+url+"; but it is not a system bundle so proceeding");
+ // Other bundles can be installed multiple times. To ignore multiples and continue to use the old one,
+ // just return the installedBundle as done just above for system bundles.
+ }
+ }
+ }
+ return null;
+ }
+
+ private static InputStream getUrlStream(String url) {
+ return ResourceUtils.create(Osgis.class).getResourceFromUrl(url);
+ }
+
+ public static boolean isExtensionBundle(Bundle bundle) {
+ String location = bundle.getLocation();
+ return location != null &&
+ EXTENSION_PROTOCOL.equals(Urls.getProtocol(location));
+ }
+
+ /** Takes a string which might be of the form "symbolic-name" or "symbolic-name:version" (or something else entirely)
+ * and returns a VersionedName. The versionedName.getVersion() will be null if if there was no version in the input
+ * (or returning {@link Maybe#absent()} if not valid, with a suitable error message). */
+ public static Maybe<VersionedName> parseOsgiIdentifier(String symbolicNameOptionalWithVersion) {
+ if (Strings.isBlank(symbolicNameOptionalWithVersion))
+ return Maybe.absent("OSGi identifier is blank");
+
+ String[] parts = symbolicNameOptionalWithVersion.split(":");
+ if (parts.length>2)
+ return Maybe.absent("OSGi identifier has too many parts; max one ':' symbol");
+
+ Version v = null;
+ if (parts.length == 2) {
+ try {
+ v = Version.parseVersion(parts[1]);
+ } catch (IllegalArgumentException e) {
+ return Maybe.absent("OSGi identifier has invalid version string ("+e.getMessage()+")");
+ }
+ }
+
+ return Maybe.of(new VersionedName(parts[0], v));
+ }
+
+ /**
+ * The class is not used, staying for future reference.
+ * Remove after OSGi transition is completed.
+ */
+ public static class ManifestHelper {
+
+ private static ManifestParser parse;
+ private Manifest manifest;
+ private String source;
+
+ private static final String WIRING_PACKAGE = PackageNamespace.PACKAGE_NAMESPACE;
+
+ public static ManifestHelper forManifestContents(String contents) throws IOException, BundleException {
+ ManifestHelper result = forManifest(Streams.newInputStreamWithContents(contents));
+ result.source = contents;
+ return result;
+ }
+
+ public static ManifestHelper forManifest(URL url) throws IOException, BundleException {
+ InputStream in = null;
+ try {
+ in = url.openStream();
+ return forManifest(in);
+ } finally {
+ if (in != null) in.close();
+ }
+ }
+
+ public static ManifestHelper forManifest(InputStream in) throws IOException, BundleException {
+ return forManifest(new Manifest(in));
+ }
+
+ public static ManifestHelper forManifest(Manifest manifest) throws BundleException {
+ ManifestHelper result = new ManifestHelper();
+ result.manifest = manifest;
+ parse = new ManifestParser(null, null, null, new StringMap(manifest.getMainAttributes()));
+ return result;
+ }
+
+ public String getSymbolicName() {
+ return parse.getSymbolicName();
+ }
+
+ public Version getVersion() {
+ return parse.getBundleVersion();
+ }
+
+ public String getSymbolicNameVersion() {
+ return getSymbolicName()+":"+getVersion();
+ }
+
+ public List<String> getExportedPackages() {
+ MutableList<String> result = MutableList.of();
+ for (BundleCapability c: parse.getCapabilities()) {
+ if (WIRING_PACKAGE.equals(c.getNamespace())) {
+ result.add((String)c.getAttributes().get(WIRING_PACKAGE));
+ }
+ }
+ return result;
+ }
+
+ @Nullable public String getSource() {
+ return source;
+ }
+
+ public Manifest getManifest() {
+ return manifest;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/AbstractExecutionContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/AbstractExecutionContext.java b/core/src/main/java/org/apache/brooklyn/core/util/task/AbstractExecutionContext.java
new file mode 100644
index 0000000..3eea5d9
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/AbstractExecutionContext.java
@@ -0,0 +1,75 @@
+/*
+ * 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.util.task;
+
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+import org.apache.brooklyn.api.management.ExecutionContext;
+import org.apache.brooklyn.api.management.ExecutionManager;
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.api.management.TaskAdaptable;
+
+import com.google.common.collect.Maps;
+
+public abstract class AbstractExecutionContext implements ExecutionContext {
+
+ /**
+ * Submits the given runnable/callable/task for execution (in a separate thread);
+ * supported keys in the map include: tags (add'l tags to put on the resulting task),
+ * description (string), and others as described in the reference below
+ *
+ * @see ExecutionManager#submit(Map, Task)
+ */
+ @Override
+ public Task<?> submit(Map<?,?> properties, Runnable runnable) { return submitInternal(properties, runnable); }
+
+ /** @see #submit(Map, Runnable) */
+ @Override
+ public Task<?> submit(Runnable runnable) { return submitInternal(Maps.newLinkedHashMap(), runnable); }
+
+ /** @see #submit(Map, Runnable) */
+ @Override
+ public <T> Task<T> submit(Callable<T> callable) { return submitInternal(Maps.newLinkedHashMap(), callable); }
+
+ /** @see #submit(Map, Runnable) */
+ @Override
+ public <T> Task<T> submit(Map<?,?> properties, Callable<T> callable) { return submitInternal(properties, callable); }
+
+ /** @see #submit(Map, Runnable) */
+ @Override
+ public <T> Task<T> submit(TaskAdaptable<T> task) { return submitInternal(Maps.newLinkedHashMap(), task.asTask()); }
+
+ /** @see #submit(Map, Runnable) */
+ @Override
+ public <T> Task<T> submit(Map<?,?> properties, TaskAdaptable<T> task) { return submitInternal(properties, task.asTask()); }
+
+ /**
+ * Provided for compatibility
+ *
+ * Submit is preferred if a handle on the resulting Task is desired (although a task can be passed in so this is not always necessary)
+ *
+ * @see #submit(Map, Runnable)
+ */
+ public void execute(Runnable r) { submit(r); }
+
+ /** does the work internally of submitting the task; note that the return value may be a wrapper task even if a task is passed in,
+ * if the execution context where the target should run is different (e.g. submitting an effector task cross-context) */
+ protected abstract <T> Task<T> submitInternal(Map<?,?> properties, Object task);
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/BasicExecutionContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/BasicExecutionContext.java b/core/src/main/java/org/apache/brooklyn/core/util/task/BasicExecutionContext.java
new file mode 100644
index 0000000..1d28b4e
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/BasicExecutionContext.java
@@ -0,0 +1,221 @@
+/*
+ * 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.util.task;
+
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.management.ExecutionContext;
+import org.apache.brooklyn.api.management.ExecutionManager;
+import org.apache.brooklyn.api.management.HasTaskChildren;
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.api.management.TaskAdaptable;
+import org.apache.brooklyn.api.management.entitlement.EntitlementContext;
+import org.apache.brooklyn.core.management.entitlement.Entitlements;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.entity.basic.BrooklynTaskTags;
+import brooklyn.entity.basic.BrooklynTaskTags.WrappedEntity;
+import brooklyn.entity.basic.EntityInternal;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
+
+/**
+ * A means of executing tasks against an ExecutionManager with a given bucket/set of tags pre-defined
+ * (so that it can look like an {@link Executor} and also supply {@link ExecutorService#submit(Callable)}
+ */
+public class BasicExecutionContext extends AbstractExecutionContext {
+
+ private static final Logger log = LoggerFactory.getLogger(BasicExecutionContext.class);
+
+ static final ThreadLocal<BasicExecutionContext> perThreadExecutionContext = new ThreadLocal<BasicExecutionContext>();
+
+ public static BasicExecutionContext getCurrentExecutionContext() { return perThreadExecutionContext.get(); }
+
+ final ExecutionManager executionManager;
+ final Set<Object> tags = new LinkedHashSet<Object>();
+
+ public BasicExecutionContext(ExecutionManager executionManager) {
+ this(Collections.emptyMap(), executionManager);
+ }
+
+ /**
+ * Supported flags are {@code tag} and {@code tags}
+ *
+ * @see ExecutionManager#submit(Map, Task)
+ */
+ public BasicExecutionContext(Map<?, ?> flags, ExecutionManager executionManager) {
+ this.executionManager = executionManager;
+
+ if (flags.get("tag") != null) tags.add(flags.remove("tag"));
+ if (flags.containsKey("tags")) tags.addAll((Collection<?>)flags.remove("tags"));
+
+ // FIXME brooklyn-specific check, just for sanity
+ // the context tag should always be a non-proxy entity, because that is what is passed to effector tasks
+ // which may require access to internal methods
+ for (Object tag: tags) {
+ if (tag instanceof BrooklynTaskTags.WrappedEntity) {
+ if (Proxy.isProxyClass(((WrappedEntity)tag).entity.getClass())) {
+ log.warn(""+this+" has entity proxy in "+tag);
+ }
+ }
+ }
+ }
+
+ public ExecutionManager getExecutionManager() {
+ return executionManager;
+ }
+
+ /** returns tasks started by this context (or tasks which have all the tags on this object) */
+ public Set<Task<?>> getTasks() { return executionManager.getTasksWithAllTags((Set<?>)tags); }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Override
+ protected <T> Task<T> submitInternal(Map<?,?> propertiesQ, final Object task) {
+ if (task instanceof TaskAdaptable<?> && !(task instanceof Task<?>))
+ return submitInternal(propertiesQ, ((TaskAdaptable<?>)task).asTask());
+
+ Map properties = propertiesQ;
+ if (properties.get("tags")==null) properties.put("tags", new ArrayList());
+ Collection taskTags = (Collection)properties.get("tags");
+
+ // FIXME some of this is brooklyn-specific logic, should be moved to a BrooklynExecContext subclass;
+ // the issue is that we want to ensure that cross-entity calls switch execution contexts;
+ // previously it was all very messy how that was handled (and it didn't really handle it in many cases)
+ if (task instanceof Task<?>) taskTags.addAll( ((Task<?>)task).getTags() );
+ Entity target = BrooklynTaskTags.getWrappedEntityOfType(taskTags, BrooklynTaskTags.TARGET_ENTITY);
+
+ if (target!=null && !tags.contains(BrooklynTaskTags.tagForContextEntity(target))) {
+ // task is switching execution context boundaries
+ /*
+ * longer notes:
+ * you fall in to this block if the caller requests a target entity different to the current context
+ * (e.g. where entity X is invoking an effector on Y, it will start in X's context,
+ * but the effector should run in Y's context).
+ *
+ * if X is invoking an effector on himself in his own context, or a sensor or other task, it will not come in to this block.
+ */
+ final ExecutionContext tc = ((EntityInternal)target).getExecutionContext();
+ if (log.isDebugEnabled())
+ log.debug("Switching task context on execution of "+task+": from "+this+" to "+target+" (in "+Tasks.current()+")");
+
+ if (task instanceof Task<?>) {
+ final Task<T> t = (Task<T>)task;
+ if (!Tasks.isQueuedOrSubmitted(t) && (!(Tasks.current() instanceof HasTaskChildren) ||
+ !Iterables.contains( ((HasTaskChildren)Tasks.current()).getChildren(), t ))) {
+ // this task is switching execution context boundaries _and_ it is not a child and not yet queued,
+ // so wrap it in a task running in this context to keep a reference to the child
+ // (this matters when we are navigating in the GUI; without it we lose the reference to the child
+ // when browsing in the context of the parent)
+ return submit(Tasks.<T>builder().name("Cross-context execution: "+t.getDescription()).dynamic(true).body(new Callable<T>() {
+ public T call() {
+ return DynamicTasks.get(t);
+ }
+ }).build());
+ } else {
+ // if we are already tracked by parent, just submit it
+ return tc.submit(t);
+ }
+ } else {
+ // as above, but here we are definitely not a child (what we are submitting isn't even a task)
+ // (will only come here if properties defines tags including a target entity, which probably never happens)
+ submit(Tasks.<T>builder().name("Cross-context execution").dynamic(true).body(new Callable<T>() {
+ public T call() {
+ if (task instanceof Callable) {
+ return DynamicTasks.queue( Tasks.<T>builder().dynamic(false).body((Callable<T>)task).build() ).getUnchecked();
+ } else if (task instanceof Runnable) {
+ return DynamicTasks.queue( Tasks.<T>builder().dynamic(false).body((Runnable)task).build() ).getUnchecked();
+ } else {
+ throw new IllegalArgumentException("Unhandled task type: "+task+"; type="+(task!=null ? task.getClass() : "null"));
+ }
+ }
+ }).build());
+ }
+ }
+
+ EntitlementContext entitlementContext = BrooklynTaskTags.getEntitlement(taskTags);
+ if (entitlementContext==null)
+ entitlementContext = Entitlements.getEntitlementContext();
+ if (entitlementContext!=null) {
+ taskTags.add(BrooklynTaskTags.tagForEntitlement(entitlementContext));
+ }
+
+ taskTags.addAll(tags);
+
+ if (Tasks.current()!=null && BrooklynTaskTags.isTransient(Tasks.current())
+ && !taskTags.contains(BrooklynTaskTags.NON_TRANSIENT_TASK_TAG) && !taskTags.contains(BrooklynTaskTags.TRANSIENT_TASK_TAG)) {
+ // tag as transient if submitter is transient, unless explicitly tagged as non-transient
+ taskTags.add(BrooklynTaskTags.TRANSIENT_TASK_TAG);
+ }
+
+ final Object startCallback = properties.get("newTaskStartCallback");
+ properties.put("newTaskStartCallback", new Function<Object,Void>() {
+ public Void apply(Object it) {
+ registerPerThreadExecutionContext();
+ if (startCallback!=null) ExecutionUtils.invoke(startCallback, it);
+ return null;
+ }});
+
+ final Object endCallback = properties.get("newTaskEndCallback");
+ properties.put("newTaskEndCallback", new Function<Object,Void>() {
+ public Void apply(Object it) {
+ try {
+ if (endCallback!=null) ExecutionUtils.invoke(endCallback, it);
+ } finally {
+ clearPerThreadExecutionContext();
+ }
+ return null;
+ }});
+
+ if (task instanceof Task) {
+ return executionManager.submit(properties, (Task)task);
+ } else if (task instanceof Callable) {
+ return executionManager.submit(properties, (Callable)task);
+ } else if (task instanceof Runnable) {
+ return (Task<T>) executionManager.submit(properties, (Runnable)task);
+ } else {
+ throw new IllegalArgumentException("Unhandled task type: task="+task+"; type="+(task!=null ? task.getClass() : "null"));
+ }
+ }
+
+ private void registerPerThreadExecutionContext() { perThreadExecutionContext.set(this); }
+
+ private void clearPerThreadExecutionContext() { perThreadExecutionContext.remove(); }
+
+ @Override
+ public boolean isShutdown() {
+ return getExecutionManager().isShutdown();
+ }
+
+ @Override
+ public String toString() {
+ return super.toString()+"("+tags+")";
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/BasicExecutionManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/BasicExecutionManager.java b/core/src/main/java/org/apache/brooklyn/core/util/task/BasicExecutionManager.java
new file mode 100644
index 0000000..f93abe1
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/BasicExecutionManager.java
@@ -0,0 +1,755 @@
+/*
+ * 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.util.task;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.brooklyn.api.management.ExecutionManager;
+import org.apache.brooklyn.api.management.HasTaskChildren;
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.api.management.TaskAdaptable;
+import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.text.Identifiers;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.CaseFormat;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Sets;
+import com.google.common.util.concurrent.ExecutionList;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+
+/**
+ * Manages the execution of atomic tasks and scheduled (recurring) tasks,
+ * including setting tags and invoking callbacks.
+ */
+public class BasicExecutionManager implements ExecutionManager {
+ private static final Logger log = LoggerFactory.getLogger(BasicExecutionManager.class);
+
+ private static final boolean RENAME_THREADS = BrooklynFeatureEnablement.isEnabled(BrooklynFeatureEnablement.FEATURE_RENAME_THREADS);
+
+ private static class PerThreadCurrentTaskHolder {
+ public static final ThreadLocal<Task<?>> perThreadCurrentTask = new ThreadLocal<Task<?>>();
+ }
+
+ public static ThreadLocal<Task<?>> getPerThreadCurrentTask() {
+ return PerThreadCurrentTaskHolder.perThreadCurrentTask;
+ }
+
+ private final ThreadFactory threadFactory;
+
+ private final ThreadFactory daemonThreadFactory;
+
+ private final ExecutorService runner;
+
+ private final ScheduledExecutorService delayedRunner;
+
+ // TODO Could have a set of all knownTasks; but instead we're having a separate set per tag,
+ // so the same task could be listed multiple times if it has multiple tags...
+
+ //access to this field AND to members in this field is synchronized,
+ //to allow us to preserve order while guaranteeing thread-safe
+ //(but more testing is needed before we are completely sure it is thread-safe!)
+ //synch blocks are as finely grained as possible for efficiency;
+ //NB CopyOnWriteArraySet is a perf bottleneck, and the simple map makes it easier to remove when a tag is empty
+ private Map<Object,Set<Task<?>>> tasksByTag = new HashMap<Object,Set<Task<?>>>();
+
+ private ConcurrentMap<String,Task<?>> tasksById = new ConcurrentHashMap<String,Task<?>>();
+
+ private ConcurrentMap<Object, TaskScheduler> schedulerByTag = new ConcurrentHashMap<Object, TaskScheduler>();
+
+ /** count of all tasks submitted, including finished */
+ private final AtomicLong totalTaskCount = new AtomicLong();
+
+ /** tasks submitted but not yet done (or in cases of interruption/cancelled not yet GC'd) */
+ private Map<String,String> incompleteTaskIds = new ConcurrentHashMap<String,String>();
+
+ /** tasks started but not yet finished */
+ private final AtomicInteger activeTaskCount = new AtomicInteger();
+
+ private final List<ExecutionListener> listeners = new CopyOnWriteArrayList<ExecutionListener>();
+
+ private final static ThreadLocal<String> threadOriginalName = new ThreadLocal<String>() {
+ protected String initialValue() {
+ // should not happen, as only access is in _afterEnd with a check that _beforeStart was invoked
+ log.warn("No original name recorded for thread "+Thread.currentThread().getName()+"; task "+Tasks.current());
+ return "brooklyn-thread-pool-"+Identifiers.makeRandomId(8);
+ }
+ };
+
+ public BasicExecutionManager(String contextid) {
+ threadFactory = newThreadFactory(contextid);
+ daemonThreadFactory = new ThreadFactoryBuilder()
+ .setThreadFactory(threadFactory)
+ .setDaemon(true)
+ .build();
+
+ // use Executors.newCachedThreadPool(daemonThreadFactory), but timeout of 1s rather than 60s for better shutdown!
+ runner = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 10L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(),
+ daemonThreadFactory);
+
+ delayedRunner = new ScheduledThreadPoolExecutor(1, daemonThreadFactory);
+ }
+
+ private final static class UncaughtExceptionHandlerImplementation implements Thread.UncaughtExceptionHandler {
+ @Override
+ public void uncaughtException(Thread t, Throwable e) {
+ log.error("Uncaught exception in thread "+t.getName(), e);
+ }
+ }
+
+ /**
+ * For use by overriders to use custom thread factory.
+ * But be extremely careful: called by constructor, so before sub-class' constructor will
+ * have been invoked!
+ */
+ protected ThreadFactory newThreadFactory(String contextid) {
+ return new ThreadFactoryBuilder()
+ .setNameFormat("brooklyn-execmanager-"+contextid+"-%d")
+ .setUncaughtExceptionHandler(new UncaughtExceptionHandlerImplementation())
+ .build();
+ }
+
+ public void shutdownNow() {
+ runner.shutdownNow();
+ delayedRunner.shutdownNow();
+ }
+
+ public void addListener(ExecutionListener listener) {
+ listeners.add(listener);
+ }
+
+ public void removeListener(ExecutionListener listener) {
+ listeners.remove(listener);
+ }
+
+ /**
+ * Deletes the given tag, including all tasks using this tag.
+ *
+ * Useful, for example, if an entity is being expunged so that we don't keep holding
+ * a reference to it as a tag.
+ */
+ public void deleteTag(Object tag) {
+ Set<Task<?>> tasks;
+ synchronized (tasksByTag) {
+ tasks = tasksByTag.remove(tag);
+ }
+ if (tasks != null) {
+ for (Task<?> task : tasks) {
+ deleteTask(task);
+ }
+ }
+ }
+
+ public void deleteTask(Task<?> task) {
+ boolean removed = deleteTaskNonRecursive(task);
+ if (!removed) return;
+
+ if (task instanceof HasTaskChildren) {
+ List<Task<?>> children = ImmutableList.copyOf(((HasTaskChildren)task).getChildren());
+ for (Task<?> child : children) {
+ deleteTask(child);
+ }
+ }
+ }
+
+ protected boolean deleteTaskNonRecursive(Task<?> task) {
+ Set<?> tags = checkNotNull(task, "task").getTags();
+ for (Object tag : tags) {
+ synchronized (tasksByTag) {
+ Set<Task<?>> tasks = tasksWithTagLiveOrNull(tag);
+ if (tasks != null) {
+ tasks.remove(task);
+ if (tasks.isEmpty()) {
+ tasksByTag.remove(tag);
+ }
+ }
+ }
+ }
+ Task<?> removed = tasksById.remove(task.getId());
+ incompleteTaskIds.remove(task.getId());
+ if (removed!=null && removed.isSubmitted() && !removed.isDone()) {
+ log.warn("Deleting submitted task before completion: "+removed+"; this task will continue to run in the background outwith "+this+", but perhaps it should have been cancelled?");
+ }
+ return removed != null;
+ }
+
+ public boolean isShutdown() {
+ return runner.isShutdown();
+ }
+
+ /** count of all tasks submitted */
+ public long getTotalTasksSubmitted() {
+ return totalTaskCount.get();
+ }
+
+ /** count of tasks submitted but not ended */
+ public long getNumIncompleteTasks() {
+ return incompleteTaskIds.size();
+ }
+
+ /** count of tasks started but not ended */
+ public long getNumActiveTasks() {
+ return activeTaskCount.get();
+ }
+
+ /** count of tasks kept in memory, often including ended tasks */
+ public long getNumInMemoryTasks() {
+ return tasksById.size();
+ }
+
+ private Set<Task<?>> tasksWithTagCreating(Object tag) {
+ Preconditions.checkNotNull(tag);
+ synchronized (tasksByTag) {
+ Set<Task<?>> result = tasksWithTagLiveOrNull(tag);
+ if (result==null) {
+ result = Collections.synchronizedSet(new LinkedHashSet<Task<?>>());
+ tasksByTag.put(tag, result);
+ }
+ return result;
+ }
+ }
+
+ /** exposes live view, for internal use only */
+ @Beta
+ public Set<Task<?>> tasksWithTagLiveOrNull(Object tag) {
+ synchronized (tasksByTag) {
+ return tasksByTag.get(tag);
+ }
+ }
+
+ @Override
+ public Task<?> getTask(String id) {
+ return tasksById.get(id);
+ }
+
+ /** not on interface because potentially expensive */
+ public List<Task<?>> getAllTasks() {
+ // not sure if synching makes any difference; have not observed CME's yet
+ // (and so far this is only called when a CME was caught on a previous operation)
+ synchronized (tasksById) {
+ return MutableList.copyOf(tasksById.values());
+ }
+ }
+
+ @Override
+ public Set<Task<?>> getTasksWithTag(Object tag) {
+ Set<Task<?>> result = tasksWithTagLiveOrNull(tag);
+ if (result==null) return Collections.emptySet();
+ synchronized (result) {
+ return (Set<Task<?>>)Collections.unmodifiableSet(new LinkedHashSet<Task<?>>(result));
+ }
+ }
+
+ @Override
+ public Set<Task<?>> getTasksWithAnyTag(Iterable<?> tags) {
+ Set<Task<?>> result = new LinkedHashSet<Task<?>>();
+ Iterator<?> ti = tags.iterator();
+ while (ti.hasNext()) {
+ Set<Task<?>> tasksForTag = tasksWithTagLiveOrNull(ti.next());
+ if (tasksForTag!=null) {
+ synchronized (tasksForTag) {
+ result.addAll(tasksForTag);
+ }
+ }
+ }
+ return Collections.unmodifiableSet(result);
+ }
+
+ /** only works with at least one tag; returns empty if no tags */
+ @Override
+ public Set<Task<?>> getTasksWithAllTags(Iterable<?> tags) {
+ //NB: for this method retrieval for multiple tags could be made (much) more efficient (if/when it is used with multiple tags!)
+ //by first looking for the least-used tag, getting those tasks, and then for each of those tasks
+ //checking whether it contains the other tags (looking for second-least used, then third-least used, etc)
+ Set<Task<?>> result = new LinkedHashSet<Task<?>>();
+ boolean first = true;
+ Iterator<?> ti = tags.iterator();
+ while (ti.hasNext()) {
+ Object tag = ti.next();
+ if (first) {
+ first = false;
+ result.addAll(getTasksWithTag(tag));
+ } else {
+ result.retainAll(getTasksWithTag(tag));
+ }
+ }
+ return Collections.unmodifiableSet(result);
+ }
+
+ /** live view of all tasks, for internal use only */
+ @Beta
+ public Collection<Task<?>> allTasksLive() { return tasksById.values(); }
+
+ public Set<Object> getTaskTags() {
+ synchronized (tasksByTag) {
+ return Collections.unmodifiableSet(Sets.newLinkedHashSet(tasksByTag.keySet()));
+ }
+ }
+
+ public Task<?> submit(Runnable r) { return submit(new LinkedHashMap<Object,Object>(1), r); }
+ public Task<?> submit(Map<?,?> flags, Runnable r) { return submit(flags, new BasicTask<Void>(flags, r)); }
+
+ public <T> Task<T> submit(Callable<T> c) { return submit(new LinkedHashMap<Object,Object>(1), c); }
+ public <T> Task<T> submit(Map<?,?> flags, Callable<T> c) { return submit(flags, new BasicTask<T>(flags, c)); }
+
+ public <T> Task<T> submit(TaskAdaptable<T> t) { return submit(new LinkedHashMap<Object,Object>(1), t); }
+ public <T> Task<T> submit(Map<?,?> flags, TaskAdaptable<T> task) {
+ if (!(task instanceof Task))
+ task = task.asTask();
+ synchronized (task) {
+ if (((TaskInternal<?>)task).getInternalFuture()!=null) return (Task<T>)task;
+ return submitNewTask(flags, (Task<T>) task);
+ }
+ }
+
+ public <T> Task<T> scheduleWith(Task<T> task) { return scheduleWith(Collections.emptyMap(), task); }
+ public <T> Task<T> scheduleWith(Map<?,?> flags, Task<T> task) {
+ synchronized (task) {
+ if (((TaskInternal<?>)task).getInternalFuture()!=null) return task;
+ return submitNewTask(flags, task);
+ }
+ }
+
+ protected Task<?> submitNewScheduledTask(final Map<?,?> flags, final ScheduledTask task) {
+ tasksById.put(task.getId(), task);
+ totalTaskCount.incrementAndGet();
+
+ beforeSubmitScheduledTaskAllIterations(flags, task);
+
+ return submitSubsequentScheduledTask(flags, task);
+ }
+
+ @SuppressWarnings("unchecked")
+ protected Task<?> submitSubsequentScheduledTask(final Map<?,?> flags, final ScheduledTask task) {
+ if (!task.isDone()) {
+ task.internalFuture = delayedRunner.schedule(new ScheduledTaskCallable(task, flags),
+ task.delay.toNanoseconds(), TimeUnit.NANOSECONDS);
+ } else {
+ afterEndScheduledTaskAllIterations(flags, task);
+ }
+ return task;
+ }
+
+ protected class ScheduledTaskCallable implements Callable<Object> {
+ public ScheduledTask task;
+ public Map<?,?> flags;
+
+ public ScheduledTaskCallable(ScheduledTask task, Map<?, ?> flags) {
+ this.task = task;
+ this.flags = flags;
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ public Object call() {
+ if (task.startTimeUtc==-1) task.startTimeUtc = System.currentTimeMillis();
+ TaskInternal<?> taskScheduled = null;
+ try {
+ beforeStartScheduledTaskSubmissionIteration(flags, task);
+ taskScheduled = (TaskInternal<?>) task.newTask();
+ taskScheduled.setSubmittedByTask(task);
+ final Callable<?> oldJob = taskScheduled.getJob();
+ final TaskInternal<?> taskScheduledF = taskScheduled;
+ taskScheduled.setJob(new Callable() { public Object call() {
+ boolean resubmitted = false;
+ task.recentRun = taskScheduledF;
+ try {
+ synchronized (task) {
+ task.notifyAll();
+ }
+ Object result;
+ try {
+ result = oldJob.call();
+ } catch (Exception e) {
+ if (!Tasks.isInterrupted()) {
+ log.warn("Error executing "+oldJob+" (scheduled job of "+task+" - "+task.getDescription()+"); cancelling scheduled execution", e);
+ } else {
+ log.debug("Interrupted executing "+oldJob+" (scheduled job of "+task+" - "+task.getDescription()+"); cancelling scheduled execution: "+e);
+ }
+ throw Exceptions.propagate(e);
+ }
+ task.runCount++;
+ if (task.period!=null && !task.isCancelled()) {
+ task.delay = task.period;
+ submitSubsequentScheduledTask(flags, task);
+ resubmitted = true;
+ }
+ return result;
+ } finally {
+ // do in finally block in case we were interrupted
+ if (!resubmitted)
+ afterEndScheduledTaskAllIterations(flags, task);
+ }
+ }});
+ task.nextRun = taskScheduled;
+ BasicExecutionContext ec = BasicExecutionContext.getCurrentExecutionContext();
+ if (ec!=null) return ec.submit(taskScheduled);
+ else return submit(taskScheduled);
+ } finally {
+ afterEndScheduledTaskSubmissionIteration(flags, task, taskScheduled);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "ScheduledTaskCallable["+task+","+flags+"]";
+ }
+ }
+
+ private final class SubmissionCallable<T> implements Callable<T> {
+ private final Map<?, ?> flags;
+ private final Task<T> task;
+
+ private SubmissionCallable(Map<?, ?> flags, Task<T> task) {
+ this.flags = flags;
+ this.task = task;
+ }
+
+ public T call() {
+ try {
+ T result = null;
+ Throwable error = null;
+ String oldThreadName = Thread.currentThread().getName();
+ try {
+ if (RENAME_THREADS) {
+ String newThreadName = oldThreadName+"-"+task.getDisplayName()+
+ "["+task.getId().substring(0, 8)+"]";
+ Thread.currentThread().setName(newThreadName);
+ }
+ beforeStartAtomicTask(flags, task);
+ if (!task.isCancelled()) {
+ result = ((TaskInternal<T>)task).getJob().call();
+ } else throw new CancellationException();
+ } catch(Throwable e) {
+ error = e;
+ } finally {
+ if (RENAME_THREADS) {
+ Thread.currentThread().setName(oldThreadName);
+ }
+ afterEndAtomicTask(flags, task);
+ }
+ if (error!=null) {
+ /* we throw, after logging debug.
+ * the throw means the error is available for task submitters to monitor.
+ * however it is possible no one is monitoring it, in which case we will have debug logging only for errors.
+ * (the alternative, of warn-level logging in lots of places where we don't want it, seems worse!)
+ */
+ if (log.isDebugEnabled()) {
+ // debug only here, because most submitters will handle failures
+ log.debug("Exception running task "+task+" (rethrowing): "+error.getMessage(), error);
+ if (log.isTraceEnabled())
+ log.trace("Trace for exception running task "+task+" (rethrowing): "+error.getMessage(), error);
+ }
+ throw Exceptions.propagate(error);
+ }
+ return result;
+ } finally {
+ ((TaskInternal<?>)task).runListeners();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "BEM.call("+task+","+flags+")";
+ }
+ }
+
+ private final static class ListenableForwardingFutureForTask<T> extends ListenableForwardingFuture<T> {
+ private final Task<T> task;
+
+ private ListenableForwardingFutureForTask(Future<T> delegate, ExecutionList list, Task<T> task) {
+ super(delegate, list);
+ this.task = task;
+ }
+
+ @Override
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ boolean result = false;
+ if (!task.isCancelled()) result |= task.cancel(mayInterruptIfRunning);
+ result |= super.cancel(mayInterruptIfRunning);
+ ((TaskInternal<?>)task).runListeners();
+ return result;
+ }
+ }
+
+ private final class SubmissionListenerToCallOtherListeners<T> implements Runnable {
+ private final Task<T> task;
+
+ private SubmissionListenerToCallOtherListeners(Task<T> task) {
+ this.task = task;
+ }
+
+ @Override
+ public void run() {
+ try {
+ ((TaskInternal<?>)task).runListeners();
+ } catch (Exception e) {
+ log.warn("Error running task listeners for task "+task+" done", e);
+ }
+
+ for (ExecutionListener listener : listeners) {
+ try {
+ listener.onTaskDone(task);
+ } catch (Exception e) {
+ log.warn("Error running execution listener "+listener+" of task "+task+" done", e);
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ protected <T> Task<T> submitNewTask(final Map<?,?> flags, final Task<T> task) {
+ if (task instanceof ScheduledTask)
+ return (Task<T>) submitNewScheduledTask(flags, (ScheduledTask)task);
+
+ tasksById.put(task.getId(), task);
+ totalTaskCount.incrementAndGet();
+
+ beforeSubmitAtomicTask(flags, task);
+
+ if (((TaskInternal<T>)task).getJob() == null)
+ throw new NullPointerException("Task "+task+" submitted with with null job: job must be supplied.");
+
+ Callable<T> job = new SubmissionCallable<T>(flags, task);
+
+ // If there's a scheduler then use that; otherwise execute it directly
+ Set<TaskScheduler> schedulers = null;
+ for (Object tago: task.getTags()) {
+ TaskScheduler scheduler = getTaskSchedulerForTag(tago);
+ if (scheduler!=null) {
+ if (schedulers==null) schedulers = new LinkedHashSet<TaskScheduler>(2);
+ schedulers.add(scheduler);
+ }
+ }
+ Future<T> future;
+ if (schedulers!=null && !schedulers.isEmpty()) {
+ if (schedulers.size()>1) log.warn("multiple schedulers detected, using only the first, for "+task+": "+schedulers);
+ future = schedulers.iterator().next().submit(job);
+ } else {
+ future = runner.submit(job);
+ }
+ // on completion, listeners get triggered above; here, below we ensure they get triggered on cancel
+ // (and we make sure the same ExecutionList is used in the future as in the task)
+ ListenableFuture<T> listenableFuture = new ListenableForwardingFutureForTask<T>(future, ((TaskInternal<T>)task).getListeners(), task);
+ // doesn't matter whether the listener is added to the listenableFuture or the task,
+ // except that for the task we can more easily wrap it so that it only logs debug if the executor is shutdown
+ // (avoid a bunch of ugly warnings in tests which start and stop things a lot!)
+ // [probably even nicer to run this in the same thread, it doesn't do much; but that is messier to implement]
+ ((TaskInternal<T>)task).addListener(new SubmissionListenerToCallOtherListeners<T>(task), runner);
+
+ ((TaskInternal<T>)task).initInternalFuture(listenableFuture);
+
+ return task;
+ }
+
+ protected void beforeSubmitScheduledTaskAllIterations(Map<?,?> flags, Task<?> task) {
+ internalBeforeSubmit(flags, task);
+ }
+ protected void beforeSubmitAtomicTask(Map<?,?> flags, Task<?> task) {
+ internalBeforeSubmit(flags, task);
+ }
+ /** invoked when a task is submitted */
+ protected void internalBeforeSubmit(Map<?,?> flags, Task<?> task) {
+ incompleteTaskIds.put(task.getId(), task.getId());
+
+ Task<?> currentTask = Tasks.current();
+ if (currentTask!=null) ((TaskInternal<?>)task).setSubmittedByTask(currentTask);
+ ((TaskInternal<?>)task).setSubmitTimeUtc(System.currentTimeMillis());
+
+ if (flags.get("tag")!=null) ((TaskInternal<?>)task).getMutableTags().add(flags.remove("tag"));
+ if (flags.get("tags")!=null) ((TaskInternal<?>)task).getMutableTags().addAll((Collection<?>)flags.remove("tags"));
+
+ for (Object tag: ((TaskInternal<?>)task).getTags()) {
+ tasksWithTagCreating(tag).add(task);
+ }
+ }
+
+ protected void beforeStartScheduledTaskSubmissionIteration(Map<?,?> flags, Task<?> task) {
+ internalBeforeStart(flags, task);
+ }
+ protected void beforeStartAtomicTask(Map<?,?> flags, Task<?> task) {
+ internalBeforeStart(flags, task);
+ }
+
+ /** invoked in a task's thread when a task is starting to run (may be some time after submitted),
+ * but before doing any of the task's work, so that we can update bookkeeping and notify callbacks */
+ protected void internalBeforeStart(Map<?,?> flags, Task<?> task) {
+ activeTaskCount.incrementAndGet();
+
+ //set thread _before_ start time, so we won't get a null thread when there is a start-time
+ if (log.isTraceEnabled()) log.trace(""+this+" beforeStart, task: "+task);
+ if (!task.isCancelled()) {
+ Thread thread = Thread.currentThread();
+ ((TaskInternal<?>)task).setThread(thread);
+ if (RENAME_THREADS) {
+ threadOriginalName.set(thread.getName());
+ String newThreadName = "brooklyn-" + CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, task.getDisplayName().replace(" ", "")) + "-" + task.getId().substring(0, 8);
+ thread.setName(newThreadName);
+ }
+ PerThreadCurrentTaskHolder.perThreadCurrentTask.set(task);
+ ((TaskInternal<?>)task).setStartTimeUtc(System.currentTimeMillis());
+ }
+ ExecutionUtils.invoke(flags.get("newTaskStartCallback"), task);
+ }
+
+ /** normally (if not interrupted) called once for each call to {@link #beforeSubmitScheduledTaskAllIterations(Map, Task)} */
+ protected void afterEndScheduledTaskAllIterations(Map<?,?> flags, Task<?> task) {
+ internalAfterEnd(flags, task, false, true);
+ }
+ /** called once for each call to {@link #beforeStartScheduledTaskSubmissionIteration(Map, Task)},
+ * with a per-iteration task generated by the surrounding scheduled task */
+ protected void afterEndScheduledTaskSubmissionIteration(Map<?,?> flags, Task<?> scheduledTask, Task<?> taskIteration) {
+ internalAfterEnd(flags, scheduledTask, true, false);
+ }
+ /** called once for each task on which {@link #beforeStartAtomicTask(Map, Task)} is invoked,
+ * and normally (if not interrupted prior to start)
+ * called once for each task on which {@link #beforeSubmitAtomicTask(Map, Task)} */
+ protected void afterEndAtomicTask(Map<?,?> flags, Task<?> task) {
+ internalAfterEnd(flags, task, true, true);
+ }
+ /** normally (if not interrupted) called once for each call to {@link #internalBeforeSubmit(Map, Task)},
+ * and, for atomic tasks and scheduled-task submission iterations where
+ * always called once if {@link #internalBeforeStart(Map, Task)} is invoked and in the same thread as that method */
+ protected void internalAfterEnd(Map<?,?> flags, Task<?> task, boolean startedInThisThread, boolean isEndingAllIterations) {
+ if (log.isTraceEnabled()) log.trace(this+" afterEnd, task: "+task);
+ if (startedInThisThread) {
+ activeTaskCount.decrementAndGet();
+ }
+ if (isEndingAllIterations) {
+ incompleteTaskIds.remove(task.getId());
+ ExecutionUtils.invoke(flags.get("newTaskEndCallback"), task);
+ ((TaskInternal<?>)task).setEndTimeUtc(System.currentTimeMillis());
+ }
+
+ if (startedInThisThread) {
+ PerThreadCurrentTaskHolder.perThreadCurrentTask.remove();
+ //clear thread _after_ endTime set, so we won't get a null thread when there is no end-time
+ if (RENAME_THREADS && startedInThisThread) {
+ Thread thread = task.getThread();
+ if (thread==null) {
+ log.warn("BasicTask.afterEnd invoked without corresponding beforeStart");
+ } else {
+ thread.setName(threadOriginalName.get());
+ threadOriginalName.remove();
+ }
+ }
+ ((TaskInternal<?>)task).setThread(null);
+ }
+ synchronized (task) { task.notifyAll(); }
+ }
+
+ public TaskScheduler getTaskSchedulerForTag(Object tag) {
+ return schedulerByTag.get(tag);
+ }
+
+ public void setTaskSchedulerForTag(Object tag, Class<? extends TaskScheduler> scheduler) {
+ synchronized (schedulerByTag) {
+ TaskScheduler old = getTaskSchedulerForTag(tag);
+ if (old!=null) {
+ if (scheduler.isAssignableFrom(old.getClass())) {
+ /* already have such an instance */
+ return;
+ }
+ //might support multiple in future...
+ throw new IllegalStateException("Not allowed to set multiple TaskSchedulers on ExecutionManager tag (tag "+tag+", has "+old+", setting new "+scheduler+")");
+ }
+ try {
+ TaskScheduler schedulerI = scheduler.newInstance();
+ // allow scheduler to have a nice name, for logging etc
+ if (schedulerI instanceof CanSetName) ((CanSetName)schedulerI).setName(""+tag);
+ setTaskSchedulerForTag(tag, schedulerI);
+ } catch (InstantiationException e) {
+ throw Exceptions.propagate(e);
+ } catch (IllegalAccessException e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+ }
+
+ /**
+ * Defines a {@link TaskScheduler} to run on all subsequently submitted jobs with the given tag.
+ *
+ * Maximum of one allowed currently. Resubmissions of the same scheduler (or scheduler class)
+ * allowed. If changing, you must call {@link #clearTaskSchedulerForTag(Object)} between the two.
+ *
+ * @see #setTaskSchedulerForTag(Object, Class)
+ */
+ public void setTaskSchedulerForTag(Object tag, TaskScheduler scheduler) {
+ synchronized (schedulerByTag) {
+ scheduler.injectExecutor(runner);
+
+ Object old = schedulerByTag.put(tag, scheduler);
+ if (old!=null && old!=scheduler) {
+ //might support multiple in future...
+ throw new IllegalStateException("Not allowed to set multiple TaskSchedulers on ExecutionManager tag (tag "+tag+")");
+ }
+ }
+ }
+
+ /**
+ * Forgets that any scheduler was associated with a tag.
+ *
+ * @see #setTaskSchedulerForTag(Object, TaskScheduler)
+ * @see #setTaskSchedulerForTag(Object, Class)
+ */
+ public boolean clearTaskSchedulerForTag(Object tag) {
+ synchronized (schedulerByTag) {
+ Object old = schedulerByTag.remove(tag);
+ return (old!=null);
+ }
+ }
+
+ @VisibleForTesting
+ public ConcurrentMap<Object, TaskScheduler> getSchedulerByTag() {
+ return schedulerByTag;
+ }
+
+}
[12/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/ShellToolAbstractTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/ShellToolAbstractTest.java b/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/ShellToolAbstractTest.java
new file mode 100644
index 0000000..794a512
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/ShellToolAbstractTest.java
@@ -0,0 +1,441 @@
+/*
+ * 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.util.internal.ssh;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.internal.ssh.ShellTool;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.text.Identifiers;
+import brooklyn.util.time.Time;
+
+import com.google.common.base.Stopwatch;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
+public abstract class ShellToolAbstractTest {
+
+ protected List<ShellTool> tools = Lists.newArrayList();
+ protected List<String> filesCreated;
+ protected String localFilePath;
+
+ protected ShellTool tool;
+
+ protected ShellTool newTool() {
+ return newTool(MutableMap.<String,Object>of());
+ }
+
+ protected ShellTool newTool(Map<String,?> flags) {
+ ShellTool t = newUnregisteredTool(flags);
+ tools.add(t);
+ return t;
+ }
+
+ protected abstract ShellTool newUnregisteredTool(Map<String,?> flags);
+
+ protected ShellTool tool() { return tool; }
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ localFilePath = "/tmp/ssh-test-local-"+Identifiers.makeRandomId(8);
+ filesCreated = new ArrayList<String>();
+ filesCreated.add(localFilePath);
+
+ tool = newTool();
+ connect(tool);
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void afterMethod() throws Exception {
+ for (ShellTool t : tools) {
+ if (t instanceof SshTool) ((SshTool)t).disconnect();
+ }
+ for (String fileCreated : filesCreated) {
+ new File(fileCreated).delete();
+ }
+ }
+
+ protected static void connect(ShellTool tool) {
+ if (tool instanceof SshTool)
+ ((SshTool)tool).connect();
+ }
+
+ @Test(groups = {"Integration"})
+ public void testExecConsecutiveCommands() throws Exception {
+ String out = execScript("echo run1");
+ String out2 = execScript("echo run2");
+
+ assertTrue(out.contains("run1"), "out="+out);
+ assertTrue(out2.contains("run2"), "out="+out);
+ }
+
+ @Test(groups = {"Integration"})
+ public void testExecScriptChainOfCommands() throws Exception {
+ String out = execScript("export MYPROP=abc", "echo val is $MYPROP");
+
+ assertTrue(out.contains("val is abc"), "out="+out);
+ }
+
+ @Test(groups = {"Integration"})
+ public void testExecScriptReturningNonZeroExitCode() throws Exception {
+ int exitcode = tool.execScript(MutableMap.<String,Object>of(), ImmutableList.of("exit 123"));
+ assertEquals(exitcode, 123);
+ }
+
+ @Test(groups = {"Integration"})
+ public void testExecScriptReturningZeroExitCode() throws Exception {
+ int exitcode = tool.execScript(MutableMap.<String,Object>of(), ImmutableList.of("date"));
+ assertEquals(exitcode, 0);
+ }
+
+ @Test(groups = {"Integration"})
+ public void testExecScriptCommandWithEnvVariables() throws Exception {
+ String out = execScript(ImmutableList.of("echo val is $MYPROP2"), ImmutableMap.of("MYPROP2", "myval"));
+
+ assertTrue(out.contains("val is myval"), "out="+out);
+ }
+
+ @Test(groups = {"Integration"})
+ public void testScriptDataNotLost() throws Exception {
+ String out = execScript("echo `echo foo``echo bar`");
+
+ assertTrue(out.contains("foobar"), "out="+out);
+ }
+
+ @Test(groups = {"Integration"})
+ public void testExecScriptWithSleepThenExit() throws Exception {
+ Stopwatch watch = Stopwatch.createStarted();
+ execScript("sleep 1", "exit 0");
+ assertTrue(watch.elapsed(TimeUnit.MILLISECONDS) > 900, "only slept "+Time.makeTimeStringRounded(watch));
+ }
+
+ // Really just tests that it returns; the command will be echo'ed automatically so this doesn't assert the command will have been executed
+ @Test(groups = {"Integration"})
+ public void testExecScriptBigCommand() throws Exception {
+ String bigstring = Strings.repeat("a", 10000);
+ String out = execScript("echo "+bigstring);
+
+ assertTrue(out.contains(bigstring), "out="+out);
+ }
+
+ @Test(groups = {"Integration"})
+ public void testExecScriptBigChainOfCommand() throws Exception {
+ String bigstring = Strings.repeat("abcdefghij", 100); // 1KB
+ List<String> cmds = Lists.newArrayList();
+ for (int i = 0; i < 10; i++) {
+ cmds.add("export MYPROP"+i+"="+bigstring);
+ cmds.add("echo val"+i+" is $MYPROP"+i);
+ }
+ String out = execScript(cmds);
+
+ for (int i = 0; i < 10; i++) {
+ assertTrue(out.contains("val"+i+" is "+bigstring), "out="+out);
+ }
+ }
+
+ @Test(groups = {"Integration"})
+ public void testExecScriptAbortsOnCommandFailure() throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ int exitcode = tool.execScript(ImmutableMap.of("out", out), ImmutableList.of("export MYPROP=myval", "acmdthatdoesnotexist", "echo val is $MYPROP"));
+ String outstr = new String(out.toByteArray());
+
+ assertFalse(outstr.contains("val is myval"), "out="+out);
+ assertNotEquals(exitcode, 0);
+ }
+
+ @Test(groups = {"Integration"})
+ public void testExecScriptWithSleepThenBigCommand() throws Exception {
+ String bigstring = Strings.repeat("abcdefghij", 1000); // 10KB
+ String out = execScript("sleep 2", "export MYPROP="+bigstring, "echo val is $MYPROP");
+ assertTrue(out.contains("val is "+bigstring), "out="+out);
+ }
+
+ @Test(groups = {"WIP", "Integration"})
+ public void testExecScriptBigConcurrentCommand() throws Exception {
+ ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
+ List<ListenableFuture<?>> futures = new ArrayList<ListenableFuture<?>>();
+ try {
+ for (int i = 0; i < 10; i++) {
+ final ShellTool localtool = newTool();
+ connect(localtool);
+
+ futures.add(executor.submit(new Runnable() {
+ public void run() {
+ String bigstring = Strings.repeat("abcdefghij", 1000); // 10KB
+ String out = execScript(localtool, ImmutableList.of("export MYPROP="+bigstring, "echo val is $MYPROP"));
+ assertTrue(out.contains("val is "+bigstring), "outSize="+out.length()+"; out="+out);
+ }}));
+ }
+ Futures.allAsList(futures).get();
+ } finally {
+ executor.shutdownNow();
+ }
+ }
+
+ @Test(groups = {"WIP", "Integration"})
+ public void testExecScriptBigConcurrentSleepyCommand() throws Exception {
+ ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
+ List<ListenableFuture<?>> futures = new ArrayList<ListenableFuture<?>>();
+ try {
+ long starttime = System.currentTimeMillis();
+ for (int i = 0; i < 10; i++) {
+ final ShellTool localtool = newTool();
+ connect(localtool);
+
+ futures.add(executor.submit(new Runnable() {
+ public void run() {
+ String bigstring = Strings.repeat("abcdefghij", 1000); // 10KB
+ String out = execScript(localtool, ImmutableList.of("sleep 2", "export MYPROP="+bigstring, "echo val is $MYPROP"));
+ assertTrue(out.contains("val is "+bigstring), "out="+out);
+ }}));
+ }
+ Futures.allAsList(futures).get();
+ long runtime = System.currentTimeMillis() - starttime;
+
+ long OVERHEAD = 20*1000;
+ assertTrue(runtime < 2000+OVERHEAD, "runtime="+runtime);
+
+ } finally {
+ executor.shutdownNow();
+ }
+ }
+
+ @Test(groups = {"Integration"})
+ public void testExecChainOfCommands() throws Exception {
+ String out = execCommands("MYPROP=abc", "echo val is $MYPROP");
+
+ assertEquals(out, "val is abc\n");
+ }
+
+ @Test(groups = {"Integration"})
+ public void testExecReturningNonZeroExitCode() throws Exception {
+ int exitcode = tool.execCommands(MutableMap.<String,Object>of(), ImmutableList.of("exit 123"));
+ assertEquals(exitcode, 123);
+ }
+
+ @Test(groups = {"Integration"})
+ public void testExecReturningZeroExitCode() throws Exception {
+ int exitcode = tool.execCommands(MutableMap.<String,Object>of(), ImmutableList.of("date"));
+ assertEquals(exitcode, 0);
+ }
+
+ @Test(groups = {"Integration"})
+ public void testExecCommandWithEnvVariables() throws Exception {
+ String out = execCommands(ImmutableList.of("echo val is $MYPROP2"), ImmutableMap.of("MYPROP2", "myval"));
+
+ assertEquals(out, "val is myval\n");
+ }
+
+ @Test(groups = {"Integration"})
+ public void testExecBigCommand() throws Exception {
+ String bigstring = Strings.repeat("abcdefghij", 1000); // 10KB
+ String out = execCommands("echo "+bigstring);
+
+ assertEquals(out, bigstring+"\n", "actualSize="+out.length()+"; expectedSize="+bigstring.length());
+ }
+
+ @Test(groups = {"Integration"})
+ public void testExecBigConcurrentCommand() throws Exception {
+ runExecBigConcurrentCommand(10, 0L);
+ }
+
+ // TODO Fails I believe due to synchronization model in SshjTool of calling connect/disconnect.
+ // Even with a retry-count of 4, it still fails because some commands are calling disconnect
+ // while another concurrently executing command expects to be still connected.
+ @Test(groups = {"Integration", "WIP"})
+ public void testExecBigConcurrentCommandWithStaggeredStart() throws Exception {
+ // This test is to vary the concurrency of concurrent actions
+ runExecBigConcurrentCommand(50, 100L);
+ }
+
+ protected void runExecBigConcurrentCommand(int numCommands, long staggeredDelayBeforeStart) throws Exception {
+ ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
+ List<ListenableFuture<?>> futures = new ArrayList<ListenableFuture<?>>();
+ try {
+ for (int i = 0; i < numCommands; i++) {
+ long delay = (long) (Math.random() * staggeredDelayBeforeStart);
+ if (i > 0) Time.sleep(delay);
+
+ futures.add(executor.submit(new Runnable() {
+ public void run() {
+ String bigstring = Strings.repeat("abcdefghij", 1000); // 10KB
+ String out = execCommands("echo "+bigstring);
+ assertEquals(out, bigstring+"\n", "actualSize="+out.length()+"; expectedSize="+bigstring.length());
+ }}));
+ }
+ Futures.allAsList(futures).get();
+ } finally {
+ executor.shutdownNow();
+ }
+ }
+
+ // fails if terminal enabled
+ @Test(groups = {"Integration"})
+ @Deprecated // tests deprecated code
+ public void testExecScriptCapturesStderr() throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayOutputStream err = new ByteArrayOutputStream();
+ String nonExistantCmd = "acmdthatdoesnotexist";
+ tool.execScript(ImmutableMap.of("out", out, "err", err), ImmutableList.of(nonExistantCmd));
+ assertTrue(new String(err.toByteArray()).contains(nonExistantCmd+": command not found"), "out="+out+"; err="+err);
+ }
+
+ // fails if terminal enabled
+ @Test(groups = {"Integration"})
+ @Deprecated // tests deprecated code
+ public void testExecCapturesStderr() throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayOutputStream err = new ByteArrayOutputStream();
+ String nonExistantCmd = "acmdthatdoesnotexist";
+ tool.execCommands(ImmutableMap.of("out", out, "err", err), ImmutableList.of(nonExistantCmd));
+ String errMsg = new String(err.toByteArray());
+ assertTrue(errMsg.contains(nonExistantCmd+": command not found\n"), "errMsg="+errMsg+"; out="+out+"; err="+err);
+
+ }
+
+ @Test(groups = {"Integration"})
+ public void testScriptHeader() {
+ final ShellTool localtool = newTool();
+ String out = execScript(MutableMap.of("scriptHeader", "#!/bin/bash -e\necho hello world\n"),
+ localtool, Arrays.asList("echo goodbye world"), null);
+ assertTrue(out.contains("goodbye world"), "no goodbye in output: "+out);
+ assertTrue(out.contains("hello world"), "no hello in output: "+out);
+ }
+
+ @Test(groups = {"Integration"})
+ public void testStdErr() {
+ final ShellTool localtool = newTool();
+ Map<String,Object> props = new LinkedHashMap<String, Object>();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayOutputStream err = new ByteArrayOutputStream();
+ props.put("out", out);
+ props.put("err", err);
+ int exitcode = localtool.execScript(props, Arrays.asList("echo hello err > /dev/stderr"), null);
+ assertFalse(out.toString().contains("hello err"), "hello found where it shouldn't have been, in stdout: "+out);
+ assertTrue(err.toString().contains("hello err"), "no hello in stderr: "+err);
+ assertEquals(0, exitcode);
+ }
+
+ @Test(groups = {"Integration"})
+ public void testRunAsRoot() {
+ final ShellTool localtool = newTool();
+ Map<String,Object> props = new LinkedHashMap<String, Object>();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayOutputStream err = new ByteArrayOutputStream();
+ props.put("out", out);
+ props.put("err", err);
+ props.put(SshTool.PROP_RUN_AS_ROOT.getName(), true);
+ int exitcode = localtool.execScript(props, Arrays.asList("whoami"), null);
+ assertTrue(out.toString().contains("root"), "not running as root; whoami is: "+out+" (err is '"+err+"')");
+ assertEquals(0, exitcode);
+ }
+
+ @Test(groups = {"Integration"})
+ public void testExecScriptEchosExecute() throws Exception {
+ String out = execScript("date");
+ assertTrue(out.toString().contains("Executed"), "Executed did not display: "+out);
+ }
+
+ @Test(groups = {"Integration"})
+ public void testExecScriptEchosDontExecuteWhenToldNoExtraOutput() throws Exception {
+ final ShellTool localtool = newTool();
+ Map<String,Object> props = new LinkedHashMap<String, Object>();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayOutputStream err = new ByteArrayOutputStream();
+ props.put("out", out);
+ props.put("err", err);
+ props.put(SshTool.PROP_NO_EXTRA_OUTPUT.getName(), true);
+ int exitcode = localtool.execScript(props, Arrays.asList("echo hello world"), null);
+ assertFalse(out.toString().contains("Executed"), "Executed should not have displayed: "+out);
+ assertEquals(out.toString().trim(), "hello world");
+ assertEquals(0, exitcode);
+ }
+
+ protected String execCommands(String... cmds) {
+ return execCommands(Arrays.asList(cmds));
+ }
+
+ protected String execCommands(List<String> cmds) {
+ return execCommands(cmds, ImmutableMap.<String,Object>of());
+ }
+
+ protected String execCommands(List<String> cmds, Map<String,?> env) {
+ return execCommands(null, cmds, env);
+ }
+
+ protected String execCommands(ConfigBag config, List<String> cmds, Map<String,?> env) {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ MutableMap<String,Object> flags = MutableMap.<String,Object>of("out", out);
+ if (config!=null) flags.add(config.getAllConfig());
+ tool.execCommands(flags, cmds, env);
+ return new String(out.toByteArray());
+ }
+
+ protected String execScript(String... cmds) {
+ return execScript(tool, Arrays.asList(cmds));
+ }
+
+ protected String execScript(ShellTool t, List<String> cmds) {
+ return execScript(ImmutableMap.<String,Object>of(), t, cmds, ImmutableMap.<String,Object>of());
+ }
+
+ protected String execScript(List<String> cmds) {
+ return execScript(cmds, ImmutableMap.<String,Object>of());
+ }
+
+ protected String execScript(List<String> cmds, Map<String,?> env) {
+ return execScript(MutableMap.<String,Object>of(), tool, cmds, env);
+ }
+
+ protected String execScript(Map<String, ?> props, ShellTool tool, List<String> cmds, Map<String,?> env) {
+ Map<String, Object> props2 = new LinkedHashMap<String, Object>(props);
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ props2.put("out", out);
+ int exitcode = tool.execScript(props2, cmds, env);
+ String outstr = new String(out.toByteArray());
+ assertEquals(exitcode, 0, outstr);
+ return outstr;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/SshToolAbstractIntegrationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/SshToolAbstractIntegrationTest.java b/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/SshToolAbstractIntegrationTest.java
new file mode 100644
index 0000000..309d4fb
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/SshToolAbstractIntegrationTest.java
@@ -0,0 +1,304 @@
+/*
+ * 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.util.internal.ssh;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.brooklyn.core.util.internal.ssh.ShellTool;
+import org.apache.brooklyn.core.util.internal.ssh.SshException;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.os.Os;
+import brooklyn.util.text.Identifiers;
+import brooklyn.util.text.Strings;
+
+import com.google.common.base.Charsets;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.io.Files;
+
+/**
+ * Test the operation of the {@link SshTool} utility class; to be extended to test concrete implementations.
+ *
+ * Requires keys set up, e.g. running:
+ *
+ * <pre>
+ * cd ~/.ssh
+ * ssh-keygen
+ * id_rsa_with_passphrase
+ * mypassphrase
+ * mypassphrase
+ * </pre>
+ *
+ */
+public abstract class SshToolAbstractIntegrationTest extends ShellToolAbstractTest {
+
+ private static final Logger log = LoggerFactory.getLogger(SshToolAbstractIntegrationTest.class);
+
+ // FIXME need tests which take properties set in entities and brooklyn.properties;
+ // but not in this class because it is lower level than entities, Aled would argue.
+
+ // TODO No tests for retry logic and exception handing yet
+
+ public static final String SSH_KEY_WITH_PASSPHRASE = System.getProperty("sshPrivateKeyWithPassphrase", "~/.ssh/id_rsa_with_passphrase");
+ public static final String SSH_PASSPHRASE = System.getProperty("sshPrivateKeyPassphrase", "mypassphrase");
+
+ protected String remoteFilePath;
+
+ protected SshTool tool() { return (SshTool)tool; }
+
+ protected abstract SshTool newUnregisteredTool(Map<String,?> flags);
+
+ @Override
+ protected SshTool newTool() {
+ return newTool(ImmutableMap.of("host", "localhost", "privateKeyFile", "~/.ssh/id_rsa"));
+ }
+
+ @Override
+ protected SshTool newTool(Map<String,?> flags) {
+ return (SshTool) super.newTool(flags);
+ }
+
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ super.setUp();
+ remoteFilePath = "/tmp/ssh-test-remote-"+Identifiers.makeRandomId(8);
+ filesCreated.add(remoteFilePath);
+ }
+
+ protected void assertRemoteFileContents(String remotePath, String expectedContents) {
+ String catout = execCommands("cat "+remotePath);
+ assertEquals(catout, expectedContents);
+ }
+
+ /**
+ * @param remotePath
+ * @param expectedPermissions Of the form, for example, "-rw-r--r--"
+ */
+ protected void assertRemoteFilePermissions(String remotePath, String expectedPermissions) {
+ String lsout = execCommands("ls -l "+remotePath);
+ assertTrue(lsout.contains(expectedPermissions), lsout);
+ }
+
+ protected void assertRemoteFileLastModifiedIsNow(String remotePath) {
+ // Check default last-modified time is `now`.
+ // Be lenient in assertion, in case unlucky that clock ticked over to next hour/minute as test was running.
+ // TODO Code could be greatly improved, but low priority!
+ // Output format:
+ // -rw-r--r-- 1 aled wheel 18 Apr 24 15:03 /tmp/ssh-test-remote-CvFN9zQA
+ // [0] [1] [2] [3] [4] [5] [6] [7] [8]
+
+ String lsout = execCommands("ls -l "+remotePath);
+
+ String[] lsparts = lsout.split("\\s+");
+ int day = Integer.parseInt(lsparts[6]);
+ int hour = Integer.parseInt(lsparts[7].split(":")[0]);
+ int minute = Integer.parseInt(lsparts[7].split(":")[1]);
+
+ Calendar expected = Calendar.getInstance();
+ int expectedDay = expected.get(Calendar.DAY_OF_MONTH);
+ int expectedHour = expected.get(Calendar.HOUR_OF_DAY);
+ int expectedMinute = expected.get(Calendar.MINUTE);
+
+ assertEquals(day, expectedDay, "ls="+lsout+"; lsparts="+Arrays.toString(lsparts)+"; expected="+expected+"; expectedDay="+expectedDay+"; day="+day+"; zone="+expected.getTimeZone());
+ assertTrue(Math.abs(hour - expectedHour) <= 1, "ls="+lsout+"; lsparts="+Arrays.toString(lsparts)+"; expected="+expected+"; expectedHour="+expectedHour+"; hour="+hour+"; zone="+expected.getTimeZone());
+ assertTrue(Math.abs(minute - expectedMinute) <= 1, "ls="+lsout+"; lsparts="+Arrays.toString(lsparts)+"; expected="+expected+"; expectedMinute="+expectedMinute+"; minute="+minute+"; zone="+expected.getTimeZone());
+ }
+
+ @Test(groups = {"Integration"})
+ public void testCopyToServerFromBytes() throws Exception {
+ String contents = "echo hello world!\n";
+ byte[] contentBytes = contents.getBytes();
+ tool().copyToServer(MutableMap.<String,Object>of(), contentBytes, remoteFilePath);
+
+ assertRemoteFileContents(remoteFilePath, contents);
+ assertRemoteFilePermissions(remoteFilePath, "-rw-r--r--");
+
+ // TODO would like to also assert lastModified time, but on jenkins the jvm locale
+ // and the OS locale are different (i.e. different timezones) so the file time-stamp
+ // is several hours out.
+ //assertRemoteFileLastModifiedIsNow(remoteFilePath);
+ }
+
+ @Test(groups = {"Integration"})
+ public void testCopyToServerFromInputStream() throws Exception {
+ String contents = "echo hello world!\n";
+ ByteArrayInputStream contentsStream = new ByteArrayInputStream(contents.getBytes());
+ tool().copyToServer(MutableMap.<String,Object>of(), contentsStream, remoteFilePath);
+
+ assertRemoteFileContents(remoteFilePath, contents);
+ }
+
+ @Test(groups = {"Integration"})
+ public void testCopyToServerWithPermissions() throws Exception {
+ tool().copyToServer(ImmutableMap.of("permissions","0754"), "echo hello world!\n".getBytes(), remoteFilePath);
+
+ assertRemoteFilePermissions(remoteFilePath, "-rwxr-xr--");
+ }
+
+ @Test(groups = {"Integration"})
+ public void testCopyToServerWithLastModifiedDate() throws Exception {
+ long lastModificationTime = 1234567;
+ tool().copyToServer(ImmutableMap.of("lastModificationDate", lastModificationTime), "echo hello world!\n".getBytes(), remoteFilePath);
+
+ String lsout = execCommands("ls -l "+remoteFilePath);//+" | awk '{print \$6 \" \" \$7 \" \" \$8}'"])
+ //execCommands([ "ls -l "+remoteFilePath+" | awk '{print \$6 \" \" \$7 \" \" \$8}'"])
+ //varies depending on timezone
+ assertTrue(lsout.contains("Jan 15 1970") || lsout.contains("Jan 14 1970") || lsout.contains("Jan 16 1970"), lsout);
+ //assertLastModified(lsout, lastModifiedDate)
+ }
+
+ @Test(groups = {"Integration"})
+ public void testCopyFileToServerWithPermissions() throws Exception {
+ String contents = "echo hello world!\n";
+ Files.write(contents, new File(localFilePath), Charsets.UTF_8);
+ tool().copyToServer(ImmutableMap.of("permissions", "0754"), new File(localFilePath), remoteFilePath);
+
+ assertRemoteFileContents(remoteFilePath, contents);
+
+ String lsout = execCommands("ls -l "+remoteFilePath);
+ assertTrue(lsout.contains("-rwxr-xr--"), lsout);
+ }
+
+ @Test(groups = {"Integration"})
+ public void testCopyFromServer() throws Exception {
+ String contentsWithoutLineBreak = "echo hello world!";
+ String contents = contentsWithoutLineBreak+"\n";
+ tool().copyToServer(MutableMap.<String,Object>of(), contents.getBytes(), remoteFilePath);
+
+ tool().copyFromServer(MutableMap.<String,Object>of(), remoteFilePath, new File(localFilePath));
+
+ List<String> actual = Files.readLines(new File(localFilePath), Charsets.UTF_8);
+ assertEquals(actual, ImmutableList.of(contentsWithoutLineBreak));
+ }
+
+ // TODO No config options in sshj or scp for auto-creating the parent directories
+ @Test(enabled=false, groups = {"Integration"})
+ public void testCopyFileToNonExistantDir() throws Exception {
+ String contents = "echo hello world!\n";
+ String remoteFileDirPath = "/tmp/ssh-test-remote-dir-"+Identifiers.makeRandomId(8);
+ String remoteFileInDirPath = remoteFileDirPath + File.separator + "ssh-test-remote-"+Identifiers.makeRandomId(8);
+ filesCreated.add(remoteFileInDirPath);
+ filesCreated.add(remoteFileDirPath);
+
+ tool().copyToServer(MutableMap.<String,Object>of(), contents.getBytes(), remoteFileInDirPath);
+
+ assertRemoteFileContents(remoteFileInDirPath, contents);
+ }
+
+
+ @Test(groups = {"Integration"})
+ public void testAllocatePty() {
+ final ShellTool localtool = newTool(MutableMap.of("host", "localhost", SshTool.PROP_ALLOCATE_PTY.getName(), true));
+ Map<String,Object> props = new LinkedHashMap<String, Object>();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayOutputStream err = new ByteArrayOutputStream();
+ props.put("out", out);
+ props.put("err", err);
+ int exitcode = localtool.execScript(props, Arrays.asList("echo hello err > /dev/stderr"), null);
+ assertTrue(out.toString().contains("hello err"), "no hello in output: "+out+" (err is '"+err+"')");
+ assertFalse(err.toString().contains("hello err"), "hello found in stderr: "+err);
+ assertEquals(0, exitcode);
+ }
+
+ // Requires setting up an extra ssh key, with a passphrase, and adding it to ~/.ssh/authorized_keys
+ @Test(groups = {"Integration"})
+ public void testSshKeyWithPassphrase() throws Exception {
+ final SshTool localtool = newTool(ImmutableMap.<String,Object>builder()
+ .put(SshTool.PROP_HOST.getName(), "localhost")
+ .put(SshTool.PROP_PRIVATE_KEY_FILE.getName(), SSH_KEY_WITH_PASSPHRASE)
+ .put(SshTool.PROP_PRIVATE_KEY_PASSPHRASE.getName(), SSH_PASSPHRASE)
+ .build());
+ localtool.connect();
+
+ assertEquals(tool.execScript(MutableMap.<String,Object>of(), ImmutableList.of("date")), 0);
+
+ // Also needs the negative test to prove that we're really using an ssh-key with a passphrase
+ try {
+ final SshTool localtool2 = newTool(ImmutableMap.<String,Object>builder()
+ .put(SshTool.PROP_HOST.getName(), "localhost")
+ .put(SshTool.PROP_PRIVATE_KEY_FILE.getName(), SSH_KEY_WITH_PASSPHRASE)
+ .build());
+ localtool2.connect();
+ fail();
+ } catch (Exception e) {
+ SshException se = Exceptions.getFirstThrowableOfType(e, SshException.class);
+ if (se == null) throw e;
+ }
+ }
+
+ @Test(groups = {"Integration"})
+ public void testConnectWithInvalidUserThrowsException() throws Exception {
+ final ShellTool localtool = newTool(ImmutableMap.of("user", "wronguser", "host", "localhost", "privateKeyFile", "~/.ssh/id_rsa"));
+ tools.add(localtool);
+ try {
+ connect(localtool);
+ fail();
+ } catch (SshException e) {
+ if (!e.toString().contains("failed to connect")) throw e;
+ }
+ }
+
+ @Test(groups = {"Integration"})
+ public void testOutputAsExpected() throws Exception {
+ final String CONTENTS = "hello world\n"
+ + "bye bye\n";
+ execCommands("cat > "+Os.mergePaths(Os.tmp(), "test1")+" << X\n"
+ + CONTENTS
+ + "X\n");
+ String read = execCommands("echo START_FOO", "cat "+Os.mergePaths(Os.tmp(), "test1"), "echo END_FOO");
+ log.debug("read back data written, as:\n"+read);
+ String contents = Strings.getFragmentBetween(read, "START_FOO", "END_FOO");
+ Assert.assertEquals(CONTENTS.trim(), contents.trim());
+ }
+
+ @Test(groups = {"Integration"})
+ public void testScriptDirPropertiesIsRespected() {
+ // For explanation of (some of) the magic behind this command, see http://stackoverflow.com/a/229606/68898
+ final String command = "if [[ \"$0\" == \"/var/tmp/\"* ]]; then true; else false; fi";
+
+ SshTool sshTool = newTool(ImmutableMap.<String, Object>builder()
+ .put(SshTool.PROP_HOST.getName(), "localhost")
+ .build());
+ int rc = sshTool.execScript(ImmutableMap.<String, Object>builder()
+ .put(SshTool.PROP_SCRIPT_DIR.getName(), "/var/tmp")
+ .build(), ImmutableList.of(command));
+ assertEquals(rc, 0);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/SshToolAbstractPerformanceTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/SshToolAbstractPerformanceTest.java b/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/SshToolAbstractPerformanceTest.java
new file mode 100644
index 0000000..1730816
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/SshToolAbstractPerformanceTest.java
@@ -0,0 +1,138 @@
+/*
+ * 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.util.internal.ssh;
+
+import java.io.ByteArrayOutputStream;
+import java.lang.management.ManagementFactory;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.text.Identifiers;
+import brooklyn.util.time.Time;
+
+import com.google.common.base.Stopwatch;
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Test the performance of different variants of invoking the sshj tool.
+ *
+ * Intended for human-invocation and inspection, to see which parts are most expensive.
+ */
+public abstract class SshToolAbstractPerformanceTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SshToolAbstractPerformanceTest.class);
+
+ private SshTool tool;
+
+ protected abstract SshTool newSshTool(Map<String,?> flags);
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ if (tool != null) tool.disconnect();
+ }
+
+ @Test(groups = {"Integration"})
+ public void testConsecutiveConnectAndDisconnect() throws Exception {
+ Runnable task = new Runnable() {
+ public void run() {
+ tool = newSshTool(MutableMap.of("host", "localhost"));
+ tool.connect();
+ tool.disconnect();
+ }
+ };
+ runMany(task, "connect-disconnect", 10);
+ }
+
+ @Test(groups = {"Integration"})
+ public void testConsecutiveSmallCommands() throws Exception {
+ runExecManyCommands(ImmutableList.of("true"), false, "small-cmd", 10);
+ }
+
+ @Test(groups = {"Integration"})
+ public void testConsecutiveSmallCommandsWithStdouterr() throws Exception {
+ runExecManyCommands(ImmutableList.of("true"), true, "small-cmd-with-stdout", 10);
+ }
+
+ @Test(groups = {"Integration"})
+ public void testConsecutiveBigStdoutCommands() throws Exception {
+ runExecManyCommands(ImmutableList.of("head -c 100000 /dev/urandom"), true, "big-stdout", 10);
+ }
+
+ @Test(groups = {"Integration"})
+ public void testConsecutiveBigStdinCommands() throws Exception {
+ String bigstr = Identifiers.makeRandomId(100000);
+ runExecManyCommands(ImmutableList.of("echo "+bigstr+" | wc -c"), true, "big-stdin", 10);
+ }
+
+ private void runExecManyCommands(final List<String> cmds, final boolean captureOutAndErr, String context, int iterations) throws Exception {
+ Runnable task = new Runnable() {
+ @Override public void run() {
+ execScript(cmds, captureOutAndErr);
+ }};
+ runMany(task, context, iterations);
+ }
+
+ private void runMany(Runnable task, String context, int iterations) throws Exception {
+ MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
+ ObjectName osMBeanName = ObjectName.getInstance(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME);
+ long preCpuTime = (Long) mbeanServer.getAttribute(osMBeanName, "ProcessCpuTime");
+ Stopwatch stopwatch = Stopwatch.createStarted();
+
+ for (int i = 0; i < iterations; i++) {
+ task.run();
+
+ long postCpuTime = (Long) mbeanServer.getAttribute(osMBeanName, "ProcessCpuTime");
+ long elapsedTime = stopwatch.elapsed(TimeUnit.MILLISECONDS);
+ double fractionCpu = (elapsedTime > 0) ? ((double)postCpuTime-preCpuTime) / TimeUnit.MILLISECONDS.toNanos(elapsedTime) : -1;
+ LOG.info("Executing {}; completed {}; took {}; fraction cpu {}", new Object[] {context, (i+1), Time.makeTimeStringRounded(elapsedTime), fractionCpu});
+ }
+ }
+
+ private int execScript(List<String> cmds, boolean captureOutandErr) {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayOutputStream err = new ByteArrayOutputStream();
+ MutableMap<String,?> flags = (captureOutandErr) ? MutableMap.of("out", out, "err", err) : MutableMap.<String,Object>of();
+
+ tool = newSshTool(MutableMap.of("host", "localhost"));
+ tool.connect();
+ int result = tool.execScript(flags, cmds);
+ tool.disconnect();
+
+ int outlen = out.toByteArray().length;
+ int errlen = out.toByteArray().length;
+ if (LOG.isTraceEnabled()) LOG.trace("Executed: result={}; stdout={}; stderr={}", new Object[] {result, outlen, errlen});
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/cli/SshCliToolIntegrationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/cli/SshCliToolIntegrationTest.java b/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/cli/SshCliToolIntegrationTest.java
new file mode 100644
index 0000000..f8efa87
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/cli/SshCliToolIntegrationTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.util.internal.ssh.cli;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.io.ByteArrayOutputStream;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.brooklyn.core.util.internal.ssh.SshException;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
+import org.apache.brooklyn.core.util.internal.ssh.SshToolAbstractIntegrationTest;
+import org.apache.brooklyn.core.util.internal.ssh.cli.SshCliTool;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import brooklyn.util.collections.MutableMap;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Test the operation of the {@link SshJschTool} utility class.
+ */
+public class SshCliToolIntegrationTest extends SshToolAbstractIntegrationTest {
+
+ private static final Logger log = LoggerFactory.getLogger(SshCliToolIntegrationTest.class);
+
+ protected SshTool newUnregisteredTool(Map<String,?> flags) {
+ return new SshCliTool(flags);
+ }
+
+ @Test(groups = {"Integration"})
+ public void testFlags() throws Exception {
+ final SshTool localtool = newTool(ImmutableMap.of("sshFlags", "-vvv -tt", "host", "localhost"));
+ tools.add(localtool);
+ try {
+ localtool.connect();
+ Map<String,Object> props = new LinkedHashMap<String, Object>();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayOutputStream err = new ByteArrayOutputStream();
+ props.put("out", out);
+ props.put("err", err);
+ int exitcode = localtool.execScript(props, Arrays.asList("echo hello err > /dev/stderr"), null);
+ Assert.assertEquals(0, exitcode, "exitCode="+exitcode+", but expected 0");
+ log.debug("OUT from ssh -vvv command is: "+out);
+ log.debug("ERR from ssh -vvv command is: "+err);
+ assertFalse(err.toString().contains("hello err"), "hello found where it shouldn't have been, in stderr (should have been tty merged to stdout): "+err);
+ assertTrue(out.toString().contains("hello err"), "no hello in stdout: "+err);
+ // look for word 'ssh' to confirm we got verbose output
+ assertTrue(err.toString().toLowerCase().contains("ssh"), "no mention of ssh in stderr: "+err);
+ } catch (SshException e) {
+ if (!e.toString().contains("failed to connect")) throw e;
+ }
+ }
+
+ // Need to have at least one test method here (rather than just inherited) for eclipse to recognize it
+ @Test(enabled = false)
+ public void testDummy() throws Exception {
+ }
+
+ // TODO When running mvn on the command line (for Aled), this test hangs when prompting for a password (but works in the IDE!)
+ // Doing .connect() isn't enough; need to cause ssh or scp to be invoked
+ @Test(enabled=false, groups = {"Integration"})
+ public void testConnectWithInvalidUserThrowsException() throws Exception {
+ final SshTool localtool = newTool(ImmutableMap.of("user", "wronguser", "host", "localhost", "privateKeyFile", "~/.ssh/id_rsa"));
+ tools.add(localtool);
+ try {
+ localtool.connect();
+ int result = localtool.execScript(ImmutableMap.<String,Object>of(), ImmutableList.of("date"));
+ fail("exitCode="+result+", but expected exception");
+ } catch (SshException e) {
+ if (!e.toString().contains("failed to connect")) throw e;
+ }
+ }
+
+ // TODO ssh-cli doesn't support pass-phrases yet
+ @Test(enabled=false, groups = {"Integration"})
+ public void testSshKeyWithPassphrase() throws Exception {
+ super.testSshKeyWithPassphrase();
+ }
+
+ // Setting last modified date not yet supported for cli-based ssh
+ @Override
+ @Test(enabled=false, groups = {"Integration"})
+ public void testCopyToServerWithLastModifiedDate() throws Exception {
+ super.testCopyToServerWithLastModifiedDate();
+ }
+
+ @Test(groups = {"Integration"})
+ public void testExecReturningNonZeroExitCode() throws Exception {
+ int exitcode = tool.execCommands(MutableMap.<String,Object>of(), ImmutableList.of("exit 123"));
+ assertEquals(exitcode, 123);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/cli/SshCliToolPerformanceTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/cli/SshCliToolPerformanceTest.java b/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/cli/SshCliToolPerformanceTest.java
new file mode 100644
index 0000000..fd01180
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/cli/SshCliToolPerformanceTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.util.internal.ssh.cli;
+
+import java.util.Map;
+
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
+import org.apache.brooklyn.core.util.internal.ssh.SshToolAbstractPerformanceTest;
+import org.apache.brooklyn.core.util.internal.ssh.cli.SshCliTool;
+import org.testng.annotations.Test;
+
+/**
+ * Test the performance of different variants of invoking the sshj tool.
+ *
+ * Intended for human-invocation and inspection, to see which parts are most expensive.
+ */
+public class SshCliToolPerformanceTest extends SshToolAbstractPerformanceTest {
+
+ @Override
+ protected SshTool newSshTool(Map<String,?> flags) {
+ return new SshCliTool(flags);
+ }
+
+ // Need to have at least one test method here (rather than just inherited) for eclipse to recognize it
+ @Test(enabled = false)
+ public void testDummy() throws Exception {
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/process/ProcessToolIntegrationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/process/ProcessToolIntegrationTest.java b/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/process/ProcessToolIntegrationTest.java
new file mode 100644
index 0000000..3dd558d
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/process/ProcessToolIntegrationTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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.util.internal.ssh.process;
+
+import static org.testng.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.Map;
+
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.internal.ssh.ShellToolAbstractTest;
+import org.apache.brooklyn.core.util.internal.ssh.process.ProcessTool;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * Test the operation of the {@link ProcessTool} utility class.
+ */
+public class ProcessToolIntegrationTest extends ShellToolAbstractTest {
+
+ @Override
+ protected ProcessTool newUnregisteredTool(Map<String,?> flags) {
+ return new ProcessTool(flags);
+ }
+
+ // ones here included as *non*-integration tests. must run on windows and linux.
+ // (also includes integration tests from parent)
+
+ @Test(groups="UNIX")
+ public void testPortableCommand() throws Exception {
+ String out = execScript("echo hello world");
+ assertTrue(out.contains("hello world"), "out="+out);
+ }
+
+ @Test(groups="Integration")
+ public void testLoginShell() {
+ // this detection scheme only works for commands; can't test whether it works for scripts without
+ // requiring stuff in bash_profile / profile / etc, which gets hard to make portable;
+ // it is nearly the same code path on the impl so this is probably enough
+
+ final String LOGIN_SHELL_CHECK = "shopt -q login_shell && echo 'yes, login shell' || echo 'no, not login shell'";
+ ConfigBag config = ConfigBag.newInstance().configure(ProcessTool.PROP_NO_EXTRA_OUTPUT, true);
+ String out;
+
+ out = execCommands(config, Arrays.asList(LOGIN_SHELL_CHECK), null);
+ Assert.assertEquals(out.trim(), "no, not login shell", "out = "+out);
+
+ config.configure(ProcessTool.PROP_LOGIN_SHELL, true);
+ out = execCommands(config, Arrays.asList(LOGIN_SHELL_CHECK), null);
+ Assert.assertEquals(out.trim(), "yes, login shell", "out = "+out);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/process/ProcessToolStaticsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/process/ProcessToolStaticsTest.java b/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/process/ProcessToolStaticsTest.java
new file mode 100644
index 0000000..eacd761
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/process/ProcessToolStaticsTest.java
@@ -0,0 +1,80 @@
+/*
+ * 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.util.internal.ssh.process;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.brooklyn.core.util.internal.ssh.process.ProcessTool;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.os.Os;
+
+public class ProcessToolStaticsTest {
+
+ ByteArrayOutputStream out;
+ ByteArrayOutputStream err;
+
+ @BeforeMethod(alwaysRun=true)
+ public void clear() {
+ out = new ByteArrayOutputStream();
+ err = new ByteArrayOutputStream();
+ }
+
+ private List<String> getTestCommand() {
+ if(Os.isMicrosoftWindows()) {
+ return Arrays.asList("cmd", "/c", "echo", "hello", "world");
+ } else {
+ return Arrays.asList("echo", "hello", "world");
+ }
+ }
+
+ @Test
+ public void testRunsWithStdout() throws Exception {
+ int code = ProcessTool.execSingleProcess(getTestCommand(), null, (File)null, out, err, this);
+ Assert.assertEquals(err.toString().trim(), "");
+ Assert.assertEquals(out.toString().trim(), "hello world");
+ Assert.assertEquals(code, 0);
+ }
+
+ @Test(groups="Integration") // *nix only
+ public void testRunsWithBashEnvVarAndStderr() throws Exception {
+ int code = ProcessTool.execSingleProcess(Arrays.asList("/bin/bash", "-c", "echo hello $NAME | tee /dev/stderr"),
+ MutableMap.of("NAME", "BOB"), (File)null, out, err, this);
+ Assert.assertEquals(err.toString().trim(), "hello BOB", "err is: "+err);
+ Assert.assertEquals(out.toString().trim(), "hello BOB", "out is: "+out);
+ Assert.assertEquals(code, 0);
+ }
+
+ @Test(groups="Integration") // *nix only
+ public void testRunsManyCommandsWithBashEnvVarAndStderr() throws Exception {
+ int code = ProcessTool.execProcesses(Arrays.asList("echo hello $NAME", "export NAME=JOHN", "echo goodbye $NAME | tee /dev/stderr"),
+ MutableMap.of("NAME", "BOB"), (File)null, out, err, " ; ", false, this);
+ Assert.assertEquals(err.toString().trim(), "goodbye JOHN", "err is: "+err);
+ Assert.assertEquals(out.toString().trim(), "hello BOB\ngoodbye JOHN", "out is: "+out);
+ Assert.assertEquals(code, 0);
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/sshj/SshjToolAsyncStubIntegrationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/sshj/SshjToolAsyncStubIntegrationTest.java b/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/sshj/SshjToolAsyncStubIntegrationTest.java
new file mode 100644
index 0000000..e3b4b7d
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/sshj/SshjToolAsyncStubIntegrationTest.java
@@ -0,0 +1,178 @@
+/*
+ * 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.util.internal.ssh.sshj;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
+import org.apache.brooklyn.core.util.internal.ssh.SshAbstractTool.SshAction;
+import org.apache.brooklyn.core.util.internal.ssh.sshj.SshjTool;
+import org.apache.brooklyn.core.util.internal.ssh.sshj.SshjTool.ShellAction;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.time.Duration;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+
+/**
+ * Tests for async-exec with {@link SshjTool}, where it stubs out the actual ssh commands
+ * to return a controlled sequence of responses.
+ */
+public class SshjToolAsyncStubIntegrationTest {
+
+ static class InjectedResult {
+ Predicate<SshjTool.ShellAction> expected;
+ Function<SshjTool.ShellAction, Integer> result;
+
+ InjectedResult(Predicate<SshjTool.ShellAction> expected, Function<SshjTool.ShellAction, Integer> result) {
+ this.expected = expected;
+ this.result = result;
+ }
+ }
+
+ private SshjTool tool;
+ private List<InjectedResult> sequence;
+ int counter = 0;
+ private boolean origFeatureEnablement;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ origFeatureEnablement = BrooklynFeatureEnablement.enable(BrooklynFeatureEnablement.FEATURE_SSH_ASYNC_EXEC);
+ sequence = Lists.newArrayList();
+ counter = 0;
+
+ tool = new SshjTool(ImmutableMap.<String,Object>of("host", "localhost")) {
+ @SuppressWarnings("unchecked")
+ protected <T, C extends SshAction<T>> T acquire(C action, int sshTries, Duration sshTriesTimeout) {
+ if (action instanceof SshjTool.ShellAction) {
+ SshjTool.ShellAction shellAction = (SshjTool.ShellAction) action;
+ InjectedResult injectedResult = sequence.get(counter);
+ assertTrue(injectedResult.expected.apply(shellAction), "counter="+counter+"; cmds="+shellAction.commands);
+ counter++;
+ return (T) injectedResult.result.apply(shellAction);
+ }
+ return super.acquire(action, sshTries, sshTriesTimeout);
+ }
+ };
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ try {
+ if (tool != null) tool.disconnect();
+ } finally {
+ BrooklynFeatureEnablement.setEnablement(BrooklynFeatureEnablement.FEATURE_SSH_ASYNC_EXEC, origFeatureEnablement);
+ }
+ }
+
+ private Predicate<SshjTool.ShellAction> containsCmd(final String cmd) {
+ return new Predicate<SshjTool.ShellAction>() {
+ @Override public boolean apply(ShellAction input) {
+ return input != null && input.commands.toString().contains(cmd);
+ }
+ };
+ }
+
+ private Function<SshjTool.ShellAction, Integer> returning(final int result, final String stdout, final String stderr) {
+ return new Function<SshjTool.ShellAction, Integer>() {
+ @Override public Integer apply(ShellAction input) {
+ try {
+ if (stdout != null && input.out != null) input.out.write(stdout.getBytes());
+ if (stderr != null && input.err != null) input.err.write(stderr.getBytes());
+ } catch (IOException e) {
+ throw Exceptions.propagate(e);
+ }
+ return result;
+ }
+ };
+ }
+
+ @Test(groups="Integration")
+ public void testPolls() throws Exception {
+ sequence = ImmutableList.of(
+ new InjectedResult(containsCmd("nohup"), returning(0, "", "")),
+ new InjectedResult(containsCmd("# Long poll"), returning(0, "mystringToStdout", "mystringToStderr")));
+
+ runTest(0, "mystringToStdout", "mystringToStderr");
+ assertEquals(counter, sequence.size());
+ }
+
+ @Test(groups="Integration")
+ public void testPollsAndReturnsNonZeroExitCode() throws Exception {
+ sequence = ImmutableList.of(
+ new InjectedResult(containsCmd("nohup"), returning(0, "", "")),
+ new InjectedResult(containsCmd("# Long poll"), returning(123, "mystringToStdout", "mystringToStderr")),
+ new InjectedResult(containsCmd("# Retrieve status"), returning(0, "123", "")));
+
+ runTest(123, "mystringToStdout", "mystringToStderr");
+ assertEquals(counter, sequence.size());
+ }
+
+ @Test(groups="Integration")
+ public void testPollsRepeatedly() throws Exception {
+ sequence = ImmutableList.of(
+ new InjectedResult(containsCmd("nohup"), returning(0, "", "")),
+ new InjectedResult(containsCmd("# Long poll"), returning(125, "mystringToStdout", "mystringToStderr")),
+ new InjectedResult(containsCmd("# Retrieve status"), returning(0, "", "")),
+ new InjectedResult(containsCmd("# Long poll"), returning(125, "mystringToStdout2", "mystringToStderr2")),
+ new InjectedResult(containsCmd("# Retrieve status"), returning(0, "", "")),
+ new InjectedResult(containsCmd("# Long poll"), returning(-1, "mystringToStdout3", "mystringToStderr3")),
+ new InjectedResult(containsCmd("# Long poll"), returning(125, "mystringToStdout4", "mystringToStderr4")),
+ new InjectedResult(containsCmd("# Retrieve status"), returning(0, "", "")),
+ new InjectedResult(containsCmd("# Long poll"), returning(0, "mystringToStdout5", "mystringToStderr5")));
+
+ runTest(0,
+ "mystringToStdout"+"mystringToStdout2"+"mystringToStdout3"+"mystringToStdout4"+"mystringToStdout5",
+ "mystringToStderr"+"mystringToStderr2"+"mystringToStderr3"+"mystringToStderr4"+"mystringToStderr5");
+ assertEquals(counter, sequence.size());
+ }
+
+ protected void runTest(int expectedExit, String expectedStdout, String expectedStderr) throws Exception {
+ List<String> cmds = ImmutableList.of("abc");
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayOutputStream err = new ByteArrayOutputStream();
+ int exitCode = tool.execScript(
+ ImmutableMap.of(
+ "out", out,
+ "err", err,
+ SshjTool.PROP_EXEC_ASYNC.getName(), true,
+ SshjTool.PROP_NO_EXTRA_OUTPUT.getName(), true,
+ SshjTool.PROP_EXEC_ASYNC_POLLING_TIMEOUT.getName(), Duration.ONE_MILLISECOND),
+ cmds,
+ ImmutableMap.<String,String>of());
+ String outStr = new String(out.toByteArray());
+ String errStr = new String(err.toByteArray());
+
+ assertEquals(exitCode, expectedExit);
+ assertEquals(outStr.trim(), expectedStdout);
+ assertEquals(errStr.trim(), expectedStderr);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/sshj/SshjToolIntegrationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/sshj/SshjToolIntegrationTest.java b/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/sshj/SshjToolIntegrationTest.java
new file mode 100644
index 0000000..bf1aafb
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/sshj/SshjToolIntegrationTest.java
@@ -0,0 +1,314 @@
+/*
+ * 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.util.internal.ssh.sshj;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+import net.schmizz.sshj.connection.channel.direct.Session;
+
+import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
+import org.apache.brooklyn.core.util.internal.ssh.SshException;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
+import org.apache.brooklyn.core.util.internal.ssh.SshToolAbstractIntegrationTest;
+import org.apache.brooklyn.core.util.internal.ssh.sshj.SshjTool;
+import org.testng.annotations.Test;
+
+import brooklyn.test.Asserts;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.exceptions.RuntimeTimeoutException;
+import brooklyn.util.os.Os;
+import brooklyn.util.time.Duration;
+
+import com.google.common.base.Stopwatch;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Test the operation of the {@link SshJschTool} utility class.
+ */
+public class SshjToolIntegrationTest extends SshToolAbstractIntegrationTest {
+
+ @Override
+ protected SshTool newUnregisteredTool(Map<String,?> flags) {
+ return new SshjTool(flags);
+ }
+
+ // TODO requires vt100 terminal emulation to work?
+ @Test(enabled = false, groups = {"Integration"})
+ public void testExecShellWithCommandTakingStdin() throws Exception {
+ // Uses `tee` to redirect stdin to the given file; cntr-d (i.e. char 4) stops tee with exit code 0
+ String content = "blah blah";
+ String out = execShellDirectWithTerminalEmulation("tee "+remoteFilePath, content, ""+(char)4, "echo file contents: `cat "+remoteFilePath+"`");
+
+ assertTrue(out.contains("file contents: blah blah"), "out="+out);
+ }
+
+ @Test(groups = {"Integration"})
+ public void testGivesUpAfterMaxRetries() throws Exception {
+ final AtomicInteger callCount = new AtomicInteger();
+
+ final SshTool localtool = new SshjTool(ImmutableMap.of("sshTries", 3, "host", "localhost", "privateKeyFile", "~/.ssh/id_rsa")) {
+ protected SshAction<Session> newSessionAction() {
+ callCount.incrementAndGet();
+ throw new RuntimeException("Simulating ssh execution failure");
+ }
+ };
+
+ tools.add(localtool);
+ try {
+ localtool.execScript(ImmutableMap.<String,Object>of(), ImmutableList.of("true"));
+ fail();
+ } catch (SshException e) {
+ if (!e.toString().contains("out of retries")) throw e;
+ assertEquals(callCount.get(), 3);
+ }
+ }
+
+ @Test(groups = {"Integration"})
+ public void testReturnsOnSuccessWhenRetrying() throws Exception {
+ final AtomicInteger callCount = new AtomicInteger();
+ final int successOnAttempt = 2;
+ final SshTool localtool = new SshjTool(ImmutableMap.of("sshTries", 3, "host", "localhost", "privateKeyFile", "~/.ssh/id_rsa")) {
+ protected SshAction<Session> newSessionAction() {
+ callCount.incrementAndGet();
+ if (callCount.incrementAndGet() >= successOnAttempt) {
+ return super.newSessionAction();
+ } else {
+ throw new RuntimeException("Simulating ssh execution failure");
+ }
+ }
+ };
+
+ tools.add(localtool);
+ localtool.execScript(ImmutableMap.<String,Object>of(), ImmutableList.of("true"));
+ assertEquals(callCount.get(), successOnAttempt);
+ }
+
+ @Test(groups = {"Integration"})
+ public void testGivesUpAfterMaxTime() throws Exception {
+ final AtomicInteger callCount = new AtomicInteger();
+ final SshTool localtool = new SshjTool(ImmutableMap.of("sshTriesTimeout", 1000, "host", "localhost", "privateKeyFile", "~/.ssh/id_rsa")) {
+ protected SshAction<Session> newSessionAction() {
+ callCount.incrementAndGet();
+ try {
+ Thread.sleep(600);
+ } catch (InterruptedException e) {
+ throw Exceptions.propagate(e);
+ }
+ throw new RuntimeException("Simulating ssh execution failure");
+ }
+ };
+
+ tools.add(localtool);
+ try {
+ localtool.execScript(ImmutableMap.<String,Object>of(), ImmutableList.of("true"));
+ fail();
+ } catch (RuntimeTimeoutException e) {
+ if (!e.toString().contains("out of time")) throw e;
+ assertEquals(callCount.get(), 2);
+ }
+ }
+
+ @Test(groups = {"Integration"})
+ public void testUsesCustomLocalTempDir() throws Exception {
+ class SshjToolForTest extends SshjTool {
+ public SshjToolForTest(Map<String, ?> map) {
+ super(map);
+ }
+ public File getLocalTempDir() {
+ return localTempDir;
+ }
+ };
+
+ final SshjToolForTest localtool = new SshjToolForTest(ImmutableMap.<String, Object>of("host", "localhost"));
+ assertNotNull(localtool.getLocalTempDir());
+ assertEquals(localtool.getLocalTempDir(), new File(Os.tidyPath(SshjTool.PROP_LOCAL_TEMP_DIR.getDefaultValue())));
+
+ String customTempDir = Os.tmp();
+ final SshjToolForTest localtool2 = new SshjToolForTest(ImmutableMap.of(
+ "host", "localhost",
+ SshjTool.PROP_LOCAL_TEMP_DIR.getName(), customTempDir));
+ assertEquals(localtool2.getLocalTempDir(), new File(customTempDir));
+
+ String customRelativeTempDir = "~/tmp";
+ final SshjToolForTest localtool3 = new SshjToolForTest(ImmutableMap.of(
+ "host", "localhost",
+ SshjTool.PROP_LOCAL_TEMP_DIR.getName(), customRelativeTempDir));
+ assertEquals(localtool3.getLocalTempDir(), new File(Os.tidyPath(customRelativeTempDir)));
+ }
+
+ @Test(groups = {"Integration"})
+ public void testAsyncExecStdoutAndStderr() throws Exception {
+ boolean origFeatureEnablement = BrooklynFeatureEnablement.enable(BrooklynFeatureEnablement.FEATURE_SSH_ASYNC_EXEC);
+ try {
+ // Include a sleep, to ensure that the contents retrieved in first poll and subsequent polls are appended
+ List<String> cmds = ImmutableList.of(
+ "echo mystringToStdout",
+ "echo mystringToStderr 1>&2",
+ "sleep 5",
+ "echo mystringPostSleepToStdout",
+ "echo mystringPostSleepToStderr 1>&2");
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayOutputStream err = new ByteArrayOutputStream();
+ int exitCode = tool.execScript(
+ ImmutableMap.of(
+ "out", out,
+ "err", err,
+ SshjTool.PROP_EXEC_ASYNC.getName(), true,
+ SshjTool.PROP_NO_EXTRA_OUTPUT.getName(), true,
+ SshjTool.PROP_EXEC_ASYNC_POLLING_TIMEOUT.getName(), Duration.ONE_SECOND),
+ cmds,
+ ImmutableMap.<String,String>of());
+ String outStr = new String(out.toByteArray());
+ String errStr = new String(err.toByteArray());
+
+ assertEquals(exitCode, 0);
+ assertEquals(outStr.trim(), "mystringToStdout\nmystringPostSleepToStdout");
+ assertEquals(errStr.trim(), "mystringToStderr\nmystringPostSleepToStderr");
+ } finally {
+ BrooklynFeatureEnablement.setEnablement(BrooklynFeatureEnablement.FEATURE_SSH_ASYNC_EXEC, origFeatureEnablement);
+ }
+ }
+
+ @Test(groups = {"Integration"})
+ public void testAsyncExecReturnsExitCode() throws Exception {
+ boolean origFeatureEnablement = BrooklynFeatureEnablement.enable(BrooklynFeatureEnablement.FEATURE_SSH_ASYNC_EXEC);
+ try {
+ int exitCode = tool.execScript(
+ ImmutableMap.of(SshjTool.PROP_EXEC_ASYNC.getName(), true),
+ ImmutableList.of("exit 123"),
+ ImmutableMap.<String,String>of());
+ assertEquals(exitCode, 123);
+ } finally {
+ BrooklynFeatureEnablement.setEnablement(BrooklynFeatureEnablement.FEATURE_SSH_ASYNC_EXEC, origFeatureEnablement);
+ }
+ }
+
+ @Test(groups = {"Integration"})
+ public void testAsyncExecTimesOut() throws Exception {
+ Stopwatch stopwatch = Stopwatch.createStarted();
+ boolean origFeatureEnablement = BrooklynFeatureEnablement.enable(BrooklynFeatureEnablement.FEATURE_SSH_ASYNC_EXEC);
+ try {
+ tool.execScript(
+ ImmutableMap.of(SshjTool.PROP_EXEC_ASYNC.getName(), true, SshjTool.PROP_EXEC_TIMEOUT.getName(), Duration.millis(1)),
+ ImmutableList.of("sleep 60"),
+ ImmutableMap.<String,String>of());
+ fail();
+ } catch (Exception e) {
+ TimeoutException te = Exceptions.getFirstThrowableOfType(e, TimeoutException.class);
+ if (te == null) throw e;
+ } finally {
+ BrooklynFeatureEnablement.setEnablement(BrooklynFeatureEnablement.FEATURE_SSH_ASYNC_EXEC, origFeatureEnablement);
+ }
+
+ long seconds = stopwatch.elapsed(TimeUnit.SECONDS);
+ assertTrue(seconds < 30, "exec took "+seconds+" seconds");
+ }
+
+ @Test(groups = {"Integration"})
+ public void testAsyncExecAbortsIfProcessFails() throws Exception {
+ final AtomicReference<Throwable> error = new AtomicReference<Throwable>();
+ Thread thread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Stopwatch stopwatch = Stopwatch.createStarted();
+ int exitStatus = tool.execScript(
+ ImmutableMap.of(SshjTool.PROP_EXEC_ASYNC.getName(), true, SshjTool.PROP_EXEC_TIMEOUT.getName(), Duration.millis(1)),
+ ImmutableList.of("sleep 63"),
+ ImmutableMap.<String,String>of());
+
+ assertEquals(exitStatus, 143 /* 128 + Signal number (SIGTERM) */);
+
+ long seconds = stopwatch.elapsed(TimeUnit.SECONDS);
+ assertTrue(seconds < 30, "exec took "+seconds+" seconds");
+ } catch (Throwable t) {
+ error.set(t);
+ }
+ }});
+
+ boolean origFeatureEnablement = BrooklynFeatureEnablement.enable(BrooklynFeatureEnablement.FEATURE_SSH_ASYNC_EXEC);
+ try {
+ thread.start();
+
+ Asserts.succeedsEventually(new Runnable() {
+ @Override
+ public void run() {
+ int exitStatus = tool.execCommands(ImmutableMap.<String,Object>of(), ImmutableList.of("ps aux| grep \"sleep 63\" | grep -v grep"));
+ assertEquals(exitStatus, 0);
+ }});
+
+ tool.execCommands(ImmutableMap.<String,Object>of(), ImmutableList.of("ps aux| grep \"sleep 63\" | grep -v grep | awk '{print($2)}' | xargs kill"));
+
+ thread.join(30*1000);
+ assertFalse(thread.isAlive());
+ if (error.get() != null) {
+ throw Exceptions.propagate(error.get());
+ }
+ } finally {
+ thread.interrupt();
+ BrooklynFeatureEnablement.setEnablement(BrooklynFeatureEnablement.FEATURE_SSH_ASYNC_EXEC, origFeatureEnablement);
+ }
+ }
+
+
+ protected String execShellDirect(List<String> cmds) {
+ return execShellDirect(cmds, ImmutableMap.<String,Object>of());
+ }
+
+ protected String execShellDirect(List<String> cmds, Map<String,?> env) {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ int exitcode = ((SshjTool)tool).execShellDirect(ImmutableMap.of("out", out), cmds, env);
+ String outstr = new String(out.toByteArray());
+ assertEquals(exitcode, 0, outstr);
+ return outstr;
+ }
+
+ private String execShellDirectWithTerminalEmulation(String... cmds) {
+ return execShellDirectWithTerminalEmulation(Arrays.asList(cmds));
+ }
+
+ private String execShellDirectWithTerminalEmulation(List<String> cmds) {
+ return execShellDirectWithTerminalEmulation(cmds, ImmutableMap.<String,Object>of());
+ }
+
+ private String execShellDirectWithTerminalEmulation(List<String> cmds, Map<String,?> env) {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ int exitcode = ((SshjTool)tool).execShellDirect(ImmutableMap.of("allocatePTY", true, "out", out), cmds, env);
+ String outstr = new String(out.toByteArray());
+ assertEquals(exitcode, 0, outstr);
+ return outstr;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/sshj/SshjToolPerformanceTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/sshj/SshjToolPerformanceTest.java b/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/sshj/SshjToolPerformanceTest.java
new file mode 100644
index 0000000..71ea4e6
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/sshj/SshjToolPerformanceTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.util.internal.ssh.sshj;
+
+import java.util.Map;
+
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
+import org.apache.brooklyn.core.util.internal.ssh.SshToolAbstractPerformanceTest;
+import org.apache.brooklyn.core.util.internal.ssh.sshj.SshjTool;
+import org.testng.annotations.Test;
+
+/**
+ * Test the performance of different variants of invoking the sshj tool.
+ *
+ * Intended for human-invocation and inspection, to see which parts are most expensive.
+ */
+public class SshjToolPerformanceTest extends SshToolAbstractPerformanceTest {
+
+ @Override
+ protected SshTool newSshTool(Map<String,?> flags) {
+ return new SshjTool(flags);
+ }
+
+ // Need to have at least one test method here (rather than just inherited) for eclipse to recognize it
+ @Test(enabled = false)
+ public void testDummy() throws Exception {
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/mutex/WithMutexesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/mutex/WithMutexesTest.java b/core/src/test/java/org/apache/brooklyn/core/util/mutex/WithMutexesTest.java
new file mode 100644
index 0000000..c37ab30
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/mutex/WithMutexesTest.java
@@ -0,0 +1,129 @@
+/*
+ * 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.util.mutex;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.brooklyn.core.util.mutex.MutexSupport;
+import org.apache.brooklyn.core.util.mutex.SemaphoreWithOwners;
+import org.apache.brooklyn.core.util.mutex.WithMutexes;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class WithMutexesTest {
+
+ @Test
+ public void testOneAcquisitionAndRelease() throws InterruptedException {
+ MutexSupport m = new MutexSupport();
+ Map<String, SemaphoreWithOwners> sems;
+ SemaphoreWithOwners s;
+ try {
+ m.acquireMutex("foo", "something foo");
+ sems = m.getAllSemaphores();
+ Assert.assertEquals(sems.size(), 1);
+ s = sems.get("foo");
+ Assert.assertEquals(s.getDescription(), "something foo");
+ Assert.assertEquals(s.getOwningThreads(), Arrays.asList(Thread.currentThread()));
+ Assert.assertEquals(s.getRequestingThreads(), Collections.emptyList());
+ Assert.assertTrue(s.isInUse());
+ Assert.assertTrue(s.isCallingThreadAnOwner());
+ } finally {
+ m.releaseMutex("foo");
+ }
+ Assert.assertFalse(s.isInUse());
+ Assert.assertFalse(s.isCallingThreadAnOwner());
+ Assert.assertEquals(s.getDescription(), "something foo");
+ Assert.assertEquals(s.getOwningThreads(), Collections.emptyList());
+ Assert.assertEquals(s.getRequestingThreads(), Collections.emptyList());
+
+ sems = m.getAllSemaphores();
+ Assert.assertEquals(sems, Collections.emptyMap());
+ }
+
+ @Test(groups = "Integration") //just because it takes a wee while
+ public void testBlockingAcquisition() throws InterruptedException {
+ final MutexSupport m = new MutexSupport();
+ m.acquireMutex("foo", "something foo");
+
+ Assert.assertFalse(m.tryAcquireMutex("foo", "something else"));
+
+ Thread t = new Thread() {
+ public void run() {
+ try {
+ m.acquireMutex("foo", "thread 2 foo");
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ m.releaseMutex("foo");
+ }
+ };
+ t.start();
+
+ t.join(500);
+ Assert.assertTrue(t.isAlive());
+ Assert.assertEquals(m.getSemaphore("foo").getRequestingThreads(), Arrays.asList(t));
+
+ m.releaseMutex("foo");
+
+ t.join(1000);
+ Assert.assertFalse(t.isAlive());
+
+ Assert.assertEquals(m.getAllSemaphores(), Collections.emptyMap());
+ }
+
+
+ public static class SampleWithMutexesDelegatingMixin implements WithMutexes {
+
+ /* other behaviour would typically go here... */
+
+ WithMutexes mutexSupport = new MutexSupport();
+
+ @Override
+ public void acquireMutex(String mutexId, String description) throws InterruptedException {
+ mutexSupport.acquireMutex(mutexId, description);
+ }
+
+ @Override
+ public boolean tryAcquireMutex(String mutexId, String description) {
+ return mutexSupport.tryAcquireMutex(mutexId, description);
+ }
+
+ @Override
+ public void releaseMutex(String mutexId) {
+ mutexSupport.releaseMutex(mutexId);
+ }
+
+ @Override
+ public boolean hasMutex(String mutexId) {
+ return mutexSupport.hasMutex(mutexId);
+ }
+ }
+
+ @Test
+ public void testDelegatingMixinPattern() throws InterruptedException {
+ WithMutexes m = new SampleWithMutexesDelegatingMixin();
+ m.acquireMutex("foo", "sample");
+ Assert.assertTrue(m.hasMutex("foo"));
+ Assert.assertFalse(m.hasMutex("bar"));
+ m.releaseMutex("foo");
+ Assert.assertFalse(m.hasMutex("foo"));
+ }
+}
[02/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/policy
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/main/java/org/apache/brooklyn/core/policy/basic/AbstractPolicy.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/policy/basic/AbstractPolicy.java b/core/src/main/java/org/apache/brooklyn/core/policy/basic/AbstractPolicy.java
new file mode 100644
index 0000000..9d809e3
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/policy/basic/AbstractPolicy.java
@@ -0,0 +1,119 @@
+/*
+ * 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.policy.basic;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.brooklyn.api.entity.rebind.RebindSupport;
+import org.apache.brooklyn.api.entity.trait.Configurable;
+import org.apache.brooklyn.api.mementos.PolicyMemento;
+import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.api.policy.PolicyType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.entity.rebind.BasicPolicyRebindSupport;
+
+import com.google.common.base.Objects;
+
+/**
+ * Base {@link Policy} implementation; all policies should extend this or its children
+ */
+public abstract class AbstractPolicy extends AbstractEntityAdjunct implements Policy, Configurable {
+ @SuppressWarnings("unused")
+ private static final Logger log = LoggerFactory.getLogger(AbstractPolicy.class);
+
+ protected String policyStatus;
+ protected AtomicBoolean suspended = new AtomicBoolean(false);
+
+ private final PolicyDynamicType policyType;
+
+ public AbstractPolicy() {
+ this(Collections.emptyMap());
+ }
+
+ public AbstractPolicy(Map<?,?> flags) {
+ super(flags);
+
+ // TODO Don't let `this` reference escape during construction
+ policyType = new PolicyDynamicType(this);
+
+ if (isLegacyConstruction() && !isLegacyNoConstructionInit()) {
+ init();
+ }
+ }
+
+ @Override
+ public PolicyType getPolicyType() {
+ return policyType.getSnapshot();
+ }
+
+ @Override
+ public void suspend() {
+ suspended.set(true);
+ }
+
+ @Override
+ public void resume() {
+ suspended.set(false);
+ }
+
+ @Override
+ public boolean isSuspended() {
+ if (suspended==null) {
+ // only if accessed during construction in super, e.g. by a call to toString in configure
+ return true;
+ }
+ return suspended.get();
+ }
+
+ @Override
+ public void destroy(){
+ suspend();
+ super.destroy();
+ }
+
+ @Override
+ public boolean isRunning() {
+ return !isSuspended() && !isDestroyed();
+ }
+
+ @Override
+ protected void onChanged() {
+ // currently changes simply trigger re-persistence; there is no intermediate listener as we do for EntityChangeListener
+ if (getManagementContext() != null) {
+ getManagementContext().getRebindManager().getChangeListener().onChanged(this);
+ }
+ }
+
+ @Override
+ public RebindSupport<PolicyMemento> getRebindSupport() {
+ return new BasicPolicyRebindSupport(this);
+ }
+
+ @Override
+ public String toString() {
+ return Objects.toStringHelper(getClass())
+ .add("name", name)
+ .add("running", isRunning())
+ .toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/main/java/org/apache/brooklyn/core/policy/basic/AdjunctType.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/policy/basic/AdjunctType.java b/core/src/main/java/org/apache/brooklyn/core/policy/basic/AdjunctType.java
new file mode 100644
index 0000000..f3d6a6c
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/policy/basic/AdjunctType.java
@@ -0,0 +1,174 @@
+/*
+ * 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.policy.basic;
+
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.brooklyn.api.policy.EntityAdjunct;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.config.ConfigKey.HasConfigKey;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Objects;
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+
+/**
+ * This is the actual type of a policy instance at runtime.
+ */
+public class AdjunctType implements Serializable {
+ private static final long serialVersionUID = -662979234559595903L;
+
+ private static final Logger LOG = LoggerFactory.getLogger(AdjunctType.class);
+
+ private final String name;
+ private final Map<String, ConfigKey<?>> configKeys;
+ private final Set<ConfigKey<?>> configKeysSet;
+
+ public AdjunctType(AbstractEntityAdjunct adjunct) {
+ this(adjunct.getClass(), adjunct);
+ }
+
+ protected AdjunctType(Class<? extends EntityAdjunct> clazz) {
+ this(clazz, null);
+ }
+
+ private AdjunctType(Class<? extends EntityAdjunct> clazz, AbstractEntityAdjunct adjunct) {
+ name = clazz.getCanonicalName();
+ configKeys = Collections.unmodifiableMap(findConfigKeys(clazz, null));
+ configKeysSet = ImmutableSet.copyOf(this.configKeys.values());
+ if (LOG.isTraceEnabled())
+ LOG.trace("Policy {} config keys: {}", name, Joiner.on(", ").join(configKeys.keySet()));
+ }
+
+ AdjunctType(String name, Map<String, ConfigKey<?>> configKeys) {
+ this.name = name;
+ this.configKeys = ImmutableMap.copyOf(configKeys);
+ this.configKeysSet = ImmutableSet.copyOf(this.configKeys.values());
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Set<ConfigKey<?>> getConfigKeys() {
+ return configKeysSet;
+ }
+
+ public ConfigKey<?> getConfigKey(String name) {
+ return configKeys.get(name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(name, configKeys);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (getClass() != obj.getClass()) return false;
+ AdjunctType o = (AdjunctType) obj;
+ if (!Objects.equal(name, o.getName())) return false;
+ if (!Objects.equal(getConfigKeys(), o.getConfigKeys())) return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return Objects.toStringHelper(name)
+ .add("configKeys", configKeys)
+ .toString();
+ }
+
+ /**
+ * Finds the config keys defined on the entity's class, statics and optionally any non-static (discouraged).
+ */
+ // TODO Remove duplication from EntityDynamicType
+ protected static Map<String,ConfigKey<?>> findConfigKeys(Class<? extends EntityAdjunct> clazz, EntityAdjunct optionalInstance) {
+ try {
+ Map<String,ConfigKey<?>> result = Maps.newLinkedHashMap();
+ Map<String,Field> configFields = Maps.newLinkedHashMap();
+ for (Field f : clazz.getFields()) {
+ boolean isConfigKey = ConfigKey.class.isAssignableFrom(f.getType());
+ if (!isConfigKey) {
+ if (!HasConfigKey.class.isAssignableFrom(f.getType())) {
+ // neither ConfigKey nor HasConfigKey
+ continue;
+ }
+ }
+ if (!Modifier.isStatic(f.getModifiers())) {
+ // require it to be static or we have an instance
+ LOG.warn("Discouraged use of non-static config key "+f+" defined in " + (optionalInstance!=null ? optionalInstance : clazz));
+ if (optionalInstance==null) continue;
+ }
+ ConfigKey<?> k = isConfigKey ? (ConfigKey<?>) f.get(optionalInstance) :
+ ((HasConfigKey<?>)f.get(optionalInstance)).getConfigKey();
+
+ Field alternativeField = configFields.get(k.getName());
+ // Allow overriding config keys (e.g. to set default values) when there is an assignable-from relationship between classes
+ Field definitiveField = alternativeField != null ? inferSubbestField(alternativeField, f) : f;
+ boolean skip = false;
+ if (definitiveField != f) {
+ // If they refer to the _same_ instance, just keep the one we already have
+ if (alternativeField.get(optionalInstance) == f.get(optionalInstance)) skip = true;
+ }
+ if (skip) {
+ //nothing
+ } else if (definitiveField == f) {
+ result.put(k.getName(), k);
+ configFields.put(k.getName(), f);
+ } else if (definitiveField != null) {
+ if (LOG.isDebugEnabled()) LOG.debug("multiple definitions for config key {} on {}; preferring that in sub-class: {} to {}", new Object[] {
+ k.getName(), optionalInstance!=null ? optionalInstance : clazz, alternativeField, f});
+ } else if (definitiveField == null) {
+ LOG.warn("multiple definitions for config key {} on {}; preferring {} to {}", new Object[] {
+ k.getName(), optionalInstance!=null ? optionalInstance : clazz, alternativeField, f});
+ }
+ }
+
+ return result;
+ } catch (IllegalAccessException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+
+ /**
+ * Gets the field that is in the sub-class; or null if one field does not come from a sub-class of the other field's class
+ */
+ // TODO Remove duplication from EntityDynamicType
+ private static Field inferSubbestField(Field f1, Field f2) {
+ Class<?> c1 = f1.getDeclaringClass();
+ Class<?> c2 = f2.getDeclaringClass();
+ boolean isSuper1 = c1.isAssignableFrom(c2);
+ boolean isSuper2 = c2.isAssignableFrom(c1);
+ return (isSuper1) ? (isSuper2 ? null : f2) : (isSuper2 ? f1 : null);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/main/java/org/apache/brooklyn/core/policy/basic/ConfigMapImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/policy/basic/ConfigMapImpl.java b/core/src/main/java/org/apache/brooklyn/core/policy/basic/ConfigMapImpl.java
new file mode 100644
index 0000000..5cdc279
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/policy/basic/ConfigMapImpl.java
@@ -0,0 +1,140 @@
+/*
+ * 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.policy.basic;
+
+import static brooklyn.util.GroovyJavaMethods.elvis;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.brooklyn.api.entity.basic.EntityLocal;
+import org.apache.brooklyn.api.management.ExecutionContext;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
+import org.apache.brooklyn.core.util.internal.ConfigKeySelfExtracting;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Maps;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.config.internal.AbstractConfigMapImpl;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.entity.basic.Sanitizer;
+import brooklyn.event.basic.StructuredConfigKey;
+import brooklyn.util.guava.Maybe;
+
+public class ConfigMapImpl extends AbstractConfigMapImpl {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ConfigMapImpl.class);
+
+ /** policy against which config resolution / task execution will occur */
+ private final AbstractEntityAdjunct adjunct;
+
+ /*
+ * TODO An alternative implementation approach would be to have:
+ * setParent(Entity o, Map<ConfigKey,Object> inheritedConfig=[:])
+ * The idea is that the parent could in theory decide explicitly what in its config
+ * would be shared.
+ * I (Aled) am undecided as to whether that would be better...
+ *
+ * (Alex) i lean toward the config key getting to make the decision
+ */
+
+ public ConfigMapImpl(AbstractEntityAdjunct adjunct) {
+ this.adjunct = Preconditions.checkNotNull(adjunct, "AbstractEntityAdjunct must be specified");
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T getConfig(ConfigKey<T> key, T defaultValue) {
+ // FIXME What about inherited task in config?!
+ // alex says: think that should work, no?
+ // FIXME What if someone calls getConfig on a task, before setting parent app?
+ // alex says: not supported (throw exception, or return the task)
+
+ // In case this entity class has overridden the given key (e.g. to set default), then retrieve this entity's key
+ // TODO If ask for a config value that's not in our configKeys, should we really continue with rest of method and return key.getDefaultValue?
+ // e.g. SshBasedJavaAppSetup calls setAttribute(JMX_USER), which calls getConfig(JMX_USER)
+ // but that example doesn't have a default...
+ ConfigKey<T> ownKey = adjunct!=null ? (ConfigKey<T>)elvis(adjunct.getAdjunctType().getConfigKey(key.getName()), key) : key;
+
+ // Don't use groovy truth: if the set value is e.g. 0, then would ignore set value and return default!
+ if (ownKey instanceof ConfigKeySelfExtracting) {
+ if (((ConfigKeySelfExtracting<T>)ownKey).isSet(ownConfig)) {
+ // FIXME Should we support config from futures? How to get execution context before setEntity?
+ EntityLocal entity = adjunct.entity;
+ ExecutionContext exec = (entity != null) ? ((EntityInternal)entity).getExecutionContext() : null;
+ return ((ConfigKeySelfExtracting<T>)ownKey).extractValue(ownConfig, exec);
+ }
+ } else {
+ LOG.warn("Config key {} of {} is not a ConfigKeySelfExtracting; cannot retrieve value; returning default", ownKey, this);
+ }
+ return TypeCoercions.coerce((defaultValue != null) ? defaultValue : ownKey.getDefaultValue(), key.getTypeToken());
+ }
+
+ @Override
+ public Maybe<Object> getConfigRaw(ConfigKey<?> key, boolean includeInherited) {
+ if (ownConfig.containsKey(key)) return Maybe.of(ownConfig.get(key));
+ return Maybe.absent();
+ }
+
+ /** returns the config of this policy */
+ @Override
+ public Map<ConfigKey<?>,Object> getAllConfig() {
+ // Don't use ImmutableMap because valide for values to be null
+ return Collections.unmodifiableMap(Maps.newLinkedHashMap(ownConfig));
+ }
+
+ public Object setConfig(ConfigKey<?> key, Object v) {
+ Object val = coerceConfigVal(key, v);
+ if (key instanceof StructuredConfigKey) {
+ return ((StructuredConfigKey)key).applyValueToMap(val, ownConfig);
+ } else {
+ return ownConfig.put(key, val);
+ }
+ }
+
+ public void addToLocalBag(Map<String, ?> vals) {
+ for (Map.Entry<String, ?> entry : vals.entrySet()) {
+ setConfig(ConfigKeys.newConfigKey(Object.class, entry.getKey()), entry.getValue());
+ }
+ }
+
+ public void removeFromLocalBag(String key) {
+ ownConfig.remove(key);
+ }
+
+ @Override
+ public ConfigMapImpl submap(Predicate<ConfigKey<?>> filter) {
+ ConfigMapImpl m = new ConfigMapImpl(adjunct);
+ for (Map.Entry<ConfigKey<?>,Object> entry: ownConfig.entrySet())
+ if (filter.apply(entry.getKey()))
+ m.ownConfig.put(entry.getKey(), entry.getValue());
+ return m;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString()+"[own="+Sanitizer.sanitize(ownConfig)+"]";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/main/java/org/apache/brooklyn/core/policy/basic/GeneralPurposePolicy.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/policy/basic/GeneralPurposePolicy.java b/core/src/main/java/org/apache/brooklyn/core/policy/basic/GeneralPurposePolicy.java
new file mode 100644
index 0000000..9d140cd
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/policy/basic/GeneralPurposePolicy.java
@@ -0,0 +1,36 @@
+/*
+ * 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.policy.basic;
+
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * @deprecated since 0.7.0; will be either deleted or moved to tests
+ */
+@Deprecated
+public class GeneralPurposePolicy extends AbstractPolicy {
+ public GeneralPurposePolicy() {
+ this(Collections.emptyMap());
+ }
+ public GeneralPurposePolicy(Map properties) {
+ super(properties);
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/main/java/org/apache/brooklyn/core/policy/basic/Policies.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/policy/basic/Policies.java b/core/src/main/java/org/apache/brooklyn/core/policy/basic/Policies.java
new file mode 100644
index 0000000..7ac8823
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/policy/basic/Policies.java
@@ -0,0 +1,73 @@
+/*
+ * 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.policy.basic;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.basic.EntityLocal;
+import org.apache.brooklyn.api.event.Sensor;
+import org.apache.brooklyn.api.event.SensorEvent;
+import org.apache.brooklyn.api.event.SensorEventListener;
+import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
+
+import groovy.lang.Closure;
+import brooklyn.entity.basic.Lifecycle;
+
+@SuppressWarnings({"rawtypes","unchecked"})
+public class Policies {
+
+ public static SensorEventListener listenerFromValueClosure(final Closure code) {
+ return new SensorEventListener() {
+ @Override
+ public void onEvent(SensorEvent event) {
+ code.call(event.getValue());
+ }
+ };
+ }
+
+ public static <T> Policy newSingleSensorValuePolicy(final Sensor<T> sensor, final Closure code) {
+ return new AbstractPolicy() {
+ @Override
+ public void setEntity(EntityLocal entity) {
+ super.setEntity(entity);
+ entity.subscribe(entity, sensor, listenerFromValueClosure(code));
+ }
+ };
+ }
+
+ public static <S,T> Policy newSingleSensorValuePolicy(final Entity remoteEntity, final Sensor<T> remoteSensor,
+ final Closure code) {
+ return new AbstractPolicy() {
+ @Override
+ public void setEntity(EntityLocal entity) {
+ super.setEntity(entity);
+ entity.subscribe(remoteEntity, remoteSensor, listenerFromValueClosure(code));
+ }
+ };
+ }
+
+ public static Lifecycle getPolicyStatus(Policy p) {
+ if (p.isRunning()) return Lifecycle.RUNNING;
+ if (p.isDestroyed()) return Lifecycle.DESTROYED;
+ if (p.isSuspended()) return Lifecycle.STOPPED;
+ // TODO could policy be in an error state?
+ return Lifecycle.CREATED;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/main/java/org/apache/brooklyn/core/policy/basic/PolicyDynamicType.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/policy/basic/PolicyDynamicType.java b/core/src/main/java/org/apache/brooklyn/core/policy/basic/PolicyDynamicType.java
new file mode 100644
index 0000000..315d03d
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/policy/basic/PolicyDynamicType.java
@@ -0,0 +1,44 @@
+/*
+ * 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.policy.basic;
+
+import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.api.policy.PolicyType;
+
+import brooklyn.basic.BrooklynDynamicType;
+
+public class PolicyDynamicType extends BrooklynDynamicType<Policy, AbstractPolicy> {
+
+ public PolicyDynamicType(Class<? extends Policy> type) {
+ super(type);
+ }
+
+ public PolicyDynamicType(AbstractPolicy policy) {
+ super(policy);
+ }
+
+ public PolicyType getSnapshot() {
+ return (PolicyType) super.getSnapshot();
+ }
+
+ @Override
+ protected PolicyTypeSnapshot newSnapshot() {
+ return new PolicyTypeSnapshot(name, value(configKeys));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/main/java/org/apache/brooklyn/core/policy/basic/PolicyTypeSnapshot.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/policy/basic/PolicyTypeSnapshot.java b/core/src/main/java/org/apache/brooklyn/core/policy/basic/PolicyTypeSnapshot.java
new file mode 100644
index 0000000..0e655b6
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/policy/basic/PolicyTypeSnapshot.java
@@ -0,0 +1,40 @@
+/*
+ * 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.policy.basic;
+
+import java.util.Map;
+
+import org.apache.brooklyn.api.policy.PolicyType;
+
+import brooklyn.basic.BrooklynTypeSnapshot;
+import brooklyn.config.ConfigKey;
+
+public class PolicyTypeSnapshot extends BrooklynTypeSnapshot implements PolicyType {
+ private static final long serialVersionUID = 4670930188951106009L;
+
+ PolicyTypeSnapshot(String name, Map<String, ConfigKey<?>> configKeys) {
+ super(name, configKeys);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ return (obj instanceof PolicyTypeSnapshot) && super.equals(obj);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/test/java/brooklyn/entity/EntityPreManagementTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/EntityPreManagementTest.java b/core/src/test/java/brooklyn/entity/EntityPreManagementTest.java
index c29682e..3fc07ed 100644
--- a/core/src/test/java/brooklyn/entity/EntityPreManagementTest.java
+++ b/core/src/test/java/brooklyn/entity/EntityPreManagementTest.java
@@ -27,6 +27,7 @@ import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
import org.apache.brooklyn.api.management.EntityManager;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import org.apache.brooklyn.test.TestUtils;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.test.entity.TestApplication;
@@ -41,7 +42,6 @@ import org.testng.annotations.Test;
import brooklyn.entity.basic.ApplicationBuilder;
import brooklyn.entity.basic.Attributes;
import brooklyn.entity.basic.Entities;
-import brooklyn.policy.basic.AbstractPolicy;
@SuppressWarnings({"rawtypes","unchecked"})
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/test/java/brooklyn/entity/basic/EntitySpecTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/basic/EntitySpecTest.java b/core/src/test/java/brooklyn/entity/basic/EntitySpecTest.java
index 80ebfb7..35a2c74 100644
--- a/core/src/test/java/brooklyn/entity/basic/EntitySpecTest.java
+++ b/core/src/test/java/brooklyn/entity/basic/EntitySpecTest.java
@@ -27,6 +27,7 @@ import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.EnricherSpec;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.test.entity.TestEntity;
import org.apache.brooklyn.test.entity.TestEntityImpl;
@@ -41,7 +42,6 @@ import brooklyn.event.basic.BasicConfigKey;
import org.apache.brooklyn.location.basic.SimulatedLocation;
-import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.test.Asserts;
import com.google.common.collect.ImmutableSet;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/test/java/brooklyn/entity/basic/PolicyRegistrationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/basic/PolicyRegistrationTest.java b/core/src/test/java/brooklyn/entity/basic/PolicyRegistrationTest.java
index 63c6a71..2f21dd8 100644
--- a/core/src/test/java/brooklyn/entity/basic/PolicyRegistrationTest.java
+++ b/core/src/test/java/brooklyn/entity/basic/PolicyRegistrationTest.java
@@ -31,6 +31,7 @@ import org.apache.brooklyn.api.event.SensorEventListener;
import org.apache.brooklyn.api.policy.EnricherSpec;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import org.apache.brooklyn.test.TestUtils;
import org.apache.brooklyn.test.entity.TestEntity;
import org.apache.brooklyn.test.entity.TestEntityNoEnrichersImpl;
@@ -38,7 +39,6 @@ import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import brooklyn.entity.BrooklynAppUnitTestSupport;
-import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.util.collections.MutableMap;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/test/java/brooklyn/entity/group/GroupPickUpEntitiesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/group/GroupPickUpEntitiesTest.java b/core/src/test/java/brooklyn/entity/group/GroupPickUpEntitiesTest.java
index 0ac1ef9..8b9fa5a 100644
--- a/core/src/test/java/brooklyn/entity/group/GroupPickUpEntitiesTest.java
+++ b/core/src/test/java/brooklyn/entity/group/GroupPickUpEntitiesTest.java
@@ -25,6 +25,7 @@ import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import org.apache.brooklyn.test.EntityTestUtils;
import org.apache.brooklyn.test.entity.TestEntity;
import org.testng.Assert;
@@ -36,7 +37,6 @@ import brooklyn.entity.basic.BasicGroup;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.trait.Startable;
-import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.test.Asserts;
import brooklyn.util.javalang.Boxing;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/test/java/brooklyn/entity/rebind/RebindCatalogItemTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindCatalogItemTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindCatalogItemTest.java
index 92383fc..996c656 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindCatalogItemTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindCatalogItemTest.java
@@ -44,6 +44,7 @@ import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
import org.apache.brooklyn.core.catalog.internal.CatalogDto;
import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import org.apache.brooklyn.test.entity.TestEntity;
import brooklyn.config.BrooklynProperties;
@@ -51,8 +52,6 @@ import brooklyn.config.BrooklynServerConfig;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
-import brooklyn.policy.basic.AbstractPolicy;
-
import com.google.common.base.Joiner;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/test/java/brooklyn/entity/rebind/RebindFailuresTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindFailuresTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindFailuresTest.java
index 674d77e..ac2d4c7 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindFailuresTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindFailuresTest.java
@@ -40,6 +40,7 @@ import org.apache.brooklyn.api.policy.EnricherSpec;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.testng.Assert;
@@ -53,7 +54,6 @@ import brooklyn.entity.basic.EntityFunctions;
import brooklyn.entity.basic.EntityPredicates;
import brooklyn.entity.rebind.RebindEntityTest.MyEntity;
import brooklyn.entity.rebind.RebindEntityTest.MyEntityImpl;
-import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.os.Os;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/test/java/brooklyn/entity/rebind/RebindPolicyTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindPolicyTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindPolicyTest.java
index d74a6fc..84413c2 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindPolicyTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindPolicyTest.java
@@ -33,6 +33,7 @@ import org.apache.brooklyn.api.mementos.BrooklynMementoManifest;
import org.apache.brooklyn.api.policy.EnricherSpec;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestEntity;
@@ -47,7 +48,6 @@ import brooklyn.entity.rebind.RebindEnricherTest.MyEnricher;
import org.apache.brooklyn.location.basic.Locations;
-import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.test.Asserts;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/test/java/brooklyn/policy/basic/BasicPolicyTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/policy/basic/BasicPolicyTest.java b/core/src/test/java/brooklyn/policy/basic/BasicPolicyTest.java
deleted file mode 100644
index 5ac58c9..0000000
--- a/core/src/test/java/brooklyn/policy/basic/BasicPolicyTest.java
+++ /dev/null
@@ -1,89 +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 brooklyn.policy.basic;
-
-import static org.testng.Assert.assertEquals;
-
-import java.util.Map;
-
-import org.apache.brooklyn.api.policy.PolicySpec;
-import org.apache.brooklyn.core.util.flags.SetFromFlag;
-import org.testng.annotations.Test;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.entity.BrooklynAppUnitTestSupport;
-import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.util.collections.MutableSet;
-
-/**
- * Test that policy can be created and accessed, by construction and by spec
- */
-public class BasicPolicyTest extends BrooklynAppUnitTestSupport {
-
- public static class MyPolicy extends AbstractPolicy {
- @SetFromFlag("intKey")
- public static final BasicConfigKey<Integer> INT_KEY = new BasicConfigKey<Integer>(Integer.class, "bkey", "b key");
-
- @SetFromFlag("strKey")
- public static final ConfigKey<String> STR_KEY = new BasicConfigKey<String>(String.class, "akey", "a key");
- public static final ConfigKey<Integer> INT_KEY_WITH_DEFAULT = new BasicConfigKey<Integer>(Integer.class, "ckey", "c key", 1);
- public static final ConfigKey<String> STR_KEY_WITH_DEFAULT = new BasicConfigKey<String>(String.class, "strKey", "str key", "str key default");
-
- MyPolicy(Map<?,?> flags) {
- super(flags);
- }
-
- public MyPolicy() {
- super();
- }
- }
-
- @Test
- public void testAddInstance() throws Exception {
- MyPolicy policy = new MyPolicy();
- policy.setDisplayName("Bob");
- policy.config().set(MyPolicy.STR_KEY, "aval");
- policy.config().set(MyPolicy.INT_KEY, 2);
- app.addPolicy(policy);
-
- assertEquals(policy.getDisplayName(), "Bob");
- assertEquals(policy.getConfig(MyPolicy.STR_KEY), "aval");
- assertEquals(policy.getConfig(MyPolicy.INT_KEY), (Integer)2);
- }
-
- @Test
- public void testAddSpec() throws Exception {
- MyPolicy policy = app.addPolicy(PolicySpec.create(MyPolicy.class)
- .displayName("Bob")
- .configure(MyPolicy.STR_KEY, "aval").configure(MyPolicy.INT_KEY, 2));
-
- assertEquals(policy.getDisplayName(), "Bob");
- assertEquals(policy.getConfig(MyPolicy.STR_KEY), "aval");
- assertEquals(policy.getConfig(MyPolicy.INT_KEY), (Integer)2);
- }
-
- @Test
- public void testTagsFromSpec() throws Exception {
- MyPolicy policy = app.addPolicy(PolicySpec.create(MyPolicy.class).tag(99).uniqueTag("x"));
-
- assertEquals(policy.tags().getTags(), MutableSet.of("x", 99));
- assertEquals(policy.getUniqueTag(), "x");
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/test/java/brooklyn/policy/basic/EnricherTypeTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/policy/basic/EnricherTypeTest.java b/core/src/test/java/brooklyn/policy/basic/EnricherTypeTest.java
deleted file mode 100644
index 14773f5..0000000
--- a/core/src/test/java/brooklyn/policy/basic/EnricherTypeTest.java
+++ /dev/null
@@ -1,59 +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 brooklyn.policy.basic;
-
-import static org.testng.Assert.assertEquals;
-
-import org.apache.brooklyn.api.policy.EnricherType;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.enricher.basic.AbstractEnricher;
-import brooklyn.event.basic.BasicConfigKey;
-
-import com.google.common.collect.ImmutableSet;
-
-public class EnricherTypeTest {
- private MyEnricher enricher;
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() throws Exception{
- enricher = new MyEnricher();
- }
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws Exception {
- // nothing to tear down; no management context not started
- }
-
- @Test
- public void testGetConfig() throws Exception {
- EnricherType enricherType = enricher.getEnricherType();
- assertEquals(enricherType.getConfigKeys(), ImmutableSet.of(MyEnricher.CONF1, MyEnricher.CONF2, AbstractEnricher.SUPPRESS_DUPLICATES));
- assertEquals(enricherType.getName(), MyEnricher.class.getCanonicalName());
- assertEquals(enricherType.getConfigKey("test.conf1"), MyEnricher.CONF1);
- assertEquals(enricherType.getConfigKey("test.conf2"), MyEnricher.CONF2);
- }
-
- public static class MyEnricher extends AbstractEnricher {
- public static final BasicConfigKey<String> CONF1 = new BasicConfigKey<String>(String.class, "test.conf1", "my descr, conf1", "defaultval1");
- public static final BasicConfigKey<Integer> CONF2 = new BasicConfigKey<Integer>(Integer.class, "test.conf2", "my descr, conf2", 2);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/test/java/brooklyn/policy/basic/PolicyConfigTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/policy/basic/PolicyConfigTest.java b/core/src/test/java/brooklyn/policy/basic/PolicyConfigTest.java
deleted file mode 100644
index b68781d..0000000
--- a/core/src/test/java/brooklyn/policy/basic/PolicyConfigTest.java
+++ /dev/null
@@ -1,202 +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 brooklyn.policy.basic;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
-
-import java.util.concurrent.Callable;
-import java.util.concurrent.CountDownLatch;
-
-import org.apache.brooklyn.test.entity.TestEntity;
-import org.testng.annotations.Test;
-
-import brooklyn.entity.BrooklynAppUnitTestSupport;
-import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.event.basic.DependentConfiguration;
-import brooklyn.policy.basic.BasicPolicyTest.MyPolicy;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.exceptions.Exceptions;
-
-import com.google.common.util.concurrent.Callables;
-
-/**
- * Test that configuration properties are usable and inherited correctly.
- */
-public class PolicyConfigTest extends BrooklynAppUnitTestSupport {
- private static final int EARLY_RETURN_GRACE = 10;
-
- private BasicConfigKey<String> differentKey = new BasicConfigKey<String>(String.class, "differentkey", "diffval");
-
- @Test
- public void testConfigFlagsPassedInAtConstructionIsAvailable() throws Exception {
- MyPolicy policy = new MyPolicy(MutableMap.builder()
- .put("strKey", "aval")
- .put("intKey", 2)
- .build());
- app.addPolicy(policy);
-
- assertEquals(policy.getConfig(MyPolicy.STR_KEY), "aval");
- assertEquals(policy.getConfig(MyPolicy.INT_KEY), (Integer)2);
- // this is set, because key name matches annotation on STR_KEY
- assertEquals(policy.getConfig(MyPolicy.STR_KEY_WITH_DEFAULT), "aval");
- }
-
- @Test
- public void testUnknownConfigPassedInAtConstructionIsWarnedAndIgnored() throws Exception {
- // TODO Also assert it's warned
- MyPolicy policy = new MyPolicy(MutableMap.builder()
- .put(differentKey, "aval")
- .build());
- app.addPolicy(policy);
-
- assertEquals(policy.getConfig(differentKey), null);
- assertEquals(policy.getPolicyType().getConfigKey(differentKey.getName()), null);
- }
-
- @Test
- public void testConfigPassedInAtConstructionIsAvailable() throws Exception {
- MyPolicy policy = new MyPolicy(MutableMap.builder()
- .put(MyPolicy.STR_KEY, "aval")
- .put(MyPolicy.INT_KEY, 2)
- .build());
- app.addPolicy(policy);
-
- assertEquals(policy.getConfig(MyPolicy.STR_KEY), "aval");
- assertEquals(policy.getConfig(MyPolicy.INT_KEY), (Integer)2);
- // this is not set (contrast with above)
- assertEquals(policy.getConfig(MyPolicy.STR_KEY_WITH_DEFAULT), MyPolicy.STR_KEY_WITH_DEFAULT.getDefaultValue());
- }
-
- @Test
- public void testConfigSetToGroovyTruthFalseIsAvailable() throws Exception {
- MyPolicy policy = new MyPolicy(MutableMap.builder()
- .put(MyPolicy.INT_KEY_WITH_DEFAULT, 0)
- .build());
- app.addPolicy(policy);
-
- assertEquals(policy.getConfig(MyPolicy.INT_KEY_WITH_DEFAULT), (Integer)0);
- }
-
- @Test
- public void testConfigSetToNullIsAvailable() throws Exception {
- MyPolicy policy = new MyPolicy(MutableMap.builder()
- .put(MyPolicy.STR_KEY_WITH_DEFAULT, null)
- .build());
- app.addPolicy(policy);
-
- assertEquals(policy.getConfig(MyPolicy.STR_KEY_WITH_DEFAULT), null);
- }
-
- @Test
- public void testConfigCanBeSetOnPolicy() throws Exception {
- MyPolicy policy = new MyPolicy();
- policy.config().set(MyPolicy.STR_KEY, "aval");
- policy.config().set(MyPolicy.INT_KEY, 2);
- app.addPolicy(policy);
-
- assertEquals(policy.getConfig(MyPolicy.STR_KEY), "aval");
- assertEquals(policy.getConfig(MyPolicy.INT_KEY), (Integer)2);
- }
-
- @Test
- public void testConfigSetterOverridesConstructorValue() throws Exception {
- MyPolicy policy = new MyPolicy(MutableMap.builder()
- .put(MyPolicy.STR_KEY, "aval")
- .build());
- policy.config().set(MyPolicy.STR_KEY, "diffval");
- app.addPolicy(policy);
-
- assertEquals(policy.getConfig(MyPolicy.STR_KEY), "diffval");
- }
-
- @Test
- public void testConfigCannotBeSetAfterApplicationIsStarted() throws Exception {
- MyPolicy policy = new MyPolicy(MutableMap.builder()
- .put(MyPolicy.STR_KEY, "origval")
- .build());
- app.addPolicy(policy);
-
- try {
- policy.config().set(MyPolicy.STR_KEY,"newval");
- fail();
- } catch (UnsupportedOperationException e) {
- // success
- }
-
- assertEquals(policy.getConfig(MyPolicy.STR_KEY), "origval");
- }
-
- @Test
- public void testConfigReturnsDefaultValueIfNotSet() throws Exception {
- MyPolicy policy = new MyPolicy();
- app.addPolicy(policy);
-
- assertEquals(policy.getConfig(MyPolicy.STR_KEY_WITH_DEFAULT), "str key default");
- }
-
- // FIXME Should we support this now?
- @Test(enabled=false)
- public void testGetFutureConfigWhenReady() throws Exception {
- MyPolicy policy = new MyPolicy(MutableMap.builder()
- .put(TestEntity.CONF_NAME, DependentConfiguration.whenDone(Callables.returning("aval")))
- .build());
- app.addPolicy(policy);
-
- assertEquals(policy.getConfig(TestEntity.CONF_NAME), "aval");
- }
-
- // FIXME Should we support this now?
- @Test(enabled=false)
- public void testGetFutureConfigBlocksUntilReady() throws Exception {
- final CountDownLatch latch = new CountDownLatch(1);
- MyPolicy policy = new MyPolicy(MutableMap.builder()
- .put(TestEntity.CONF_NAME, DependentConfiguration.whenDone(new Callable<String>() {
- public String call() {
- try {
- latch.await(); return "aval";
- } catch (InterruptedException e) {
- throw Exceptions.propagate(e);
- }
- }}))
- .build());
- app.addPolicy(policy);
-
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- Thread.sleep(10+EARLY_RETURN_GRACE); latch.countDown();
- } catch (InterruptedException e) {
- throw Exceptions.propagate(e);
- }
- }});
- try {
- long starttime = System.currentTimeMillis();
- t.start();
- assertEquals(policy.getConfig(TestEntity.CONF_NAME), "aval");
- long endtime = System.currentTimeMillis();
-
- assertTrue((endtime - starttime) >= 10, "starttime="+starttime+"; endtime="+endtime);
-
- } finally {
- t.interrupt();
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/test/java/brooklyn/policy/basic/PolicySubscriptionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/policy/basic/PolicySubscriptionTest.java b/core/src/test/java/brooklyn/policy/basic/PolicySubscriptionTest.java
deleted file mode 100644
index e3b2dc8..0000000
--- a/core/src/test/java/brooklyn/policy/basic/PolicySubscriptionTest.java
+++ /dev/null
@@ -1,125 +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 brooklyn.policy.basic;
-
-import static org.testng.Assert.assertEquals;
-
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.entity.BrooklynAppUnitTestSupport;
-
-import org.apache.brooklyn.api.entity.proxying.EntitySpec;
-import org.apache.brooklyn.api.management.SubscriptionHandle;
-import org.apache.brooklyn.entity.basic.RecordingSensorEventListener;
-import org.apache.brooklyn.test.entity.TestEntity;
-
-import brooklyn.event.basic.BasicSensorEvent;
-import org.apache.brooklyn.location.basic.SimulatedLocation;
-import brooklyn.test.Asserts;
-
-import com.google.common.collect.ImmutableList;
-
-public class PolicySubscriptionTest extends BrooklynAppUnitTestSupport {
-
- // TODO Duplication between this and EntitySubscriptionTest
-
- private static final long SHORT_WAIT_MS = 100;
-
- private SimulatedLocation loc;
- private TestEntity entity;
- private TestEntity otherEntity;
- private AbstractPolicy policy;
- private RecordingSensorEventListener<Object> listener;
-
- @BeforeMethod(alwaysRun=true)
- @Override
- public void setUp() throws Exception {
- super.setUp();
- loc = app.newSimulatedLocation();
- entity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
- otherEntity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
- listener = new RecordingSensorEventListener<>();
- policy = new AbstractPolicy() {};
- entity.addPolicy(policy);
- app.start(ImmutableList.of(loc));
- }
-
- @Test
- public void testSubscriptionReceivesEvents() throws Exception {
- policy.subscribe(entity, TestEntity.SEQUENCE, listener);
- policy.subscribe(entity, TestEntity.NAME, listener);
- policy.subscribe(entity, TestEntity.MY_NOTIF, listener);
-
- otherEntity.setAttribute(TestEntity.SEQUENCE, 456);
- entity.setAttribute(TestEntity.SEQUENCE, 123);
- entity.setAttribute(TestEntity.NAME, "myname");
- entity.emit(TestEntity.MY_NOTIF, 789);
-
- Asserts.succeedsEventually(new Runnable() {
- @Override public void run() {
- assertEquals(listener.getEvents(), ImmutableList.of(
- new BasicSensorEvent<Integer>(TestEntity.SEQUENCE, entity, 123),
- new BasicSensorEvent<String>(TestEntity.NAME, entity, "myname"),
- new BasicSensorEvent<Integer>(TestEntity.MY_NOTIF, entity, 789)));
- }});
- }
-
- @Test
- public void testUnsubscribeRemovesAllSubscriptionsForThatEntity() throws Exception {
- policy.subscribe(entity, TestEntity.SEQUENCE, listener);
- policy.subscribe(entity, TestEntity.NAME, listener);
- policy.subscribe(entity, TestEntity.MY_NOTIF, listener);
- policy.subscribe(otherEntity, TestEntity.SEQUENCE, listener);
- policy.unsubscribe(entity);
-
- entity.setAttribute(TestEntity.SEQUENCE, 123);
- entity.setAttribute(TestEntity.NAME, "myname");
- entity.emit(TestEntity.MY_NOTIF, 456);
- otherEntity.setAttribute(TestEntity.SEQUENCE, 789);
-
- Thread.sleep(SHORT_WAIT_MS);
- Asserts.succeedsEventually(new Runnable() {
- @Override public void run() {
- assertEquals(listener.getEvents(), ImmutableList.of(
- new BasicSensorEvent<Integer>(TestEntity.SEQUENCE, otherEntity, 789)));
- }});
- }
-
- @Test
- public void testUnsubscribeUsingHandleStopsEvents() throws Exception {
- SubscriptionHandle handle1 = policy.subscribe(entity, TestEntity.SEQUENCE, listener);
- SubscriptionHandle handle2 = policy.subscribe(entity, TestEntity.NAME, listener);
- SubscriptionHandle handle3 = policy.subscribe(otherEntity, TestEntity.SEQUENCE, listener);
-
- policy.unsubscribe(entity, handle2);
-
- entity.setAttribute(TestEntity.SEQUENCE, 123);
- entity.setAttribute(TestEntity.NAME, "myname");
- otherEntity.setAttribute(TestEntity.SEQUENCE, 456);
-
- Asserts.succeedsEventually(new Runnable() {
- @Override public void run() {
- assertEquals(listener.getEvents(), ImmutableList.of(
- new BasicSensorEvent<Integer>(TestEntity.SEQUENCE, entity, 123),
- new BasicSensorEvent<Integer>(TestEntity.SEQUENCE, otherEntity, 456)));
- }});
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/test/java/brooklyn/policy/basic/PolicyTypeTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/policy/basic/PolicyTypeTest.java b/core/src/test/java/brooklyn/policy/basic/PolicyTypeTest.java
deleted file mode 100644
index cd9b6a7..0000000
--- a/core/src/test/java/brooklyn/policy/basic/PolicyTypeTest.java
+++ /dev/null
@@ -1,58 +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 brooklyn.policy.basic;
-
-import static org.testng.Assert.assertEquals;
-
-import org.apache.brooklyn.api.policy.PolicyType;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.event.basic.BasicConfigKey;
-
-import com.google.common.collect.ImmutableSet;
-
-public class PolicyTypeTest {
- private MyPolicy policy;
-
- @BeforeMethod(alwaysRun=true)
- public void setUpTestEntity() throws Exception{
- policy = new MyPolicy();
- }
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws Exception {
- // nothing to tear down; no management context not started
- }
-
- @Test
- public void testGetConfig() throws Exception {
- PolicyType policyType = policy.getPolicyType();
- assertEquals(policyType.getConfigKeys(), ImmutableSet.of(MyPolicy.CONF1, MyPolicy.CONF2));
- assertEquals(policyType.getName(), MyPolicy.class.getCanonicalName());
- assertEquals(policyType.getConfigKey("test.conf1"), MyPolicy.CONF1);
- assertEquals(policyType.getConfigKey("test.conf2"), MyPolicy.CONF2);
- }
-
- public static class MyPolicy extends AbstractPolicy {
- public static final BasicConfigKey<String> CONF1 = new BasicConfigKey<String>(String.class, "test.conf1", "my descr, conf1", "defaultval1");
- public static final BasicConfigKey<Integer> CONF2 = new BasicConfigKey<Integer>(Integer.class, "test.conf2", "my descr, conf2", 2);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/test/java/brooklyn/test/policy/TestPolicy.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/test/policy/TestPolicy.java b/core/src/test/java/brooklyn/test/policy/TestPolicy.java
index 184eb4e..e30fd2c 100644
--- a/core/src/test/java/brooklyn/test/policy/TestPolicy.java
+++ b/core/src/test/java/brooklyn/test/policy/TestPolicy.java
@@ -22,12 +22,12 @@ import java.util.Collections;
import java.util.Map;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.policy.basic.AbstractPolicy;
import com.google.common.reflect.TypeToken;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/test/java/org/apache/brooklyn/core/policy/basic/BasicPolicyTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/policy/basic/BasicPolicyTest.java b/core/src/test/java/org/apache/brooklyn/core/policy/basic/BasicPolicyTest.java
new file mode 100644
index 0000000..852e658
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/policy/basic/BasicPolicyTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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.policy.basic;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.Map;
+
+import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
+import org.testng.annotations.Test;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.BrooklynAppUnitTestSupport;
+import brooklyn.event.basic.BasicConfigKey;
+import brooklyn.util.collections.MutableSet;
+
+/**
+ * Test that policy can be created and accessed, by construction and by spec
+ */
+public class BasicPolicyTest extends BrooklynAppUnitTestSupport {
+
+ public static class MyPolicy extends AbstractPolicy {
+ @SetFromFlag("intKey")
+ public static final BasicConfigKey<Integer> INT_KEY = new BasicConfigKey<Integer>(Integer.class, "bkey", "b key");
+
+ @SetFromFlag("strKey")
+ public static final ConfigKey<String> STR_KEY = new BasicConfigKey<String>(String.class, "akey", "a key");
+ public static final ConfigKey<Integer> INT_KEY_WITH_DEFAULT = new BasicConfigKey<Integer>(Integer.class, "ckey", "c key", 1);
+ public static final ConfigKey<String> STR_KEY_WITH_DEFAULT = new BasicConfigKey<String>(String.class, "strKey", "str key", "str key default");
+
+ MyPolicy(Map<?,?> flags) {
+ super(flags);
+ }
+
+ public MyPolicy() {
+ super();
+ }
+ }
+
+ @Test
+ public void testAddInstance() throws Exception {
+ MyPolicy policy = new MyPolicy();
+ policy.setDisplayName("Bob");
+ policy.config().set(MyPolicy.STR_KEY, "aval");
+ policy.config().set(MyPolicy.INT_KEY, 2);
+ app.addPolicy(policy);
+
+ assertEquals(policy.getDisplayName(), "Bob");
+ assertEquals(policy.getConfig(MyPolicy.STR_KEY), "aval");
+ assertEquals(policy.getConfig(MyPolicy.INT_KEY), (Integer)2);
+ }
+
+ @Test
+ public void testAddSpec() throws Exception {
+ MyPolicy policy = app.addPolicy(PolicySpec.create(MyPolicy.class)
+ .displayName("Bob")
+ .configure(MyPolicy.STR_KEY, "aval").configure(MyPolicy.INT_KEY, 2));
+
+ assertEquals(policy.getDisplayName(), "Bob");
+ assertEquals(policy.getConfig(MyPolicy.STR_KEY), "aval");
+ assertEquals(policy.getConfig(MyPolicy.INT_KEY), (Integer)2);
+ }
+
+ @Test
+ public void testTagsFromSpec() throws Exception {
+ MyPolicy policy = app.addPolicy(PolicySpec.create(MyPolicy.class).tag(99).uniqueTag("x"));
+
+ assertEquals(policy.tags().getTags(), MutableSet.of("x", 99));
+ assertEquals(policy.getUniqueTag(), "x");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/test/java/org/apache/brooklyn/core/policy/basic/EnricherTypeTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/policy/basic/EnricherTypeTest.java b/core/src/test/java/org/apache/brooklyn/core/policy/basic/EnricherTypeTest.java
new file mode 100644
index 0000000..380192d
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/policy/basic/EnricherTypeTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.policy.basic;
+
+import static org.testng.Assert.assertEquals;
+
+import org.apache.brooklyn.api.policy.EnricherType;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.enricher.basic.AbstractEnricher;
+import brooklyn.event.basic.BasicConfigKey;
+
+import com.google.common.collect.ImmutableSet;
+
+public class EnricherTypeTest {
+ private MyEnricher enricher;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception{
+ enricher = new MyEnricher();
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ // nothing to tear down; no management context not started
+ }
+
+ @Test
+ public void testGetConfig() throws Exception {
+ EnricherType enricherType = enricher.getEnricherType();
+ assertEquals(enricherType.getConfigKeys(), ImmutableSet.of(MyEnricher.CONF1, MyEnricher.CONF2, AbstractEnricher.SUPPRESS_DUPLICATES));
+ assertEquals(enricherType.getName(), MyEnricher.class.getCanonicalName());
+ assertEquals(enricherType.getConfigKey("test.conf1"), MyEnricher.CONF1);
+ assertEquals(enricherType.getConfigKey("test.conf2"), MyEnricher.CONF2);
+ }
+
+ public static class MyEnricher extends AbstractEnricher {
+ public static final BasicConfigKey<String> CONF1 = new BasicConfigKey<String>(String.class, "test.conf1", "my descr, conf1", "defaultval1");
+ public static final BasicConfigKey<Integer> CONF2 = new BasicConfigKey<Integer>(Integer.class, "test.conf2", "my descr, conf2", 2);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/test/java/org/apache/brooklyn/core/policy/basic/PolicyConfigTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/policy/basic/PolicyConfigTest.java b/core/src/test/java/org/apache/brooklyn/core/policy/basic/PolicyConfigTest.java
new file mode 100644
index 0000000..295d621
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/policy/basic/PolicyConfigTest.java
@@ -0,0 +1,202 @@
+/*
+ * 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.policy.basic;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+
+import org.apache.brooklyn.core.policy.basic.BasicPolicyTest.MyPolicy;
+import org.apache.brooklyn.test.entity.TestEntity;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.BrooklynAppUnitTestSupport;
+import brooklyn.event.basic.BasicConfigKey;
+import brooklyn.event.basic.DependentConfiguration;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+
+import com.google.common.util.concurrent.Callables;
+
+/**
+ * Test that configuration properties are usable and inherited correctly.
+ */
+public class PolicyConfigTest extends BrooklynAppUnitTestSupport {
+ private static final int EARLY_RETURN_GRACE = 10;
+
+ private BasicConfigKey<String> differentKey = new BasicConfigKey<String>(String.class, "differentkey", "diffval");
+
+ @Test
+ public void testConfigFlagsPassedInAtConstructionIsAvailable() throws Exception {
+ MyPolicy policy = new MyPolicy(MutableMap.builder()
+ .put("strKey", "aval")
+ .put("intKey", 2)
+ .build());
+ app.addPolicy(policy);
+
+ assertEquals(policy.getConfig(MyPolicy.STR_KEY), "aval");
+ assertEquals(policy.getConfig(MyPolicy.INT_KEY), (Integer)2);
+ // this is set, because key name matches annotation on STR_KEY
+ assertEquals(policy.getConfig(MyPolicy.STR_KEY_WITH_DEFAULT), "aval");
+ }
+
+ @Test
+ public void testUnknownConfigPassedInAtConstructionIsWarnedAndIgnored() throws Exception {
+ // TODO Also assert it's warned
+ MyPolicy policy = new MyPolicy(MutableMap.builder()
+ .put(differentKey, "aval")
+ .build());
+ app.addPolicy(policy);
+
+ assertEquals(policy.getConfig(differentKey), null);
+ assertEquals(policy.getPolicyType().getConfigKey(differentKey.getName()), null);
+ }
+
+ @Test
+ public void testConfigPassedInAtConstructionIsAvailable() throws Exception {
+ MyPolicy policy = new MyPolicy(MutableMap.builder()
+ .put(MyPolicy.STR_KEY, "aval")
+ .put(MyPolicy.INT_KEY, 2)
+ .build());
+ app.addPolicy(policy);
+
+ assertEquals(policy.getConfig(MyPolicy.STR_KEY), "aval");
+ assertEquals(policy.getConfig(MyPolicy.INT_KEY), (Integer)2);
+ // this is not set (contrast with above)
+ assertEquals(policy.getConfig(MyPolicy.STR_KEY_WITH_DEFAULT), MyPolicy.STR_KEY_WITH_DEFAULT.getDefaultValue());
+ }
+
+ @Test
+ public void testConfigSetToGroovyTruthFalseIsAvailable() throws Exception {
+ MyPolicy policy = new MyPolicy(MutableMap.builder()
+ .put(MyPolicy.INT_KEY_WITH_DEFAULT, 0)
+ .build());
+ app.addPolicy(policy);
+
+ assertEquals(policy.getConfig(MyPolicy.INT_KEY_WITH_DEFAULT), (Integer)0);
+ }
+
+ @Test
+ public void testConfigSetToNullIsAvailable() throws Exception {
+ MyPolicy policy = new MyPolicy(MutableMap.builder()
+ .put(MyPolicy.STR_KEY_WITH_DEFAULT, null)
+ .build());
+ app.addPolicy(policy);
+
+ assertEquals(policy.getConfig(MyPolicy.STR_KEY_WITH_DEFAULT), null);
+ }
+
+ @Test
+ public void testConfigCanBeSetOnPolicy() throws Exception {
+ MyPolicy policy = new MyPolicy();
+ policy.config().set(MyPolicy.STR_KEY, "aval");
+ policy.config().set(MyPolicy.INT_KEY, 2);
+ app.addPolicy(policy);
+
+ assertEquals(policy.getConfig(MyPolicy.STR_KEY), "aval");
+ assertEquals(policy.getConfig(MyPolicy.INT_KEY), (Integer)2);
+ }
+
+ @Test
+ public void testConfigSetterOverridesConstructorValue() throws Exception {
+ MyPolicy policy = new MyPolicy(MutableMap.builder()
+ .put(MyPolicy.STR_KEY, "aval")
+ .build());
+ policy.config().set(MyPolicy.STR_KEY, "diffval");
+ app.addPolicy(policy);
+
+ assertEquals(policy.getConfig(MyPolicy.STR_KEY), "diffval");
+ }
+
+ @Test
+ public void testConfigCannotBeSetAfterApplicationIsStarted() throws Exception {
+ MyPolicy policy = new MyPolicy(MutableMap.builder()
+ .put(MyPolicy.STR_KEY, "origval")
+ .build());
+ app.addPolicy(policy);
+
+ try {
+ policy.config().set(MyPolicy.STR_KEY,"newval");
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // success
+ }
+
+ assertEquals(policy.getConfig(MyPolicy.STR_KEY), "origval");
+ }
+
+ @Test
+ public void testConfigReturnsDefaultValueIfNotSet() throws Exception {
+ MyPolicy policy = new MyPolicy();
+ app.addPolicy(policy);
+
+ assertEquals(policy.getConfig(MyPolicy.STR_KEY_WITH_DEFAULT), "str key default");
+ }
+
+ // FIXME Should we support this now?
+ @Test(enabled=false)
+ public void testGetFutureConfigWhenReady() throws Exception {
+ MyPolicy policy = new MyPolicy(MutableMap.builder()
+ .put(TestEntity.CONF_NAME, DependentConfiguration.whenDone(Callables.returning("aval")))
+ .build());
+ app.addPolicy(policy);
+
+ assertEquals(policy.getConfig(TestEntity.CONF_NAME), "aval");
+ }
+
+ // FIXME Should we support this now?
+ @Test(enabled=false)
+ public void testGetFutureConfigBlocksUntilReady() throws Exception {
+ final CountDownLatch latch = new CountDownLatch(1);
+ MyPolicy policy = new MyPolicy(MutableMap.builder()
+ .put(TestEntity.CONF_NAME, DependentConfiguration.whenDone(new Callable<String>() {
+ public String call() {
+ try {
+ latch.await(); return "aval";
+ } catch (InterruptedException e) {
+ throw Exceptions.propagate(e);
+ }
+ }}))
+ .build());
+ app.addPolicy(policy);
+
+ Thread t = new Thread(new Runnable() {
+ public void run() {
+ try {
+ Thread.sleep(10+EARLY_RETURN_GRACE); latch.countDown();
+ } catch (InterruptedException e) {
+ throw Exceptions.propagate(e);
+ }
+ }});
+ try {
+ long starttime = System.currentTimeMillis();
+ t.start();
+ assertEquals(policy.getConfig(TestEntity.CONF_NAME), "aval");
+ long endtime = System.currentTimeMillis();
+
+ assertTrue((endtime - starttime) >= 10, "starttime="+starttime+"; endtime="+endtime);
+
+ } finally {
+ t.interrupt();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/test/java/org/apache/brooklyn/core/policy/basic/PolicySubscriptionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/policy/basic/PolicySubscriptionTest.java b/core/src/test/java/org/apache/brooklyn/core/policy/basic/PolicySubscriptionTest.java
new file mode 100644
index 0000000..b775598
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/policy/basic/PolicySubscriptionTest.java
@@ -0,0 +1,128 @@
+/*
+ * 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.policy.basic;
+
+import static org.testng.Assert.assertEquals;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.BrooklynAppUnitTestSupport;
+
+import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.api.management.SubscriptionHandle;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
+import org.apache.brooklyn.entity.basic.RecordingSensorEventListener;
+import org.apache.brooklyn.test.entity.TestEntity;
+
+import brooklyn.event.basic.BasicSensorEvent;
+
+import org.apache.brooklyn.location.basic.SimulatedLocation;
+
+import brooklyn.test.Asserts;
+
+import com.google.common.collect.ImmutableList;
+
+public class PolicySubscriptionTest extends BrooklynAppUnitTestSupport {
+
+ // TODO Duplication between this and EntitySubscriptionTest
+
+ private static final long SHORT_WAIT_MS = 100;
+
+ private SimulatedLocation loc;
+ private TestEntity entity;
+ private TestEntity otherEntity;
+ private AbstractPolicy policy;
+ private RecordingSensorEventListener<Object> listener;
+
+ @BeforeMethod(alwaysRun=true)
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ loc = app.newSimulatedLocation();
+ entity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+ otherEntity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+ listener = new RecordingSensorEventListener<>();
+ policy = new AbstractPolicy() {};
+ entity.addPolicy(policy);
+ app.start(ImmutableList.of(loc));
+ }
+
+ @Test
+ public void testSubscriptionReceivesEvents() throws Exception {
+ policy.subscribe(entity, TestEntity.SEQUENCE, listener);
+ policy.subscribe(entity, TestEntity.NAME, listener);
+ policy.subscribe(entity, TestEntity.MY_NOTIF, listener);
+
+ otherEntity.setAttribute(TestEntity.SEQUENCE, 456);
+ entity.setAttribute(TestEntity.SEQUENCE, 123);
+ entity.setAttribute(TestEntity.NAME, "myname");
+ entity.emit(TestEntity.MY_NOTIF, 789);
+
+ Asserts.succeedsEventually(new Runnable() {
+ @Override public void run() {
+ assertEquals(listener.getEvents(), ImmutableList.of(
+ new BasicSensorEvent<Integer>(TestEntity.SEQUENCE, entity, 123),
+ new BasicSensorEvent<String>(TestEntity.NAME, entity, "myname"),
+ new BasicSensorEvent<Integer>(TestEntity.MY_NOTIF, entity, 789)));
+ }});
+ }
+
+ @Test
+ public void testUnsubscribeRemovesAllSubscriptionsForThatEntity() throws Exception {
+ policy.subscribe(entity, TestEntity.SEQUENCE, listener);
+ policy.subscribe(entity, TestEntity.NAME, listener);
+ policy.subscribe(entity, TestEntity.MY_NOTIF, listener);
+ policy.subscribe(otherEntity, TestEntity.SEQUENCE, listener);
+ policy.unsubscribe(entity);
+
+ entity.setAttribute(TestEntity.SEQUENCE, 123);
+ entity.setAttribute(TestEntity.NAME, "myname");
+ entity.emit(TestEntity.MY_NOTIF, 456);
+ otherEntity.setAttribute(TestEntity.SEQUENCE, 789);
+
+ Thread.sleep(SHORT_WAIT_MS);
+ Asserts.succeedsEventually(new Runnable() {
+ @Override public void run() {
+ assertEquals(listener.getEvents(), ImmutableList.of(
+ new BasicSensorEvent<Integer>(TestEntity.SEQUENCE, otherEntity, 789)));
+ }});
+ }
+
+ @Test
+ public void testUnsubscribeUsingHandleStopsEvents() throws Exception {
+ SubscriptionHandle handle1 = policy.subscribe(entity, TestEntity.SEQUENCE, listener);
+ SubscriptionHandle handle2 = policy.subscribe(entity, TestEntity.NAME, listener);
+ SubscriptionHandle handle3 = policy.subscribe(otherEntity, TestEntity.SEQUENCE, listener);
+
+ policy.unsubscribe(entity, handle2);
+
+ entity.setAttribute(TestEntity.SEQUENCE, 123);
+ entity.setAttribute(TestEntity.NAME, "myname");
+ otherEntity.setAttribute(TestEntity.SEQUENCE, 456);
+
+ Asserts.succeedsEventually(new Runnable() {
+ @Override public void run() {
+ assertEquals(listener.getEvents(), ImmutableList.of(
+ new BasicSensorEvent<Integer>(TestEntity.SEQUENCE, entity, 123),
+ new BasicSensorEvent<Integer>(TestEntity.SEQUENCE, otherEntity, 456)));
+ }});
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/test/java/org/apache/brooklyn/core/policy/basic/PolicyTypeTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/policy/basic/PolicyTypeTest.java b/core/src/test/java/org/apache/brooklyn/core/policy/basic/PolicyTypeTest.java
new file mode 100644
index 0000000..40c4df3
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/policy/basic/PolicyTypeTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.policy.basic;
+
+import static org.testng.Assert.assertEquals;
+
+import org.apache.brooklyn.api.policy.PolicyType;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.event.basic.BasicConfigKey;
+
+import com.google.common.collect.ImmutableSet;
+
+public class PolicyTypeTest {
+ private MyPolicy policy;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUpTestEntity() throws Exception{
+ policy = new MyPolicy();
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ // nothing to tear down; no management context not started
+ }
+
+ @Test
+ public void testGetConfig() throws Exception {
+ PolicyType policyType = policy.getPolicyType();
+ assertEquals(policyType.getConfigKeys(), ImmutableSet.of(MyPolicy.CONF1, MyPolicy.CONF2));
+ assertEquals(policyType.getName(), MyPolicy.class.getCanonicalName());
+ assertEquals(policyType.getConfigKey("test.conf1"), MyPolicy.CONF1);
+ assertEquals(policyType.getConfigKey("test.conf2"), MyPolicy.CONF2);
+ }
+
+ public static class MyPolicy extends AbstractPolicy {
+ public static final BasicConfigKey<String> CONF1 = new BasicConfigKey<String>(String.class, "test.conf1", "my descr, conf1", "defaultval1");
+ public static final BasicConfigKey<Integer> CONF2 = new BasicConfigKey<Integer>(Integer.class, "test.conf2", "my descr, conf2", 2);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/locations/jclouds/src/main/java/brooklyn/policy/os/AdvertiseWinrmLoginPolicy.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/brooklyn/policy/os/AdvertiseWinrmLoginPolicy.java b/locations/jclouds/src/main/java/brooklyn/policy/os/AdvertiseWinrmLoginPolicy.java
index 266f738..f5257e5 100644
--- a/locations/jclouds/src/main/java/brooklyn/policy/os/AdvertiseWinrmLoginPolicy.java
+++ b/locations/jclouds/src/main/java/brooklyn/policy/os/AdvertiseWinrmLoginPolicy.java
@@ -24,6 +24,7 @@ import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -32,8 +33,6 @@ import brooklyn.event.basic.Sensors;
import org.apache.brooklyn.location.basic.WinRmMachineLocation;
-import brooklyn.policy.basic.AbstractPolicy;
-
import com.google.common.annotations.Beta;
/**
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/locations/jclouds/src/main/java/brooklyn/policy/os/CreateUserPolicy.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/brooklyn/policy/os/CreateUserPolicy.java b/locations/jclouds/src/main/java/brooklyn/policy/os/CreateUserPolicy.java
index 8327cf1..dd33058 100644
--- a/locations/jclouds/src/main/java/brooklyn/policy/os/CreateUserPolicy.java
+++ b/locations/jclouds/src/main/java/brooklyn/policy/os/CreateUserPolicy.java
@@ -26,6 +26,7 @@ import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.core.util.internal.ssh.SshTool;
import org.jclouds.compute.config.AdminAccessConfiguration;
@@ -43,7 +44,6 @@ import brooklyn.event.basic.Sensors;
import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.util.text.Identifiers;
import com.google.common.annotations.Beta;
[36/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/internal/ssh/sshj/SshjTool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/internal/ssh/sshj/SshjTool.java b/core/src/main/java/brooklyn/util/internal/ssh/sshj/SshjTool.java
deleted file mode 100644
index e069aa9..0000000
--- a/core/src/main/java/brooklyn/util/internal/ssh/sshj/SshjTool.java
+++ /dev/null
@@ -1,1091 +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 brooklyn.util.internal.ssh.sshj;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Throwables.getCausalChain;
-import static com.google.common.collect.Iterables.any;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Callable;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicReference;
-
-import net.schmizz.sshj.connection.ConnectionException;
-import net.schmizz.sshj.connection.channel.direct.PTYMode;
-import net.schmizz.sshj.connection.channel.direct.Session;
-import net.schmizz.sshj.connection.channel.direct.Session.Command;
-import net.schmizz.sshj.connection.channel.direct.Session.Shell;
-import net.schmizz.sshj.connection.channel.direct.SessionChannel;
-import net.schmizz.sshj.sftp.FileAttributes;
-import net.schmizz.sshj.sftp.SFTPClient;
-import net.schmizz.sshj.transport.TransportException;
-import net.schmizz.sshj.xfer.InMemorySourceFile;
-
-import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
-import org.apache.commons.io.input.ProxyInputStream;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.exceptions.RuntimeTimeoutException;
-import brooklyn.util.internal.ssh.BackoffLimitedRetryHandler;
-import brooklyn.util.internal.ssh.ShellTool;
-import brooklyn.util.internal.ssh.SshAbstractTool;
-import brooklyn.util.internal.ssh.SshTool;
-import brooklyn.util.io.FileUtil;
-import brooklyn.util.repeat.Repeater;
-import brooklyn.util.stream.KnownSizeInputStream;
-import brooklyn.util.stream.StreamGobbler;
-import brooklyn.util.stream.Streams;
-import brooklyn.util.text.Strings;
-import brooklyn.util.time.Duration;
-import brooklyn.util.time.Time;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Joiner;
-import com.google.common.base.Predicate;
-import com.google.common.base.Stopwatch;
-import com.google.common.base.Supplier;
-import com.google.common.base.Suppliers;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.io.CountingOutputStream;
-import com.google.common.net.HostAndPort;
-import com.google.common.primitives.Ints;
-
-/**
- * For ssh and scp-style commands, using the sshj library.
- */
-public class SshjTool extends SshAbstractTool implements SshTool {
-
- /*
- * TODO synchronization of connect/disconnect needs revisited!
- * Saw SshjToolIntegrationTest.testExecBigConcurrentCommand fail with:
- * Caused by: java.lang.AssertionError
- * at net.schmizz.sshj.SSHClient.auth(SSHClient.java:204)
- * i.e. another thread had called disconnect just before the failing thread
- * did SSHClient.auth.
- * Having multiple threads call connect/disconnect is going to be brittle. With
- * our retries we can get away with it usually, but it's not good!
- *
- * TODO need to upgrade sshj version from 0.8.1 to 0.9, but jclouds 1.7.2 still
- * relies on 0.8.1. In 0.9, it fixes the https://github.com/shikhar/sshj/issues/89
- * so does not throw AssertionError.
- */
-
- private static final Logger LOG = LoggerFactory.getLogger(SshjTool.class);
-
- protected final int sshTries;
- protected final long sshTriesTimeout;
- protected final BackoffLimitedRetryHandler backoffLimitedRetryHandler;
-
- /** Terminal type name for {@code allocatePTY} option. */
- final static String TERM = "vt100"; // "dumb"
-
- private class CloseFtpChannelOnCloseInputStream extends ProxyInputStream {
- private final SFTPClient sftp;
-
- private CloseFtpChannelOnCloseInputStream(InputStream proxy, SFTPClient sftp) {
- super(proxy);
- this.sftp = sftp;
- }
-
- @Override
- public void close() throws IOException {
- super.close();
- closeWhispering(sftp, this);
- }
- }
-
- private final SshjClientConnection sshClientConnection;
-
- public static SshjToolBuilder builder() {
- return new SshjToolBuilder();
- }
-
- public static class SshjToolBuilder extends Builder<SshjTool, SshjToolBuilder> {
- }
-
- public static class Builder<T extends SshjTool, B extends Builder<T,B>> extends AbstractSshToolBuilder<T,B> {
- protected long connectTimeout;
- protected long sessionTimeout;
- protected int sshTries = 4; //allow 4 tries by default, much safer
- protected long sshTriesTimeout = 2*60*1000; //allow 2 minutes by default (so if too slow trying sshTries times, abort anyway)
- protected long sshRetryDelay = 50L;
-
- @Override
- public B from(Map<String,?> props) {
- super.from(props);
- sshTries = getOptionalVal(props, PROP_SSH_TRIES);
- sshTriesTimeout = getOptionalVal(props, PROP_SSH_TRIES_TIMEOUT);
- sshRetryDelay = getOptionalVal(props, PROP_SSH_RETRY_DELAY);
- connectTimeout = getOptionalVal(props, PROP_CONNECT_TIMEOUT);
- sessionTimeout = getOptionalVal(props, PROP_SESSION_TIMEOUT);
- return self();
- }
- public B connectTimeout(int val) {
- this.connectTimeout = val; return self();
- }
- public B sessionTimeout(int val) {
- this.sessionTimeout = val; return self();
- }
- public B sshRetries(int val) {
- this.sshTries = val; return self();
- }
- public B sshRetriesTimeout(int val) {
- this.sshTriesTimeout = val; return self();
- }
- public B sshRetryDelay(long val) {
- this.sshRetryDelay = val; return self();
- }
- @Override
- @SuppressWarnings("unchecked")
- public T build() {
- return (T) new SshjTool(this);
- }
- }
-
- public SshjTool(Map<String,?> map) {
- this(builder().from(map));
- }
-
- protected SshjTool(Builder<?,?> builder) {
- super(builder);
-
- sshTries = builder.sshTries;
- sshTriesTimeout = builder.sshTriesTimeout;
- backoffLimitedRetryHandler = new BackoffLimitedRetryHandler(sshTries, builder.sshRetryDelay);
-
- sshClientConnection = SshjClientConnection.builder()
- .hostAndPort(HostAndPort.fromParts(host, port))
- .username(user)
- .password(password)
- .privateKeyPassphrase(privateKeyPassphrase)
- .privateKeyData(privateKeyData)
- .privateKeyFile(privateKeyFile)
- .strictHostKeyChecking(strictHostKeyChecking)
- .connectTimeout(builder.connectTimeout)
- .sessionTimeout(builder.sessionTimeout)
- .build();
-
- if (LOG.isTraceEnabled()) LOG.trace("Created SshTool {} ({})", this, System.identityHashCode(this));
- }
-
- @Override
- public void connect() {
- try {
- if (LOG.isTraceEnabled()) LOG.trace("Connecting SshjTool {} ({})", this, System.identityHashCode(this));
- acquire(sshClientConnection);
- } catch (Exception e) {
- if (LOG.isDebugEnabled()) LOG.debug(toString()+" failed to connect (rethrowing)", e);
- throw propagate(e, "failed to connect");
- }
- }
-
- @Override
- @Deprecated // see super
- public void connect(int maxAttempts) {
- connect(); // FIXME Should callers instead configure sshTries? But that would apply to all ssh attempts
- }
-
- @Override
- public void disconnect() {
- if (LOG.isTraceEnabled()) LOG.trace("Disconnecting SshjTool {} ({})", this, System.identityHashCode(this));
- try {
- Stopwatch perfStopwatch = Stopwatch.createStarted();
- sshClientConnection.clear();
- if (LOG.isTraceEnabled()) LOG.trace("SSH Performance: {} disconnect took {}", sshClientConnection.getHostAndPort(), Time.makeTimeStringRounded(perfStopwatch));
- } catch (Exception e) {
- throw Exceptions.propagate(e);
- }
- }
-
- @Override
- public boolean isConnected() {
- return sshClientConnection.isConnected() && sshClientConnection.isAuthenticated();
- }
-
- @Override
- public int copyToServer(java.util.Map<String,?> props, byte[] contents, String pathAndFileOnRemoteServer) {
- return copyToServer(props, newInputStreamSupplier(contents), contents.length, pathAndFileOnRemoteServer);
- }
-
- @Override
- public int copyToServer(Map<String,?> props, InputStream contents, String pathAndFileOnRemoteServer) {
- /* sshj needs to:
- * 1) to know the length of the InputStream to copy the file to perform copy; and
- * 2) re-read the input stream on retry if the first attempt fails.
- * For now, write it to a file, unless caller supplies a KnownSizeInputStream
- *
- * (We could have a switch where we hold it in memory if less than some max size,
- * but most the routines should supply a string or byte array or similar,
- * so we probably don't come here too often.)
- */
- if (contents instanceof KnownSizeInputStream) {
- return copyToServer(props, Suppliers.ofInstance(contents), ((KnownSizeInputStream)contents).length(), pathAndFileOnRemoteServer);
- } else {
- File tempFile = writeTempFile(contents);
- try {
- return copyToServer(props, tempFile, pathAndFileOnRemoteServer);
- } finally {
- tempFile.delete();
- }
- }
- }
-
- @Override
- public int copyToServer(Map<String,?> props, File localFile, String pathAndFileOnRemoteServer) {
- return copyToServer(props, newInputStreamSupplier(localFile), (int)localFile.length(), pathAndFileOnRemoteServer);
- }
-
- private int copyToServer(Map<String,?> props, Supplier<InputStream> contentsSupplier, long length, String pathAndFileOnRemoteServer) {
- acquire(new PutFileAction(props, pathAndFileOnRemoteServer, contentsSupplier, length));
- return 0; // TODO Can we assume put will have thrown exception if failed? Rather than exit code != 0?
- }
-
-
- @Override
- public int copyFromServer(Map<String,?> props, String pathAndFileOnRemoteServer, File localFile) {
- InputStream contents = acquire(new GetFileAction(pathAndFileOnRemoteServer));
- try {
- FileUtil.copyTo(contents, localFile);
- return 0; // TODO Can we assume put will have thrown exception if failed? Rather than exit code != 0?
- } finally {
- Streams.closeQuietly(contents);
- }
- }
-
- /**
- * This creates a script containing the user's commands, copies it to the remote server, and
- * executes the script. The script is then deleted.
- * <p>
- * Executing commands directly is fraught with dangers! Here are other options, and their problems:
- * <ul>
- * <li>Use execCommands, rather than shell.
- * The user's environment will not be setup normally (e.g. ~/.bash_profile will not have been sourced)
- * so things like wget may not be on the PATH.
- * <li>Send the stream of commands to the shell.
- * But characters being sent can be lost.
- * Try the following (e.g. in an OS X terminal):
- * - sleep 5
- * - <paste a command that is 1000s of characters long>
- * Only the first 1024 characters appear. The rest are lost.
- * If sending a stream of commands, you need to be careful not send the next (big) command while the
- * previous one is still executing.
- * <li>Send a stream to the shell, but spot when the previous command has completed.
- * e.g. by looking for the prompt (but what if the commands being executed change the prompt?)
- * e.g. by putting every second command as "echo <uid>", and waiting for the stdout.
- * This gets fiddly...
- * </ul>
- *
- * So on balance, the script-based approach seems most reliable, even if there is an overhead
- * of separate message(s) for copying the file!
- *
- * Another consideration is long-running scripts. On some clouds when executing a script that takes
- * several minutes, we have seen it fail with -1 (e.g. 1 in 20 times). This suggests the ssh connection
- * is being dropped. To avoid this problem, we can execute the script asynchronously, writing to files
- * the stdout/stderr/pid/exitStatus. We then periodically poll to retrieve the contents of these files.
- * Use {@link #PROP_EXEC_ASYNC} to force this mode of execution.
- */
- @Override
- public int execScript(final Map<String,?> props, final List<String> commands, final Map<String,?> env) {
- Boolean execAsync = getOptionalVal(props, PROP_EXEC_ASYNC);
- if (Boolean.TRUE.equals(execAsync) && BrooklynFeatureEnablement.isEnabled(BrooklynFeatureEnablement.FEATURE_SSH_ASYNC_EXEC)) {
- return execScriptAsyncAndPoll(props, commands, env);
- } else {
- if (Boolean.TRUE.equals(execAsync)) {
- if (LOG.isDebugEnabled()) LOG.debug("Ignoring ssh exec-async configuration, because feature is disabled");
- }
- return new ToolAbstractExecScript(props) {
- public int run() {
- String scriptContents = toScript(props, commands, env);
- if (LOG.isTraceEnabled()) LOG.trace("Running shell command at {} as script: {}", host, scriptContents);
- copyToServer(ImmutableMap.of("permissions", "0700"), scriptContents.getBytes(), scriptPath);
- return asInt(acquire(new ShellAction(buildRunScriptCommand(), out, err, execTimeout)), -1);
- }
- }.run();
- }
- }
-
- /**
- * Executes the script in the background (`nohup ... &`), and then executes other ssh commands to poll for the
- * stdout, stderr and exit code of that original process (which will each have been written to separate files).
- *
- * The polling is a "long poll". That is, it executes a long-running ssh command to retrieve the stdout, etc.
- * If that long-poll command fails, then we just execute another one to pick up from where it left off.
- * This means we do not need to execute many ssh commands (which are expensive), but can still return promptly
- * when the command completes.
- *
- * Much of this was motivated by https://issues.apache.org/jira/browse/BROOKLYN-106, which is no longer
- * an issue. The retries (e.g. in the upload-script) are arguably overkill given that {@link #acquire(SshAction)}
- * will already retry. However, leaving this in place as it could prove useful when working with flakey
- * networks in the future.
- *
- * TODO There are (probably) issues with this method when using {@link ShellTool#PROP_RUN_AS_ROOT}.
- * I (Aled) saw the .pid file having an owner of root:root, and a failure message in stderr of:
- * -bash: line 3: /tmp/brooklyn-20150113-161203056-XMEo-move_install_dir_from_user_to_.pid: Permission denied
- */
- protected int execScriptAsyncAndPoll(final Map<String,?> props, final List<String> commands, final Map<String,?> env) {
- return new ToolAbstractAsyncExecScript(props) {
- private int maxConsecutiveSshFailures = 3;
- private Duration maxDelayBetweenPolls = Duration.seconds(20);
- private Duration pollTimeout = getOptionalVal(props, PROP_EXEC_ASYNC_POLLING_TIMEOUT, Duration.FIVE_MINUTES);
- private int iteration = 0;
- private int consecutiveSshFailures = 0;
- private int stdoutCount = 0;
- private int stderrCount = 0;
- private Stopwatch timer;
-
- public int run() {
- timer = Stopwatch.createStarted();
- final String scriptContents = toScript(props, commands, env);
- if (LOG.isTraceEnabled()) LOG.trace("Running shell command at {} as async script: {}", host, scriptContents);
-
- // Upload script; try repeatedly because have seen timeout intermittently on vcloud-director (BROOKLYN-106 related).
- boolean uploadSuccess = Repeater.create("async script upload on "+SshjTool.this.toString()+" (for "+getSummary()+")")
- .backoffTo(maxDelayBetweenPolls)
- .limitIterationsTo(3)
- .rethrowException()
- .until(new Callable<Boolean>() {
- @Override
- public Boolean call() throws Exception {
- iteration++;
- if (LOG.isDebugEnabled()) {
- String msg = "Uploading (iteration="+iteration+") for async script on "+SshjTool.this.toString()+" (for "+getSummary()+")";
- if (iteration == 1) {
- LOG.trace(msg);
- } else {
- LOG.debug(msg);
- }
- }
- copyToServer(ImmutableMap.of("permissions", "0700"), scriptContents.getBytes(), scriptPath);
- return true;
- }})
- .run();
-
- if (!uploadSuccess) {
- // Unexpected! Should have either returned true or have rethrown the exception; should never get false.
- String msg = "Unexpected state: repeated failure for async script upload on "+SshjTool.this.toString()+" ("+getSummary()+")";
- LOG.warn(msg+"; rethrowing");
- throw new IllegalStateException(msg);
- }
-
- // Execute script asynchronously
- int execResult = asInt(acquire(new ShellAction(buildRunScriptCommand(), out, err, execTimeout)), -1);
- if (execResult != 0) return execResult;
-
- // Long polling to get the status
- try {
- final AtomicReference<Integer> result = new AtomicReference<Integer>();
- boolean success = Repeater.create("async script long-poll on "+SshjTool.this.toString()+" (for "+getSummary()+")")
- .backoffTo(maxDelayBetweenPolls)
- .limitTimeTo(execTimeout)
- .until(new Callable<Boolean>() {
- @Override
- public Boolean call() throws Exception {
- iteration++;
- if (LOG.isDebugEnabled()) LOG.debug("Doing long-poll (iteration="+iteration+") for async script to complete on "+SshjTool.this.toString()+" (for "+getSummary()+")");
- Integer exitstatus = longPoll();
- result.set(exitstatus);
- return exitstatus != null;
- }})
- .run();
-
- if (!success) {
- // Timed out
- String msg = "Timeout for async script to complete on "+SshjTool.this.toString()+" ("+getSummary()+")";
- LOG.warn(msg+"; rethrowing");
- throw new TimeoutException(msg);
- }
-
- return result.get();
-
- } catch (Exception e) {
- LOG.debug("Problem polling for async script on "+SshjTool.this.toString()+" (for "+getSummary()+"); rethrowing after deleting temporary files", e);
- throw Exceptions.propagate(e);
- } finally {
- // Delete the temporary files created (and the `tail -c` commands that might have been left behind by long-polls).
- // Using pollTimeout so doesn't wait forever, but waits for a reasonable (configurable) length of time.
- // TODO also execute this if the `buildRunScriptCommand` fails, as that might have left files behind?
- try {
- int execDeleteResult = asInt(acquire(new ShellAction(deleteTemporaryFilesCommand(), out, err, pollTimeout)), -1);
- if (execDeleteResult != 0) {
- LOG.debug("Problem deleting temporary files of async script on "+SshjTool.this.toString()+" (for "+getSummary()+"): exit status "+execDeleteResult);
- }
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- LOG.debug("Problem deleting temporary files of async script on "+SshjTool.this.toString()+" (for "+getSummary()+"); continuing", e);
- }
- }
- }
-
- Integer longPoll() throws IOException {
- // Long-polling to get stdout, stderr + exit status of async task.
- // If our long-poll disconnects, we will just re-execute.
- // We wrap the stdout/stderr so that we can get the size count.
- // If we disconnect, we will pick up from that char of the stream.
- // TODO Additional stdout/stderr written by buildLongPollCommand() could interfere,
- // causing us to miss some characters.
- Duration nextPollTimeout = Duration.min(pollTimeout, Duration.millis(execTimeout.toMilliseconds()-timer.elapsed(TimeUnit.MILLISECONDS)));
- CountingOutputStream countingOut = (out == null) ? null : new CountingOutputStream(out);
- CountingOutputStream countingErr = (err == null) ? null : new CountingOutputStream(err);
- List<String> pollCommand = buildLongPollCommand(stdoutCount, stderrCount, nextPollTimeout);
- Duration sshJoinTimeout = nextPollTimeout.add(Duration.TEN_SECONDS);
- ShellAction action = new ShellAction(pollCommand, countingOut, countingErr, sshJoinTimeout);
-
- int longPollResult;
- try {
- longPollResult = asInt(acquire(action, 3, nextPollTimeout), -1);
- } catch (RuntimeTimeoutException e) {
- if (LOG.isDebugEnabled()) LOG.debug("Long-poll timed out on "+SshjTool.this.toString()+" (for "+getSummary()+"): "+e);
- return null;
- }
- stdoutCount += (countingOut == null) ? 0 : countingOut.getCount();
- stderrCount += (countingErr == null) ? 0 : countingErr.getCount();
-
- if (longPollResult == 0) {
- if (LOG.isDebugEnabled()) LOG.debug("Long-poll succeeded (exit status 0) on "+SshjTool.this.toString()+" (for "+getSummary()+")");
- return longPollResult; // success
-
- } else if (longPollResult == -1) {
- // probably a connection failure; try again
- if (LOG.isDebugEnabled()) LOG.debug("Long-poll received exit status -1; will retry on "+SshjTool.this.toString()+" (for "+getSummary()+")");
- return null;
-
- } else if (longPollResult == 125) {
- // 125 is the special code for timeout in long-poll (see buildLongPollCommand).
- // However, there is a tiny chance that the underlying command might have returned that exact exit code!
- // Don't treat a timeout as a "consecutiveSshFailure".
- if (LOG.isDebugEnabled()) LOG.debug("Long-poll received exit status "+longPollResult+"; most likely timeout; retrieving actual status on "+SshjTool.this.toString()+" (for "+getSummary()+")");
- return retrieveStatusCommand();
-
- } else {
- // want to double-check whether this is the exit-code from the async process, or
- // some unexpected failure in our long-poll command.
- if (LOG.isDebugEnabled()) LOG.debug("Long-poll received exit status "+longPollResult+"; retrieving actual status on "+SshjTool.this.toString()+" (for "+getSummary()+")");
- Integer result = retrieveStatusCommand();
- if (result != null) {
- return result;
- }
- }
-
- consecutiveSshFailures++;
- if (consecutiveSshFailures > maxConsecutiveSshFailures) {
- LOG.warn("Aborting on "+consecutiveSshFailures+" consecutive ssh connection errors (return -1) when polling for async script to complete on "+SshjTool.this.toString()+" ("+getSummary()+")");
- return -1;
- } else {
- LOG.info("Retrying after ssh connection error when polling for async script to complete on "+SshjTool.this.toString()+" ("+getSummary()+")");
- return null;
- }
- }
-
- Integer retrieveStatusCommand() throws IOException {
- // want to double-check whether this is the exit-code from the async process, or
- // some unexpected failure in our long-poll command.
- ByteArrayOutputStream statusOut = new ByteArrayOutputStream();
- ByteArrayOutputStream statusErr = new ByteArrayOutputStream();
- int statusResult = asInt(acquire(new ShellAction(buildRetrieveStatusCommand(), statusOut, statusErr, execTimeout)), -1);
-
- if (statusResult == 0) {
- // The status we retrieved really is valid; return it.
- // TODO How to ensure no additional output in stdout/stderr when parsing below?
- String statusOutStr = new String(statusOut.toByteArray()).trim();
- if (Strings.isEmpty(statusOutStr)) {
- // suggests not yet completed; will retry with long-poll
- if (LOG.isDebugEnabled()) LOG.debug("Long-poll retrieved status directly; command successful but no result available on "+SshjTool.this.toString()+" (for "+getSummary()+")");
- return null;
- } else {
- if (LOG.isDebugEnabled()) LOG.debug("Long-poll retrieved status directly; returning '"+statusOutStr+"' on "+SshjTool.this.toString()+" (for "+getSummary()+")");
- int result = Integer.parseInt(statusOutStr);
- return result;
- }
-
- } else if (statusResult == -1) {
- // probably a connection failure; try again with long-poll
- if (LOG.isDebugEnabled()) LOG.debug("Long-poll retrieving status directly received exit status -1; will retry on "+SshjTool.this.toString()+" (for "+getSummary()+")");
- return null;
-
- } else {
- if (out != null) {
- out.write(toUTF8ByteArray("retrieving status failed with exit code "+statusResult+" (stdout follow)"));
- out.write(statusOut.toByteArray());
- }
- if (err != null) {
- err.write(toUTF8ByteArray("retrieving status failed with exit code "+statusResult+" (stderr follow)"));
- err.write(statusErr.toByteArray());
- }
-
- if (LOG.isDebugEnabled()) LOG.debug("Long-poll retrieving status failed; returning "+statusResult+" on "+SshjTool.this.toString()+" (for "+getSummary()+")");
- return statusResult;
- }
- }
- }.run();
- }
-
- public int execShellDirect(Map<String,?> props, List<String> commands, Map<String,?> env) {
- OutputStream out = getOptionalVal(props, PROP_OUT_STREAM);
- OutputStream err = getOptionalVal(props, PROP_ERR_STREAM);
- Duration execTimeout = getOptionalVal(props, PROP_EXEC_TIMEOUT);
-
- List<String> cmdSequence = toCommandSequence(commands, env);
- List<String> allcmds = ImmutableList.<String>builder()
- .add(getOptionalVal(props, PROP_DIRECT_HEADER))
- .addAll(cmdSequence)
- .add("exit $?")
- .build();
-
- if (LOG.isTraceEnabled()) LOG.trace("Running shell command at {}: {}", host, allcmds);
-
- Integer result = acquire(new ShellAction(allcmds, out, err, execTimeout));
- if (LOG.isTraceEnabled()) LOG.trace("Running shell command at {} completed: return status {}", host, result);
- return asInt(result, -1);
- }
-
- @Override
- public int execCommands(Map<String,?> props, List<String> commands, Map<String,?> env) {
- if (Boolean.FALSE.equals(props.get("blocks"))) {
- throw new IllegalArgumentException("Cannot exec non-blocking: command="+commands);
- }
-
- // If async is set, then do it as execScript
- Boolean execAsync = getOptionalVal(props, PROP_EXEC_ASYNC);
- if (Boolean.TRUE.equals(execAsync) && BrooklynFeatureEnablement.isEnabled(BrooklynFeatureEnablement.FEATURE_SSH_ASYNC_EXEC)) {
- return execScriptAsyncAndPoll(props, commands, env);
- }
-
- OutputStream out = getOptionalVal(props, PROP_OUT_STREAM);
- OutputStream err = getOptionalVal(props, PROP_ERR_STREAM);
- String separator = getOptionalVal(props, PROP_SEPARATOR);
- Duration execTimeout = getOptionalVal(props, PROP_EXEC_TIMEOUT);
-
- List<String> allcmds = toCommandSequence(commands, env);
- String singlecmd = Joiner.on(separator).join(allcmds);
-
- if (Boolean.TRUE.equals(getOptionalVal(props, PROP_RUN_AS_ROOT))) {
- LOG.warn("Cannot run as root when executing as command; run as a script instead (will run as normal user): "+singlecmd);
- }
-
- if (LOG.isTraceEnabled()) LOG.trace("Running command at {}: {}", host, singlecmd);
-
- Command result = acquire(new ExecAction(singlecmd, out, err, execTimeout));
- if (LOG.isTraceEnabled()) LOG.trace("Running command at {} completed: exit code {}", host, result.getExitStatus());
- // can be null if no exit status is received (observed on kill `ps aux | grep thing-to-grep-for | awk {print $2}`
- if (result.getExitStatus()==null) LOG.warn("Null exit status running at {}: {}", host, singlecmd);
-
- return asInt(result.getExitStatus(), -1);
- }
-
- protected void checkConnected() {
- if (!isConnected()) {
- throw new IllegalStateException(String.format("(%s) ssh not connected!", toString()));
- }
- }
-
- protected void backoffForAttempt(int retryAttempt, String message) {
- backoffLimitedRetryHandler.imposeBackoffExponentialDelay(retryAttempt, message);
- }
-
- protected <T, C extends SshAction<T>> T acquire(C action) {
- return acquire(action, sshTries, sshTriesTimeout == 0 ? Duration.PRACTICALLY_FOREVER : Duration.millis(sshTriesTimeout));
- }
-
- protected <T, C extends SshAction<T>> T acquire(C action, int sshTries, Duration sshTriesTimeout) {
- Stopwatch stopwatch = Stopwatch.createStarted();
-
- for (int i = 0; i < sshTries; i++) {
- try {
- action.clear();
- if (LOG.isTraceEnabled()) LOG.trace(">> ({}) acquiring {}", toString(), action);
- Stopwatch perfStopwatch = Stopwatch.createStarted();
-
- T returnVal;
- try {
- returnVal = action.create();
- } catch (AssertionError e) {
- /*
- * TODO In net.schmizz.sshj.SSHClient.auth(SSHClient.java:204) throws AssertionError
- * if not connected. This can happen if another thread has called disconnect
- * concurrently. This is changed in sshj v0.9.0 to instead throw an IllegalStateException.
- *
- * For now, we'll retry. See "TODO" at top of class about synchronization.
- */
- throw new IllegalStateException("Problem in "+toString()+" for "+action, e);
- }
-
- if (LOG.isTraceEnabled()) LOG.trace("<< ({}) acquired {}", toString(), returnVal);
- if (LOG.isTraceEnabled()) LOG.trace("SSH Performance: {} {} took {}", new Object[] {
- sshClientConnection.getHostAndPort(),
- action.getClass().getSimpleName() != null ? action.getClass().getSimpleName() : action,
- Time.makeTimeStringRounded(perfStopwatch)});
- return returnVal;
- } catch (Exception e) {
- // uninformative net.schmizz.sshj.connection.ConnectionException:
- // Request failed (reason=UNKNOWN) may mean remote Subsytem is disabled (e.g. for FTP)
- // if key is missing, get a UserAuth error
- String errorMessage = String.format("(%s) error acquiring %s", toString(), action);
- String fullMessage = String.format("%s (attempt %s/%s, in time %s/%s)",
- errorMessage, (i+1), sshTries, Time.makeTimeStringRounded(stopwatch.elapsed(TimeUnit.MILLISECONDS)),
- (sshTriesTimeout.equals(Duration.PRACTICALLY_FOREVER) ? "unlimited" : Time.makeTimeStringRounded(sshTriesTimeout)));
- try {
- disconnect();
- } catch (Exception e2) {
- LOG.debug("<< ("+toString()+") error closing connection: "+e+" / "+e2, e);
- }
- if (i + 1 == sshTries) {
- LOG.debug("<< {} (rethrowing, out of retries): {}", fullMessage, e.getMessage());
- throw propagate(e, fullMessage + "; out of retries");
- } else if (sshTriesTimeout.isShorterThan(stopwatch)) {
- LOG.debug("<< {} (rethrowing, out of time - max {}): {}", new Object[] { fullMessage, Time.makeTimeStringRounded(sshTriesTimeout), e.getMessage() });
- throw new RuntimeTimeoutException(fullMessage + "; out of time", e);
- } else {
- if (LOG.isDebugEnabled()) LOG.debug("<< {}: {}", fullMessage, e.getMessage());
- backoffForAttempt(i + 1, errorMessage + ": " + e.getMessage());
- if (action != sshClientConnection)
- connect();
- continue;
- }
- }
- }
- assert false : "should not reach here";
- return null;
- }
-
- private final SshAction<SFTPClient> sftpConnection = new SshAction<SFTPClient>() {
-
- private SFTPClient sftp;
-
- @Override
- public void clear() {
- closeWhispering(sftp, this);
- sftp = null;
- }
-
- @Override
- public SFTPClient create() throws IOException {
- checkConnected();
- sftp = sshClientConnection.ssh.newSFTPClient();
- return sftp;
- }
-
- @Override
- public String toString() {
- return "SFTPClient()";
- }
- };
-
- private class GetFileAction implements SshAction<InputStream> {
- private final String path;
- private SFTPClient sftp;
-
- GetFileAction(String path) {
- this.path = checkNotNull(path, "path");
- }
-
- @Override
- public void clear() throws IOException {
- closeWhispering(sftp, this);
- sftp = null;
- }
-
- @Override
- public InputStream create() throws Exception {
- sftp = acquire(sftpConnection);
- return new CloseFtpChannelOnCloseInputStream(
- sftp.getSFTPEngine().open(path).getInputStream(), sftp);
- }
-
- @Override
- public String toString() {
- return "Payload(path=[" + path + "])";
- }
- }
-
- private class PutFileAction implements SshAction<Void> {
- // TODO support backup as a property?
-
- private SFTPClient sftp;
- private final String path;
- private final int permissionsMask;
- private final long lastModificationDate;
- private final long lastAccessDate;
- private final int uid;
- private final Supplier<InputStream> contentsSupplier;
- private final Integer length;
-
- PutFileAction(Map<String,?> props, String path, Supplier<InputStream> contentsSupplier, long length) {
- String permissions = getOptionalVal(props, PROP_PERMISSIONS);
- long lastModificationDateVal = getOptionalVal(props, PROP_LAST_MODIFICATION_DATE);
- long lastAccessDateVal = getOptionalVal(props, PROP_LAST_ACCESS_DATE);
- if (lastAccessDateVal <= 0 ^ lastModificationDateVal <= 0) {
- lastAccessDateVal = Math.max(lastAccessDateVal, lastModificationDateVal);
- lastModificationDateVal = Math.max(lastAccessDateVal, lastModificationDateVal);
- }
- this.permissionsMask = Integer.parseInt(permissions, 8);
- this.lastAccessDate = lastAccessDateVal;
- this.lastModificationDate = lastModificationDateVal;
- this.uid = getOptionalVal(props, PROP_OWNER_UID);
- this.path = checkNotNull(path, "path");
- this.contentsSupplier = checkNotNull(contentsSupplier, "contents");
- this.length = Ints.checkedCast(checkNotNull((long)length, "size"));
- }
-
- @Override
- public void clear() {
- closeWhispering(sftp, this);
- sftp = null;
- }
-
- @Override
- public Void create() throws Exception {
- final AtomicReference<InputStream> inputStreamRef = new AtomicReference<InputStream>();
- sftp = acquire(sftpConnection);
- try {
- sftp.put(new InMemorySourceFile() {
- @Override public String getName() {
- return path;
- }
- @Override public long getLength() {
- return length;
- }
- @Override public InputStream getInputStream() throws IOException {
- InputStream contents = contentsSupplier.get();
- inputStreamRef.set(contents);
- return contents;
- }
- }, path);
- sftp.chmod(path, permissionsMask);
- if (uid != -1) {
- sftp.chown(path, uid);
- }
- if (lastAccessDate > 0) {
- sftp.setattr(path, new FileAttributes.Builder()
- .withAtimeMtime(lastAccessDate, lastModificationDate)
- .build());
- }
- } finally {
- closeWhispering(inputStreamRef.get(), this);
- }
- return null;
- }
-
- @Override
- public String toString() {
- return "Put(path=[" + path + " "+length+"])";
- }
- }
-
- // TODO simpler not to use predicates
- @VisibleForTesting
- Predicate<String> causalChainHasMessageContaining(final Exception from) {
- return new Predicate<String>() {
- @Override
- public boolean apply(final String input) {
- return any(getCausalChain(from), new Predicate<Throwable>() {
- @Override
- public boolean apply(Throwable throwable) {
- return (throwable.toString().contains(input))
- || (throwable.getMessage() != null && throwable.getMessage().contains(input));
- }
- });
- }
- };
- }
-
- protected SshAction<Session> newSessionAction() {
-
- return new SshAction<Session>() {
-
- private Session session = null;
-
- @Override
- public void clear() throws TransportException, ConnectionException {
- closeWhispering(session, this);
- session = null;
- }
-
- @Override
- public Session create() throws Exception {
- checkConnected();
- session = sshClientConnection.ssh.startSession();
- if (allocatePTY) {
- session.allocatePTY(TERM, 80, 24, 0, 0, Collections.<PTYMode, Integer> emptyMap());
- }
- return session;
- }
-
- @Override
- public String toString() {
- return "Session()";
- }
- };
-
- }
-
- class ExecAction implements SshAction<Command> {
- private final String command;
- private final OutputStream out;
- private final OutputStream err;
- private final Duration timeout;
-
- private Session session;
- private Shell shell;
- private StreamGobbler outgobbler;
- private StreamGobbler errgobbler;
-
- ExecAction(String command, OutputStream out, OutputStream err, Duration timeout) {
- this.command = checkNotNull(command, "command");
- this.out = out;
- this.err = err;
- Duration sessionTimeout = (sshClientConnection.getSessionTimeout() == 0)
- ? Duration.PRACTICALLY_FOREVER
- : Duration.millis(sshClientConnection.getSessionTimeout());
- this.timeout = (timeout == null) ? sessionTimeout : Duration.min(timeout, sessionTimeout);
- }
-
- @Override
- public void clear() throws TransportException, ConnectionException {
- closeWhispering(session, this);
- closeWhispering(shell, this);
- closeWhispering(outgobbler, this);
- closeWhispering(errgobbler, this);
- session = null;
- shell = null;
- }
-
- @Override
- public Command create() throws Exception {
- try {
- session = acquire(newSessionAction());
-
- Command output = session.exec(checkNotNull(command, "command"));
-
- if (out != null) {
- outgobbler = new StreamGobbler(output.getInputStream(), out, (Logger)null);
- outgobbler.start();
- }
- if (err != null) {
- errgobbler = new StreamGobbler(output.getErrorStream(), err, (Logger)null);
- errgobbler.start();
- }
- try {
- output.join((int)Math.min(timeout.toMilliseconds(), Integer.MAX_VALUE), TimeUnit.MILLISECONDS);
- return output;
-
- } finally {
- // wait for all stdout/stderr to have been re-directed
- try {
- // Don't use forever (i.e. 0) because BROOKLYN-106: ssh hangs
- long joinTimeout = 10*1000;
- if (outgobbler != null) outgobbler.join(joinTimeout);
- if (errgobbler != null) errgobbler.join(joinTimeout);
- } catch (InterruptedException e) {
- LOG.warn("Interrupted gobbling streams from ssh: "+command, e);
- Thread.currentThread().interrupt();
- }
- }
-
- } finally {
- clear();
- }
- }
-
- @Override
- public String toString() {
- return "Exec(command=[" + command + "])";
- }
- }
-
- class ShellAction implements SshAction<Integer> {
- @VisibleForTesting
- final List<String> commands;
- @VisibleForTesting
- final OutputStream out;
- @VisibleForTesting
- final OutputStream err;
-
- private Session session;
- private Shell shell;
- private StreamGobbler outgobbler;
- private StreamGobbler errgobbler;
- private Duration timeout;
-
- ShellAction(List<String> commands, OutputStream out, OutputStream err, Duration timeout) {
- this.commands = checkNotNull(commands, "commands");
- this.out = out;
- this.err = err;
- Duration sessionTimeout = (sshClientConnection.getSessionTimeout() == 0)
- ? Duration.PRACTICALLY_FOREVER
- : Duration.millis(sshClientConnection.getSessionTimeout());
- this.timeout = (timeout == null) ? sessionTimeout : Duration.min(timeout, sessionTimeout);
- }
-
- @Override
- public void clear() throws TransportException, ConnectionException {
- closeWhispering(session, this);
- closeWhispering(shell, this);
- closeWhispering(outgobbler, this);
- closeWhispering(errgobbler, this);
- session = null;
- shell = null;
- }
-
- @Override
- public Integer create() throws Exception {
- try {
- session = acquire(newSessionAction());
-
- shell = session.startShell();
-
- if (out != null) {
- InputStream outstream = shell.getInputStream();
- outgobbler = new StreamGobbler(outstream, out, (Logger)null);
- outgobbler.start();
- }
- if (err != null) {
- InputStream errstream = shell.getErrorStream();
- errgobbler = new StreamGobbler(errstream, err, (Logger)null);
- errgobbler.start();
- }
-
- OutputStream output = shell.getOutputStream();
-
- for (CharSequence cmd : commands) {
- try {
- output.write(toUTF8ByteArray(cmd+"\n"));
- output.flush();
- } catch (ConnectionException e) {
- if (!shell.isOpen()) {
- // shell is closed; presumably the user command did `exit`
- if (LOG.isDebugEnabled()) LOG.debug("Shell closed to {} when executing {}", SshjTool.this.toString(), commands);
- break;
- } else {
- throw e;
- }
- }
- }
- // workaround attempt for SSHJ deadlock - https://github.com/shikhar/sshj/issues/105
- synchronized (shell.getOutputStream()) {
- shell.sendEOF();
- }
- closeWhispering(output, this);
-
- boolean timedOut = false;
- try {
- long timeoutMillis = Math.min(timeout.toMilliseconds(), Integer.MAX_VALUE);
- long timeoutEnd = System.currentTimeMillis() + timeoutMillis;
- Exception last = null;
- do {
- if (!shell.isOpen() && ((SessionChannel)session).getExitStatus()!=null)
- // shell closed, and exit status returned
- break;
- boolean endBecauseReturned =
- // if either condition is satisfied, then wait 1s in hopes the other does, then return
- (!shell.isOpen() || ((SessionChannel)session).getExitStatus()!=null);
- try {
- shell.join(1000, TimeUnit.MILLISECONDS);
- } catch (ConnectionException e) {
- last = e;
- }
- if (endBecauseReturned) {
- // shell is still open, ie some process is running
- // but we have a result code, so main shell is finished
- // we waited one second extra to allow any background process
- // which is nohupped to really be in the background (#162)
- // now let's bail out
- break;
- }
- } while (System.currentTimeMillis() < timeoutEnd);
- if (shell.isOpen() && ((SessionChannel)session).getExitStatus()==null) {
- LOG.debug("Timeout ({}) in SSH shell to {}", timeout, this);
- // we timed out, or other problem -- reproduce the error.
- // The shell.join should always have thrown ConnectionExceptoin (looking at code of
- // AbstractChannel), but javadoc of Channel doesn't explicity say that so play it safe.
- timedOut = true;
- throw (last != null) ? last : new TimeoutException("Timeout after "+timeout+" executing "+this);
- }
- return ((SessionChannel)session).getExitStatus();
- } finally {
- // wait for all stdout/stderr to have been re-directed
- closeWhispering(shell, this);
- shell = null;
- try {
- // Don't use forever (i.e. 0) because BROOKLYN-106: ssh hangs
- long joinTimeout = (timedOut) ? 1000 : 10*1000;
- if (outgobbler != null) {
- outgobbler.join(joinTimeout);
- outgobbler.close();
- }
- if (errgobbler != null) {
- errgobbler.join(joinTimeout);
- errgobbler.close();
- }
- } catch (InterruptedException e) {
- LOG.warn("Interrupted gobbling streams from ssh: "+commands, e);
- Thread.currentThread().interrupt();
- }
- }
-
- } finally {
- clear();
- }
- }
-
- @Override
- public String toString() {
- return "Shell(command=[" + commands + "])";
- }
- }
-
- private byte[] toUTF8ByteArray(String string) {
- return org.bouncycastle.util.Strings.toUTF8ByteArray(string);
- }
-
- private Supplier<InputStream> newInputStreamSupplier(final byte[] contents) {
- return new Supplier<InputStream>() {
- @Override public InputStream get() {
- return new ByteArrayInputStream(contents);
- }
- };
- }
-
- private Supplier<InputStream> newInputStreamSupplier(final File file) {
- return new Supplier<InputStream>() {
- @Override public InputStream get() {
- try {
- return new FileInputStream(file);
- } catch (FileNotFoundException e) {
- throw Exceptions.propagate(e);
- }
- }
- };
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/javalang/ReflectionScanner.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/javalang/ReflectionScanner.java b/core/src/main/java/brooklyn/util/javalang/ReflectionScanner.java
deleted file mode 100644
index 66a5a72..0000000
--- a/core/src/main/java/brooklyn/util/javalang/ReflectionScanner.java
+++ /dev/null
@@ -1,135 +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 brooklyn.util.javalang;
-
-import java.lang.annotation.Annotation;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Set;
-
-import org.reflections.ReflectionUtils;
-import org.reflections.Reflections;
-import org.reflections.Store;
-import org.reflections.scanners.Scanner;
-import org.reflections.scanners.SubTypesScanner;
-import org.reflections.scanners.TypeAnnotationsScanner;
-import org.reflections.util.ClasspathHelper;
-import org.reflections.util.ConfigurationBuilder;
-import org.reflections.util.FilterBuilder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.util.text.Strings;
-
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-
-/** Facade on {@link Reflections} which logs warnings for unloadable classes but does not fail */
-public class ReflectionScanner {
-
- private static final Logger log = LoggerFactory.getLogger(ReflectionScanner.class);
-
- protected final ClassLoader[] classLoaders;
- protected final Reflections reflections;
-
- /** scanner which will look in the given urls
- * (or if those are null attempt to infer from the first entry in the classloaders,
- * although currently that seems to only pick up directories, not JAR's),
- * optionally filtering for the given prefix;
- * any or all arguments can be null to accept all (and use default classpath for classloading).
- **/
- public ReflectionScanner(
- final Iterable<URL> urlsToScan,
- final String optionalPrefix,
- final ClassLoader ...classLoaders) {
- reflections = new Reflections(new ConfigurationBuilder() {
- {
- final Predicate<String> filter =
- Strings.isNonEmpty(optionalPrefix) ? new FilterBuilder.Include(FilterBuilder.prefix(optionalPrefix)) : null;
-
- if (urlsToScan!=null)
- setUrls(ImmutableSet.copyOf(urlsToScan));
- else if (classLoaders.length>0 && classLoaders[0]!=null)
- setUrls(
- ClasspathHelper.forPackage(Strings.isNonEmpty(optionalPrefix) ? optionalPrefix : "",
- asClassLoaderVarArgs(classLoaders[0])));
-
- if (filter!=null) filterInputsBy(filter);
-
- Scanner typeScanner = new TypeAnnotationsScanner();
- if (filter!=null) typeScanner = typeScanner.filterResultsBy(filter);
- Scanner subTypeScanner = new SubTypesScanner();
- if (filter!=null) subTypeScanner = subTypeScanner.filterResultsBy(filter);
- setScanners(typeScanner, subTypeScanner);
-
- for (ClassLoader cl: classLoaders)
- if (cl!=null) addClassLoader(cl);
- }
- });
- this.classLoaders = Iterables.toArray(Iterables.filter(Arrays.asList(classLoaders), Predicates.notNull()), ClassLoader.class);
- }
-
- private static ClassLoader[] asClassLoaderVarArgs(final ClassLoader classLoaderToSearch) {
- return classLoaderToSearch==null ? new ClassLoader[0] : new ClassLoader[] { classLoaderToSearch };
- }
-
- public Store getStore() {
- return reflections.getStore();
- }
-
- /** overrides delegate so as to log rather than throw exception if a class cannot be loaded */
- public <T> Set<Class<? extends T>> getSubTypesOf(final Class<T> type) {
- Set<String> subTypes = getStore().getSubTypesOf(type.getName());
- return ImmutableSet.copyOf(this.<T>forNames(subTypes, "sub-type of "+type));
- }
-
- /** overrides delegate so as to log rather than throw exception if a class cannot be loaded */
- public Set<Class<?>> getTypesAnnotatedWith(Class<? extends Annotation> annotation) {
- Set<String> annotatedWith = getStore().getTypesAnnotatedWith(annotation.getName());
- return ImmutableSet.copyOf(this.forNames(annotatedWith, "annotated "+annotation.getName()));
- }
-
- @SuppressWarnings("unchecked")
- protected <T> List<Class<? extends T>> forNames(Set<String> classNames, final String context) {
- List<Class<? extends T>> result = new ArrayList<Class<? extends T>>();
- for (String className : classNames) {
- //noinspection unchecked
- try {
- Class<? extends T> clazz = (Class<? extends T>) loadClass(className);
- if (clazz != null) {
- result.add(clazz);
- } else {
- log.warn("Unable to instantiate '"+className+"' ("+context+")");
- }
- } catch (Throwable e) {
- log.warn("Unable to instantiate '"+className+"' ("+context+"): "+e);
- }
- }
- return result;
- }
-
- protected Class<?> loadClass(String className) {
- return ReflectionUtils.forName(className, classLoaders);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/javalang/UrlClassLoader.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/javalang/UrlClassLoader.java b/core/src/main/java/brooklyn/util/javalang/UrlClassLoader.java
deleted file mode 100644
index d847174..0000000
--- a/core/src/main/java/brooklyn/util/javalang/UrlClassLoader.java
+++ /dev/null
@@ -1,69 +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 brooklyn.util.javalang;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.Arrays;
-
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.exceptions.Exceptions;
-
-/** like URLClassLoader (and delegates to it) but:
- * * has a nice toString
- * * supports var args constructor
- * * supports file://~/xxx semantics (remaps it to user.home);
- * ideally we'd also support mvn, classpath, osgi, etc
- */
-public class UrlClassLoader extends URLClassLoader {
-
- private URL[] urls;
-
- public UrlClassLoader(URL ...urls) {
- super(tidy(urls));
- this.urls = urls;
- }
-
- public UrlClassLoader(String ...urls) {
- this(asUrls(urls));
- }
-
- private static URL[] asUrls(String[] urls) {
- URL[] urlo = new URL[urls.length];
- try {
- for (int i=0; i<urls.length; i++)
- urlo[i] = new URL(urls[i]);
- } catch (MalformedURLException e) {
- throw Exceptions.propagate(e);
- }
- return urlo;
- }
-
- private static URL[] tidy(URL[] urls) {
- for (int i=0; i<urls.length; i++)
- urls[i] = ResourceUtils.tidy(urls[i]);
- return urls;
- }
-
- @Override
- public String toString() {
- return "UrlClassLoader"+Arrays.asList(urls);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/mutex/MutexSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/mutex/MutexSupport.java b/core/src/main/java/brooklyn/util/mutex/MutexSupport.java
deleted file mode 100644
index c0794cf..0000000
--- a/core/src/main/java/brooklyn/util/mutex/MutexSupport.java
+++ /dev/null
@@ -1,120 +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 brooklyn.util.mutex;
-
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.util.task.Tasks;
-
-import com.google.common.collect.ImmutableMap;
-
-public class MutexSupport implements WithMutexes {
-
- private static final Logger log = LoggerFactory.getLogger(MutexSupport.class);
- private final Map<String,SemaphoreWithOwners> semaphores = new LinkedHashMap<String,SemaphoreWithOwners>();
-
- protected synchronized SemaphoreWithOwners getSemaphore(String mutexId) {
- return getSemaphore(mutexId, false);
- }
- // NB: the map could be "lock-striped" (hashed on mutexId) to avoid the central lock
- protected synchronized SemaphoreWithOwners getSemaphore(String mutexId, boolean requestBeforeReturning) {
- SemaphoreWithOwners s = semaphores.get(mutexId);
- if (s==null) {
- s = new SemaphoreWithOwners(mutexId);
- semaphores.put(mutexId, s);
- }
- if (requestBeforeReturning) s.indicateCallingThreadWillRequest();
- return s;
- }
- /** forces deletion of the given mutex if it is unused;
- * normally not required as is done automatically on close
- * (but possibly needed where there are cancelations and risk of memory leaks) */
- public synchronized void cleanupMutex(String mutexId) {
- SemaphoreWithOwners s = semaphores.get(mutexId);
- if (!s.isInUse()) semaphores.remove(mutexId);
- }
- public synchronized void cleanup() {
- Iterator<SemaphoreWithOwners> si = semaphores.values().iterator();
- while (si.hasNext()) {
- SemaphoreWithOwners s = si.next();
- if (!s.isInUse()) si.remove();
- }
- }
-
- @Override
- public synchronized boolean hasMutex(String mutexId) {
- SemaphoreWithOwners s = semaphores.get(mutexId);
- if (s!=null) return s.isCallingThreadAnOwner();
- return false;
- }
-
- @Override
- public void acquireMutex(String mutexId, String description) throws InterruptedException {
- SemaphoreWithOwners s = getSemaphore(mutexId, true);
- if (description!=null) Tasks.setBlockingDetails(description+" - waiting for "+mutexId);
- if (log.isDebugEnabled())
- log.debug("Acquiring mutex: "+mutexId+"@"+this+" - "+description);
- s.acquire();
- if (description!=null) Tasks.setBlockingDetails(null);
- s.setDescription(description);
- if (log.isDebugEnabled())
- log.debug("Acquired mutex: "+mutexId+"@"+this+" - "+description);
- }
-
- @Override
- public boolean tryAcquireMutex(String mutexId, String description) {
- SemaphoreWithOwners s = getSemaphore(mutexId, true);
- if (s.tryAcquire()) {
- if (log.isDebugEnabled())
- log.debug("Acquired mutex (opportunistic): "+mutexId+"@"+this+" - "+description);
- s.setDescription(description);
- return true;
- }
- return false;
- }
-
- @Override
- public synchronized void releaseMutex(String mutexId) {
- SemaphoreWithOwners s;
- if (log.isDebugEnabled())
- log.debug("Releasing mutex: "+mutexId+"@"+this);
- synchronized (this) { s = semaphores.get(mutexId); }
- if (s==null) throw new IllegalStateException("No mutex known for '"+mutexId+"'");
- s.release();
- cleanupMutex(mutexId);
- }
-
- @Override
- public synchronized String toString() {
- return super.toString()+"["+semaphores.size()+" semaphores: "+semaphores.values()+"]";
- }
-
- /** Returns the semaphores in use at the time the method is called, for inspection purposes (and testing).
- * The semaphores used by this class may change over time so callers are strongly discouraged
- * from manipulating the semaphore objects themselves.
- */
- public synchronized Map<String,SemaphoreWithOwners> getAllSemaphores() {
- return ImmutableMap.<String,SemaphoreWithOwners>copyOf(semaphores);
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/mutex/SemaphoreForTasks.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/mutex/SemaphoreForTasks.java b/core/src/main/java/brooklyn/util/mutex/SemaphoreForTasks.java
deleted file mode 100644
index 5bdfdfa..0000000
--- a/core/src/main/java/brooklyn/util/mutex/SemaphoreForTasks.java
+++ /dev/null
@@ -1,112 +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 brooklyn.util.mutex;
-
-import java.util.List;
-import java.util.Set;
-
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.api.management.Task;
-
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.collections.MutableSet;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.time.Time;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-
-
-/** A subclass of {@link SemaphoreWithOwners}
- * which additionally sets Task blocking information.
- * <p>
- * TODO As tasks are distributed this should support distribution across the management context. */
-public class SemaphoreForTasks extends SemaphoreWithOwners {
-
- private static final long serialVersionUID = 7898283056223005952L;
-
- /** unused at present, but wanted on the API for when this may be federated */
- @SuppressWarnings("unused")
- private final ManagementContext mgmt;
-
- final private MutableList<Task<?>> owningTasks = new MutableList<Task<?>>();
- final private MutableSet<Task<?>> requestingTasks = new MutableSet<Task<?>>();
-
- public SemaphoreForTasks(String name, ManagementContext mgmt) {
- super(name);
- this.mgmt = Preconditions.checkNotNull(mgmt);
- }
-
- public SemaphoreForTasks(String name, int permits, boolean fair, ManagementContext mgmt) {
- super(name, permits, fair);
- this.mgmt = Preconditions.checkNotNull(mgmt);
- }
-
- public synchronized Set<Task<?>> getRequestingTasks() {
- return ImmutableSet.copyOf(requestingTasks);
- }
-
- public synchronized List<Task<?>> getOwningTasks() {
- return ImmutableList.copyOf(owningTasks);
- }
-
- @Override
- protected synchronized void onRequesting() {
- if (!owningTasks.isEmpty() || !requestingTasks.isEmpty()) {
- Tasks.setBlockingTask( !requestingTasks.isEmpty() ? Iterables.getLast(requestingTasks) : Iterables.getFirst(owningTasks, null) );
- Tasks.setBlockingDetails("Waiting on semaphore "+getName()+" ("+getDescription()+"); "
- + "queued at "+Time.makeDateString()+" when "+getRequestingThreads().size()+" ahead in queue");
- }
- requestingTasks.addIfNotNull(Tasks.current());
- super.onRequesting();
- }
-
- @Override
- protected synchronized void onRequestFinished() {
- super.onRequestFinished();
- requestingTasks.removeIfNotNull(Tasks.current());
-
- Tasks.resetBlockingDetails();
- Tasks.resetBlockingTask();
- }
-
- @Override
- protected synchronized void onAcquired(int permits) {
- super.onAcquired(permits);
- for (int i=0; i<permits; i++)
- owningTasks.appendIfNotNull(Tasks.current());
- }
-
- @Override
- protected synchronized void onReleased(int permits) {
- super.onReleased(permits);
- for (int i=0; i<permits; i++)
- owningTasks.removeIfNotNull(Tasks.current());
- }
-
- @Override
- public synchronized String toString() {
- return super.toString()+"["
- + "owningTasks="+owningTasks
- + "; requestingTasks="+requestingTasks+"]";
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/mutex/SemaphoreWithOwners.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/mutex/SemaphoreWithOwners.java b/core/src/main/java/brooklyn/util/mutex/SemaphoreWithOwners.java
deleted file mode 100644
index 6f3132c..0000000
--- a/core/src/main/java/brooklyn/util/mutex/SemaphoreWithOwners.java
+++ /dev/null
@@ -1,231 +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 brooklyn.util.mutex;
-
-import java.util.ArrayList;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-import brooklyn.util.exceptions.Exceptions;
-
-import com.google.common.collect.ImmutableList;
-
-/** a subclass of {@link Semaphore}
- * which tracks who created and released the semaphores,
- * and which requires the same thread to release as created it. */
-public class SemaphoreWithOwners extends Semaphore {
- public SemaphoreWithOwners(String name) {
- this(name, 1, true);
- }
- public SemaphoreWithOwners(String name, int permits, boolean fair) {
- super(permits, fair);
- this.name = name;
- }
- private static final long serialVersionUID = -5303474637353009454L;
- final private List<Thread> owningThreads = new ArrayList<Thread>();
- final private Set<Thread> requestingThreads = new LinkedHashSet<Thread>();
-
- @Override
- public void acquire() throws InterruptedException {
- try {
- onRequesting();
- super.acquire();
- onAcquired(1);
- } finally {
- onRequestFinished();
- }
- }
- @Override
- public void acquire(int permits) throws InterruptedException {
- try {
- onRequesting();
- super.acquire(permits);
- onAcquired(permits);
- } finally {
- onRequestFinished();
- }
- }
- @Override
- public void acquireUninterruptibly() {
- try {
- onRequesting();
- super.acquireUninterruptibly();
- onAcquired(1);
- } finally {
- onRequestFinished();
- }
- }
- @Override
- public void acquireUninterruptibly(int permits) {
- try {
- onRequesting();
- super.acquireUninterruptibly(permits);
- onAcquired(permits);
- } finally {
- onRequestFinished();
- }
- }
-
- public void acquireUnchecked() {
- try {
- acquire();
- } catch (InterruptedException e) {
- throw Exceptions.propagate(e);
- }
- }
- public void acquireUnchecked(int numPermits) {
- try {
- acquire(numPermits);
- } catch (InterruptedException e) {
- throw Exceptions.propagate(e);
- }
- }
-
- @Override
- public boolean tryAcquire() {
- try {
- onRequesting();
- if (super.tryAcquire()) {
- onAcquired(1);
- return true;
- }
- return false;
- } finally {
- onRequestFinished();
- }
- }
- @Override
- public boolean tryAcquire(int permits) {
- try {
- onRequesting();
- if (super.tryAcquire(permits)) {
- onAcquired(permits);
- return true;
- }
- return false;
- } finally {
- onRequestFinished();
- }
- }
- @Override
- public boolean tryAcquire(int permits, long timeout, TimeUnit unit) throws InterruptedException {
- try {
- onRequesting();
- if (super.tryAcquire(permits, timeout, unit)) {
- onAcquired(permits);
- return true;
- }
- return false;
- } finally {
- onRequestFinished();
- }
- }
- @Override
- public boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException {
- try {
- onRequesting();
- if (super.tryAcquire(timeout, unit)) {
- onAcquired(1);
- return true;
- }
- return false;
- } finally {
- onRequestFinished();
- }
- }
-
- /** invoked when a caller successfully acquires a mutex, before {@link #onRequestFinished()} */
- protected synchronized void onAcquired(int permits) {
- for (int i=0; i<permits; i++) owningThreads.add(Thread.currentThread());
- }
- /** invoked when a caller is about to request a semaphore (before it might block);
- * guaranteed to call {@link #onRequestFinished()} after the blocking,
- * with a call to {@link #onAcquired(int)} beforehand if the acquisition was successful */
- protected synchronized void onRequesting() {
- requestingThreads.add(Thread.currentThread());
- }
- /** invoked when a caller has completed requesting a mutex, whether successful, aborted, or interrupted */
- protected synchronized void onRequestFinished() {
- requestingThreads.remove(Thread.currentThread());
- }
-
- @Override
- public void release() {
- super.release();
- onReleased(1);
- }
- @Override
- public void release(int permits) {
- super.release(permits);
- onReleased(permits);
- }
-
- /** invoked when a caller has released permits */
- protected synchronized void onReleased(int permits) {
- boolean result = true;
- for (int i=0; i<permits; i++) result = owningThreads.remove(Thread.currentThread()) & result;
- if (!result) throw new IllegalStateException("Thread "+Thread.currentThread()+" which released "+this+" did not own it.");
- }
-
- /** true iff there are any owners or any requesters (callers blocked trying to acquire) */
- public synchronized boolean isInUse() {
- return !owningThreads.isEmpty() || !requestingThreads.isEmpty();
- }
-
- /** true iff the calling thread is one of the owners */
- public synchronized boolean isCallingThreadAnOwner() {
- return owningThreads.contains(Thread.currentThread());
- }
-
- private final String name;
- /** constructor-time supplied name */
- public String getName() { return name; }
-
- private String description;
- public void setDescription(String description) { this.description = description; }
- /** caller supplied description */
- public String getDescription() { return description; }
-
- /** unmodifiable view of threads owning the permits; threads with multiple permits listed multiply */
- public synchronized List<Thread> getOwningThreads() {
- return ImmutableList.<Thread>copyOf(owningThreads);
- }
- /** unmodifiable view of threads requesting access (blocked or briefly trying to acquire);
- * this is guaranteed to be cleared _after_ getOwners
- * (synchronizing on this class while reading both fields will give canonical access) */
- public synchronized List<Thread> getRequestingThreads() {
- return ImmutableList.<Thread>copyOf(requestingThreads);
- }
-
- @Override
- public synchronized String toString() {
- return super.toString()+"["+name+"; description="+description+"; owning="+owningThreads+"; requesting="+requestingThreads+"]";
- }
-
- /** Indicate that the calling thread is going to acquire or tryAcquire,
- * in order to set up the semaphore's isInUse() value appropriately for certain checks.
- * It *must* do so after invoking this method. */
- public void indicateCallingThreadWillRequest() {
- requestingThreads.add(Thread.currentThread());
- }
-
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/mutex/WithMutexes.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/mutex/WithMutexes.java b/core/src/main/java/brooklyn/util/mutex/WithMutexes.java
deleted file mode 100644
index e772df8..0000000
--- a/core/src/main/java/brooklyn/util/mutex/WithMutexes.java
+++ /dev/null
@@ -1,45 +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 brooklyn.util.mutex;
-
-/** interface which allows multiple callers to co-operate using named mutexes, inspectably,
- * and containing implementation as inner class
- * <p>
- * MutexSupport is a common implementation of this.
- * mixin code frequently delegates to this,
- * as shown in the test case's WithMutexesTest.SampleWithMutexesDelegatingMixin class
- **/
-public interface WithMutexes {
-
- /** returns true if the calling thread has the mutex with the given ID */
- public boolean hasMutex(String mutexId);
-
- /** acquires a mutex, if available, otherwise blocks on its becoming available;
- * caller must release after use */
- public void acquireMutex(String mutexId, String description) throws InterruptedException;
-
- /** acquires a mutex and returns true, if available; otherwise immediately returns false;
- * caller must release after use if this returns true */
- public boolean tryAcquireMutex(String mutexId, String description);
-
- /** releases a mutex, triggering another thread to use it or cleaning it up if no one else is waiting;
- * this should only be called by the mutex owner (thread) */
- public void releaseMutex(String mutexId);
-
-}
[38/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/flags/TypeCoercions.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/flags/TypeCoercions.java b/core/src/main/java/brooklyn/util/flags/TypeCoercions.java
deleted file mode 100644
index 31f27be..0000000
--- a/core/src/main/java/brooklyn/util/flags/TypeCoercions.java
+++ /dev/null
@@ -1,879 +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 brooklyn.util.flags;
-
-import groovy.lang.Closure;
-import groovy.time.TimeDuration;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.net.InetAddress;
-import java.net.URI;
-import java.net.URL;
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.GuardedBy;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.event.AttributeSensor;
-import org.apache.brooklyn.api.event.Sensor;
-import org.apache.brooklyn.core.internal.BrooklynInitialization;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.entity.basic.BrooklynTaskTags;
-import brooklyn.entity.basic.ClosureEntityFactory;
-import brooklyn.entity.basic.ConfigurableEntityFactory;
-import brooklyn.entity.basic.ConfigurableEntityFactoryFromEntityFactory;
-import brooklyn.event.basic.Sensors;
-import brooklyn.util.JavaGroovyEquivalents;
-import brooklyn.util.collections.MutableSet;
-import brooklyn.util.collections.QuorumCheck;
-import brooklyn.util.collections.QuorumCheck.QuorumChecks;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.guava.Maybe;
-import brooklyn.util.javalang.Enums;
-import brooklyn.util.net.Cidr;
-import brooklyn.util.net.Networking;
-import brooklyn.util.net.UserAndHostAndPort;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.text.StringEscapes.JavaStringEscapes;
-import brooklyn.util.text.Strings;
-import brooklyn.util.time.Duration;
-import brooklyn.util.time.Time;
-import brooklyn.util.yaml.Yamls;
-
-import com.google.common.base.CaseFormat;
-import com.google.common.base.Function;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.collect.HashBasedTable;
-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.collect.Maps;
-import com.google.common.collect.Sets;
-import com.google.common.collect.Table;
-import com.google.common.net.HostAndPort;
-import com.google.common.primitives.Primitives;
-import com.google.common.reflect.TypeToken;
-
-@SuppressWarnings("rawtypes")
-public class TypeCoercions {
-
- private static final Logger log = LoggerFactory.getLogger(TypeCoercions.class);
-
- private TypeCoercions() {}
-
- /** Store the coercion {@link Function functions} in a {@link Table table}. */
- @GuardedBy("TypeCoercions.class")
- private static Table<Class, Class, Function> registry = HashBasedTable.create();
-
- /**
- * Attempts to coerce {@code value} to {@code targetType}.
- * <p>
- * Maintains a registry of adapter functions for type pairs in a {@link Table} which
- * is searched after checking various strategies, including the following:
- * <ul>
- * <li>{@code value.asTargetType()}
- * <li>{@code TargetType.fromType(value)} (if {@code value instanceof Type})
- * <li>{@code value.targetTypeValue()} (handy for primitives)
- * <li>{@code TargetType.valueOf(value)} (for enums)
- * </ul>
- * <p>
- * A default set of adapters will handle most common Java-type coercions
- * as well as <code>String</code> coercion to:
- * <ul>
- * <li> {@link Set}, {@link List}, {@link Map} and similar -- parses as YAML
- * <li> {@link Date} -- parses using {@link Time#parseDate(String)}
- * <li> {@link Duration} -- parses using {@link Duration#parse(String)}
- * </ul>
- */
- public static <T> T coerce(Object value, Class<T> targetType) {
- return coerce(value, TypeToken.of(targetType));
- }
-
- /** @see #coerce(Object, Class) */
- public static <T> Maybe<T> tryCoerce(Object value, TypeToken<T> targetTypeToken) {
- try {
- return Maybe.of( coerce(value, targetTypeToken) );
- } catch (Throwable t) {
- Exceptions.propagateIfFatal(t);
- return Maybe.absent(t);
- }
- }
-
- /** @see #coerce(Object, Class) */
- @SuppressWarnings({ "unchecked" })
- public static <T> T coerce(Object value, TypeToken<T> targetTypeToken) {
- if (value==null) return null;
- Class<? super T> targetType = targetTypeToken.getRawType();
-
- //recursive coercion of parameterized collections and map entries
- if (targetTypeToken.getType() instanceof ParameterizedType) {
- if (value instanceof Collection && Collection.class.isAssignableFrom(targetType)) {
- Type[] arguments = ((ParameterizedType) targetTypeToken.getType()).getActualTypeArguments();
- if (arguments.length != 1) {
- throw new IllegalStateException("Unexpected number of parameters in collection type: " + arguments);
- }
- Collection coerced = Lists.newLinkedList();
- TypeToken<?> listEntryType = TypeToken.of(arguments[0]);
- for (Object entry : (Iterable<?>) value) {
- coerced.add(coerce(entry, listEntryType));
- }
- if (Set.class.isAssignableFrom(targetType)) {
- return (T) Sets.newLinkedHashSet(coerced);
- } else {
- return (T) Lists.newArrayList(coerced);
- }
- } else if (value instanceof Map && Map.class.isAssignableFrom(targetType)) {
- Type[] arguments = ((ParameterizedType) targetTypeToken.getType()).getActualTypeArguments();
- if (arguments.length != 2) {
- throw new IllegalStateException("Unexpected number of parameters in map type: " + arguments);
- }
- Map coerced = Maps.newLinkedHashMap();
- TypeToken<?> mapKeyType = TypeToken.of(arguments[0]);
- TypeToken<?> mapValueType = TypeToken.of(arguments[1]);
- for (Map.Entry entry : ((Map<?,?>) value).entrySet()) {
- coerced.put(coerce(entry.getKey(), mapKeyType), coerce(entry.getValue(), mapValueType));
- }
- return (T) Maps.newLinkedHashMap(coerced);
- }
- }
-
- if (targetType.isInstance(value)) return (T) value;
-
- // TODO use registry first?
-
- //deal with primitive->primitive casting
- if (isPrimitiveOrBoxer(targetType) && isPrimitiveOrBoxer(value.getClass())) {
- // Don't just rely on Java to do its normal casting later; if caller writes
- // long `l = coerce(new Integer(1), Long.class)` then letting java do its casting will fail,
- // because an Integer will not automatically be unboxed and cast to a long
- return castPrimitive(value, (Class<T>)targetType);
- }
-
- //deal with string->primitive
- if (value instanceof String && isPrimitiveOrBoxer(targetType)) {
- return stringToPrimitive((String)value, (Class<T>)targetType);
- }
-
- //deal with primitive->string
- if (isPrimitiveOrBoxer(value.getClass()) && targetType.equals(String.class)) {
- return (T) value.toString();
- }
-
- //look for value.asType where Type is castable to targetType
- String targetTypeSimpleName = getVerySimpleName(targetType);
- if (targetTypeSimpleName!=null && targetTypeSimpleName.length()>0) {
- for (Method m: value.getClass().getMethods()) {
- if (m.getName().startsWith("as") && m.getParameterTypes().length==0 &&
- targetType.isAssignableFrom(m.getReturnType()) ) {
- if (m.getName().equals("as"+getVerySimpleName(m.getReturnType()))) {
- try {
- return (T) m.invoke(value);
- } catch (Exception e) {
- throw new ClassCoercionException("Cannot coerce type "+value.getClass()+" to "+targetType.getCanonicalName()+" ("+value+"): "+m.getName()+" adapting failed, "+e);
- }
- }
- }
- }
- }
-
- //now look for static TargetType.fromType(Type t) where value instanceof Type
- for (Method m: targetType.getMethods()) {
- if (((m.getModifiers()&Modifier.STATIC)==Modifier.STATIC) &&
- m.getName().startsWith("from") && m.getParameterTypes().length==1 &&
- m.getParameterTypes()[0].isInstance(value)) {
- if (m.getName().equals("from"+getVerySimpleName(m.getParameterTypes()[0]))) {
- try {
- return (T) m.invoke(null, value);
- } catch (Exception e) {
- throw new ClassCoercionException("Cannot coerce type "+value.getClass()+" to "+targetType.getCanonicalName()+" ("+value+"): "+m.getName()+" adapting failed, "+e);
- }
- }
- }
- }
-
- //ENHANCEMENT could look in type hierarchy of both types for a conversion method...
-
- //primitives get run through again boxed up
- Class boxedT = UNBOXED_TO_BOXED_TYPES.get(targetType);
- Class boxedVT = UNBOXED_TO_BOXED_TYPES.get(value.getClass());
- if (boxedT!=null || boxedVT!=null) {
- try {
- if (boxedT==null) boxedT=targetType;
- Object boxedV;
- if (boxedVT==null) { boxedV = value; }
- else { boxedV = boxedVT.getConstructor(value.getClass()).newInstance(value); }
- return (T) coerce(boxedV, boxedT);
- } catch (Exception e) {
- throw new ClassCoercionException("Cannot coerce type "+value.getClass()+" to "+targetType.getCanonicalName()+" ("+value+"): unboxing failed, "+e);
- }
- }
-
- //for enums call valueOf with the string representation of the value
- if (targetType.isEnum()) {
- T result = (T) stringToEnum((Class<Enum>) targetType, null).apply(String.valueOf(value));
- if (result != null) return result;
- }
-
- //now look in registry
- synchronized (TypeCoercions.class) {
- Map<Class, Function> adapters = registry.row(targetType);
- for (Map.Entry<Class, Function> entry : adapters.entrySet()) {
- if (entry.getKey().isInstance(value)) {
- T result = (T) entry.getValue().apply(value);
-
- // Check if need to unwrap again (e.g. if want List<Integer> and are given a String "1,2,3"
- // then we'll have so far converted to List.of("1", "2", "3"). Call recursively.
- // First check that value has changed, to avoid stack overflow!
- if (!Objects.equal(value, result) && targetTypeToken.getType() instanceof ParameterizedType) {
- // Could duplicate check for `result instanceof Collection` etc; but recursive call
- // will be fine as if that doesn't match we'll safely reach `targetType.isInstance(value)`
- // and just return the result.
- return coerce(result, targetTypeToken);
- }
- return result;
- }
- }
- }
-
- //not found
- throw new ClassCoercionException("Cannot coerce type "+value.getClass()+" to "+targetType.getCanonicalName()+" ("+value+"): no adapter known");
- }
-
- /**
- * Returns a function that does a type coercion to the given type. For example,
- * {@code TypeCoercions.function(Double.class)} will return a function that will
- * coerce its input value to a {@link Double} (or throw a {@link ClassCoercionException}
- * if that is not possible).
- */
- public static <T> Function<Object, T> function(final Class<T> type) {
- return new CoerceFunction<T>(type);
- }
-
- private static class CoerceFunction<T> implements Function<Object, T> {
- private final Class<T> type;
-
- public CoerceFunction(Class<T> type) {
- this.type = type;
- }
- @Override
- public T apply(Object input) {
- return coerce(input, type);
- }
- }
-
- /**
- * Type coercion {@link Function function} for {@link Enum enums}.
- * <p>
- * Tries to convert the string to {@link CaseFormat#UPPER_UNDERSCORE} first,
- * handling all of the different {@link CaseFormat format} possibilites. Failing
- * that, it tries a case-insensitive comparison with the valid enum values.
- * <p>
- * Returns {@code defaultValue} if the string cannot be converted.
- *
- * @see TypeCoercions#coerce(Object, Class)
- * @see Enum#valueOf(Class, String)
- */
- public static <E extends Enum<E>> Function<String, E> stringToEnum(final Class<E> type, @Nullable final E defaultValue) {
- return new StringToEnumFunction<E>(type, defaultValue);
- }
-
- private static class StringToEnumFunction<E extends Enum<E>> implements Function<String, E> {
- private final Class<E> type;
- private final E defaultValue;
-
- public StringToEnumFunction(Class<E> type, @Nullable E defaultValue) {
- this.type = type;
- this.defaultValue = defaultValue;
- }
- @Override
- public E apply(String input) {
- Preconditions.checkNotNull(input, "input");
- List<String> options = ImmutableList.of(
- input,
- CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, input),
- CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_UNDERSCORE, input),
- CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, input),
- CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, input));
- for (String value : options) {
- try {
- return Enum.valueOf(type, value);
- } catch (IllegalArgumentException iae) {
- continue;
- }
- }
- Maybe<E> result = Enums.valueOfIgnoreCase(type, input);
- return (result.isPresent()) ? result.get() : defaultValue;
- }
- }
-
- /**
- * Sometimes need to explicitly cast primitives, rather than relying on Java casting.
- * For example, when using generics then type-erasure means it doesn't actually cast,
- * which causes tests to fail with 0 != 0.0
- */
- @SuppressWarnings("unchecked")
- public static <T> T castPrimitive(Object value, Class<T> targetType) {
- if (value==null) return null;
- assert isPrimitiveOrBoxer(targetType) : "targetType="+targetType;
- assert isPrimitiveOrBoxer(value.getClass()) : "value="+targetType+"; valueType="+value.getClass();
-
- Class<?> sourceWrapType = Primitives.wrap(value.getClass());
- Class<?> targetWrapType = Primitives.wrap(targetType);
-
- // optimization, for when already correct type
- if (sourceWrapType == targetWrapType) {
- return (T) value;
- }
-
- if (targetWrapType == Boolean.class) {
- // only char can be mapped to boolean
- // (we could say 0=false, nonzero=true, but there is no compelling use case so better
- // to encourage users to write as boolean)
- if (sourceWrapType == Character.class)
- return (T) stringToPrimitive(value.toString(), targetType);
-
- throw new ClassCoercionException("Cannot cast "+sourceWrapType+" ("+value+") to "+targetType);
- } else if (sourceWrapType == Boolean.class) {
- // boolean can't cast to anything else
-
- throw new ClassCoercionException("Cannot cast "+sourceWrapType+" ("+value+") to "+targetType);
- }
-
- // for whole-numbers (where casting to long won't lose anything)...
- long v = 0;
- boolean islong = true;
- if (sourceWrapType == Character.class) {
- v = (long) ((Character)value).charValue();
- } else if (sourceWrapType == Byte.class) {
- v = (long) ((Byte)value).byteValue();
- } else if (sourceWrapType == Short.class) {
- v = (long) ((Short)value).shortValue();
- } else if (sourceWrapType == Integer.class) {
- v = (long) ((Integer)value).intValue();
- } else if (sourceWrapType == Long.class) {
- v = ((Long)value).longValue();
- } else {
- islong = false;
- }
- if (islong) {
- if (targetWrapType == Character.class) return (T) Character.valueOf((char)v);
- if (targetWrapType == Byte.class) return (T) Byte.valueOf((byte)v);
- if (targetWrapType == Short.class) return (T) Short.valueOf((short)v);
- if (targetWrapType == Integer.class) return (T) Integer.valueOf((int)v);
- if (targetWrapType == Long.class) return (T) Long.valueOf((long)v);
- if (targetWrapType == Float.class) return (T) Float.valueOf((float)v);
- if (targetWrapType == Double.class) return (T) Double.valueOf((double)v);
- throw new IllegalStateException("Unexpected: sourceType="+sourceWrapType+"; targetType="+targetWrapType);
- }
-
- // for real-numbers (cast to double)...
- double d = 0;
- boolean isdouble = true;
- if (sourceWrapType == Float.class) {
- d = (double) ((Float)value).floatValue();
- } else if (sourceWrapType == Double.class) {
- d = (double) ((Double)value).doubleValue();
- } else {
- isdouble = false;
- }
- if (isdouble) {
- if (targetWrapType == Character.class) return (T) Character.valueOf((char)d);
- if (targetWrapType == Byte.class) return (T) Byte.valueOf((byte)d);
- if (targetWrapType == Short.class) return (T) Short.valueOf((short)d);
- if (targetWrapType == Integer.class) return (T) Integer.valueOf((int)d);
- if (targetWrapType == Long.class) return (T) Long.valueOf((long)d);
- if (targetWrapType == Float.class) return (T) Float.valueOf((float)d);
- if (targetWrapType == Double.class) return (T) Double.valueOf((double)d);
- throw new IllegalStateException("Unexpected: sourceType="+sourceWrapType+"; targetType="+targetWrapType);
- } else {
- throw new IllegalStateException("Unexpected: sourceType="+sourceWrapType+"; targetType="+targetWrapType);
- }
- }
-
- public static boolean isPrimitiveOrBoxer(Class<?> type) {
- return Primitives.allPrimitiveTypes().contains(type) || Primitives.allWrapperTypes().contains(type);
- }
-
- @SuppressWarnings("unchecked")
- public static <T> T stringToPrimitive(String value, Class<T> targetType) {
- assert Primitives.allPrimitiveTypes().contains(targetType) || Primitives.allWrapperTypes().contains(targetType) : "targetType="+targetType;
- // If char, then need to do explicit conversion
- if (targetType == Character.class || targetType == char.class) {
- if (value.length() == 1) {
- return (T) (Character) value.charAt(0);
- } else if (value.length() != 1) {
- throw new ClassCoercionException("Cannot coerce type String to "+targetType.getCanonicalName()+" ("+value+"): adapting failed");
- }
- }
- value = value.trim();
- // For boolean we could use valueOf, but that returns false whereas we'd rather throw errors on bad values
- if (targetType == Boolean.class || targetType == boolean.class) {
- if ("true".equalsIgnoreCase(value)) return (T) Boolean.TRUE;
- if ("false".equalsIgnoreCase(value)) return (T) Boolean.FALSE;
- if ("yes".equalsIgnoreCase(value)) return (T) Boolean.TRUE;
- if ("no".equalsIgnoreCase(value)) return (T) Boolean.FALSE;
- if ("t".equalsIgnoreCase(value)) return (T) Boolean.TRUE;
- if ("f".equalsIgnoreCase(value)) return (T) Boolean.FALSE;
- if ("y".equalsIgnoreCase(value)) return (T) Boolean.TRUE;
- if ("n".equalsIgnoreCase(value)) return (T) Boolean.FALSE;
-
- throw new ClassCoercionException("Cannot coerce type String to "+targetType.getCanonicalName()+" ("+value+"): adapting failed");
- }
-
- // Otherwise can use valueOf reflectively
- Class<?> wrappedType;
- if (Primitives.allPrimitiveTypes().contains(targetType)) {
- wrappedType = Primitives.wrap(targetType);
- } else {
- wrappedType = targetType;
- }
-
- try {
- return (T) wrappedType.getMethod("valueOf", String.class).invoke(null, value);
- } catch (Exception e) {
- ClassCoercionException tothrow = new ClassCoercionException("Cannot coerce "+JavaStringEscapes.wrapJavaString(value)+" to "+targetType.getCanonicalName()+" ("+value+"): adapting failed");
- tothrow.initCause(e);
- throw tothrow;
- }
- }
-
- /** returns the simple class name, and for any inner class the portion after the $ */
- public static String getVerySimpleName(Class c) {
- String s = c.getSimpleName();
- if (s.indexOf('$')>=0)
- s = s.substring(s.lastIndexOf('$')+1);
- return s;
- }
- public static final Map<Class,Class> BOXED_TO_UNBOXED_TYPES = ImmutableMap.<Class,Class>builder().
- put(Integer.class, Integer.TYPE).
- put(Long.class, Long.TYPE).
- put(Boolean.class, Boolean.TYPE).
- put(Byte.class, Byte.TYPE).
- put(Double.class, Double.TYPE).
- put(Float.class, Float.TYPE).
- put(Character.class, Character.TYPE).
- put(Short.class, Short.TYPE).
- build();
- public static final Map<Class,Class> UNBOXED_TO_BOXED_TYPES = ImmutableMap.<Class,Class>builder().
- put(Integer.TYPE, Integer.class).
- put(Long.TYPE, Long.class).
- put(Boolean.TYPE, Boolean.class).
- put(Byte.TYPE, Byte.class).
- put(Double.TYPE, Double.class).
- put(Float.TYPE, Float.class).
- put(Character.TYPE, Character.class).
- put(Short.TYPE, Short.class).
- build();
-
- /** for automatic conversion */
- public static Object getMatchingConstructor(Class target, Object ...arguments) {
- Constructor[] cc = target.getConstructors();
- for (Constructor c: cc) {
- if (c.getParameterTypes().length != arguments.length)
- continue;
- boolean matches = true;
- Class[] tt = c.getParameterTypes();
- for (int i=0; i<tt.length; i++) {
- if (arguments[i]!=null && !tt[i].isInstance(arguments[i])) {
- matches=false;
- break;
- }
- }
- if (matches)
- return c;
- }
- return null;
- }
-
- /** Registers an adapter for use with type coercion. Returns any old adapter. */
- public synchronized static <A,B> Function registerAdapter(Class<A> sourceType, Class<B> targetType, Function<? super A,B> fn) {
- return registry.put(targetType, sourceType, fn);
- }
-
- static { BrooklynInitialization.initTypeCoercionStandardAdapters(); }
-
- public static void initStandardAdapters() {
- registerAdapter(CharSequence.class, String.class, new Function<CharSequence,String>() {
- @Override
- public String apply(CharSequence input) {
- return input.toString();
- }
- });
- registerAdapter(byte[].class, String.class, new Function<byte[],String>() {
- @Override
- public String apply(byte[] input) {
- return new String(input);
- }
- });
- registerAdapter(Collection.class, Set.class, new Function<Collection,Set>() {
- @SuppressWarnings("unchecked")
- @Override
- public Set apply(Collection input) {
- return Sets.newLinkedHashSet(input);
- }
- });
- registerAdapter(Collection.class, List.class, new Function<Collection,List>() {
- @SuppressWarnings("unchecked")
- @Override
- public List apply(Collection input) {
- return Lists.newArrayList(input);
- }
- });
- registerAdapter(String.class, InetAddress.class, new Function<String,InetAddress>() {
- @Override
- public InetAddress apply(String input) {
- return Networking.getInetAddressWithFixedName(input);
- }
- });
- registerAdapter(String.class, HostAndPort.class, new Function<String,HostAndPort>() {
- @Override
- public HostAndPort apply(String input) {
- return HostAndPort.fromString(input);
- }
- });
- registerAdapter(String.class, UserAndHostAndPort.class, new Function<String,UserAndHostAndPort>() {
- @Override
- public UserAndHostAndPort apply(String input) {
- return UserAndHostAndPort.fromString(input);
- }
- });
- registerAdapter(String.class, Cidr.class, new Function<String,Cidr>() {
- @Override
- public Cidr apply(String input) {
- return new Cidr(input);
- }
- });
- registerAdapter(String.class, URL.class, new Function<String,URL>() {
- @Override
- public URL apply(String input) {
- try {
- return new URL(input);
- } catch (Exception e) {
- throw Exceptions.propagate(e);
- }
- }
- });
- registerAdapter(String.class, URI.class, new Function<String,URI>() {
- @Override
- public URI apply(String input) {
- return URI.create(input);
- }
- });
- registerAdapter(Closure.class, ConfigurableEntityFactory.class, new Function<Closure,ConfigurableEntityFactory>() {
- @SuppressWarnings("unchecked")
- @Override
- public ConfigurableEntityFactory apply(Closure input) {
- return new ClosureEntityFactory(input);
- }
- });
- @SuppressWarnings({"unused", "deprecation"})
- Function<?,?> ignoredVarHereToAllowSuppressDeprecationWarning1 = registerAdapter(brooklyn.entity.basic.EntityFactory.class, ConfigurableEntityFactory.class, new Function<brooklyn.entity.basic.EntityFactory,ConfigurableEntityFactory>() {
- @SuppressWarnings("unchecked")
- @Override
- public ConfigurableEntityFactory apply(brooklyn.entity.basic.EntityFactory input) {
- if (input instanceof ConfigurableEntityFactory) return (ConfigurableEntityFactory)input;
- return new ConfigurableEntityFactoryFromEntityFactory(input);
- }
- });
- @SuppressWarnings({"unused", "deprecation"})
- Function<?,?> ignoredVarHereToAllowSuppressDeprecationWarning2 = registerAdapter(Closure.class, brooklyn.entity.basic.EntityFactory.class, new Function<Closure,brooklyn.entity.basic.EntityFactory>() {
- @SuppressWarnings("unchecked")
- @Override
- public brooklyn.entity.basic.EntityFactory apply(Closure input) {
- return new ClosureEntityFactory(input);
- }
- });
- registerAdapter(Closure.class, Predicate.class, new Function<Closure,Predicate>() {
- @Override
- public Predicate<?> apply(final Closure closure) {
- return new Predicate<Object>() {
- @Override public boolean apply(Object input) {
- return (Boolean) closure.call(input);
- }
- };
- }
- });
- registerAdapter(Closure.class, Function.class, new Function<Closure,Function>() {
- @Override
- public Function apply(final Closure closure) {
- return new Function() {
- @Override public Object apply(Object input) {
- return closure.call(input);
- }
- };
- }
- });
- registerAdapter(Object.class, Duration.class, new Function<Object,Duration>() {
- @Override
- public Duration apply(final Object input) {
- return brooklyn.util.time.Duration.of(input);
- }
- });
- registerAdapter(Object.class, TimeDuration.class, new Function<Object,TimeDuration>() {
- @SuppressWarnings("deprecation")
- @Override
- public TimeDuration apply(final Object input) {
- log.warn("deprecated automatic coercion of Object to TimeDuration (set breakpoint in TypeCoercions to inspect, convert to Duration)");
- return JavaGroovyEquivalents.toTimeDuration(input);
- }
- });
- registerAdapter(TimeDuration.class, Long.class, new Function<TimeDuration,Long>() {
- @Override
- public Long apply(final TimeDuration input) {
- log.warn("deprecated automatic coercion of TimeDuration to Long (set breakpoint in TypeCoercions to inspect, use Duration instead of Long!)");
- return input.toMilliseconds();
- }
- });
- registerAdapter(Integer.class, AtomicLong.class, new Function<Integer,AtomicLong>() {
- @Override public AtomicLong apply(final Integer input) {
- return new AtomicLong(input);
- }
- });
- registerAdapter(Long.class, AtomicLong.class, new Function<Long,AtomicLong>() {
- @Override public AtomicLong apply(final Long input) {
- return new AtomicLong(input);
- }
- });
- registerAdapter(String.class, AtomicLong.class, new Function<String,AtomicLong>() {
- @Override public AtomicLong apply(final String input) {
- return new AtomicLong(Long.parseLong(input.trim()));
- }
- });
- registerAdapter(Integer.class, AtomicInteger.class, new Function<Integer,AtomicInteger>() {
- @Override public AtomicInteger apply(final Integer input) {
- return new AtomicInteger(input);
- }
- });
- registerAdapter(String.class, AtomicInteger.class, new Function<String,AtomicInteger>() {
- @Override public AtomicInteger apply(final String input) {
- return new AtomicInteger(Integer.parseInt(input.trim()));
- }
- });
- /** This always returns a {@link Double}, cast as a {@link Number};
- * however primitives and boxers get exact typing due to call in #stringToPrimitive */
- registerAdapter(String.class, Number.class, new Function<String,Number>() {
- @Override
- public Number apply(String input) {
- return Double.valueOf(input);
- }
- });
- registerAdapter(BigDecimal.class, Double.class, new Function<BigDecimal,Double>() {
- @Override
- public Double apply(BigDecimal input) {
- return input.doubleValue();
- }
- });
- registerAdapter(BigInteger.class, Long.class, new Function<BigInteger,Long>() {
- @Override
- public Long apply(BigInteger input) {
- return input.longValue();
- }
- });
- registerAdapter(BigInteger.class, Integer.class, new Function<BigInteger,Integer>() {
- @Override
- public Integer apply(BigInteger input) {
- return input.intValue();
- }
- });
- registerAdapter(String.class, BigDecimal.class, new Function<String,BigDecimal>() {
- @Override
- public BigDecimal apply(String input) {
- return new BigDecimal(input);
- }
- });
- registerAdapter(Double.class, BigDecimal.class, new Function<Double,BigDecimal>() {
- @Override
- public BigDecimal apply(Double input) {
- return BigDecimal.valueOf(input);
- }
- });
- registerAdapter(String.class, BigInteger.class, new Function<String,BigInteger>() {
- @Override
- public BigInteger apply(String input) {
- return new BigInteger(input);
- }
- });
- registerAdapter(Long.class, BigInteger.class, new Function<Long,BigInteger>() {
- @Override
- public BigInteger apply(Long input) {
- return BigInteger.valueOf(input);
- }
- });
- registerAdapter(Integer.class, BigInteger.class, new Function<Integer,BigInteger>() {
- @Override
- public BigInteger apply(Integer input) {
- return BigInteger.valueOf(input);
- }
- });
- registerAdapter(String.class, Date.class, new Function<String,Date>() {
- @Override
- public Date apply(final String input) {
- return Time.parseDate(input);
- }
- });
- registerAdapter(String.class, Class.class, new Function<String,Class>() {
- @Override
- public Class apply(final String input) {
- try {
- return Class.forName(input);
- } catch (ClassNotFoundException e) {
- throw Exceptions.propagate(e);
- }
- }
- });
- registerAdapter(String.class, AttributeSensor.class, new Function<String,AttributeSensor>() {
- @Override
- public AttributeSensor apply(final String input) {
- Entity entity = BrooklynTaskTags.getContextEntity(Tasks.current());
- if (entity!=null) {
- Sensor<?> result = entity.getEntityType().getSensor(input);
- if (result instanceof AttributeSensor)
- return (AttributeSensor) result;
- }
- return Sensors.newSensor(Object.class, input);
- }
- });
- registerAdapter(String.class, Sensor.class, new Function<String,Sensor>() {
- @Override
- public AttributeSensor apply(final String input) {
- Entity entity = BrooklynTaskTags.getContextEntity(Tasks.current());
- if (entity!=null) {
- Sensor<?> result = entity.getEntityType().getSensor(input);
- if (result != null)
- return (AttributeSensor) result;
- }
- return Sensors.newSensor(Object.class, input);
- }
- });
- registerAdapter(String.class, List.class, new Function<String,List>() {
- @Override
- public List<String> apply(final String input) {
- return JavaStringEscapes.unwrapJsonishListIfPossible(input);
- }
- });
- registerAdapter(String.class, Set.class, new Function<String,Set>() {
- @Override
- public Set<String> apply(final String input) {
- return MutableSet.copyOf(JavaStringEscapes.unwrapJsonishListIfPossible(input)).asUnmodifiable();
- }
- });
- registerAdapter(String.class, QuorumCheck.class, new Function<String,QuorumCheck>() {
- @Override
- public QuorumCheck apply(final String input) {
- return QuorumChecks.of(input);
- }
- });
- registerAdapter(Iterable.class, String[].class, new Function<Iterable, String[]>() {
- @Nullable
- @Override
- public String[] apply(@Nullable Iterable list) {
- if (list == null) return null;
- String[] result = new String[Iterables.size(list)];
- int count = 0;
- for (Object element : list) {
- result[count++] = coerce(element, String.class);
- }
- return result;
- }
- });
- registerAdapter(Iterable.class, Integer[].class, new Function<Iterable, Integer[]>() {
- @Nullable
- @Override
- public Integer[] apply(@Nullable Iterable list) {
- if (list == null) return null;
- Integer[] result = new Integer[Iterables.size(list)];
- int count = 0;
- for (Object element : list) {
- result[count++] = coerce(element, Integer.class);
- }
- return result;
- }
- });
- registerAdapter(Iterable.class, int[].class, new Function<Iterable, int[]>() {
- @Nullable
- @Override
- public int[] apply(@Nullable Iterable list) {
- if (list == null) return null;
- int[] result = new int[Iterables.size(list)];
- int count = 0;
- for (Object element : list) {
- result[count++] = coerce(element, int.class);
- }
- return result;
- }
- });
- registerAdapter(String.class, Map.class, new Function<String,Map>() {
- @Override
- public Map apply(final String input) {
- Exception error = null;
-
- // first try wrapping in braces if needed
- if (!input.trim().startsWith("{")) {
- try {
- return apply("{ "+input+" }");
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- // prefer this error
- error = e;
- // fall back to parsing without braces, e.g. if it's multiline
- }
- }
-
- try {
- return Yamls.getAs( Yamls.parseAll(input), Map.class );
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- if (error!=null && input.indexOf('\n')==-1) {
- // prefer the original error if it wasn't braced and wasn't multiline
- e = error;
- }
- throw new IllegalArgumentException("Cannot parse string as map with flexible YAML parsing; "+
- (e instanceof ClassCastException ? "yaml treats it as a string" :
- (e instanceof IllegalArgumentException && Strings.isNonEmpty(e.getMessage())) ? e.getMessage() :
- ""+e) );
- }
-
- // NB: previously we supported this also, when we did json above;
- // yaml support is better as it supports quotes (and better than json because it allows dropping quotes)
- // snake-yaml, our parser, also accepts key=value -- although i'm not sure this is strictly yaml compliant;
- // our tests will catch it if snake behaviour changes, and we can reinstate this
- // (but note it doesn't do quotes; see http://code.google.com/p/guava-libraries/issues/detail?id=412 for that):
-// return ImmutableMap.copyOf(Splitter.on(",").trimResults().omitEmptyStrings().withKeyValueSeparator("=").split(input));
- }
- });
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/http/HttpTool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/http/HttpTool.java b/core/src/main/java/brooklyn/util/http/HttpTool.java
deleted file mode 100644
index a812cfc..0000000
--- a/core/src/main/java/brooklyn/util/http/HttpTool.java
+++ /dev/null
@@ -1,387 +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 brooklyn.util.http;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-
-import java.net.URI;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import org.apache.commons.codec.binary.Base64;
-import org.apache.http.ConnectionReuseStrategy;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpResponse;
-import org.apache.http.NameValuePair;
-import org.apache.http.auth.AuthScope;
-import org.apache.http.auth.Credentials;
-import org.apache.http.auth.UsernamePasswordCredentials;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.entity.UrlEncodedFormEntity;
-import org.apache.http.client.methods.HttpDelete;
-import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.methods.HttpHead;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.client.methods.HttpPut;
-import org.apache.http.client.methods.HttpUriRequest;
-import org.apache.http.conn.ClientConnectionManager;
-import org.apache.http.conn.scheme.Scheme;
-import org.apache.http.conn.scheme.SchemeSocketFactory;
-import org.apache.http.conn.ssl.SSLSocketFactory;
-import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
-import org.apache.http.conn.ssl.TrustStrategy;
-import org.apache.http.conn.ssl.X509HostnameVerifier;
-import org.apache.http.entity.ByteArrayEntity;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.impl.client.LaxRedirectStrategy;
-import org.apache.http.message.BasicNameValuePair;
-import org.apache.http.params.BasicHttpParams;
-import org.apache.http.params.HttpConnectionParams;
-import org.apache.http.params.HttpParams;
-import org.apache.http.util.EntityUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.util.crypto.SslTrustUtils;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.net.URLParamEncoder;
-import brooklyn.util.text.Strings;
-import brooklyn.util.time.Duration;
-
-import com.google.common.base.Function;
-import com.google.common.base.Joiner;
-import com.google.common.base.Optional;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Multimap;
-
-public class HttpTool {
-
- private static final Logger LOG = LoggerFactory.getLogger(HttpTool.class);
-
- /** Apache HTTP commons utility for trusting all.
- * <p>
- * For generic java HTTP usage, see {@link SslTrustUtils#trustAll(java.net.URLConnection)}
- * and static constants in the same class. */
- public static class TrustAllStrategy implements TrustStrategy {
- @Override
- public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
- return true;
- }
- }
-
- public static HttpClientBuilder httpClientBuilder() {
- return new HttpClientBuilder();
- }
-
- public static class HttpClientBuilder {
- private ClientConnectionManager clientConnectionManager;
- private HttpParams httpParams;
- private URI uri;
- private Integer port;
- private Credentials credentials;
- private boolean laxRedirect;
- private Boolean https;
- private SchemeSocketFactory socketFactory;
- private ConnectionReuseStrategy reuseStrategy;
- private boolean trustAll;
- private boolean trustSelfSigned;
-
- public HttpClientBuilder clientConnectionManager(ClientConnectionManager val) {
- this.clientConnectionManager = checkNotNull(val, "clientConnectionManager");
- return this;
- }
- public HttpClientBuilder httpParams(HttpParams val) {
- checkState(httpParams == null, "Must not call httpParams multiple times, or after other methods like connectionTimeout");
- this.httpParams = checkNotNull(val, "httpParams");
- return this;
- }
- public HttpClientBuilder connectionTimeout(Duration val) {
- if (httpParams == null) httpParams = new BasicHttpParams();
- long millis = checkNotNull(val, "connectionTimeout").toMilliseconds();
- if (millis > Integer.MAX_VALUE) throw new IllegalStateException("HttpClient only accepts upto max-int millis for connectionTimeout, but given "+val);
- HttpConnectionParams.setConnectionTimeout(httpParams, (int) millis);
- return this;
- }
- public HttpClientBuilder socketTimeout(Duration val) {
- if (httpParams == null) httpParams = new BasicHttpParams();
- long millis = checkNotNull(val, "socketTimeout").toMilliseconds();
- if (millis > Integer.MAX_VALUE) throw new IllegalStateException("HttpClient only accepts upto max-int millis for socketTimeout, but given "+val);
- HttpConnectionParams.setSoTimeout(httpParams, (int) millis);
- return this;
- }
- public HttpClientBuilder reuseStrategy(ConnectionReuseStrategy val) {
- this.reuseStrategy = checkNotNull(val, "reuseStrategy");
- return this;
- }
- public HttpClientBuilder uri(String val) {
- return uri(URI.create(checkNotNull(val, "uri")));
- }
- public HttpClientBuilder uri(URI val) {
- this.uri = checkNotNull(val, "uri");
- if (https == null) https = ("https".equalsIgnoreCase(uri.getScheme()));
- return this;
- }
- public HttpClientBuilder port(int val) {
- this.port = val;
- return this;
- }
- public HttpClientBuilder credentials(Credentials val) {
- this.credentials = checkNotNull(val, "credentials");
- return this;
- }
- public void credential(Optional<Credentials> val) {
- if (val.isPresent()) credentials = val.get();
- }
- /** similar to curl --post301 -L` */
- public HttpClientBuilder laxRedirect(boolean val) {
- this.laxRedirect = val;
- return this;
- }
- public HttpClientBuilder https(boolean val) {
- this.https = val;
- return this;
- }
- public HttpClientBuilder socketFactory(SchemeSocketFactory val) {
- this.socketFactory = checkNotNull(val, "socketFactory");
- return this;
- }
- public HttpClientBuilder trustAll() {
- this.trustAll = true;
- return this;
- }
- public HttpClientBuilder trustSelfSigned() {
- this.trustSelfSigned = true;
- return this;
- }
- public HttpClient build() {
- final DefaultHttpClient httpClient = new DefaultHttpClient(clientConnectionManager);
- httpClient.setParams(httpParams);
-
- // support redirects for POST (similar to `curl --post301 -L`)
- // http://stackoverflow.com/questions/3658721/httpclient-4-error-302-how-to-redirect
- if (laxRedirect) {
- httpClient.setRedirectStrategy(new LaxRedirectStrategy());
- }
- if (reuseStrategy != null) {
- httpClient.setReuseStrategy(reuseStrategy);
- }
- if (https == Boolean.TRUE || (uri!=null && uri.toString().startsWith("https:"))) {
- try {
- if (port == null) {
- port = (uri != null && uri.getPort() >= 0) ? uri.getPort() : 443;
- }
- if (socketFactory == null) {
- if (trustAll) {
- TrustStrategy trustStrategy = new TrustAllStrategy();
- X509HostnameVerifier hostnameVerifier = SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
- socketFactory = new SSLSocketFactory(trustStrategy, hostnameVerifier);
- } else if (trustSelfSigned) {
- TrustStrategy trustStrategy = new TrustSelfSignedStrategy();
- X509HostnameVerifier hostnameVerifier = SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
- socketFactory = new SSLSocketFactory(trustStrategy, hostnameVerifier);
- } else {
- // Using default https scheme: based on default java truststore, which is pretty strict!
- }
- }
- if (socketFactory != null) {
- Scheme sch = new Scheme("https", port, socketFactory);
- httpClient.getConnectionManager().getSchemeRegistry().register(sch);
- }
- } catch (Exception e) {
- LOG.warn("Error setting trust for uri {}", uri);
- throw Exceptions.propagate(e);
- }
- }
-
- // Set credentials
- if (uri != null && credentials != null) {
- String hostname = uri.getHost();
- int port = uri.getPort();
- httpClient.getCredentialsProvider().setCredentials(new AuthScope(hostname, port), credentials);
- }
- if (uri==null && credentials!=null) {
- LOG.warn("credentials have no effect in builder unless URI for host is specified");
- }
-
- return httpClient;
- }
- }
-
- protected static abstract class HttpRequestBuilder<B extends HttpRequestBuilder<B, R>, R extends HttpRequest> {
- protected R req;
-
- protected HttpRequestBuilder(R req) {
- this.req = req;
- }
- @SuppressWarnings("unchecked")
- protected B self() {
- return (B) this;
- }
- public B headers(Map<String,String> headers) {
- if (headers!=null) {
- for (Map.Entry<String,String> entry : headers.entrySet()) {
- req.addHeader(entry.getKey(), entry.getValue());
- }
- }
- return self();
- }
- public B headers(Multimap<String,String> headers) {
- if (headers!=null) {
- for (Map.Entry<String,String> entry : headers.entries()) {
- req.addHeader(entry.getKey(), entry.getValue());
- }
- }
- return self();
- }
- public R build() {
- return req;
- }
- }
-
- protected static abstract class HttpEntityEnclosingRequestBaseBuilder<B extends HttpEntityEnclosingRequestBaseBuilder<B,R>, R extends HttpEntityEnclosingRequestBase> extends HttpRequestBuilder<B, R> {
- protected HttpEntityEnclosingRequestBaseBuilder(R req) {
- super(req);
- }
- public B body(byte[] body) {
- if (body != null) {
- HttpEntity httpEntity = new ByteArrayEntity(body);
- req.setEntity(httpEntity);
- }
- return self();
- }
- }
-
- public static class HttpGetBuilder extends HttpRequestBuilder<HttpGetBuilder, HttpGet> {
- public HttpGetBuilder(URI uri) {
- super(new HttpGet(uri));
- }
- }
-
- public static class HttpHeadBuilder extends HttpRequestBuilder<HttpHeadBuilder, HttpHead> {
- public HttpHeadBuilder(URI uri) {
- super(new HttpHead(uri));
- }
- }
-
- public static class HttpDeleteBuilder extends HttpRequestBuilder<HttpDeleteBuilder, HttpDelete> {
- public HttpDeleteBuilder(URI uri) {
- super(new HttpDelete(uri));
- }
- }
-
- public static class HttpPostBuilder extends HttpEntityEnclosingRequestBaseBuilder<HttpPostBuilder, HttpPost> {
- HttpPostBuilder(URI uri) {
- super(new HttpPost(uri));
- }
- }
-
- public static class HttpFormPostBuilder extends HttpRequestBuilder<HttpFormPostBuilder, HttpPost> {
- HttpFormPostBuilder(URI uri) {
- super(new HttpPost(uri));
- }
-
- public HttpFormPostBuilder params(Map<String, String> params) {
- if (params != null) {
- Collection<NameValuePair> httpParams = new ArrayList<NameValuePair>(params.size());
- for (Entry<String, String> param : params.entrySet()) {
- httpParams.add(new BasicNameValuePair(param.getKey(), param.getValue()));
- }
- req.setEntity(new UrlEncodedFormEntity(httpParams));
- }
- return self();
- }
- }
-
- public static class HttpPutBuilder extends HttpEntityEnclosingRequestBaseBuilder<HttpPutBuilder, HttpPut> {
- public HttpPutBuilder(URI uri) {
- super(new HttpPut(uri));
- }
- }
-
- public static HttpToolResponse httpGet(HttpClient httpClient, URI uri, Map<String,String> headers) {
- HttpGet req = new HttpGetBuilder(uri).headers(headers).build();
- return execAndConsume(httpClient, req);
- }
-
- public static HttpToolResponse httpPost(HttpClient httpClient, URI uri, Map<String,String> headers, byte[] body) {
- HttpPost req = new HttpPostBuilder(uri).headers(headers).body(body).build();
- return execAndConsume(httpClient, req);
- }
-
- public static HttpToolResponse httpPut(HttpClient httpClient, URI uri, Map<String, String> headers, byte[] body) {
- HttpPut req = new HttpPutBuilder(uri).headers(headers).body(body).build();
- return execAndConsume(httpClient, req);
- }
-
- public static HttpToolResponse httpPost(HttpClient httpClient, URI uri, Map<String,String> headers, Map<String, String> params) {
- HttpPost req = new HttpFormPostBuilder(uri).headers(headers).params(params).build();
- return execAndConsume(httpClient, req);
- }
-
- public static HttpToolResponse httpDelete(HttpClient httpClient, URI uri, Map<String,String> headers) {
- HttpDelete req = new HttpDeleteBuilder(uri).headers(headers).build();
- return execAndConsume(httpClient, req);
- }
-
- public static HttpToolResponse httpHead(HttpClient httpClient, URI uri, Map<String,String> headers) {
- HttpHead req = new HttpHeadBuilder(uri).headers(headers).build();
- return execAndConsume(httpClient, req);
- }
-
- public static HttpToolResponse execAndConsume(HttpClient httpClient, HttpUriRequest req) {
- long startTime = System.currentTimeMillis();
- try {
- HttpResponse httpResponse = httpClient.execute(req);
-
- try {
- return new HttpToolResponse(httpResponse, startTime);
- } finally {
- EntityUtils.consume(httpResponse.getEntity());
- }
- } catch (Exception e) {
- throw Exceptions.propagate(e);
- }
- }
-
- public static boolean isStatusCodeHealthy(int code) { return (code>=200 && code<=299); }
-
- public static String toBasicAuthorizationValue(UsernamePasswordCredentials credentials) {
- return "Basic "+Base64.encodeBase64String( (credentials.getUserName()+":"+credentials.getPassword()).getBytes() );
- }
-
- public static String encodeUrlParams(Map<?,?> data) {
- if (data==null) return "";
- Iterable<String> args = Iterables.transform(data.entrySet(),
- new Function<Map.Entry<?,?>,String>() {
- @Override public String apply(Map.Entry<?,?> entry) {
- Object k = entry.getKey();
- Object v = entry.getValue();
- return URLParamEncoder.encode(Strings.toString(k)) + (v != null ? "=" + URLParamEncoder.encode(Strings.toString(v)) : "");
- }
- });
- return Joiner.on("&").join(args);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/http/HttpToolResponse.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/http/HttpToolResponse.java b/core/src/main/java/brooklyn/util/http/HttpToolResponse.java
deleted file mode 100644
index 1837a87..0000000
--- a/core/src/main/java/brooklyn/util/http/HttpToolResponse.java
+++ /dev/null
@@ -1,185 +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 brooklyn.util.http;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.http.Header;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.event.feed.http.HttpPollValue;
-import brooklyn.util.guava.Maybe;
-import brooklyn.util.stream.Streams;
-import brooklyn.util.time.Duration;
-import brooklyn.util.time.Time;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Throwables;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-import com.google.common.io.ByteStreams;
-
-public class HttpToolResponse implements HttpPollValue {
-
- private static final Logger log = LoggerFactory.getLogger(HttpToolResponse.class);
-
- private final Object mutex = new Object();
- private final HttpResponse response;
- private final long startTime;
- private final long durationMillisOfFirstResponse;
- private final long durationMillisOfFullContent;
- private int responseCode;
- private String reasonPhrase;
- private Map<String,List<String>> headerLists;
- private byte[] content;
-
-
- public HttpToolResponse(HttpResponse response, long startTime) {
- this.response = response;
- this.startTime = startTime;
-
- try {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- HttpEntity entity = response.getEntity();
- if (entity != null) {
- entity.getContentLength();
- durationMillisOfFirstResponse = Duration.sinceUtc(startTime).toMilliseconds();
-
- ByteStreams.copy(entity.getContent(), out);
- content = out.toByteArray();
-
- entity.getContentLength();
- } else {
- durationMillisOfFirstResponse = Duration.sinceUtc(startTime).toMilliseconds();
- content = new byte[0];
- }
- durationMillisOfFullContent = Duration.sinceUtc(startTime).toMilliseconds();
- if (log.isTraceEnabled())
- log.trace("HttpPollValue latency "+Time.makeTimeStringRounded(durationMillisOfFirstResponse)+" / "+Time.makeTimeStringRounded(durationMillisOfFullContent)+", content size "+content.length);
- } catch (IOException e) {
- throw Throwables.propagate(e);
- }
- }
-
- public HttpToolResponse(int responseCode, Map<String,? extends List<String>> headers, byte[] content,
- long startTime, long durationMillisOfFirstResponse, long durationMillisOfFullContent) {
- this.response = null;
- this.responseCode = responseCode;
- this.headerLists = ImmutableMap.copyOf(headers);
- this.content = content;
- this.startTime = startTime;
- this.durationMillisOfFirstResponse = durationMillisOfFirstResponse;
- this.durationMillisOfFullContent = durationMillisOfFullContent;
- }
-
- public int getResponseCode() {
- synchronized (mutex) {
- if (responseCode == 0) {
- responseCode = response.getStatusLine().getStatusCode();
- }
- }
- return responseCode;
- }
-
- public String getReasonPhrase() {
- synchronized (mutex) {
- if (reasonPhrase == null) {
- reasonPhrase = response.getStatusLine().getReasonPhrase();
- }
- }
- return reasonPhrase;
- }
-
- /** returns the timestamp (millis since 1970) when this request was started */
- public long getStartTime() {
- return startTime;
- }
-
- /** returns latency, in milliseconds, if value was initialized with a start time */
- public long getLatencyFullContent() {
- return durationMillisOfFullContent;
- }
-
- /** returns latency, in milliseconds, before response started coming in */
- public long getLatencyFirstResponse() {
- return durationMillisOfFirstResponse;
- }
-
- public Map<String, List<String>> getHeaderLists() {
- synchronized (mutex) {
- if (headerLists == null) {
- Map<String, List<String>> headerListsMutable = Maps.newLinkedHashMap();
- for (Header header : response.getAllHeaders()) {
- List<String> vals = headerListsMutable.get(header.getName());
- if (vals == null) {
- vals = new ArrayList<String>();
- headerListsMutable.put(header.getName(), vals);
- }
- vals.add(header.getValue());
- }
- headerLists = Collections.unmodifiableMap(headerListsMutable);
- }
- }
- return headerLists;
- }
-
- public byte[] getContent() {
- synchronized (mutex) {
- if (content == null) {
- InputStream in = null;
- try {
- in = response.getEntity().getContent();
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ByteStreams.copy(in, out);
- content = out.toByteArray();
- } catch (IOException e) {
- throw Throwables.propagate(e);
- } finally {
- Streams.closeQuietly(in);
- }
- }
- }
- return content;
- }
-
- public String getContentAsString() {
- return new String(getContent());
- }
-
- public Maybe<HttpResponse> getResponse() {
- return Maybe.fromNullable(response);
- }
-
- @Override
- public String toString() {
- return Objects.toStringHelper(getClass())
- .add("responseCode", responseCode)
- .toString();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/internal/ConfigKeySelfExtracting.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/internal/ConfigKeySelfExtracting.java b/core/src/main/java/brooklyn/util/internal/ConfigKeySelfExtracting.java
deleted file mode 100644
index 5048b0e..0000000
--- a/core/src/main/java/brooklyn/util/internal/ConfigKeySelfExtracting.java
+++ /dev/null
@@ -1,41 +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 brooklyn.util.internal;
-
-import java.util.Map;
-
-import org.apache.brooklyn.api.management.ExecutionContext;
-
-import brooklyn.config.ConfigKey;
-
-/** Interface for resolving key values; typically implemented by the config key,
- * but discouraged for external usage.
- */
-public interface ConfigKeySelfExtracting<T> extends ConfigKey<T> {
-
- /**
- * Extracts the value for this config key from the given map.
- */
- T extractValue(Map<?,?> configMap, ExecutionContext exec);
-
- /**
- * @return True if there is an entry in the configMap that could be extracted
- */
- boolean isSet(Map<?,?> configMap);
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/internal/Repeater.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/internal/Repeater.java b/core/src/main/java/brooklyn/util/internal/Repeater.java
deleted file mode 100644
index ef149ba..0000000
--- a/core/src/main/java/brooklyn/util/internal/Repeater.java
+++ /dev/null
@@ -1,369 +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 brooklyn.util.internal;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.Map;
-import java.util.concurrent.Callable;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.util.JavaGroovyEquivalents;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.FlagUtils;
-import brooklyn.util.flags.SetFromFlag;
-import brooklyn.util.time.Duration;
-import brooklyn.util.time.Time;
-
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.Callables;
-
-/**
- * Simple DSL to repeat a fragment of code periodically until a condition is satisfied.
- *
- * In its simplest case, it is passed two {@link groovy.lang.Closure}s / {@link Callable} -
- * the first is executed, then the second. If the second closure returns false, the loop
- * is repeated; if true, it finishes. Further customization can be applied to set the period
- * between loops and place a maximum limit on how long the loop should run for.
- * <p>
- * It is configured in a <em>fluent</em> manner. For example, in Groovy:
- * <pre>
- * {@code
- * Repeater.create("Wait until the Frobnitzer is ready")
- * .repeat {
- * status = frobnitzer.getStatus()
- * }
- * .until {
- * status == "Ready" || status == "Failed"
- * }
- * .limitIterationsTo(30)
- * .run()
- * }
- * </pre>
- *
- * Or in Java:
- * <pre>
- * {@code
- * Repeater.create("Wait until the Frobnitzer is ready")
- * .until(new Callable<Boolean>() {
- * public Boolean call() {
- * String status = frobnitzer.getStatus()
- * return "Ready".equals(status) || "Failed".equals(status);
- * }})
- * .limitIterationsTo(30)
- * .run()
- * }
- * </pre>
- *
- * @deprecated since 0.7.0, use {@link brooklyn.util.repeat.Repeater} instead
- */
-@Deprecated
-public class Repeater {
-
- // TODO Was converted to Java, from groovy. Needs thorough review and improvements
- // to use idiomatic java
-
- private static final Logger log = LoggerFactory.getLogger(Repeater.class);
-
- static { TimeExtras.init(); }
-
- @SetFromFlag
- private String description;
- private Callable<?> body = Callables.returning(null);
- private Callable<Boolean> exitCondition;
- @SetFromFlag
- private Long period = null;
- @SetFromFlag("timeout")
- private Long durationLimit = null;
- private int iterationLimit = 0;
- private boolean rethrowException = false;
- private boolean rethrowExceptionImmediately = false;
- private boolean warnOnUnRethrownException = true;
-
- public Repeater() {
- this(MutableMap.of(), null);
- }
-
- public Repeater(Map<?,?> flags) {
- this(flags, null);
- }
-
- public Repeater(String description) {
- this(MutableMap.of(), description);
- }
-
- /**
- * Construct a new instance of Repeater.
- *
- * @param flags can include period, timeout, description
- * @param description a description of the operation that will appear in debug logs.
- */
- public Repeater(Map<?,?> flags, String description) {
- setFromFlags(flags);
- this.description = JavaGroovyEquivalents.elvis(description, this.description, "Repeater");
- }
-
- public void setFromFlags(Map<?,?> flags) {
- FlagUtils.setFieldsFromFlags(flags, this);
- }
-
- public static Repeater create() {
- return create(MutableMap.of());
- }
- public static Repeater create(Map<?,?> flags) {
- return create(flags, null);
- }
- public static Repeater create(String description) {
- return create(MutableMap.of(), description);
- }
- public static Repeater create(Map<?,?> flags, String description) {
- return new Repeater(flags, description);
- }
-
- /**
- * Sets the main body of the loop to be a no-op.
- *
- * @return {@literal this} to aid coding in a fluent style.
- */
- public Repeater repeat() {
- return repeat(Callables.returning(null));
- }
-
- /**
- * Sets the main body of the loop.
- *
- * @param body a closure or other Runnable that is executed in the main body of the loop.
- * @return {@literal this} to aid coding in a fluent style.
- */
- public Repeater repeat(Runnable body) {
- checkNotNull(body, "body must not be null");
- this.body = (body instanceof Callable) ? (Callable<?>)body : Executors.callable(body);
- return this;
- }
-
- /**
- * Sets the main body of the loop.
- *
- * @param body a closure or other Callable that is executed in the main body of the loop.
- * @return {@literal this} to aid coding in a fluent style.
- */
- public Repeater repeat(Callable<?> body) {
- checkNotNull(body, "body must not be null");
- this.body = body;
- return this;
- }
-
- /**
- * Set how long to wait between loop iterations.
- *
- * @param period how long to wait between loop iterations.
- * @param unit the unit of measurement of the period.
- * @return {@literal this} to aid coding in a fluent style.
- */
- public Repeater every(long period, TimeUnit unit) {
- Preconditions.checkArgument(period > 0, "period must be positive: %s", period);
- checkNotNull(unit, "unit must not be null");
- this.period = unit.toMillis(period);
- return this;
- }
-
- /**
- * @see #every(long, TimeUnit)
- */
- public Repeater every(Duration duration) {
- Preconditions.checkNotNull(duration, "duration must not be null");
- Preconditions.checkArgument(duration.toMilliseconds()>0, "period must be positive: %s", duration);
- this.period = duration.toMilliseconds();
- return this;
- }
-
- public Repeater every(groovy.time.Duration duration) {
- return every(Duration.of(duration));
- }
-
- /**
- * @see #every(long, TimeUnit)
- * @deprecated specify unit
- */
- public Repeater every(long duration) {
- return every(duration, TimeUnit.MILLISECONDS);
- }
-
- /**
- * Set code fragment that tests if the loop has completed.
- *
- * @param exitCondition a closure or other Callable that returns a boolean. If this code returns {@literal true} then the
- * loop will stop executing.
- * @return {@literal this} to aid coding in a fluent style.
- */
- public Repeater until(Callable<Boolean> exitCondition) {
- Preconditions.checkNotNull(exitCondition, "exitCondition must not be null");
- this.exitCondition = exitCondition;
- return this;
- }
-
- /**
- * If the exit condition check throws an exception, it will be recorded and the last exception will be thrown on failure.
- *
- * @return {@literal this} to aid coding in a fluent style.
- */
- public Repeater rethrowException() {
- this.rethrowException = true;
- return this;
- }
-
- /**
- * If the repeated body or the exit condition check throws an exception, then propagate that exception immediately.
- *
- * @return {@literal this} to aid coding in a fluent style.
- */
- public Repeater rethrowExceptionImmediately() {
- this.rethrowExceptionImmediately = true;
- return this;
- }
-
- public Repeater suppressWarnings() {
- this.warnOnUnRethrownException = false;
- return this;
- }
-
- /**
- * Set the maximum number of iterations.
- *
- * The loop will exit if the condition has not been satisfied after this number of iterations.
- *
- * @param iterationLimit the maximum number of iterations.
- * @return {@literal this} to aid coding in a fluent style.
- */
- public Repeater limitIterationsTo(int iterationLimit) {
- Preconditions.checkArgument(iterationLimit > 0, "iterationLimit must be positive: %s", iterationLimit);
- this.iterationLimit = iterationLimit;
- return this;
- }
-
- /**
- * Set the amount of time to wait for the condition.
- * The repeater will wait at least this long for the condition to be true,
- * and will exit soon after even if the condition is false.
- *
- * @param deadline the time that the loop should wait.
- * @param unit the unit of measurement of the period.
- * @return {@literal this} to aid coding in a fluent style.
- */
- public Repeater limitTimeTo(long deadline, TimeUnit unit) {
- Preconditions.checkArgument(deadline > 0, "deadline must be positive: %s", deadline);
- Preconditions.checkNotNull(unit, "unit must not be null");
- this.durationLimit = unit.toMillis(deadline);
- return this;
- }
-
- /**
- * @see #limitTimeTo(long, TimeUnit)
- */
- public Repeater limitTimeTo(Duration duration) {
- Preconditions.checkNotNull(duration, "duration must not be null");
- Preconditions.checkArgument(duration.toMilliseconds() > 0, "deadline must be positive: %s", duration);
- this.durationLimit = duration.toMilliseconds();
- return this;
- }
-
- /**
- * Run the loop.
- *
- * @return true if the exit condition was satisfied; false if the loop terminated for any other reason.
- */
- public boolean run() {
- Preconditions.checkState(body != null, "repeat() method has not been called to set the body");
- Preconditions.checkState(exitCondition != null, "until() method has not been called to set the exit condition");
- Preconditions.checkState(period != null, "every() method has not been called to set the loop period time units");
-
- Throwable lastError = null;
- int iterations = 0;
- long endTime = -1;
- if (durationLimit != null) {
- endTime = System.currentTimeMillis() + durationLimit;
- }
-
- while (true) {
- iterations++;
-
- try {
- body.call();
- } catch (Exception e) {
- log.warn(description, e);
- if (rethrowExceptionImmediately) throw Exceptions.propagate(e);
- }
-
- boolean done = false;
- try {
- lastError = null;
- done = exitCondition.call();
- } catch (Exception e) {
- if (log.isDebugEnabled()) log.debug(description, e);
- lastError = e;
- if (rethrowExceptionImmediately) throw Exceptions.propagate(e);
- }
- if (done) {
- if (log.isDebugEnabled()) log.debug("{}: condition satisfied", description);
- return true;
- } else {
- if (log.isDebugEnabled()) {
- String msg = String.format("%s: unsatisfied during iteration %s %s", description, iterations,
- (iterationLimit > 0 ? "(max "+iterationLimit+" attempts)" : "") +
- (endTime > 0 ? "("+Time.makeTimeStringRounded(endTime - System.currentTimeMillis())+" remaining)" : ""));
- if (iterations == 1) {
- log.debug(msg);
- } else {
- log.trace(msg);
- }
- }
- }
-
- if (iterationLimit > 0 && iterations == iterationLimit) {
- if (log.isDebugEnabled()) log.debug("{}: condition not satisfied and exceeded iteration limit", description);
- if (rethrowException && lastError != null) {
- log.warn("{}: error caught checking condition (rethrowing): {}", description, lastError.getMessage());
- throw Exceptions.propagate(lastError);
- }
- if (warnOnUnRethrownException && lastError != null)
- log.warn("{}: error caught checking condition: {}", description, lastError.getMessage());
- return false;
- }
-
- if (endTime > 0) {
- if (System.currentTimeMillis() > endTime) {
- if (log.isDebugEnabled()) log.debug("{}: condition not satisfied and deadline {} passed",
- description, Time.makeTimeStringRounded(endTime - System.currentTimeMillis()));
- if (rethrowException && lastError != null) {
- log.error("{}: error caught checking condition: {}", description, lastError.getMessage());
- throw Exceptions.propagate(lastError);
- }
- return false;
- }
- }
-
- Time.sleep(period);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/internal/ssh/BackoffLimitedRetryHandler.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/internal/ssh/BackoffLimitedRetryHandler.java b/core/src/main/java/brooklyn/util/internal/ssh/BackoffLimitedRetryHandler.java
deleted file mode 100644
index 1e2b435..0000000
--- a/core/src/main/java/brooklyn/util/internal/ssh/BackoffLimitedRetryHandler.java
+++ /dev/null
@@ -1,74 +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 brooklyn.util.internal.ssh;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.util.exceptions.Exceptions;
-
-/**
- * Allow replayable request to be retried a limited number of times, and impose an exponential back-off
- * delay before returning.
- * <p>
- * Copied and modified from jclouds; original author was James Murty
- */
-public class BackoffLimitedRetryHandler {
-
- private static final Logger LOG = LoggerFactory.getLogger(BackoffLimitedRetryHandler.class);
-
- private final int retryCountLimit;
-
- private final long delayStart;
-
- public BackoffLimitedRetryHandler() {
- this(5, 50L);
- }
-
- public BackoffLimitedRetryHandler(int retryCountLimit, long delayStart) {
- this.retryCountLimit = retryCountLimit;
- this.delayStart = delayStart;
- }
-
- public void imposeBackoffExponentialDelay(int failureCount, String commandDescription) {
- imposeBackoffExponentialDelay(delayStart, 2, failureCount, retryCountLimit, commandDescription);
- }
-
- public void imposeBackoffExponentialDelay(long period, int pow, int failureCount, int max, String commandDescription) {
- imposeBackoffExponentialDelay(period, period * 10l, pow, failureCount, max, commandDescription);
- }
-
- public void imposeBackoffExponentialDelay(long period,
- long maxPeriod,
- int pow,
- int failureCount,
- int max,
- String commandDescription) {
- long delayMs = (long) (period * Math.pow(failureCount, pow));
- delayMs = (delayMs > maxPeriod) ? maxPeriod : delayMs;
- if (LOG.isDebugEnabled()) LOG.debug("Retry {}/{}: delaying for {} ms: {}",
- new Object[] {failureCount, max, delayMs, commandDescription});
- try {
- Thread.sleep(delayMs);
- } catch (InterruptedException e) {
- Exceptions.propagate(e);
- }
- }
-
-}
[13/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/file/ArchiveBuilderTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/file/ArchiveBuilderTest.java b/core/src/test/java/org/apache/brooklyn/core/util/file/ArchiveBuilderTest.java
new file mode 100644
index 0000000..0ce8298
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/file/ArchiveBuilderTest.java
@@ -0,0 +1,194 @@
+/*
+ * 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.util.file;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.core.util.file.ArchiveBuilder;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import brooklyn.util.collections.MutableSet;
+import brooklyn.util.os.Os;
+import brooklyn.util.text.Identifiers;
+
+import com.google.common.base.Charsets;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.io.Files;
+
+/**
+ * Test the operation of the {@link ArchiveBuilder} class.
+ */
+@Test
+public class ArchiveBuilderTest {
+
+ private File parentDir, tmpDir, tmpDir2;
+ private Predicate<ZipEntry> isDirectory = new Predicate<ZipEntry>() {
+ @Override
+ public boolean apply(@Nullable ZipEntry input) {
+ return input.isDirectory();
+ }
+ };
+
+ @BeforeClass
+ public void createTmpDirAndFiles() throws IOException {
+ parentDir = Os.newTempDir(getClass().getSimpleName());
+ Os.deleteOnExitRecursively(parentDir);
+ tmpDir = new File(parentDir, Identifiers.makeRandomId(4));
+ Os.mkdirs(tmpDir);
+ Files.write("abcdef", new File(tmpDir, "data01.txt"), Charsets.US_ASCII);
+ Files.write("123456", new File(tmpDir, "data02.txt"), Charsets.US_ASCII);
+ Files.write("qqqqqq", new File(tmpDir, "data03.txt"), Charsets.US_ASCII);
+
+ tmpDir2 = new File(parentDir, Identifiers.makeRandomId(4));
+ Os.mkdirs(tmpDir2);
+ Files.write("zzzzzz", new File(tmpDir2, "data04.txt"), Charsets.US_ASCII);
+ }
+
+ @Test
+ public void testCreateZipFromDir() throws Exception {
+ File archive = ArchiveBuilder.zip().addDirContentsAt(tmpDir, ".").create();
+ archive.deleteOnExit();
+
+ List<ZipEntry> entries = Lists.newArrayList();
+ ZipInputStream input = new ZipInputStream(new FileInputStream(archive));
+ ZipEntry entry = input.getNextEntry();
+ while (entry != null) {
+ entries.add(entry);
+ entry = input.getNextEntry();
+ }
+ assertEquals(entries.size(), 4);
+ Iterable<ZipEntry> directories = Iterables.filter(entries, isDirectory);
+ Iterable<ZipEntry> files = Iterables.filter(entries, Predicates.not(isDirectory));
+ assertEquals(Iterables.size(directories), 1);
+ assertEquals(Iterables.size(files), 3);
+ String dirName = Iterables.getOnlyElement(directories).getName();
+ assertEquals(dirName, "./");
+
+ Set<String> names = MutableSet.of();
+ for (ZipEntry file : files) {
+ assertTrue(file.getName().startsWith(dirName));
+ names.add(file.getName());
+ }
+ assertTrue(names.contains("./data01.txt"));
+ assertFalse(names.contains("./data04.txt"));
+ input.close();
+ }
+
+ @Test
+ public void testCreateZipFromTwoDirs() throws Exception {
+ File archive = ArchiveBuilder.zip().addDirContentsAt(tmpDir, ".").addDirContentsAt(tmpDir2, ".").create();
+ archive.deleteOnExit();
+
+ List<ZipEntry> entries = Lists.newArrayList();
+ ZipInputStream input = new ZipInputStream(new FileInputStream(archive));
+ ZipEntry entry = input.getNextEntry();
+ while (entry != null) {
+ entries.add(entry);
+ entry = input.getNextEntry();
+ }
+ assertEquals(entries.size(), 5);
+ Iterable<ZipEntry> directories = Iterables.filter(entries, isDirectory);
+ Iterable<ZipEntry> files = Iterables.filter(entries, Predicates.not(isDirectory));
+ assertEquals(Iterables.size(directories), 1);
+ assertEquals(Iterables.size(files), 4);
+ String dirName = Iterables.getOnlyElement(directories).getName();
+ assertEquals(dirName, "./");
+
+ Set<String> names = MutableSet.of();
+ for (ZipEntry file : files) {
+ assertTrue(file.getName().startsWith(dirName));
+ names.add(file.getName());
+ }
+ assertTrue(names.contains("./data01.txt"));
+ assertTrue(names.contains("./data04.txt"));
+ input.close();
+ }
+ @Test
+ public void testCreateZipFromFiles() throws Exception {
+ ArchiveBuilder builder = ArchiveBuilder.zip();
+ for (String fileName : Arrays.asList("data01.txt", "data02.txt", "data03.txt")) {
+ builder.addAt(new File(tmpDir, fileName), ".");
+ }
+ File archive = builder.create();
+ archive.deleteOnExit();
+
+ List<ZipEntry> entries = Lists.newArrayList();
+ ZipInputStream input = new ZipInputStream(new FileInputStream(archive));
+ ZipEntry entry = input.getNextEntry();
+ while (entry != null) {
+ entries.add(entry);
+ entry = input.getNextEntry();
+ }
+ assertEquals(entries.size(), 3);
+ Iterable<ZipEntry> directories = Iterables.filter(entries, isDirectory);
+ Iterable<ZipEntry> files = Iterables.filter(entries, Predicates.not(isDirectory));
+ assertTrue(Iterables.isEmpty(directories));
+ assertEquals(Iterables.size(files), 3);
+ for (ZipEntry file : files) {
+ assertTrue(file.getName().startsWith(Os.mergePathsUnix(".", "data")));
+ }
+ input.close();
+ }
+
+ @Test
+ public void testCreateZipFromFilesWithBaseDir() throws Exception {
+ ArchiveBuilder builder = ArchiveBuilder.zip();
+ String baseDir = tmpDir.getName();
+ for (String fileName : Arrays.asList("data01.txt", "data02.txt", "data03.txt")) {
+ builder.addFromLocalBaseDir(parentDir, Os.mergePaths(baseDir, fileName));
+ }
+ File archive = builder.create();
+ archive.deleteOnExit();
+
+ List<ZipEntry> entries = Lists.newArrayList();
+ ZipInputStream input = new ZipInputStream(new FileInputStream(archive));
+ ZipEntry entry = input.getNextEntry();
+ while (entry != null) {
+ entries.add(entry);
+ entry = input.getNextEntry();
+ }
+ assertEquals(entries.size(), 3);
+ Iterable<ZipEntry> directories = Iterables.filter(entries, isDirectory);
+ Iterable<ZipEntry> files = Iterables.filter(entries, Predicates.not(isDirectory));
+ assertTrue(Iterables.isEmpty(directories));
+ assertEquals(Iterables.size(files), 3);
+ for (ZipEntry file : files) {
+ assertTrue(file.getName().startsWith(Os.mergePathsUnix(".", baseDir)));
+ }
+ input.close();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/file/ArchiveUtilsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/file/ArchiveUtilsTest.java b/core/src/test/java/org/apache/brooklyn/core/util/file/ArchiveUtilsTest.java
new file mode 100644
index 0000000..a13ef63
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/file/ArchiveUtilsTest.java
@@ -0,0 +1,139 @@
+/*
+ * 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.util.file;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.io.File;
+import java.util.Map;
+
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.BrooklynAppUnitTestSupport;
+
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.file.ArchiveBuilder;
+import org.apache.brooklyn.core.util.file.ArchiveUtils;
+import org.apache.brooklyn.location.basic.SshMachineLocation;
+
+import brooklyn.util.os.Os;
+
+import com.google.api.client.repackaged.com.google.common.base.Joiner;
+import com.google.common.base.Charsets;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.io.Files;
+
+// Test are integration, because relies on ssh/scp via SshMachineLocation
+public class ArchiveUtilsTest extends BrooklynAppUnitTestSupport {
+
+ private SshMachineLocation machine;
+ private ResourceUtils resourceUtils;
+
+ private Map<String, String> archiveContents = ImmutableMap.of("a.txt", "mya");
+ private File destDir;
+ private File origZip;
+ private File origJar;
+
+ @BeforeClass(alwaysRun=true)
+ public void setUpClass() throws Exception {
+ origZip = newZip(archiveContents);
+ origJar = Os.newTempFile(ArchiveUtilsTest.class, ".jar");
+ Files.copy(origZip, origJar);
+ }
+
+ @AfterClass(alwaysRun=true)
+ public void tearDownClass() throws Exception {
+ if (origZip != null) origZip.delete();
+ if (origJar != null) origJar.delete();
+ }
+
+ @BeforeMethod(alwaysRun=true)
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ machine = app.newLocalhostProvisioningLocation().obtain();
+ resourceUtils = ResourceUtils.create(ArchiveUtilsTest.class);
+ destDir = Os.newTempDir(getClass().getSimpleName());
+ }
+
+ @AfterMethod(alwaysRun=true)
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+ if (destDir != null) Os.deleteRecursively(destDir);
+ }
+
+ @Test(groups="Integration")
+ public void testDeployZipWithNoOptionalArgsSupplied() throws Exception {
+ boolean result = ArchiveUtils.deploy(resourceUtils, ImmutableMap.<String, Object>of(), origZip.getAbsolutePath(), machine, destDir.getAbsolutePath(), true, null, null);
+ assertTrue(result);
+ assertFilesEqual(new File(destDir, origZip.getName()), origZip);
+ assertSubFilesEqual(destDir, archiveContents);
+ }
+
+ @Test(groups="Integration")
+ public void testDeployZipDeletingArchiveAfterUnpack() throws Exception {
+ boolean result = ArchiveUtils.deploy(resourceUtils, ImmutableMap.<String, Object>of(), origZip.getAbsolutePath(), machine, destDir.getAbsolutePath(), false, null, null);
+ assertTrue(result);
+ assertFalse(new File(destDir, origZip.getName()).exists());
+ assertSubFilesEqual(destDir, archiveContents);
+ }
+
+ @Test(groups="Integration")
+ public void testDeployJarNotUnpacked() throws Exception {
+ ArchiveUtils.deploy(origJar.getAbsolutePath(), machine, destDir.getAbsolutePath());
+ assertFilesEqual(new File(destDir, origJar.getName()), origJar);
+ }
+
+ @Test(groups="Integration")
+ public void testDeployExplicitDestFile() throws Exception {
+ String destFile = "custom-destFile.jar";
+ ArchiveUtils.deploy(origJar.getAbsolutePath(), machine, destDir.getAbsolutePath(), destFile);
+ assertFilesEqual(new File(destDir, destFile), origJar);
+ }
+
+ private File newZip(Map<String, String> files) throws Exception {
+ File parentDir = Os.newTempDir(getClass().getSimpleName()+"-archive");
+ for (Map.Entry<String, String> entry : files.entrySet()) {
+ File subFile = new File(Os.mergePaths(parentDir.getAbsolutePath(), entry.getKey()));
+ subFile.getParentFile().mkdirs();
+ Files.write(entry.getValue(), subFile, Charsets.UTF_8);
+ }
+ return ArchiveBuilder.zip().addDirContentsAt(parentDir, ".").create();
+ }
+
+ private void assertFilesEqual(File f1, File f2) throws Exception {
+ byte[] bytes1 = Files.asByteSource(f1).read();
+ byte[] bytes2 = Files.asByteSource(f1).read();
+ assertEquals(bytes1, bytes2, "f1="+f1+"; f2="+f2);
+ }
+
+ private void assertSubFilesEqual(File parentDir, Map<String, String> files) throws Exception {
+ for (Map.Entry<String, String> entry : archiveContents.entrySet()) {
+ File subFile = new File(Os.mergePaths(parentDir.getAbsolutePath(), entry.getKey()));
+ assertEquals(Joiner.on("\n").join(Files.readLines(subFile, Charsets.UTF_8)), entry.getValue());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/flags/MethodCoercionsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/flags/MethodCoercionsTest.java b/core/src/test/java/org/apache/brooklyn/core/util/flags/MethodCoercionsTest.java
new file mode 100644
index 0000000..2d1efa3
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/flags/MethodCoercionsTest.java
@@ -0,0 +1,149 @@
+/*
+ * 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.util.flags;
+
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.guava.Maybe;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+
+import org.apache.brooklyn.core.util.flags.MethodCoercions;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class MethodCoercionsTest {
+
+ private Method singleParameterMethod;
+ private Method multiParameterMethod;
+ private Method singleCollectionParameterMethod;
+
+ @BeforeClass
+ public void testFixtureSetUp() {
+ try {
+ singleParameterMethod = TestClass.class.getMethod("singleParameterMethod", int.class);
+ multiParameterMethod = TestClass.class.getMethod("multiParameterMethod", boolean.class, int.class);
+ singleCollectionParameterMethod = TestClass.class.getMethod("singleCollectionParameterMethod", List.class);
+ } catch (NoSuchMethodException e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ @Test
+ public void testMatchSingleParameterMethod() throws Exception {
+ Predicate<Method> predicate = MethodCoercions.matchSingleParameterMethod("singleParameterMethod", "42");
+ assertTrue(predicate.apply(singleParameterMethod));
+ assertFalse(predicate.apply(multiParameterMethod));
+ assertFalse(predicate.apply(singleCollectionParameterMethod));
+ }
+
+ @Test
+ public void testTryFindAndInvokeSingleParameterMethod() throws Exception {
+ TestClass instance = new TestClass();
+ Maybe<?> maybe = MethodCoercions.tryFindAndInvokeSingleParameterMethod(instance, "singleParameterMethod", "42");
+ assertTrue(maybe.isPresent());
+ assertTrue(instance.wasSingleParameterMethodCalled());
+ }
+
+ @Test
+ public void testMatchMultiParameterMethod() throws Exception {
+ Predicate<Method> predicate = MethodCoercions.matchMultiParameterMethod("multiParameterMethod", ImmutableList.of("true", "42"));
+ assertFalse(predicate.apply(singleParameterMethod));
+ assertTrue(predicate.apply(multiParameterMethod));
+ assertFalse(predicate.apply(singleCollectionParameterMethod));
+ }
+
+ @Test
+ public void testTryFindAndInvokeMultiParameterMethod() throws Exception {
+ TestClass instance = new TestClass();
+ Maybe<?> maybe = MethodCoercions.tryFindAndInvokeMultiParameterMethod(instance, "multiParameterMethod", ImmutableList.of("true", "42"));
+ assertTrue(maybe.isPresent());
+ assertTrue(instance.wasMultiParameterMethodCalled());
+ }
+
+ @Test
+ public void testTryFindAndInvokeBestMatchingMethod() throws Exception {
+ TestClass instance = new TestClass();
+ Maybe<?> maybe = MethodCoercions.tryFindAndInvokeBestMatchingMethod(instance, "singleParameterMethod", "42");
+ assertTrue(maybe.isPresent());
+ assertTrue(instance.wasSingleParameterMethodCalled());
+
+ instance = new TestClass();
+ maybe = MethodCoercions.tryFindAndInvokeBestMatchingMethod(instance, "multiParameterMethod", ImmutableList.of("true", "42"));
+ assertTrue(maybe.isPresent());
+ assertTrue(instance.wasMultiParameterMethodCalled());
+
+ instance = new TestClass();
+ maybe = MethodCoercions.tryFindAndInvokeBestMatchingMethod(instance, "singleCollectionParameterMethod", ImmutableList.of("fred", "joe"));
+ assertTrue(maybe.isPresent());
+ assertTrue(instance.wasSingleCollectionParameterMethodCalled());
+ }
+/*
+ @Test
+ public void testMatchSingleCollectionParameterMethod() throws Exception {
+ Predicate<Method> predicate = MethodCoercions.matchSingleCollectionParameterMethod("singleCollectionParameterMethod", ImmutableList.of("42"));
+ assertFalse(predicate.apply(singleParameterMethod));
+ assertFalse(predicate.apply(multiParameterMethod));
+ assertTrue(predicate.apply(singleCollectionParameterMethod));
+ }
+
+ @Test
+ public void testTryFindAndInvokeSingleCollectionParameterMethod() throws Exception {
+ TestClass instance = new TestClass();
+ Maybe<?> maybe = MethodCoercions.tryFindAndInvokeSingleCollectionParameterMethod(instance, "singleCollectionParameterMethod", ImmutableList.of("42"));
+ assertTrue(maybe.isPresent());
+ assertTrue(instance.wasSingleCollectionParameterMethodCalled());
+ }
+*/
+ public static class TestClass {
+
+ private boolean singleParameterMethodCalled;
+ private boolean multiParameterMethodCalled;
+ private boolean singleCollectionParameterMethodCalled;
+
+ public void singleParameterMethod(int parameter) {
+ singleParameterMethodCalled = true;
+ }
+
+ public void multiParameterMethod(boolean parameter1, int parameter2) {
+ multiParameterMethodCalled = true;
+ }
+
+ public void singleCollectionParameterMethod(List<String> parameter) {
+ singleCollectionParameterMethodCalled = true;
+ }
+
+ public boolean wasSingleParameterMethodCalled() {
+ return singleParameterMethodCalled;
+ }
+
+ public boolean wasMultiParameterMethodCalled() {
+ return multiParameterMethodCalled;
+ }
+
+ public boolean wasSingleCollectionParameterMethodCalled() {
+ return singleCollectionParameterMethodCalled;
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/http/BetterMockWebServer.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/http/BetterMockWebServer.java b/core/src/test/java/org/apache/brooklyn/core/util/http/BetterMockWebServer.java
new file mode 100644
index 0000000..f02689b
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/http/BetterMockWebServer.java
@@ -0,0 +1,138 @@
+/*
+ * 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.util.http;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.Proxy;
+import java.net.URL;
+
+import javax.net.ssl.SSLSocketFactory;
+
+import com.google.common.base.Throwables;
+import com.google.mockwebserver.Dispatcher;
+import com.google.mockwebserver.MockResponse;
+import com.google.mockwebserver.MockWebServer;
+import com.google.mockwebserver.RecordedRequest;
+
+/** like MockWebServer (and delegating) but:
+ * <li> allows subclassing
+ * <li> easy way to create instance which returns localhost for {@link #getHostName()}
+ * (since otherwise you can get failures on networks which misconfigure hostname)
+ * */
+public class BetterMockWebServer {
+
+ final MockWebServer delegate = new MockWebServer();
+ String hostname = null;
+ boolean isHttps = false;
+
+ public static BetterMockWebServer newInstanceLocalhost() {
+ return new BetterMockWebServer().setHostName("localhost");
+ }
+
+ /** use {@link #newInstanceLocalhost()} or subclass */
+ protected BetterMockWebServer() {}
+
+ public BetterMockWebServer setHostName(String hostname) {
+ this.hostname = hostname;
+ return this;
+ }
+
+
+ // --- delegate methods (unchanged)
+
+ public void enqueue(MockResponse response) {
+ delegate.enqueue(response);
+ }
+
+ public boolean equals(Object obj) {
+ return delegate.equals(obj);
+ }
+
+ public String getCookieDomain() {
+ return delegate.getCookieDomain();
+ }
+
+ public String getHostName() {
+ if (hostname!=null) return hostname;
+ return delegate.getHostName();
+ }
+
+ public int getPort() {
+ return delegate.getPort();
+ }
+
+ public int getRequestCount() {
+ return delegate.getRequestCount();
+ }
+
+ public URL getUrl(String path) {
+ try {
+ return isHttps
+ ? new URL("https://" + getHostName() + ":" + getPort() + path)
+ : new URL("http://" + getHostName() + ":" + getPort() + path);
+ } catch (MalformedURLException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+
+ public int hashCode() {
+ return delegate.hashCode();
+ }
+
+ public void play() throws IOException {
+ delegate.play();
+ }
+
+ public void play(int port) throws IOException {
+ delegate.play(port);
+ }
+
+ public void setBodyLimit(int maxBodyLength) {
+ delegate.setBodyLimit(maxBodyLength);
+ }
+
+ public void setDispatcher(Dispatcher dispatcher) {
+ delegate.setDispatcher(dispatcher);
+ }
+
+ public void shutdown() throws IOException {
+ delegate.shutdown();
+ }
+
+ public RecordedRequest takeRequest() throws InterruptedException {
+ return delegate.takeRequest();
+ }
+
+ public Proxy toProxyAddress() {
+ return delegate.toProxyAddress();
+ }
+
+ public String toString() {
+ return delegate.toString();
+ }
+
+ public void useHttps(SSLSocketFactory sslSocketFactory, boolean tunnelProxy) {
+ isHttps = true;
+ delegate.useHttps(sslSocketFactory, tunnelProxy);
+ }
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/http/HttpToolIntegrationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/http/HttpToolIntegrationTest.java b/core/src/test/java/org/apache/brooklyn/core/util/http/HttpToolIntegrationTest.java
new file mode 100644
index 0000000..f557955
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/http/HttpToolIntegrationTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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.util.http;
+
+import static org.testng.Assert.assertTrue;
+
+import java.net.URI;
+
+import org.apache.http.client.HttpClient;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.apache.brooklyn.core.util.http.HttpTool;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
+import org.apache.brooklyn.location.basic.PortRanges;
+
+import brooklyn.test.HttpService;
+
+import com.google.common.collect.ImmutableMap;
+
+public class HttpToolIntegrationTest {
+
+ // TODO Expand test coverage for credentials etc
+
+ private HttpService httpService;
+ private HttpService httpsService;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ httpService = new HttpService(PortRanges.fromString("9000+"), false).start();
+ httpsService = new HttpService(PortRanges.fromString("9000+"), true).start();
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ if (httpService != null) httpService.shutdown();
+ if (httpsService != null) httpsService.shutdown();
+ }
+
+ @Test(groups = {"Integration"})
+ public void testHttpGet() throws Exception {
+ URI baseUri = new URI(httpService.getUrl());
+
+ HttpClient client = HttpTool.httpClientBuilder().build();
+ HttpToolResponse result = HttpTool.httpGet(client, baseUri, ImmutableMap.<String,String>of());
+ assertTrue(new String(result.getContent()).contains("Hello, World"), "val="+new String(result.getContent()));
+ }
+
+ @Test(groups = {"Integration"})
+ public void testHttpRedirect() throws Exception {
+ URI baseUri = new URI(httpService.getUrl() + "hello/redirectAbsolute");
+
+ HttpClient client = HttpTool.httpClientBuilder().laxRedirect(true).build();
+ HttpToolResponse result = HttpTool.httpGet(client, baseUri, ImmutableMap.<String,String>of());
+ assertTrue(new String(result.getContent()).contains("Hello, World"), "val="+new String(result.getContent()));
+ }
+
+ @Test(groups = {"Integration"})
+ public void testHttpPost() throws Exception {
+ URI baseUri = new URI(httpService.getUrl());
+
+ HttpClient client = HttpTool.httpClientBuilder().build();
+ HttpToolResponse result = HttpTool.httpPost(client, baseUri, ImmutableMap.<String,String>of(), new byte[0]);
+ assertTrue(new String(result.getContent()).contains("Hello, World"), "val="+new String(result.getContent()));
+ }
+
+ @Test(groups = {"Integration"})
+ public void testHttpsGetWithTrustAll() throws Exception {
+ URI baseUri = new URI(httpsService.getUrl());
+
+ HttpClient client = HttpTool.httpClientBuilder().https(true).trustAll().build();
+ HttpToolResponse result = HttpTool.httpGet(client, baseUri, ImmutableMap.<String,String>of());
+ assertTrue(new String(result.getContent()).contains("Hello, World"), "val="+new String(result.getContent()));
+ }
+
+ @Test(groups = {"Integration"})
+ public void testHttpsPostWithTrustSelfSigned() throws Exception {
+ URI baseUri = new URI(httpsService.getUrl());
+
+ HttpClient client = HttpTool.httpClientBuilder().https(true).trustSelfSigned().build();
+ HttpToolResponse result = HttpTool.httpPost(client, baseUri, ImmutableMap.<String,String>of(), new byte[0]);
+ assertTrue(new String(result.getContent()).contains("Hello, World"), "val="+new String(result.getContent()));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/internal/FlagUtilsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/internal/FlagUtilsTest.java b/core/src/test/java/org/apache/brooklyn/core/util/internal/FlagUtilsTest.java
new file mode 100644
index 0000000..02becf6
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/internal/FlagUtilsTest.java
@@ -0,0 +1,314 @@
+/*
+ * 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.util.internal;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.lang.reflect.Field;
+import java.net.InetAddress;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.brooklyn.api.entity.trait.Configurable;
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.FlagUtils;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.Test;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.config.ConfigKey.HasConfigKey;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.event.basic.BasicConfigKey;
+import brooklyn.util.collections.MutableMap;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+
+public class FlagUtilsTest {
+
+ public static final Logger log = LoggerFactory.getLogger(FlagUtilsTest.class);
+
+ @Test
+ public void testGetAllFields() {
+ log.info("types {}", FlagUtils.getAllAssignableTypes(Baz.class));
+ assertEquals(FlagUtils.getAllAssignableTypes(Baz.class), ImmutableList.of(Baz.class, Foo.class, Bar.class));
+ List<Field> fs = FlagUtils.getAllFields(Baz.class);
+ for (Field f : fs) {
+ log.info("field {} {}", f.getName(), f);
+ }
+ List<String> fsn = ImmutableList.copyOf(Iterables.transform(fs, new Function<Field, String>() {
+ @Override public String apply(Field f) {
+ return f.getName();
+ }}));
+ assertTrue(fsn.indexOf("A") >= 0);
+ assertTrue(fsn.indexOf("w") > fsn.indexOf("A"));
+ assertTrue(fsn.indexOf("x") > fsn.indexOf("A") );
+ assertTrue(fsn.indexOf("yNotY") > fsn.indexOf("A"));
+ assertTrue(fsn.indexOf("Z") > fsn.indexOf("yNotY") );
+ }
+
+ @Test
+ public void testSetFieldsFromFlags() {
+ Foo f = new Foo();
+ Map<?,?> m = MutableMap.of("w", 3, "x", 1, "y", 7, "z", 9);
+ Map<?, ?> unused = FlagUtils.setFieldsFromFlags(m, f);
+ assertEquals(f.w, 3);
+ assertEquals(f.x, 1);
+ assertEquals(f.yNotY, 7);
+ assertEquals(unused, ImmutableMap.of("z", 9));
+ Map<?,?> m2 = FlagUtils.getFieldsWithValues(f);
+ m.remove("z");
+ assertEquals(m2, m);
+ }
+
+ @Test
+ public void testCollectionCoercionOnSetFromFlags() {
+ WithSpecialFieldTypes s = new WithSpecialFieldTypes();
+ Map<?,?> m = ImmutableMap.of("set", ImmutableSet.of(1));
+ FlagUtils.setFieldsFromFlags(m, s);
+ assertEquals(s.set, ImmutableSet.of(1));
+ }
+
+ @Test
+ public void testInetAddressCoercionOnSetFromFlags() {
+ WithSpecialFieldTypes s = new WithSpecialFieldTypes();
+ Map<?,?> m = ImmutableMap.of("inet", "127.0.0.1");
+ FlagUtils.setFieldsFromFlags(m, s);
+ assertEquals(s.inet.getHostAddress(), "127.0.0.1");
+ }
+
+ @Test
+ public void testNonImmutableField() {
+ Foo f = new Foo();
+ FlagUtils.setFieldsFromFlags(ImmutableMap.of("w", 8), f);
+ assertEquals(f.w, 8);
+ FlagUtils.setFieldsFromFlags(ImmutableMap.of("w", 9), f);
+ assertEquals(f.w, 9);
+ }
+
+ @Test
+ public void testImmutableIntField() {
+ Foo f = new Foo();
+ FlagUtils.setFieldsFromFlags(ImmutableMap.of("x", 8), f);
+ assertEquals(f.x, 8);
+ boolean succeededWhenShouldntHave = false;
+ try {
+ FlagUtils.setFieldsFromFlags(ImmutableMap.of("x", 9), f);
+ succeededWhenShouldntHave = true;
+ } catch (IllegalStateException e) {
+ //expected
+ }
+ assertFalse(succeededWhenShouldntHave);
+ assertEquals(f.x, 8);
+ }
+
+ @Test
+ public void testImmutableObjectField() {
+ WithImmutableNonNullableObject o = new WithImmutableNonNullableObject();
+ FlagUtils.setFieldsFromFlags(ImmutableMap.of("a", "a", "b", "b"), o);
+ assertEquals(o.a, "a");
+ assertEquals(o.b, "b");
+
+ FlagUtils.setFieldsFromFlags(ImmutableMap.of("a", "a2"), o);
+ assertEquals(o.a, "a2");
+
+ boolean succeededWhenShouldntHave = false;
+ try {
+ FlagUtils.setFieldsFromFlags(ImmutableMap.of("b", "b2"), o);
+ succeededWhenShouldntHave = true;
+ } catch (IllegalStateException e) {
+ //expected
+ }
+ assertFalse(succeededWhenShouldntHave);
+ assertEquals(o.b, "b");
+ }
+
+ @Test
+ public void testNonNullable() {
+ WithImmutableNonNullableObject o = new WithImmutableNonNullableObject();
+ //allowed
+ FlagUtils.setFieldsFromFlags(MutableMap.of("a", null), o);
+ assertEquals(o.a, null);
+ assertEquals(o.b, null);
+ //not allowed
+ boolean succeededWhenShouldntHave = false;
+ try {
+ FlagUtils.setFieldsFromFlags(MutableMap.of("b", null), o);
+ succeededWhenShouldntHave = true;
+ } catch (IllegalArgumentException e) {
+ //expected
+ }
+ assertFalse(succeededWhenShouldntHave);
+ assertEquals(o.b, null);
+ }
+
+ @Test
+ public void testGetAnnotatedFields() throws Exception {
+ Map<Field, SetFromFlag> fm = FlagUtils.getAnnotatedFields(WithImmutableNonNullableObject.class);
+ assertEquals(fm.keySet().size(), 2);
+ assertTrue(fm.get(WithImmutableNonNullableObject.class.getDeclaredField("b")).immutable());
+ }
+
+ @Test
+ public void testCheckRequired() {
+ WithImmutableNonNullableObject f = new WithImmutableNonNullableObject();
+ FlagUtils.setFieldsFromFlags(ImmutableMap.of("a", "a is a"), f);
+ assertEquals(f.a, "a is a");
+ assertEquals(f.b, null);
+ int exceptions = 0;
+ try {
+ FlagUtils.checkRequiredFields(f);
+ } catch (IllegalStateException e) {
+ exceptions++;
+ }
+ assertEquals(exceptions, 1);
+ }
+
+ @Test
+ public void testSetConfigKeys() {
+ FooCK f = new FooCK();
+ Map<?,?> unused = FlagUtils.setFieldsFromFlags(ImmutableMap.of("f1", 9, "ck1", "do-set", "ck2", "dont-set", "c3", "do-set"), f);
+ assertEquals(f.bag.get(FooCK.CK1), "do-set");
+ assertEquals(f.bag.get(FooCK.CK3), "do-set");
+ assertEquals(f.f1, 9);
+ assertEquals(f.bag.containsKey(FooCK.CK2), false);
+ assertEquals(unused, ImmutableMap.of("ck2", "dont-set"));
+ }
+
+ @Test
+ public void testSetAllConfigKeys() {
+ FooCK f = new FooCK();
+ Map<?,?> unused = FlagUtils.setAllConfigKeys(ImmutableMap.of("f1", 9, "ck1", "do-set", "ck2", "do-set-2", "c3", "do-set"), f, true);
+ assertEquals(f.bag.get(FooCK.CK1), "do-set");
+ assertEquals(f.bag.get(FooCK.CK3), "do-set");
+ assertEquals(f.bag.containsKey(FooCK.CK2), true);
+ assertEquals(f.bag.get(FooCK.CK2), "do-set-2");
+ assertEquals(unused, ImmutableMap.of("f1", 9));
+ }
+
+ @Test
+ public void testSetFromConfigKeys() {
+ FooCK f = new FooCK();
+ Map<?, ?> unused = FlagUtils.setFieldsFromFlags(ImmutableMap.of(new BasicConfigKey<Integer>(Integer.class, "f1"), 9, "ck1", "do-set", "ck2", "dont-set"), f);
+ assertEquals(f.bag.get(FooCK.CK1), "do-set");
+ assertEquals(f.f1, 9);
+ assertEquals(f.bag.containsKey(FooCK.CK2), false);
+ assertEquals(unused, ImmutableMap.of("ck2", "dont-set"));
+ }
+
+ public static class Foo {
+ @SetFromFlag
+ int w;
+
+ @SetFromFlag(immutable=true)
+ private int x;
+
+ @SetFromFlag("y")
+ public int yNotY;
+ }
+
+ public static interface Bar {
+ static final String Z = "myzval";
+ }
+
+ public static class Baz extends Foo implements Bar {
+ @SuppressWarnings("unused") //inspected by reflection
+ private static int A;
+ }
+
+ public static class WithImmutableNonNullableObject {
+ @SetFromFlag
+ Object a;
+ @SetFromFlag(immutable=true, nullable=false)
+ public Object b;
+ }
+
+ public static class WithSpecialFieldTypes {
+ @SetFromFlag Set<?> set;
+ @SetFromFlag InetAddress inet;
+ }
+
+ public static class FooCK implements Configurable {
+ @SetFromFlag
+ public static ConfigKey<String> CK1 = ConfigKeys.newStringConfigKey("ck1");
+
+ public static ConfigKey<String> CK2 = ConfigKeys.newStringConfigKey("ck2");
+
+ @SetFromFlag("c3")
+ public static ConfigKey<String> CK3 = ConfigKeys.newStringConfigKey("ck3");
+
+ @SetFromFlag
+ int f1;
+
+ ConfigBag bag = new ConfigBag();
+ BasicConfigurationSupport configSupport = new BasicConfigurationSupport();
+
+ @Override
+ public ConfigurationSupport config() {
+ return configSupport;
+ }
+
+ public <T> T setConfig(ConfigKey<T> key, T val) {
+ return config().set(key, val);
+ }
+
+ private class BasicConfigurationSupport implements ConfigurationSupport {
+ @Override
+ public <T> T get(ConfigKey<T> key) {
+ return bag.get(key);
+ }
+
+ @Override
+ public <T> T get(HasConfigKey<T> key) {
+ return get(key.getConfigKey());
+ }
+
+ @Override
+ public <T> T set(ConfigKey<T> key, T val) {
+ T old = bag.get(key);
+ bag.configure(key, val);
+ return old;
+ }
+
+ @Override
+ public <T> T set(HasConfigKey<T> key, T val) {
+ return set(key.getConfigKey(), val);
+ }
+
+ @Override
+ public <T> T set(ConfigKey<T> key, Task<T> val) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public <T> T set(HasConfigKey<T> key, Task<T> val) {
+ return set(key.getConfigKey(), val);
+ }
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/internal/RepeaterTest.groovy
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/internal/RepeaterTest.groovy b/core/src/test/java/org/apache/brooklyn/core/util/internal/RepeaterTest.groovy
new file mode 100644
index 0000000..08ef0da
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/internal/RepeaterTest.groovy
@@ -0,0 +1,257 @@
+/*
+ * 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.util.internal
+
+import static java.util.concurrent.TimeUnit.*
+import static org.testng.Assert.*
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit
+
+import org.apache.brooklyn.core.util.internal.Repeater;
+import org.testng.annotations.Test
+
+import brooklyn.util.internal.TimeExtras;
+import brooklyn.util.time.Duration;
+
+import com.google.common.base.Stopwatch
+
+public class RepeaterTest {
+ static { TimeExtras.init() }
+
+ @Test
+ public void sanityTest() {
+ new Repeater("Sanity test")
+ .repeat()
+ .until { true }
+ .every(10 * MILLISECONDS);
+ }
+
+ @Test
+ public void sanityTestDescription() {
+ new Repeater()
+ .repeat()
+ .until { true }
+ .every(10 * MILLISECONDS);
+ }
+
+ @Test
+ public void sanityTestBuilder() {
+ Repeater.create("Sanity test")
+ .repeat()
+ .until { true }
+ .every(10 * MILLISECONDS);
+ }
+
+ @Test
+ public void sanityTestBuilderDescription() {
+ Repeater.create()
+ .repeat()
+ .until { true }
+ .every(10 * MILLISECONDS);
+ }
+
+ @Test(expectedExceptions = [ NullPointerException.class ])
+ public void repeatFailsIfClosureIsNull() {
+ new Repeater("repeatFailsIfClosureIsNull").repeat((Callable<?>)null);
+ fail "Expected exception was not thrown"
+ }
+
+ @Test
+ public void repeatSucceedsIfClosureIsNonNull() {
+ new Repeater("repeatSucceedsIfClosureIsNonNull").repeat { true };
+ }
+
+ @Test(expectedExceptions = [ NullPointerException.class ])
+ public void untilFailsIfClosureIsNull() {
+ new Repeater("untilFailsIfClosureIsNull").until(null);
+ fail "Expected exception was not thrown"
+ }
+
+ @Test
+ public void untilSucceedsIfClosureIsNonNull() {
+ new Repeater("untilSucceedsIfClosureIsNonNull").until { true };
+ }
+
+ @Test(expectedExceptions = [ IllegalArgumentException.class ])
+ public void everyFailsIfPeriodIsZero() {
+ new Repeater("everyFailsIfPeriodIsZero").every(0 * MILLISECONDS);
+ fail "Expected exception was not thrown"
+ }
+
+ @Test(expectedExceptions = [ IllegalArgumentException.class ])
+ public void everyFailsIfPeriodIsNegative() {
+ new Repeater("everyFailsIfPeriodIsNegative").every(-1 * MILLISECONDS);
+ fail "Expected exception was not thrown"
+ }
+
+ @Test(expectedExceptions = [ NullPointerException.class ])
+ public void everyFailsIfUnitsIsNull() {
+ new Repeater("everyFailsIfUnitsIsNull").every(10, null);
+ fail "Expected exception was not thrown"
+ }
+
+ @Test
+ public void everySucceedsIfPeriodIsPositiveAndUnitsIsNonNull() {
+ new Repeater("repeatSucceedsIfClosureIsNonNull").every(10 * MILLISECONDS);
+ }
+
+ @Test(expectedExceptions = [ IllegalArgumentException.class ])
+ public void limitTimeToFailsIfPeriodIsZero() {
+ new Repeater("limitTimeToFailsIfPeriodIsZero").limitTimeTo(0, TimeUnit.MILLISECONDS);
+ fail "Expected exception was not thrown"
+ }
+
+ @Test(expectedExceptions = [ IllegalArgumentException.class ])
+ public void limitTimeToFailsIfPeriodIsNegative() {
+ new Repeater("limitTimeToFailsIfPeriodIsNegative").limitTimeTo(-1, TimeUnit.MILLISECONDS);
+ fail "Expected exception was not thrown"
+ }
+
+ @Test(expectedExceptions = [ NullPointerException.class ])
+ public void limitTimeToFailsIfUnitsIsNull() {
+ new Repeater("limitTimeToFailsIfUnitsIsNull").limitTimeTo(10, null);
+ fail "Expected exception was not thrown"
+ }
+
+ @Test
+ public void limitTimeToSucceedsIfPeriodIsPositiveAndUnitsIsNonNull() {
+ new Repeater("limitTimeToSucceedsIfClosureIsNonNull").limitTimeTo(10, TimeUnit.MILLISECONDS);
+ }
+
+ @Test
+ public void everyAcceptsDuration() {
+ new Repeater("everyAcceptsDuration").every(Duration.ONE_SECOND);
+ }
+
+ @Test
+ public void everyAcceptsLong() {
+ new Repeater("everyAcceptsLong").every(1000L);
+ }
+
+ @Test
+ public void everyAcceptsTimeUnit() {
+ new Repeater("everyAcceptsTimeUnit").every(1000000L, TimeUnit.MICROSECONDS);
+ }
+
+ @Test
+ public void runReturnsTrueIfExitConditionIsTrue() {
+ assertTrue new Repeater("runReturnsTrueIfExitConditionIsTrue")
+ .repeat()
+ .every(1 * MILLISECONDS)
+ .until { true }
+ .run();
+ }
+
+ @Test
+ public void runRespectsMaximumIterationLimitAndReturnsFalseIfReached() {
+ int iterations = 0;
+ assertFalse new Repeater("runRespectsMaximumIterationLimitAndReturnsFalseIfReached")
+ .repeat { iterations++ }
+ .every(1 * MILLISECONDS)
+ .until { false }
+ .limitIterationsTo(5)
+ .run();
+ assertEquals 5, iterations;
+ }
+
+ /**
+ * Check that the {@link Repeater} will stop after a time limit.
+ *
+ * The repeater is configured to run every 100ms and never stop until the limit is reached.
+ * This is given as {@link Repeater#limitTimeTo(groovy.time.Duration)} and the execution time
+ * is then checked to ensure it is between 100% and 400% of the specified value. Due to scheduling
+ * delays and other factors in a non RTOS system it is expected that the repeater will take much
+ * longer to exit occasionally.
+ *
+ * @see #runRespectsMaximumIterationLimitAndReturnsFalseIfReached()
+ */
+ @Test(groups="Integration")
+ public void runRespectsTimeLimitAndReturnsFalseIfReached() {
+ final long LIMIT = 2000l;
+ Repeater repeater = new Repeater("runRespectsTimeLimitAndReturnsFalseIfReached")
+ .repeat()
+ .every(100 * MILLISECONDS)
+ .until { false }
+ .limitTimeTo(LIMIT, TimeUnit.MILLISECONDS);
+
+ Stopwatch stopwatch = new Stopwatch().start();
+ boolean result = repeater.run();
+ stopwatch.stop();
+
+ assertFalse result;
+
+ long difference = stopwatch.elapsed(TimeUnit.MILLISECONDS);
+ assertTrue(difference >= LIMIT, "Difference was: " + difference);
+ assertTrue(difference < 4 * LIMIT, "Difference was: " + difference);
+ }
+
+ @Test(expectedExceptions = [ IllegalStateException.class ])
+ public void runFailsIfUntilWasNotSet() {
+ new Repeater("runFailsIfUntilWasNotSet")
+ .repeat()
+ .every(10 * MILLISECONDS)
+ .run();
+ fail "Expected exception was not thrown"
+ }
+
+ @Test(expectedExceptions = [ IllegalStateException.class ])
+ public void runFailsIfEveryWasNotSet() {
+ new Repeater("runFailsIfEveryWasNotSet")
+ .repeat()
+ .until { true }
+ .run();
+ fail "Expected exception was not thrown"
+ }
+
+ @Test(expectedExceptions = [ UnsupportedOperationException.class ])
+ public void testRethrowsException() {
+ boolean result = new Repeater("throwRuntimeException")
+ .repeat()
+ .every(10 * MILLISECONDS)
+ .until { throw new UnsupportedOperationException("fail") }
+ .rethrowException()
+ .limitIterationsTo(2)
+ .run();
+ fail "Expected exception was not thrown"
+ }
+
+ @Test
+ public void testNoRethrowsException() {
+ try {
+ boolean result = new Repeater("throwRuntimeException")
+ .repeat()
+ .every(10 * MILLISECONDS)
+ .until { throw new UnsupportedOperationException("fail") }
+ .limitIterationsTo(2)
+ .run();
+ assertFalse result
+ } catch (RuntimeException re) {
+ fail "Exception should not have been thrown: " + re.getMessage()
+ }
+ }
+
+ public void testFlags() {
+ int count=0;
+ new Repeater(period: 5*MILLISECONDS, timeout: 100*MILLISECONDS).repeat({ count++ }).until({ count>100}).run();
+ assertTrue count>10
+ assertTrue count<30
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/internal/TypeCoercionsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/internal/TypeCoercionsTest.java b/core/src/test/java/org/apache/brooklyn/core/util/internal/TypeCoercionsTest.java
new file mode 100644
index 0000000..f1bb3f9
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/internal/TypeCoercionsTest.java
@@ -0,0 +1,360 @@
+/*
+ * 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.util.internal;
+
+import static org.testng.Assert.assertEquals;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.brooklyn.core.util.flags.ClassCoercionException;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
+import org.codehaus.groovy.runtime.GStringImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.basic.Lifecycle;
+import brooklyn.util.collections.MutableSet;
+import brooklyn.util.text.StringPredicates;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.reflect.TypeToken;
+
+public class TypeCoercionsTest {
+
+ private static final Logger log = LoggerFactory.getLogger(TypeCoercionsTest.class);
+
+ @Test
+ public void testCoerceCharSequenceToString() {
+ assertEquals(TypeCoercions.coerce(new StringBuilder("abc"), String.class), "abc");
+ assertEquals(TypeCoercions.coerce(new GStringImpl(new Object[0], new String[0]), String.class), "");
+ }
+
+ @Test
+ public void testCoerceStringToPrimitive() {
+ assertEquals(TypeCoercions.coerce("1", Character.class), (Character)'1');
+ assertEquals(TypeCoercions.coerce(" ", Character.class), (Character)' ');
+ assertEquals(TypeCoercions.coerce("1", Short.class), (Short)((short)1));
+ assertEquals(TypeCoercions.coerce("1", Integer.class), (Integer)1);
+ assertEquals(TypeCoercions.coerce("1", Long.class), (Long)1l);
+ assertEquals(TypeCoercions.coerce("1", Float.class), (Float)1f);
+ assertEquals(TypeCoercions.coerce("1", Double.class), (Double)1d);
+ assertEquals(TypeCoercions.coerce("true", Boolean.class), (Boolean)true);
+ assertEquals(TypeCoercions.coerce("False", Boolean.class), (Boolean)false);
+ assertEquals(TypeCoercions.coerce("true ", Boolean.class), (Boolean)true);
+
+ assertEquals(TypeCoercions.coerce("1", char.class), (Character)'1');
+ assertEquals(TypeCoercions.coerce("1", short.class), (Short)((short)1));
+ assertEquals(TypeCoercions.coerce("1", int.class), (Integer)1);
+ assertEquals(TypeCoercions.coerce("1", long.class), (Long)1l);
+ assertEquals(TypeCoercions.coerce("1", float.class), (Float)1f);
+ assertEquals(TypeCoercions.coerce("1", double.class), (Double)1d);
+ assertEquals(TypeCoercions.coerce("TRUE", boolean.class), (Boolean)true);
+ assertEquals(TypeCoercions.coerce("false", boolean.class), (Boolean)false);
+ }
+
+ @Test
+ public void testCoercePrimitivesToSameType() {
+ assertEquals(TypeCoercions.coerce('1', Character.class), (Character)'1');
+ assertEquals(TypeCoercions.coerce((short)1, Short.class), (Short)((short)1));
+ assertEquals(TypeCoercions.coerce(1, Integer.class), (Integer)1);
+ assertEquals(TypeCoercions.coerce(1l, Long.class), (Long)1l);
+ assertEquals(TypeCoercions.coerce(1f, Float.class), (Float)1f);
+ assertEquals(TypeCoercions.coerce(1d, Double.class), (Double)1d);
+ assertEquals(TypeCoercions.coerce(true, Boolean.class), (Boolean)true);
+ }
+
+ @Test
+ public void testCastPrimitives() {
+ assertEquals(TypeCoercions.coerce(1L, Character.class), (Character)(char)1);
+ assertEquals(TypeCoercions.coerce(1L, Byte.class), (Byte)(byte)1);
+ assertEquals(TypeCoercions.coerce(1L, Short.class), (Short)(short)1);
+ assertEquals(TypeCoercions.coerce(1L, Integer.class), (Integer)1);
+ assertEquals(TypeCoercions.coerce(1L, Long.class), (Long)(long)1);
+ assertEquals(TypeCoercions.coerce(1L, Float.class), (Float)(float)1);
+ assertEquals(TypeCoercions.coerce(1L, Double.class), (Double)(double)1);
+
+ assertEquals(TypeCoercions.coerce(1L, char.class), (Character)(char)1);
+ assertEquals(TypeCoercions.coerce(1L, byte.class), (Byte)(byte)1);
+ assertEquals(TypeCoercions.coerce(1L, short.class), (Short)(short)1);
+ assertEquals(TypeCoercions.coerce(1L, int.class), (Integer)1);
+ assertEquals(TypeCoercions.coerce(1L, long.class), (Long)(long)1);
+ assertEquals(TypeCoercions.coerce(1L, float.class), (Float)(float)1);
+ assertEquals(TypeCoercions.coerce(1L, double.class), (Double)(double)1);
+
+ assertEquals(TypeCoercions.coerce((char)1, Integer.class), (Integer)1);
+ assertEquals(TypeCoercions.coerce((byte)1, Integer.class), (Integer)1);
+ assertEquals(TypeCoercions.coerce((short)1, Integer.class), (Integer)1);
+ assertEquals(TypeCoercions.coerce((int)1, Integer.class), (Integer)1);
+ assertEquals(TypeCoercions.coerce((long)1, Integer.class), (Integer)1);
+ assertEquals(TypeCoercions.coerce((float)1, Integer.class), (Integer)1);
+ assertEquals(TypeCoercions.coerce((double)1, Integer.class), (Integer)1);
+ }
+
+ @Test
+ public void testCoercePrimitiveFailures() {
+ // error messages don't have to be this exactly, but they should include sufficient information...
+ assertCoercionFailsWithErrorMatching("maybe", boolean.class, StringPredicates.containsAllLiterals("String", "boolean", "maybe"));
+ assertCoercionFailsWithErrorMatching("NaN", int.class, StringPredicates.containsAllLiterals("int", "NaN"));
+ assertCoercionFailsWithErrorMatching('c', boolean.class, StringPredicates.containsAllLiterals("boolean", "(c)")); // will say 'string' rather than 'char'
+ assertCoercionFailsWithErrorMatching(0, boolean.class, StringPredicates.containsAllLiterals("Integer", "boolean", "0"));
+ }
+
+ protected void assertCoercionFailsWithErrorMatching(Object input, Class<?> type, Predicate<? super String> errorMessageRequirement) {
+ try {
+ Object result = TypeCoercions.coerce(input, type);
+ Assert.fail("Should have failed type coercion of "+input+" to "+type+", instead got: "+result);
+ } catch (Exception e) {
+ if (errorMessageRequirement==null || errorMessageRequirement.apply(e.toString()))
+ log.info("Primitive coercion failed as expected, with: "+e);
+ else
+ Assert.fail("Error from type coercion of "+input+" to "+type+" failed with wrong exception; expected match of "+errorMessageRequirement+" but got: "+e);
+ }
+
+ }
+
+ @Test
+ public void testCastToNumericPrimitives() {
+ assertEquals(TypeCoercions.coerce(BigInteger.ONE, Integer.class), (Integer)1);
+ assertEquals(TypeCoercions.coerce(BigInteger.ONE, int.class), (Integer)1);
+ assertEquals(TypeCoercions.coerce(BigInteger.valueOf(Long.MAX_VALUE), Long.class), (Long)Long.MAX_VALUE);
+ assertEquals(TypeCoercions.coerce(BigInteger.valueOf(Long.MAX_VALUE), long.class), (Long)Long.MAX_VALUE);
+
+ assertEquals(TypeCoercions.coerce(BigDecimal.valueOf(0.5), Double.class), 0.5d, 0.00001d);
+ assertEquals(TypeCoercions.coerce(BigDecimal.valueOf(0.5), double.class), 0.5d, 0.00001d);
+ }
+
+ @Test
+ public void testCoerceStringToBigNumber() {
+ assertEquals(TypeCoercions.coerce("0.5", BigDecimal.class), BigDecimal.valueOf(0.5));
+ assertEquals(TypeCoercions.coerce("1", BigInteger.class), BigInteger.valueOf(1));
+ }
+
+ @Test
+ public void testCoerceStringToEnum() {
+ assertEquals(TypeCoercions.coerce("STARTING", Lifecycle.class), Lifecycle.STARTING);
+ assertEquals(TypeCoercions.coerce("Starting", Lifecycle.class), Lifecycle.STARTING);
+ assertEquals(TypeCoercions.coerce("starting", Lifecycle.class), Lifecycle.STARTING);
+
+ assertEquals(TypeCoercions.coerce("LOWERCASE", PerverseEnum.class), PerverseEnum.lowercase);
+ assertEquals(TypeCoercions.coerce("CAMELCASE", PerverseEnum.class), PerverseEnum.camelCase);
+ assertEquals(TypeCoercions.coerce("upper", PerverseEnum.class), PerverseEnum.UPPER);
+ assertEquals(TypeCoercions.coerce("upper_with_underscore", PerverseEnum.class), PerverseEnum.UPPER_WITH_UNDERSCORE);
+ assertEquals(TypeCoercions.coerce("LOWER_WITH_UNDERSCORE", PerverseEnum.class), PerverseEnum.lower_with_underscore);
+ }
+ public static enum PerverseEnum {
+ lowercase,
+ camelCase,
+ UPPER,
+ UPPER_WITH_UNDERSCORE,
+ lower_with_underscore;
+ }
+
+ @Test(expectedExceptions = ClassCoercionException.class)
+ public void testCoerceStringToEnumFailure() {
+ TypeCoercions.coerce("scrambled-eggs", Lifecycle.class);
+ }
+
+ @Test
+ public void testListToSetCoercion() {
+ Set<?> s = TypeCoercions.coerce(ImmutableList.of(1), Set.class);
+ Assert.assertEquals(s, ImmutableSet.of(1));
+ }
+
+ @Test
+ public void testSetToListCoercion() {
+ List<?> s = TypeCoercions.coerce(ImmutableSet.of(1), List.class);
+ Assert.assertEquals(s, ImmutableList.of(1));
+ }
+
+ @Test
+ public void testIterableToArrayCoercion() {
+ String[] s = TypeCoercions.coerce(ImmutableList.of("a", "b"), String[].class);
+ Assert.assertTrue(Arrays.equals(s, new String[] {"a", "b"}), "result="+Arrays.toString(s));
+
+ Integer[] i = TypeCoercions.coerce(ImmutableList.of(1, 2), Integer[].class);
+ Assert.assertTrue(Arrays.equals(i, new Integer[] {1, 2}), "result="+Arrays.toString(i));
+
+ int[] i2 = TypeCoercions.coerce(ImmutableList.of(1, 2), int[].class);
+ Assert.assertTrue(Arrays.equals(i2, new int[] {1, 2}), "result="+Arrays.toString(i2));
+
+ int[] i3 = TypeCoercions.coerce(MutableSet.of("1", 2), int[].class);
+ Assert.assertTrue(Arrays.equals(i3, new int[] {1, 2}), "result="+Arrays.toString(i3));
+ }
+
+ @Test
+ public void testListEntryCoercion() {
+ List<?> s = TypeCoercions.coerce(ImmutableList.of("java.lang.Integer", "java.lang.Double"), new TypeToken<List<Class<?>>>() { });
+ Assert.assertEquals(s, ImmutableList.of(Integer.class, Double.class));
+ }
+
+ @Test
+ public void testListEntryToSetCoercion() {
+ Set<?> s = TypeCoercions.coerce(ImmutableList.of("java.lang.Integer", "java.lang.Double"), new TypeToken<Set<Class<?>>>() { });
+ Assert.assertEquals(s, ImmutableSet.of(Integer.class, Double.class));
+ }
+
+ @Test
+ public void testListEntryToCollectionCoercion() {
+ Collection<?> s = TypeCoercions.coerce(ImmutableList.of("java.lang.Integer", "java.lang.Double"), new TypeToken<Collection<Class<?>>>() { });
+ Assert.assertEquals(s, ImmutableList.of(Integer.class, Double.class));
+ }
+
+ @Test
+ public void testMapValueCoercion() {
+ Map<?,?> s = TypeCoercions.coerce(ImmutableMap.of("int", "java.lang.Integer", "double", "java.lang.Double"), new TypeToken<Map<String, Class<?>>>() { });
+ Assert.assertEquals(s, ImmutableMap.of("int", Integer.class, "double", Double.class));
+ }
+
+ @Test
+ public void testMapKeyCoercion() {
+ Map<?,?> s = TypeCoercions.coerce(ImmutableMap.of("java.lang.Integer", "int", "java.lang.Double", "double"), new TypeToken<Map<Class<?>, String>>() { });
+ Assert.assertEquals(s, ImmutableMap.of(Integer.class, "int", Double.class, "double"));
+ }
+
+ @Test
+ public void testStringToListCoercion() {
+ List<?> s = TypeCoercions.coerce("a,b,c", List.class);
+ Assert.assertEquals(s, ImmutableList.of("a", "b", "c"));
+ }
+
+ @Test
+ @SuppressWarnings("serial")
+ public void testCoerceRecursivelyStringToGenericsCollection() {
+ assertEquals(TypeCoercions.coerce("1,2", new TypeToken<List<Integer>>() {}), ImmutableList.of(1, 2));
+ }
+
+ @Test
+ public void testJsonStringToMapCoercion() {
+ Map<?,?> s = TypeCoercions.coerce("{ \"a\" : \"1\", b : 2 }", Map.class);
+ Assert.assertEquals(s, ImmutableMap.of("a", "1", "b", 2));
+ }
+
+ @Test
+ public void testJsonStringWithoutQuotesToMapCoercion() {
+ Map<?,?> s = TypeCoercions.coerce("{ a : 1 }", Map.class);
+ Assert.assertEquals(s, ImmutableMap.of("a", 1));
+ }
+
+ @Test
+ public void testJsonComplexTypesToMapCoercion() {
+ Map<?,?> s = TypeCoercions.coerce("{ a : [1, \"2\", '\"3\"'], b: { c: d, 'e': \"f\" } }", Map.class);
+ Assert.assertEquals(s, ImmutableMap.of("a", ImmutableList.<Object>of(1, "2", "\"3\""),
+ "b", ImmutableMap.of("c", "d", "e", "f")));
+ }
+
+ @Test
+ public void testJsonStringWithoutBracesToMapCoercion() {
+ Map<?,?> s = TypeCoercions.coerce("a : 1", Map.class);
+ Assert.assertEquals(s, ImmutableMap.of("a", 1));
+ }
+
+ @Test
+ public void testJsonStringWithoutBracesWithMultipleToMapCoercion() {
+ Map<?,?> s = TypeCoercions.coerce("a : 1, b : 2", Map.class);
+ Assert.assertEquals(s, ImmutableMap.of("a", 1, "b", 2));
+ }
+
+ @Test
+ public void testKeyEqualsValueStringToMapCoercion() {
+ Map<?,?> s = TypeCoercions.coerce("a=1,b=2", Map.class);
+ Assert.assertEquals(s, ImmutableMap.of("a", "1", "b", "2"));
+ }
+
+ @Test(expectedExceptions=IllegalArgumentException.class)
+ public void testJsonStringWithoutBracesOrSpaceDisallowedAsMapCoercion() {
+ // yaml requires spaces after the colon
+ Map<?,?> s = TypeCoercions.coerce("a:1,b:2", Map.class);
+ Assert.assertEquals(s, ImmutableMap.of("a", 1, "b", 2));
+ }
+
+ @Test
+ public void testEqualsInBracesMapCoercion() {
+ Map<?,?> s = TypeCoercions.coerce("{ a = 1, b = '2' }", Map.class);
+ Assert.assertEquals(s, ImmutableMap.of("a", 1, "b", "2"));
+ }
+
+ @Test
+ public void testKeyEqualsOrColonValueWithBracesStringToMapCoercion() {
+ Map<?,?> s = TypeCoercions.coerce("{ a=1, b: 2 }", Map.class);
+ Assert.assertEquals(s, ImmutableMap.of("a", "1", "b", 2));
+ }
+
+ @Test
+ public void testKeyEqualsOrColonValueWithoutBracesStringToMapCoercion() {
+ Map<?,?> s = TypeCoercions.coerce("a=1, b: 2", Map.class);
+ Assert.assertEquals(s, ImmutableMap.of("a", "1", "b", 2));
+ }
+
+ @Test
+ public void testAs() {
+ Integer x = TypeCoercions.coerce(new WithAs("3"), Integer.class);
+ Assert.assertEquals(x, (Integer)3);
+ }
+
+ @Test
+ public void testFrom() {
+ WithFrom x = TypeCoercions.coerce("3", WithFrom.class);
+ Assert.assertEquals(x.value, 3);
+ }
+
+ @Test
+ public void testCoerceStringToNumber() {
+ assertEquals(TypeCoercions.coerce("1", Number.class), (Number) Double.valueOf(1));
+ assertEquals(TypeCoercions.coerce("1.0", Number.class), (Number) Double.valueOf(1.0));
+ }
+
+ @Test(expectedExceptions = ClassCoercionException.class)
+ public void testInvalidCoercionThrowsClassCoercionException() {
+ TypeCoercions.coerce(new Object(), TypeToken.of(Integer.class));
+ }
+
+ @Test
+ public void testCoercionFunction() {
+ assertEquals(TypeCoercions.function(Double.class).apply("1"), Double.valueOf(1));
+ }
+
+ public static class WithAs {
+ String value;
+ public WithAs(Object x) { value = ""+x; }
+ public Integer asInteger() {
+ return Integer.parseInt(value);
+ }
+ }
+
+ public static class WithFrom {
+ int value;
+ public static WithFrom fromString(String s) {
+ WithFrom result = new WithFrom();
+ result.value = Integer.parseInt(s);
+ return result;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/RecordingSshTool.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/RecordingSshTool.java b/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/RecordingSshTool.java
new file mode 100644
index 0000000..fdf3e73
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/internal/ssh/RecordingSshTool.java
@@ -0,0 +1,97 @@
+/*
+ * 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.util.internal.ssh;
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+
+/** Mock tool */
+public class RecordingSshTool implements SshTool {
+
+ public static class ExecCmd {
+ public final Map<String,?> props;
+ public final String summaryForLogging;
+ public final List<String> commands;
+ public final Map<?,?> env;
+
+ ExecCmd(Map<String,?> props, String summaryForLogging, List<String> commands, Map env) {
+ this.props = props;
+ this.summaryForLogging = summaryForLogging;
+ this.commands = commands;
+ this.env = env;
+ }
+
+ @Override
+ public String toString() {
+ return "ExecCmd["+summaryForLogging+": "+commands+"; "+props+"; "+env+"]";
+ }
+ }
+
+ public static List<ExecCmd> execScriptCmds = Lists.newCopyOnWriteArrayList();
+
+ private boolean connected;
+
+ public RecordingSshTool(Map<?,?> props) {
+ }
+ @Override public void connect() {
+ connected = true;
+ }
+ @Override public void connect(int maxAttempts) {
+ connected = true;
+ }
+ @Override public void disconnect() {
+ connected = false;
+ }
+ @Override public boolean isConnected() {
+ return connected;
+ }
+ @Override public int execScript(Map<String, ?> props, List<String> commands, Map<String, ?> env) {
+ execScriptCmds.add(new ExecCmd(props, "", commands, env));
+ return 0;
+ }
+ @Override public int execScript(Map<String, ?> props, List<String> commands) {
+ return execScript(props, commands, ImmutableMap.<String,Object>of());
+ }
+ @Override public int execCommands(Map<String, ?> props, List<String> commands, Map<String, ?> env) {
+ execScriptCmds.add(new ExecCmd(props, "", commands, env));
+ return 0;
+ }
+ @Override public int execCommands(Map<String, ?> props, List<String> commands) {
+ return execCommands(props, commands, ImmutableMap.<String,Object>of());
+ }
+ @Override public int copyToServer(Map<String, ?> props, File localFile, String pathAndFileOnRemoteServer) {
+ return 0;
+ }
+ @Override public int copyToServer(Map<String, ?> props, InputStream contents, String pathAndFileOnRemoteServer) {
+ return 0;
+ }
+ @Override public int copyToServer(Map<String, ?> props, byte[] contents, String pathAndFileOnRemoteServer) {
+ return 0;
+ }
+ @Override public int copyFromServer(Map<String, ?> props, String pathAndFileOnRemoteServer, File local) {
+ return 0;
+ }
+}
\ No newline at end of file
[07/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/service/InitdServiceInstaller.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/service/InitdServiceInstaller.java b/software/base/src/main/java/brooklyn/entity/service/InitdServiceInstaller.java
index 6cde4d3..04048af 100644
--- a/software/base/src/main/java/brooklyn/entity/service/InitdServiceInstaller.java
+++ b/software/base/src/main/java/brooklyn/entity/service/InitdServiceInstaller.java
@@ -27,6 +27,12 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.trait.HasShortName;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.policy.Enricher;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.core.util.task.ssh.SshPutTaskWrapper;
+import org.apache.brooklyn.core.util.task.ssh.SshTasks;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
+import org.apache.brooklyn.core.util.text.TemplateProcessor;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.Attributes;
@@ -38,15 +44,9 @@ import brooklyn.entity.effector.EffectorTasks;
import org.apache.brooklyn.location.basic.SshMachineLocation;
import org.apache.brooklyn.location.cloud.names.AbstractCloudMachineNamer;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.os.Os;
import brooklyn.util.ssh.BashCommands;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.task.ssh.SshPutTaskWrapper;
-import brooklyn.util.task.ssh.SshTasks;
-import brooklyn.util.task.system.ProcessTaskWrapper;
-import brooklyn.util.text.TemplateProcessor;
public class InitdServiceInstaller implements SystemServiceInstaller {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/service/SystemServiceEnricher.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/service/SystemServiceEnricher.java b/software/base/src/main/java/brooklyn/entity/service/SystemServiceEnricher.java
index 7c4ada5..bbad039 100644
--- a/software/base/src/main/java/brooklyn/entity/service/SystemServiceEnricher.java
+++ b/software/base/src/main/java/brooklyn/entity/service/SystemServiceEnricher.java
@@ -25,6 +25,13 @@ import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.management.ExecutionContext;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.policy.Enricher;
+import org.apache.brooklyn.core.util.task.BasicExecutionManager;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.TaskBuilder;
+import org.apache.brooklyn.core.util.task.ssh.SshPutTaskWrapper;
+import org.apache.brooklyn.core.util.task.ssh.SshTasks;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskFactory;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
import brooklyn.config.ConfigKey;
import brooklyn.enricher.basic.AbstractEnricher;
@@ -39,13 +46,6 @@ import brooklyn.entity.effector.EffectorTasks;
import org.apache.brooklyn.location.basic.SshMachineLocation;
import brooklyn.util.net.Urls;
-import brooklyn.util.task.BasicExecutionManager;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.TaskBuilder;
-import brooklyn.util.task.ssh.SshPutTaskWrapper;
-import brooklyn.util.task.ssh.SshTasks;
-import brooklyn.util.task.system.ProcessTaskFactory;
-import brooklyn.util.task.system.ProcessTaskWrapper;
import com.google.common.collect.ImmutableSet;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/software/MachineInitTasks.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/software/MachineInitTasks.java b/software/base/src/main/java/brooklyn/entity/software/MachineInitTasks.java
index 2e68f6f..3173aa4 100644
--- a/software/base/src/main/java/brooklyn/entity/software/MachineInitTasks.java
+++ b/software/base/src/main/java/brooklyn/entity/software/MachineInitTasks.java
@@ -22,6 +22,9 @@ import java.util.List;
import java.util.concurrent.Callable;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.core.util.task.ssh.SshTasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -32,15 +35,14 @@ import com.google.common.collect.Lists;
import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.entity.basic.EntityInternal;
+
import org.apache.brooklyn.location.basic.SshMachineLocation;
+
import brooklyn.util.net.Protocol;
import brooklyn.util.ssh.BashCommands;
import brooklyn.util.ssh.IptablesCommands;
import brooklyn.util.ssh.IptablesCommands.Chain;
import brooklyn.util.ssh.IptablesCommands.Policy;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.task.ssh.SshTasks;
import brooklyn.util.text.Strings;
/**
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java b/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java
index 97add55..34cd86e 100644
--- a/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java
+++ b/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java
@@ -37,6 +37,10 @@ import org.apache.brooklyn.api.location.MachineProvisioningLocation;
import org.apache.brooklyn.api.location.NoMachinesAvailableException;
import org.apache.brooklyn.api.location.MachineManagementMixins.SuspendsMachines;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -77,15 +81,11 @@ import org.apache.brooklyn.location.basic.SshMachineLocation;
import org.apache.brooklyn.location.cloud.CloudLocationConfig;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.guava.Maybe;
import brooklyn.util.net.UserAndHostAndPort;
import brooklyn.util.os.Os;
import brooklyn.util.ssh.BashCommands;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.task.system.ProcessTaskWrapper;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/software/ProvidesProvisioningFlags.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/software/ProvidesProvisioningFlags.java b/software/base/src/main/java/brooklyn/entity/software/ProvidesProvisioningFlags.java
index 91c6666..8052ece 100644
--- a/software/base/src/main/java/brooklyn/entity/software/ProvidesProvisioningFlags.java
+++ b/software/base/src/main/java/brooklyn/entity/software/ProvidesProvisioningFlags.java
@@ -19,8 +19,7 @@
package brooklyn.entity.software;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
-
-import brooklyn.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import com.google.common.annotations.Beta;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/software/SshEffectorTasks.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/software/SshEffectorTasks.java b/software/base/src/main/java/brooklyn/entity/software/SshEffectorTasks.java
index e40170c..f5ca922 100644
--- a/software/base/src/main/java/brooklyn/entity/software/SshEffectorTasks.java
+++ b/software/base/src/main/java/brooklyn/entity/software/SshEffectorTasks.java
@@ -27,6 +27,18 @@ import org.apache.brooklyn.api.entity.Effector;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.core.util.task.ssh.SshFetchTaskFactory;
+import org.apache.brooklyn.core.util.task.ssh.SshFetchTaskWrapper;
+import org.apache.brooklyn.core.util.task.ssh.SshPutTaskFactory;
+import org.apache.brooklyn.core.util.task.ssh.SshPutTaskWrapper;
+import org.apache.brooklyn.core.util.task.ssh.SshTasks;
+import org.apache.brooklyn.core.util.task.ssh.internal.AbstractSshExecTaskFactory;
+import org.apache.brooklyn.core.util.task.ssh.internal.PlainSshExecTaskFactory;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskFactory;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -44,19 +56,7 @@ import brooklyn.entity.effector.EffectorTasks.EffectorTaskFactory;
import org.apache.brooklyn.location.basic.LocationInternal;
import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.internal.ssh.SshTool;
import brooklyn.util.ssh.BashCommands;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.task.ssh.SshFetchTaskFactory;
-import brooklyn.util.task.ssh.SshFetchTaskWrapper;
-import brooklyn.util.task.ssh.SshPutTaskFactory;
-import brooklyn.util.task.ssh.SshPutTaskWrapper;
-import brooklyn.util.task.ssh.SshTasks;
-import brooklyn.util.task.ssh.internal.AbstractSshExecTaskFactory;
-import brooklyn.util.task.ssh.internal.PlainSshExecTaskFactory;
-import brooklyn.util.task.system.ProcessTaskFactory;
-import brooklyn.util.task.system.ProcessTaskWrapper;
import com.google.common.annotations.Beta;
import com.google.common.base.Function;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/software/StaticSensor.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/software/StaticSensor.java b/software/base/src/main/java/brooklyn/entity/software/StaticSensor.java
index a0c1b82..b0d8881 100644
--- a/software/base/src/main/java/brooklyn/entity/software/StaticSensor.java
+++ b/software/base/src/main/java/brooklyn/entity/software/StaticSensor.java
@@ -20,6 +20,9 @@ package brooklyn.entity.software;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.core.util.task.ValueResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -27,10 +30,7 @@ import brooklyn.config.ConfigKey;
import brooklyn.enricher.basic.Propagator;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.effector.AddSensor;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.guava.Maybe;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.task.ValueResolver;
import com.google.common.base.Supplier;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/software/http/HttpRequestSensor.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/software/http/HttpRequestSensor.java b/software/base/src/main/java/brooklyn/entity/software/http/HttpRequestSensor.java
index 8d0047a..c9f87a5 100644
--- a/software/base/src/main/java/brooklyn/entity/software/http/HttpRequestSensor.java
+++ b/software/base/src/main/java/brooklyn/entity/software/http/HttpRequestSensor.java
@@ -23,6 +23,7 @@ import java.net.URI;
import net.minidev.json.JSONObject;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -34,7 +35,6 @@ import brooklyn.entity.software.ssh.SshCommandSensor;
import brooklyn.event.feed.http.HttpFeed;
import brooklyn.event.feed.http.HttpPollConfig;
import brooklyn.event.feed.http.HttpValueFunctions;
-import brooklyn.util.config.ConfigBag;
import com.google.common.annotations.Beta;
import com.google.common.base.Functions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/software/java/JmxAttributeSensor.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/software/java/JmxAttributeSensor.java b/software/base/src/main/java/brooklyn/entity/software/java/JmxAttributeSensor.java
index b866be3..0802b22 100644
--- a/software/base/src/main/java/brooklyn/entity/software/java/JmxAttributeSensor.java
+++ b/software/base/src/main/java/brooklyn/entity/software/java/JmxAttributeSensor.java
@@ -25,6 +25,9 @@ import javax.management.ObjectName;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -38,9 +41,6 @@ import brooklyn.event.basic.DependentConfiguration;
import brooklyn.event.feed.jmx.JmxAttributePollConfig;
import brooklyn.event.feed.jmx.JmxFeed;
import brooklyn.event.feed.jmx.JmxHelper;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.Tasks;
import brooklyn.util.time.Duration;
import com.google.common.annotations.Beta;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/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 ca26baa..8d15270 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
@@ -22,6 +22,7 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.Effector;
import org.apache.brooklyn.api.entity.ParameterType;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
@@ -33,7 +34,6 @@ import brooklyn.entity.effector.Effectors.EffectorBuilder;
import brooklyn.entity.software.SshEffectorTasks;
import brooklyn.entity.software.SshEffectorTasks.SshEffectorTaskFactory;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.text.Strings;
import com.google.common.base.Preconditions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/software/ssh/SshCommandSensor.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/software/ssh/SshCommandSensor.java b/software/base/src/main/java/brooklyn/entity/software/ssh/SshCommandSensor.java
index 4443ece..1b6e99b 100644
--- a/software/base/src/main/java/brooklyn/entity/software/ssh/SshCommandSensor.java
+++ b/software/base/src/main/java/brooklyn/entity/software/ssh/SshCommandSensor.java
@@ -22,6 +22,8 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.entity.proxying.EntityInitializer;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -35,8 +37,6 @@ import brooklyn.event.feed.ssh.SshFeed;
import brooklyn.event.feed.ssh.SshPollConfig;
import brooklyn.event.feed.ssh.SshValueFunctions;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.os.Os;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/software/winrm/WindowsPerformanceCounterSensors.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/software/winrm/WindowsPerformanceCounterSensors.java b/software/base/src/main/java/brooklyn/entity/software/winrm/WindowsPerformanceCounterSensors.java
index 1a3656f..310f855 100644
--- a/software/base/src/main/java/brooklyn/entity/software/winrm/WindowsPerformanceCounterSensors.java
+++ b/software/base/src/main/java/brooklyn/entity/software/winrm/WindowsPerformanceCounterSensors.java
@@ -23,6 +23,7 @@ import java.util.Set;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.entity.proxying.EntityInitializer;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -31,7 +32,6 @@ import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.event.basic.Sensors;
import brooklyn.event.feed.windows.WindowsPerformanceCounterFeed;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.text.Strings;
import com.google.common.reflect.TypeToken;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/event/feed/jmx/JmxHelper.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/event/feed/jmx/JmxHelper.java b/software/base/src/main/java/brooklyn/event/feed/jmx/JmxHelper.java
index c39ca9f..f809d31 100644
--- a/software/base/src/main/java/brooklyn/event/feed/jmx/JmxHelper.java
+++ b/software/base/src/main/java/brooklyn/event/feed/jmx/JmxHelper.java
@@ -61,12 +61,12 @@ import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
+import org.apache.brooklyn.core.util.crypto.SecureKeys;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.entity.java.JmxSupport;
import brooklyn.entity.java.UsesJmx;
-import brooklyn.util.crypto.SecureKeys;
import brooklyn.util.crypto.SslTrustUtils;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.exceptions.RuntimeInterruptedException;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessEntityLatchTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessEntityLatchTest.java b/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessEntityLatchTest.java
index aa46dd1..ab59e39 100644
--- a/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessEntityLatchTest.java
+++ b/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessEntityLatchTest.java
@@ -29,6 +29,7 @@ import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.task.TaskInternal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.BeforeMethod;
@@ -44,7 +45,6 @@ import org.apache.brooklyn.location.basic.FixedListMachineProvisioningLocation;
import org.apache.brooklyn.location.basic.SshMachineLocation;
import brooklyn.test.Asserts;
-import brooklyn.util.task.TaskInternal;
import brooklyn.util.time.Duration;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessEntityRebindTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessEntityRebindTest.java b/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessEntityRebindTest.java
index 7ae7b54..ee9723a 100644
--- a/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessEntityRebindTest.java
+++ b/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessEntityRebindTest.java
@@ -34,6 +34,7 @@ import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
import org.apache.brooklyn.api.location.NoMachinesAvailableException;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.test.EntityTestUtils;
import org.apache.brooklyn.test.entity.TestApplication;
import org.testng.annotations.AfterMethod;
@@ -48,8 +49,6 @@ import brooklyn.entity.rebind.RebindTestUtils;
import org.apache.brooklyn.location.basic.AbstractLocation;
import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.flags.SetFromFlag;
-
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.io.Files;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessEntityTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessEntityTest.java b/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessEntityTest.java
index 3d8ddda..7a1deb4 100644
--- a/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessEntityTest.java
+++ b/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessEntityTest.java
@@ -40,6 +40,9 @@ import org.apache.brooklyn.api.location.MachineLocation;
import org.apache.brooklyn.api.management.EntityManager;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.management.TaskAdaptable;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.apache.brooklyn.test.EntityTestUtils;
import org.apache.brooklyn.test.entity.TestApplication;
import org.jclouds.util.Throwables2;
@@ -74,13 +77,10 @@ import org.apache.brooklyn.location.basic.SshMachineLocation;
import brooklyn.test.Asserts;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.exceptions.PropagatedRuntimeException;
import brooklyn.util.net.UserAndHostAndPort;
import brooklyn.util.os.Os;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.Tasks;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessSshDriverIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessSshDriverIntegrationTest.java b/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessSshDriverIntegrationTest.java
index f528f7c..aadb1ea 100644
--- a/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessSshDriverIntegrationTest.java
+++ b/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessSshDriverIntegrationTest.java
@@ -34,6 +34,7 @@ import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.util.BrooklynNetworkUtils;
import org.apache.brooklyn.test.entity.TestApplication;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
@@ -45,7 +46,6 @@ import brooklyn.entity.trait.Startable;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.BrooklynNetworkUtils;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.os.Os;
import brooklyn.util.stream.KnownSizeInputStream;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/test/java/brooklyn/entity/basic/VanillaSoftwareProcessAndChildrenIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/basic/VanillaSoftwareProcessAndChildrenIntegrationTest.java b/software/base/src/test/java/brooklyn/entity/basic/VanillaSoftwareProcessAndChildrenIntegrationTest.java
index 8b516ad..f8fb978 100644
--- a/software/base/src/test/java/brooklyn/entity/basic/VanillaSoftwareProcessAndChildrenIntegrationTest.java
+++ b/software/base/src/test/java/brooklyn/entity/basic/VanillaSoftwareProcessAndChildrenIntegrationTest.java
@@ -23,6 +23,7 @@ import java.util.concurrent.TimeUnit;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.util.ResourceUtils;
import org.apache.brooklyn.test.EntityTestUtils;
import org.apache.brooklyn.test.entity.TestApplication;
import org.slf4j.Logger;
@@ -33,7 +34,6 @@ import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import brooklyn.entity.basic.SoftwareProcess.ChildStartableMode;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.javalang.JavaClassNames;
import brooklyn.util.os.Os;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/test/java/brooklyn/entity/basic/lifecycle/MyEntityImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/basic/lifecycle/MyEntityImpl.java b/software/base/src/test/java/brooklyn/entity/basic/lifecycle/MyEntityImpl.java
index c8eca43..9f7c290 100644
--- a/software/base/src/test/java/brooklyn/entity/basic/lifecycle/MyEntityImpl.java
+++ b/software/base/src/test/java/brooklyn/entity/basic/lifecycle/MyEntityImpl.java
@@ -26,11 +26,13 @@ import brooklyn.entity.basic.SoftwareProcess;
import brooklyn.entity.basic.SoftwareProcessDriver;
import brooklyn.entity.basic.SoftwareProcessImpl;
import brooklyn.entity.java.JavaSoftwareProcessSshDriver;
+
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.ResourceUtils;
+
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.text.Identifiers;
public class MyEntityImpl extends SoftwareProcessImpl implements MyEntity {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/test/java/brooklyn/entity/basic/lifecycle/NaiveScriptRunnerTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/basic/lifecycle/NaiveScriptRunnerTest.java b/software/base/src/test/java/brooklyn/entity/basic/lifecycle/NaiveScriptRunnerTest.java
index 5ab4228..aedc116 100644
--- a/software/base/src/test/java/brooklyn/entity/basic/lifecycle/NaiveScriptRunnerTest.java
+++ b/software/base/src/test/java/brooklyn/entity/basic/lifecycle/NaiveScriptRunnerTest.java
@@ -26,6 +26,9 @@ import java.util.concurrent.Callable;
import org.apache.brooklyn.api.location.NoMachinesAvailableException;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.task.BasicExecutionContext;
+import org.apache.brooklyn.core.util.task.BasicExecutionManager;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
@@ -39,9 +42,6 @@ import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.repeat.Repeater;
-import brooklyn.util.task.BasicExecutionContext;
-import brooklyn.util.task.BasicExecutionManager;
-import brooklyn.util.task.Tasks;
import brooklyn.util.time.Duration;
import com.google.common.base.Throwables;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/test/java/brooklyn/entity/basic/lifecycle/StartStopSshDriverTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/basic/lifecycle/StartStopSshDriverTest.java b/software/base/src/test/java/brooklyn/entity/basic/lifecycle/StartStopSshDriverTest.java
index 1ef3e94..83c7dec 100644
--- a/software/base/src/test/java/brooklyn/entity/basic/lifecycle/StartStopSshDriverTest.java
+++ b/software/base/src/test/java/brooklyn/entity/basic/lifecycle/StartStopSshDriverTest.java
@@ -31,6 +31,9 @@ import java.util.Map;
import java.util.Set;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
+import org.apache.brooklyn.core.util.internal.ssh.cli.SshCliTool;
+import org.apache.brooklyn.core.util.internal.ssh.sshj.SshjTool;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestApplicationImpl;
import org.apache.brooklyn.test.entity.TestEntity;
@@ -41,13 +44,12 @@ import org.testng.annotations.Test;
import brooklyn.entity.basic.AbstractSoftwareProcessSshDriver;
import brooklyn.entity.basic.BrooklynConfigKeys;
import brooklyn.entity.basic.Entities;
+
import org.apache.brooklyn.location.basic.SshMachineLocation;
+
import brooklyn.test.Asserts;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableSet;
-import brooklyn.util.internal.ssh.SshTool;
-import brooklyn.util.internal.ssh.cli.SshCliTool;
-import brooklyn.util.internal.ssh.sshj.SshjTool;
import brooklyn.util.stream.StreamGobbler;
import com.google.common.base.Function;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/test/java/brooklyn/entity/brooklynnode/BrooklynNodeIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/brooklynnode/BrooklynNodeIntegrationTest.java b/software/base/src/test/java/brooklyn/entity/brooklynnode/BrooklynNodeIntegrationTest.java
index a088996..e473f52 100644
--- a/software/base/src/test/java/brooklyn/entity/brooklynnode/BrooklynNodeIntegrationTest.java
+++ b/software/base/src/test/java/brooklyn/entity/brooklynnode/BrooklynNodeIntegrationTest.java
@@ -35,6 +35,9 @@ import org.apache.brooklyn.api.entity.Effector;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.http.HttpTool;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
import org.apache.brooklyn.test.EntityTestUtils;
import org.apache.brooklyn.test.HttpTestUtils;
import org.apache.http.auth.UsernamePasswordCredentials;
@@ -58,17 +61,16 @@ import brooklyn.entity.brooklynnode.BrooklynNode.ExistingFileBehaviour;
import brooklyn.entity.brooklynnode.BrooklynNode.StopNodeAndKillAppsEffector;
import brooklyn.entity.proxying.EntityProxyImpl;
import brooklyn.event.feed.http.JsonFunctions;
+
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
import org.apache.brooklyn.location.basic.Locations;
import org.apache.brooklyn.location.basic.PortRanges;
import org.apache.brooklyn.location.basic.SshMachineLocation;
+
import brooklyn.test.Asserts;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.guava.Functionals;
-import brooklyn.util.http.HttpTool;
-import brooklyn.util.http.HttpToolResponse;
import brooklyn.util.javalang.JavaClassNames;
import brooklyn.util.net.Networking;
import brooklyn.util.net.Urls;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/test/java/brooklyn/entity/brooklynnode/CallbackEntityHttpClient.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/brooklynnode/CallbackEntityHttpClient.java b/software/base/src/test/java/brooklyn/entity/brooklynnode/CallbackEntityHttpClient.java
index ad5d1f2..e9a73bf 100644
--- a/software/base/src/test/java/brooklyn/entity/brooklynnode/CallbackEntityHttpClient.java
+++ b/software/base/src/test/java/brooklyn/entity/brooklynnode/CallbackEntityHttpClient.java
@@ -23,13 +23,13 @@ import java.util.List;
import java.util.Map;
import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
+import org.apache.brooklyn.core.util.http.HttpTool.HttpClientBuilder;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import brooklyn.entity.brooklynnode.EntityHttpClient;
-import brooklyn.util.http.HttpTool.HttpClientBuilder;
-import brooklyn.util.http.HttpToolResponse;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/test/java/brooklyn/entity/chef/ChefLiveTestSupport.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/chef/ChefLiveTestSupport.java b/software/base/src/test/java/brooklyn/entity/chef/ChefLiveTestSupport.java
index a04d9fa..2b65f58 100644
--- a/software/base/src/test/java/brooklyn/entity/chef/ChefLiveTestSupport.java
+++ b/software/base/src/test/java/brooklyn/entity/chef/ChefLiveTestSupport.java
@@ -25,6 +25,7 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.util.ResourceUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.BeforeMethod;
@@ -34,7 +35,6 @@ import brooklyn.entity.basic.EntityInternal;
import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.io.FileUtil;
import brooklyn.util.stream.InputStreamSupplier;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/test/java/brooklyn/entity/chef/ChefServerTasksIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/chef/ChefServerTasksIntegrationTest.java b/software/base/src/test/java/brooklyn/entity/chef/ChefServerTasksIntegrationTest.java
index ff7dfb1..1d175b1 100644
--- a/software/base/src/test/java/brooklyn/entity/chef/ChefServerTasksIntegrationTest.java
+++ b/software/base/src/test/java/brooklyn/entity/chef/ChefServerTasksIntegrationTest.java
@@ -22,6 +22,7 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
import org.apache.brooklyn.test.entity.TestApplication;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,7 +34,6 @@ import org.testng.annotations.Test;
import brooklyn.entity.basic.ApplicationBuilder;
import brooklyn.entity.basic.Entities;
import brooklyn.util.stream.StreamGobbler;
-import brooklyn.util.task.system.ProcessTaskWrapper;
import brooklyn.util.time.Duration;
import brooklyn.util.time.Time;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/test/java/brooklyn/entity/chef/mysql/ChefSoloDriverMySqlEntityLiveTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/chef/mysql/ChefSoloDriverMySqlEntityLiveTest.java b/software/base/src/test/java/brooklyn/entity/chef/mysql/ChefSoloDriverMySqlEntityLiveTest.java
index 941ba0f..75133c7 100644
--- a/software/base/src/test/java/brooklyn/entity/chef/mysql/ChefSoloDriverMySqlEntityLiveTest.java
+++ b/software/base/src/test/java/brooklyn/entity/chef/mysql/ChefSoloDriverMySqlEntityLiveTest.java
@@ -20,12 +20,12 @@ package brooklyn.entity.chef.mysql;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
import org.testng.annotations.Test;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.SoftwareProcess;
import brooklyn.entity.software.SshEffectorTasks;
-import brooklyn.util.task.system.ProcessTaskWrapper;
public class ChefSoloDriverMySqlEntityLiveTest extends AbstractChefToyMySqlEntityLiveTest {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/test/java/brooklyn/entity/java/JavaOptsTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/java/JavaOptsTest.java b/software/base/src/test/java/brooklyn/entity/java/JavaOptsTest.java
index b7034e0..f5213d9 100644
--- a/software/base/src/test/java/brooklyn/entity/java/JavaOptsTest.java
+++ b/software/base/src/test/java/brooklyn/entity/java/JavaOptsTest.java
@@ -31,6 +31,9 @@ import java.util.Set;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.location.MachineLocation;
+import org.apache.brooklyn.core.util.internal.ssh.RecordingSshTool;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
+import org.apache.brooklyn.core.util.internal.ssh.RecordingSshTool.ExecCmd;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.AfterMethod;
@@ -44,9 +47,6 @@ import org.apache.brooklyn.location.basic.SshMachineLocation;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
-import brooklyn.util.internal.ssh.RecordingSshTool;
-import brooklyn.util.internal.ssh.RecordingSshTool.ExecCmd;
-import brooklyn.util.internal.ssh.SshTool;
import brooklyn.util.jmx.jmxmp.JmxmpAgent;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/test/java/brooklyn/entity/java/JmxSupportTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/java/JmxSupportTest.java b/software/base/src/test/java/brooklyn/entity/java/JmxSupportTest.java
index caaf757..97df90b 100644
--- a/software/base/src/test/java/brooklyn/entity/java/JmxSupportTest.java
+++ b/software/base/src/test/java/brooklyn/entity/java/JmxSupportTest.java
@@ -20,6 +20,8 @@ package brooklyn.entity.java;
import static org.testng.Assert.assertEquals;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import org.apache.brooklyn.test.entity.TestApplication;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -29,9 +31,7 @@ import org.testng.annotations.Test;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.java.UsesJmx.JmxAgentModes;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.javalang.JavaClassNames;
import brooklyn.util.maven.MavenRetriever;
import brooklyn.util.stream.Streams;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/test/java/brooklyn/entity/java/SslKeyConfigTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/java/SslKeyConfigTest.java b/software/base/src/test/java/brooklyn/entity/java/SslKeyConfigTest.java
index 01c2cfb..eab15ca 100644
--- a/software/base/src/test/java/brooklyn/entity/java/SslKeyConfigTest.java
+++ b/software/base/src/test/java/brooklyn/entity/java/SslKeyConfigTest.java
@@ -24,12 +24,11 @@ import java.security.Key;
import java.security.KeyStore;
import java.security.cert.Certificate;
+import org.apache.brooklyn.core.util.crypto.FluentKeySigner;
+import org.apache.brooklyn.core.util.crypto.SecureKeys;
import org.testng.Assert;
import org.testng.annotations.Test;
-import brooklyn.util.crypto.FluentKeySigner;
-import brooklyn.util.crypto.SecureKeys;
-
public class SslKeyConfigTest {
@Test
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/test/java/brooklyn/entity/java/VanillaJavaAppRebindTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/java/VanillaJavaAppRebindTest.java b/software/base/src/test/java/brooklyn/entity/java/VanillaJavaAppRebindTest.java
index dd2b9b0..eaabfed 100644
--- a/software/base/src/test/java/brooklyn/entity/java/VanillaJavaAppRebindTest.java
+++ b/software/base/src/test/java/brooklyn/entity/java/VanillaJavaAppRebindTest.java
@@ -25,6 +25,7 @@ import java.io.File;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.util.ResourceUtils;
import org.apache.brooklyn.test.EntityTestUtils;
import org.apache.brooklyn.test.entity.TestApplication;
import org.slf4j.Logger;
@@ -42,7 +43,6 @@ import brooklyn.event.basic.Sensors;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/test/java/brooklyn/entity/java/VanillaJavaAppTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/java/VanillaJavaAppTest.java b/software/base/src/test/java/brooklyn/entity/java/VanillaJavaAppTest.java
index 73a2675..067f86e 100644
--- a/software/base/src/test/java/brooklyn/entity/java/VanillaJavaAppTest.java
+++ b/software/base/src/test/java/brooklyn/entity/java/VanillaJavaAppTest.java
@@ -43,6 +43,9 @@ import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.crypto.FluentKeySigner;
+import org.apache.brooklyn.core.util.crypto.SecureKeys;
import org.apache.brooklyn.test.entity.TestApplication;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -53,13 +56,12 @@ import org.testng.annotations.Test;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.Lifecycle;
import brooklyn.event.feed.jmx.JmxHelper;
+
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
import org.apache.brooklyn.location.basic.PortRanges;
+
import brooklyn.test.Asserts;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.crypto.FluentKeySigner;
-import brooklyn.util.crypto.SecureKeys;
import brooklyn.util.crypto.SslTrustUtils;
import brooklyn.util.jmx.jmxmp.JmxmpAgent;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/test/java/brooklyn/entity/software/MachineLifecycleEffectorTasksTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/software/MachineLifecycleEffectorTasksTest.java b/software/base/src/test/java/brooklyn/entity/software/MachineLifecycleEffectorTasksTest.java
index 2fcd1df..c143adf 100644
--- a/software/base/src/test/java/brooklyn/entity/software/MachineLifecycleEffectorTasksTest.java
+++ b/software/base/src/test/java/brooklyn/entity/software/MachineLifecycleEffectorTasksTest.java
@@ -29,6 +29,7 @@ import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.task.TaskInternal;
import org.apache.brooklyn.test.entity.TestApplication;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@@ -50,9 +51,10 @@ import brooklyn.entity.basic.SoftwareProcess.StopSoftwareParameters.StopMode;
import brooklyn.entity.trait.Startable;
import brooklyn.event.basic.DependentConfiguration;
import brooklyn.event.basic.Sensors;
+
import org.apache.brooklyn.location.jclouds.BailOutJcloudsLocation;
+
import brooklyn.test.Asserts;
-import brooklyn.util.task.TaskInternal;
import brooklyn.util.time.Duration;
public class MachineLifecycleEffectorTasksTest {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/test/java/brooklyn/entity/software/SoftwareEffectorTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/software/SoftwareEffectorTest.java b/software/base/src/test/java/brooklyn/entity/software/SoftwareEffectorTest.java
index 599b7ac..61389c9 100644
--- a/software/base/src/test/java/brooklyn/entity/software/SoftwareEffectorTest.java
+++ b/software/base/src/test/java/brooklyn/entity/software/SoftwareEffectorTest.java
@@ -24,6 +24,8 @@ import org.apache.brooklyn.api.entity.Effector;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
import org.apache.brooklyn.test.entity.TestApplication;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -39,9 +41,6 @@ import brooklyn.entity.software.SshEffectorTasks.SshEffectorBody;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.task.system.ProcessTaskWrapper;
-
import com.google.common.base.Throwables;
public class SoftwareEffectorTest {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/test/java/brooklyn/entity/software/SshEffectorTasksTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/software/SshEffectorTasksTest.java b/software/base/src/test/java/brooklyn/entity/software/SshEffectorTasksTest.java
index 8494e36..f0a4364 100644
--- a/software/base/src/test/java/brooklyn/entity/software/SshEffectorTasksTest.java
+++ b/software/base/src/test/java/brooklyn/entity/software/SshEffectorTasksTest.java
@@ -26,6 +26,9 @@ import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.TaskAdaptable;
import org.apache.brooklyn.api.management.TaskFactory;
+import org.apache.brooklyn.core.util.task.ssh.SshFetchTaskWrapper;
+import org.apache.brooklyn.core.util.task.ssh.SshPutTaskWrapper;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
@@ -42,9 +45,6 @@ import org.apache.brooklyn.location.basic.SshMachineLocation;
import brooklyn.util.exceptions.PropagatedRuntimeException;
import brooklyn.util.net.Urls;
-import brooklyn.util.task.ssh.SshFetchTaskWrapper;
-import brooklyn.util.task.ssh.SshPutTaskWrapper;
-import brooklyn.util.task.system.ProcessTaskWrapper;
import com.google.common.io.Files;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/test/java/brooklyn/entity/software/StaticSensorTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/software/StaticSensorTest.java b/software/base/src/test/java/brooklyn/entity/software/StaticSensorTest.java
index 7ec8952..285122d 100644
--- a/software/base/src/test/java/brooklyn/entity/software/StaticSensorTest.java
+++ b/software/base/src/test/java/brooklyn/entity/software/StaticSensorTest.java
@@ -19,13 +19,13 @@
package brooklyn.entity.software;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.test.EntityTestUtils;
import org.testng.annotations.Test;
import brooklyn.entity.BrooklynAppUnitTestSupport;
import brooklyn.entity.basic.BasicEntity;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.config.ConfigBag;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/test/java/brooklyn/entity/software/http/HttpRequestSensorTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/software/http/HttpRequestSensorTest.java b/software/base/src/test/java/brooklyn/entity/software/http/HttpRequestSensorTest.java
index eb53f3e..8ae262b 100644
--- a/software/base/src/test/java/brooklyn/entity/software/http/HttpRequestSensorTest.java
+++ b/software/base/src/test/java/brooklyn/entity/software/http/HttpRequestSensorTest.java
@@ -22,6 +22,7 @@ import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.test.EntityTestUtils;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestEntity;
@@ -34,7 +35,6 @@ import brooklyn.entity.basic.Entities;
import brooklyn.event.basic.Sensors;
import brooklyn.test.TestHttpRequestHandler;
import brooklyn.test.TestHttpServer;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.time.Duration;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/test/java/brooklyn/entity/software/mysql/AbstractToyMySqlEntityTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/software/mysql/AbstractToyMySqlEntityTest.java b/software/base/src/test/java/brooklyn/entity/software/mysql/AbstractToyMySqlEntityTest.java
index 98bae62..12266b5 100644
--- a/software/base/src/test/java/brooklyn/entity/software/mysql/AbstractToyMySqlEntityTest.java
+++ b/software/base/src/test/java/brooklyn/entity/software/mysql/AbstractToyMySqlEntityTest.java
@@ -21,6 +21,7 @@ package brooklyn.entity.software.mysql;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
import org.apache.brooklyn.test.EntityTestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -38,7 +39,6 @@ import org.apache.brooklyn.location.basic.SshMachineLocation;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.task.system.ProcessTaskWrapper;
import brooklyn.util.time.Duration;
import brooklyn.util.time.Time;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/test/java/brooklyn/entity/software/mysql/DynamicToyMySqlEntityBuilder.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/software/mysql/DynamicToyMySqlEntityBuilder.java b/software/base/src/test/java/brooklyn/entity/software/mysql/DynamicToyMySqlEntityBuilder.java
index df3e436..8e1ee2e 100644
--- a/software/base/src/test/java/brooklyn/entity/software/mysql/DynamicToyMySqlEntityBuilder.java
+++ b/software/base/src/test/java/brooklyn/entity/software/mysql/DynamicToyMySqlEntityBuilder.java
@@ -26,6 +26,10 @@ import org.apache.brooklyn.api.entity.proxying.EntityInitializer;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.location.MachineLocation;
import org.apache.brooklyn.api.location.OsDetails;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.core.util.task.ssh.SshTasks;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -40,10 +44,6 @@ import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation.L
import org.apache.brooklyn.location.basic.SshMachineLocation;
import brooklyn.util.ssh.BashCommands;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.task.ssh.SshTasks;
-import brooklyn.util.task.system.ProcessTaskWrapper;
import brooklyn.util.text.ComparableVersion;
import brooklyn.util.time.Duration;
import brooklyn.util.time.Time;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/test/java/brooklyn/entity/software/ssh/SshCommandIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/software/ssh/SshCommandIntegrationTest.java b/software/base/src/test/java/brooklyn/entity/software/ssh/SshCommandIntegrationTest.java
index 2d142e4..6316d03 100644
--- a/software/base/src/test/java/brooklyn/entity/software/ssh/SshCommandIntegrationTest.java
+++ b/software/base/src/test/java/brooklyn/entity/software/ssh/SshCommandIntegrationTest.java
@@ -27,6 +27,7 @@ import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.test.EntityTestUtils;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestEntity;
@@ -43,7 +44,6 @@ import brooklyn.event.basic.Sensors;
import org.apache.brooklyn.location.basic.SshMachineLocation;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.time.Duration;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/database/src/main/java/brooklyn/entity/database/DatastoreMixins.java
----------------------------------------------------------------------
diff --git a/software/database/src/main/java/brooklyn/entity/database/DatastoreMixins.java b/software/database/src/main/java/brooklyn/entity/database/DatastoreMixins.java
index 90f8a62..4727473 100644
--- a/software/database/src/main/java/brooklyn/entity/database/DatastoreMixins.java
+++ b/software/database/src/main/java/brooklyn/entity/database/DatastoreMixins.java
@@ -25,13 +25,13 @@ import javax.annotation.Nullable;
import org.apache.brooklyn.api.entity.Effector;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.effector.Effectors;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.stream.KnownSizeInputStream;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/database/src/main/java/brooklyn/entity/database/crate/CrateNode.java
----------------------------------------------------------------------
diff --git a/software/database/src/main/java/brooklyn/entity/database/crate/CrateNode.java b/software/database/src/main/java/brooklyn/entity/database/crate/CrateNode.java
index 8d5fae3..8373648 100644
--- a/software/database/src/main/java/brooklyn/entity/database/crate/CrateNode.java
+++ b/software/database/src/main/java/brooklyn/entity/database/crate/CrateNode.java
@@ -20,6 +20,7 @@ package brooklyn.entity.database.crate;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.Attributes;
@@ -33,8 +34,8 @@ import brooklyn.event.basic.AttributeSensorAndConfigKey;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
import brooklyn.event.basic.Sensors;
+
import org.apache.brooklyn.location.basic.PortRanges;
-import brooklyn.util.flags.SetFromFlag;
@ImplementedBy(CrateNodeImpl.class)
public interface CrateNode extends SoftwareProcess, UsesJava,UsesJmx, UsesJavaMXBeans, DatastoreCommon {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbDriver.java
----------------------------------------------------------------------
diff --git a/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbDriver.java b/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbDriver.java
index 3d92173..2db7f2ef4 100644
--- a/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbDriver.java
+++ b/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbDriver.java
@@ -18,8 +18,9 @@
*/
package brooklyn.entity.database.mariadb;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
+
import brooklyn.entity.basic.SoftwareProcessDriver;
-import brooklyn.util.task.system.ProcessTaskWrapper;
/**
* The {@link SoftwareProcessDriver} for MariaDB.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbNode.java
----------------------------------------------------------------------
diff --git a/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbNode.java b/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbNode.java
index d067625..ab77af5 100644
--- a/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbNode.java
+++ b/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbNode.java
@@ -22,6 +22,7 @@ import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.entity.trait.HasShortName;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.Attributes;
@@ -34,8 +35,8 @@ import brooklyn.event.basic.BasicAttributeSensorAndConfigKey.StringAttributeSens
import brooklyn.event.basic.MapConfigKey;
import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
import brooklyn.event.basic.Sensors;
+
import org.apache.brooklyn.location.basic.PortRanges;
-import brooklyn.util.flags.SetFromFlag;
@Catalog(name="MariaDB Node", description="MariaDB is an open source relational database management system (RDBMS)", iconUrl="classpath:///mariadb-logo-180x119.png")
@ImplementedBy(MariaDbNodeImpl.class)
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbNodeImpl.java
----------------------------------------------------------------------
diff --git a/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbNodeImpl.java b/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbNodeImpl.java
index 0212749..a22af08 100644
--- a/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbNodeImpl.java
+++ b/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbNodeImpl.java
@@ -26,9 +26,11 @@ import brooklyn.entity.effector.EffectorBody;
import brooklyn.event.feed.ssh.SshFeed;
import brooklyn.event.feed.ssh.SshPollConfig;
import brooklyn.event.feed.ssh.SshPollValue;
+
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.location.basic.Locations;
import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.config.ConfigBag;
+
import brooklyn.util.guava.Maybe;
import brooklyn.util.text.Identifiers;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbSshDriver.java
----------------------------------------------------------------------
diff --git a/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbSshDriver.java b/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbSshDriver.java
index b35a1cd..4d916b9 100644
--- a/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbSshDriver.java
+++ b/software/database/src/main/java/brooklyn/entity/database/mariadb/MariaDbSshDriver.java
@@ -41,14 +41,14 @@ import brooklyn.entity.database.DatastoreMixins;
import brooklyn.entity.software.SshEffectorTasks;
import org.apache.brooklyn.api.location.OsDetails;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
import org.apache.brooklyn.location.basic.SshMachineLocation;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.net.Urls;
import brooklyn.util.os.Os;
import brooklyn.util.ssh.BashCommands;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.system.ProcessTaskWrapper;
import brooklyn.util.text.Identifiers;
import brooklyn.util.text.Strings;
import brooklyn.util.time.CountdownTimer;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlClusterImpl.java
----------------------------------------------------------------------
diff --git a/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlClusterImpl.java b/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlClusterImpl.java
index 683f13b..f86ad43 100644
--- a/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlClusterImpl.java
+++ b/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlClusterImpl.java
@@ -31,6 +31,8 @@ import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.TaskBuilder;
import com.google.common.base.Function;
import com.google.common.base.Functions;
@@ -56,8 +58,6 @@ import brooklyn.event.feed.function.FunctionPollConfig;
import brooklyn.util.collections.CollectionFunctionals;
import brooklyn.util.guava.Functionals;
import brooklyn.util.guava.IfFunctions;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.TaskBuilder;
import brooklyn.util.text.Identifiers;
import brooklyn.util.text.StringPredicates;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlDriver.java
----------------------------------------------------------------------
diff --git a/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlDriver.java b/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlDriver.java
index ddfce38..2c90142 100644
--- a/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlDriver.java
+++ b/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlDriver.java
@@ -18,8 +18,9 @@
*/
package brooklyn.entity.database.mysql;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
+
import brooklyn.entity.basic.SoftwareProcessDriver;
-import brooklyn.util.task.system.ProcessTaskWrapper;
/**
* The {@link SoftwareProcessDriver} for MySQL.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlNode.java
----------------------------------------------------------------------
diff --git a/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlNode.java b/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlNode.java
index 0ab51d0..99b53c5 100644
--- a/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlNode.java
+++ b/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlNode.java
@@ -22,6 +22,7 @@ import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.entity.trait.HasShortName;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.annotation.Effector;
@@ -36,8 +37,8 @@ import brooklyn.event.basic.BasicAttributeSensorAndConfigKey.StringAttributeSens
import brooklyn.event.basic.MapConfigKey;
import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
import brooklyn.event.basic.Sensors;
+
import org.apache.brooklyn.location.basic.PortRanges;
-import brooklyn.util.flags.SetFromFlag;
@Catalog(name="MySql Node", description="MySql is an open source relational database management system (RDBMS)", iconUrl="classpath:///mysql-logo-110x57.png")
@ImplementedBy(MySqlNodeImpl.class)
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlNodeImpl.java
----------------------------------------------------------------------
diff --git a/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlNodeImpl.java b/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlNodeImpl.java
index 00a591b..dfbcbf1 100644
--- a/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlNodeImpl.java
+++ b/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlNodeImpl.java
@@ -21,6 +21,7 @@ package brooklyn.entity.database.mysql;
import java.util.Map;
import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -29,10 +30,11 @@ import brooklyn.entity.effector.EffectorBody;
import brooklyn.event.feed.ssh.SshFeed;
import brooklyn.event.feed.ssh.SshPollConfig;
import brooklyn.event.feed.ssh.SshPollValue;
+
import org.apache.brooklyn.location.basic.Locations;
import org.apache.brooklyn.location.basic.SshMachineLocation;
+
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.guava.Maybe;
import brooklyn.util.text.Identifiers;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlSshDriver.java
----------------------------------------------------------------------
diff --git a/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlSshDriver.java b/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlSshDriver.java
index 2e748e8..32b530d 100644
--- a/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlSshDriver.java
+++ b/software/database/src/main/java/brooklyn/entity/database/mysql/MySqlSshDriver.java
@@ -43,6 +43,8 @@ import brooklyn.entity.database.DatastoreMixins;
import brooklyn.entity.software.SshEffectorTasks;
import org.apache.brooklyn.api.location.OsDetails;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
import org.apache.brooklyn.location.basic.BasicOsDetails.OsVersions;
import org.apache.brooklyn.location.basic.SshMachineLocation;
@@ -53,8 +55,6 @@ import brooklyn.util.net.Urls;
import brooklyn.util.os.Os;
import brooklyn.util.ssh.BashCommands;
import brooklyn.util.stream.Streams;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.system.ProcessTaskWrapper;
import brooklyn.util.text.ComparableVersion;
import brooklyn.util.text.Identifiers;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/database/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlDriver.java
----------------------------------------------------------------------
diff --git a/software/database/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlDriver.java b/software/database/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlDriver.java
index 9aaf7c2..02ad039 100644
--- a/software/database/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlDriver.java
+++ b/software/database/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlDriver.java
@@ -18,8 +18,9 @@
*/
package brooklyn.entity.database.postgresql;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
+
import brooklyn.entity.basic.SoftwareProcessDriver;
-import brooklyn.util.task.system.ProcessTaskWrapper;
/**
* The {@link brooklyn.entity.basic.SoftwareProcessDriver} for PostgreSQL.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/database/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlNode.java
----------------------------------------------------------------------
diff --git a/software/database/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlNode.java b/software/database/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlNode.java
index 793debf..20f4b76 100644
--- a/software/database/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlNode.java
+++ b/software/database/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlNode.java
@@ -22,6 +22,7 @@ import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.Effector;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.entity.trait.HasShortName;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
@@ -31,8 +32,8 @@ import brooklyn.entity.database.DatastoreMixins;
import brooklyn.entity.database.DatastoreMixins.DatastoreCommon;
import brooklyn.entity.effector.Effectors;
import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
+
import org.apache.brooklyn.location.basic.PortRanges;
-import brooklyn.util.flags.SetFromFlag;
/**
* PostgreSQL database node entity.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/database/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlNodeChefImplFromScratch.java
----------------------------------------------------------------------
diff --git a/software/database/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlNodeChefImplFromScratch.java b/software/database/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlNodeChefImplFromScratch.java
index 7572845..d82e637 100644
--- a/software/database/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlNodeChefImplFromScratch.java
+++ b/software/database/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlNodeChefImplFromScratch.java
@@ -19,6 +19,9 @@
package brooklyn.entity.database.postgresql;
import org.apache.brooklyn.api.entity.Effector;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -34,14 +37,13 @@ import brooklyn.entity.effector.Effectors;
import brooklyn.entity.software.SshEffectorTasks;
import brooklyn.event.feed.ssh.SshFeed;
import brooklyn.event.feed.ssh.SshPollConfig;
+
import org.apache.brooklyn.location.basic.Locations;
import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.ResourceUtils;
+
import brooklyn.util.collections.Jsonya;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.guava.Maybe;
import brooklyn.util.ssh.BashCommands;
-import brooklyn.util.task.DynamicTasks;
public class PostgreSqlNodeChefImplFromScratch extends EffectorStartableImpl implements PostgreSqlNode {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/database/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlNodeImpl.java
----------------------------------------------------------------------
diff --git a/software/database/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlNodeImpl.java b/software/database/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlNodeImpl.java
index 71f63d9..c4b02de 100644
--- a/software/database/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlNodeImpl.java
+++ b/software/database/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlNodeImpl.java
@@ -18,12 +18,12 @@
*/
package brooklyn.entity.database.postgresql;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.entity.basic.SoftwareProcessImpl;
import brooklyn.entity.effector.EffectorBody;
-import brooklyn.util.config.ConfigBag;
public class PostgreSqlNodeImpl extends SoftwareProcessImpl implements PostgreSqlNode {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/database/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlSshDriver.java
----------------------------------------------------------------------
diff --git a/software/database/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlSshDriver.java b/software/database/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlSshDriver.java
index a23f2bc..5ff0175 100644
--- a/software/database/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlSshDriver.java
+++ b/software/database/src/main/java/brooklyn/entity/database/postgresql/PostgreSqlSshDriver.java
@@ -48,6 +48,10 @@ import brooklyn.entity.database.DatastoreMixins;
import brooklyn.entity.software.SshEffectorTasks;
import org.apache.brooklyn.api.location.OsDetails;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.ssh.SshTasks;
+import org.apache.brooklyn.core.util.task.ssh.SshTasks.OnFailingTask;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
import org.apache.brooklyn.location.basic.SshMachineLocation;
import brooklyn.util.collections.MutableList;
@@ -56,10 +60,6 @@ import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.net.Urls;
import brooklyn.util.os.Os;
import brooklyn.util.stream.Streams;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.ssh.SshTasks;
-import brooklyn.util.task.ssh.SshTasks.OnFailingTask;
-import brooklyn.util.task.system.ProcessTaskWrapper;
import brooklyn.util.text.Identifiers;
import brooklyn.util.text.StringFunctions;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/database/src/main/java/brooklyn/entity/database/rubyrep/RubyRepNode.java
----------------------------------------------------------------------
diff --git a/software/database/src/main/java/brooklyn/entity/database/rubyrep/RubyRepNode.java b/software/database/src/main/java/brooklyn/entity/database/rubyrep/RubyRepNode.java
index 8e990dd..edfbda5 100644
--- a/software/database/src/main/java/brooklyn/entity/database/rubyrep/RubyRepNode.java
+++ b/software/database/src/main/java/brooklyn/entity/database/rubyrep/RubyRepNode.java
@@ -21,6 +21,7 @@ package brooklyn.entity.database.rubyrep;
import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.Attributes;
@@ -31,7 +32,6 @@ import brooklyn.entity.database.DatastoreMixins.DatastoreCommon;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey.StringAttributeSensorAndConfigKey;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
@Catalog(name = "RubyRep Node", description = "RubyRep is a database replication system", iconUrl = "classpath:///rubyrep-logo.jpeg")
@ImplementedBy(RubyRepNodeImpl.class)
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/database/src/test/java/brooklyn/entity/database/postgresql/PostgreSqlChefTest.java
----------------------------------------------------------------------
diff --git a/software/database/src/test/java/brooklyn/entity/database/postgresql/PostgreSqlChefTest.java b/software/database/src/test/java/brooklyn/entity/database/postgresql/PostgreSqlChefTest.java
index 5d8e984..36eb963 100644
--- a/software/database/src/test/java/brooklyn/entity/database/postgresql/PostgreSqlChefTest.java
+++ b/software/database/src/test/java/brooklyn/entity/database/postgresql/PostgreSqlChefTest.java
@@ -33,10 +33,10 @@ import brooklyn.entity.effector.EffectorTasks;
import brooklyn.entity.software.SshEffectorTasks;
import org.apache.brooklyn.api.location.PortRange;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
import org.apache.brooklyn.location.basic.PortRanges;
import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.task.system.ProcessTaskWrapper;
import brooklyn.util.time.Duration;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/messaging/src/main/java/brooklyn/entity/messaging/activemq/ActiveMQBroker.java
----------------------------------------------------------------------
diff --git a/software/messaging/src/main/java/brooklyn/entity/messaging/activemq/ActiveMQBroker.java b/software/messaging/src/main/java/brooklyn/entity/messaging/activemq/ActiveMQBroker.java
index 2e59bd4..b8bbdca 100644
--- a/software/messaging/src/main/java/brooklyn/entity/messaging/activemq/ActiveMQBroker.java
+++ b/software/messaging/src/main/java/brooklyn/entity/messaging/activemq/ActiveMQBroker.java
@@ -20,6 +20,7 @@ package brooklyn.entity.messaging.activemq;
import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.Attributes;
@@ -33,7 +34,6 @@ import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey.StringAttributeSensorAndConfigKey;
import brooklyn.event.basic.BasicConfigKey;
import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.time.Duration;
/**
* An {@link org.apache.brooklyn.api.entity.Entity} that represents a single ActiveMQ broker instance.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/messaging/src/main/java/brooklyn/entity/messaging/amqp/AmqpExchange.java
----------------------------------------------------------------------
diff --git a/software/messaging/src/main/java/brooklyn/entity/messaging/amqp/AmqpExchange.java b/software/messaging/src/main/java/brooklyn/entity/messaging/amqp/AmqpExchange.java
index f2eeee3..0ddd854 100644
--- a/software/messaging/src/main/java/brooklyn/entity/messaging/amqp/AmqpExchange.java
+++ b/software/messaging/src/main/java/brooklyn/entity/messaging/amqp/AmqpExchange.java
@@ -19,9 +19,9 @@
package brooklyn.entity.messaging.amqp;
import org.apache.brooklyn.api.event.Sensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
-import brooklyn.util.flags.SetFromFlag;
/**
* An interface that describes an AMQP exchange.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/messaging/src/main/java/brooklyn/entity/messaging/kafka/Kafka.java
----------------------------------------------------------------------
diff --git a/software/messaging/src/main/java/brooklyn/entity/messaging/kafka/Kafka.java b/software/messaging/src/main/java/brooklyn/entity/messaging/kafka/Kafka.java
index ff7c368..64123b3 100644
--- a/software/messaging/src/main/java/brooklyn/entity/messaging/kafka/Kafka.java
+++ b/software/messaging/src/main/java/brooklyn/entity/messaging/kafka/Kafka.java
@@ -18,12 +18,13 @@
*/
package brooklyn.entity.messaging.kafka;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
+
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.Attributes;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.SoftwareProcess;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
-import brooklyn.util.flags.SetFromFlag;
/**
* Shared Kafka broker and zookeeper properties.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/messaging/src/main/java/brooklyn/entity/messaging/kafka/KafkaBroker.java
----------------------------------------------------------------------
diff --git a/software/messaging/src/main/java/brooklyn/entity/messaging/kafka/KafkaBroker.java b/software/messaging/src/main/java/brooklyn/entity/messaging/kafka/KafkaBroker.java
index 28b51c9..71b20c5 100644
--- a/software/messaging/src/main/java/brooklyn/entity/messaging/kafka/KafkaBroker.java
+++ b/software/messaging/src/main/java/brooklyn/entity/messaging/kafka/KafkaBroker.java
@@ -20,6 +20,7 @@ package brooklyn.entity.messaging.kafka;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
@@ -30,8 +31,9 @@ import brooklyn.entity.zookeeper.ZooKeeperNode;
import brooklyn.event.basic.BasicConfigKey;
import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
import brooklyn.event.basic.Sensors;
+
import org.apache.brooklyn.location.basic.PortRanges;
-import brooklyn.util.flags.SetFromFlag;
+
import brooklyn.util.time.Duration;
/**
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/messaging/src/main/java/brooklyn/entity/messaging/kafka/KafkaCluster.java
----------------------------------------------------------------------
diff --git a/software/messaging/src/main/java/brooklyn/entity/messaging/kafka/KafkaCluster.java b/software/messaging/src/main/java/brooklyn/entity/messaging/kafka/KafkaCluster.java
index 8ebe328..3a24377 100644
--- a/software/messaging/src/main/java/brooklyn/entity/messaging/kafka/KafkaCluster.java
+++ b/software/messaging/src/main/java/brooklyn/entity/messaging/kafka/KafkaCluster.java
@@ -24,6 +24,7 @@ import org.apache.brooklyn.api.entity.Group;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.BrooklynConfigKeys;
@@ -35,7 +36,6 @@ import brooklyn.entity.trait.Startable;
import brooklyn.entity.zookeeper.ZooKeeperNode;
import brooklyn.event.basic.BasicAttributeSensor;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.time.Duration;
/**
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/messaging/src/main/java/brooklyn/entity/messaging/kafka/KafkaZooKeeper.java
----------------------------------------------------------------------
diff --git a/software/messaging/src/main/java/brooklyn/entity/messaging/kafka/KafkaZooKeeper.java b/software/messaging/src/main/java/brooklyn/entity/messaging/kafka/KafkaZooKeeper.java
index fa4e915..106690a 100644
--- a/software/messaging/src/main/java/brooklyn/entity/messaging/kafka/KafkaZooKeeper.java
+++ b/software/messaging/src/main/java/brooklyn/entity/messaging/kafka/KafkaZooKeeper.java
@@ -19,6 +19,7 @@
package brooklyn.entity.messaging.kafka;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.annotation.Effector;
@@ -27,7 +28,6 @@ import brooklyn.entity.basic.SoftwareProcess;
import brooklyn.entity.zookeeper.ZooKeeperNode;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.time.Duration;
/**
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/messaging/src/main/java/brooklyn/entity/messaging/qpid/QpidBroker.java
----------------------------------------------------------------------
diff --git a/software/messaging/src/main/java/brooklyn/entity/messaging/qpid/QpidBroker.java b/software/messaging/src/main/java/brooklyn/entity/messaging/qpid/QpidBroker.java
index 876ade8..a2af8a4 100644
--- a/software/messaging/src/main/java/brooklyn/entity/messaging/qpid/QpidBroker.java
+++ b/software/messaging/src/main/java/brooklyn/entity/messaging/qpid/QpidBroker.java
@@ -22,6 +22,7 @@ import java.util.Map;
import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.Attributes;
@@ -34,7 +35,6 @@ import brooklyn.entity.messaging.jms.JMSBroker;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
import brooklyn.event.basic.BasicConfigKey;
import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
-import brooklyn.util.flags.SetFromFlag;
/**
* An {@link org.apache.brooklyn.api.entity.Entity} that represents a single Qpid broker instance, using AMQP 0-10.
[42/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
[BROOKLYN-162] Refactor package in ./core/util
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/a4c0e5fd
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/a4c0e5fd
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/a4c0e5fd
Branch: refs/heads/master
Commit: a4c0e5fdee499265f80cf6d8feb0e6159cd04c30
Parents: ff7f580
Author: Hadrian Zbarcea <ha...@apache.org>
Authored: Mon Aug 17 01:00:29 2015 -0400
Committer: Hadrian Zbarcea <ha...@apache.org>
Committed: Mon Aug 17 14:52:04 2015 -0400
----------------------------------------------------------------------
.../src/main/java/brooklyn/BrooklynVersion.java | 6 +-
.../brooklyn/basic/AbstractBrooklynObject.java | 4 +-
.../brooklyn/basic/BasicConfigurableObject.java | 4 +-
.../brooklyn/basic/BrooklynDynamicType.java | 2 +-
.../brooklyn/basic/BrooklynObjectInternal.java | 2 +-
.../basic/internal/ApiObjectsFactoryImpl.java | 2 +-
.../brooklyn/config/BrooklynProperties.java | 6 +-
.../brooklyn/config/BrooklynServerPaths.java | 2 +-
.../config/internal/AbstractConfigMapImpl.java | 4 +-
.../enricher/CustomAggregatingEnricher.java | 2 +-
.../main/java/brooklyn/enricher/Enrichers.java | 2 +-
.../enricher/basic/AbstractEnricher.java | 2 +-
.../basic/AbstractMultipleSensorAggregator.java | 2 +-
.../basic/AbstractTypeTransformingEnricher.java | 2 +-
.../brooklyn/enricher/basic/Aggregator.java | 2 +-
.../java/brooklyn/enricher/basic/Joiner.java | 2 +-
.../brooklyn/enricher/basic/Propagator.java | 6 +-
.../brooklyn/enricher/basic/Transformer.java | 4 +-
.../brooklyn/enricher/basic/UpdatingMap.java | 2 +-
.../basic/YamlTimeWeightedDeltaEnricher.java | 2 +-
.../brooklyn/entity/basic/AbstractEffector.java | 4 +-
.../brooklyn/entity/basic/AbstractEntity.java | 8 +-
.../java/brooklyn/entity/basic/BasicGroup.java | 2 +-
.../entity/basic/BrooklynConfigKeys.java | 4 +-
.../entity/basic/BrooklynShutdownHooks.java | 2 +-
.../brooklyn/entity/basic/BrooklynTaskTags.java | 6 +-
.../java/brooklyn/entity/basic/ConfigKeys.java | 2 +-
.../java/brooklyn/entity/basic/DataEntity.java | 2 +-
.../brooklyn/entity/basic/DynamicGroup.java | 2 +-
.../brooklyn/entity/basic/DynamicGroupImpl.java | 2 +-
.../entity/basic/EffectorStartableImpl.java | 3 +-
.../java/brooklyn/entity/basic/Entities.java | 18 +-
.../brooklyn/entity/basic/EntityConfigMap.java | 10 +-
.../brooklyn/entity/basic/EntityFunctions.java | 2 +-
.../brooklyn/entity/basic/EntityInternal.java | 2 +-
.../basic/EntityTransientCopyInternal.java | 2 +-
.../java/brooklyn/entity/basic/Lifecycle.java | 2 +-
.../brooklyn/entity/basic/MethodEffector.java | 2 +-
.../java/brooklyn/entity/basic/Sanitizer.java | 2 +-
.../entity/basic/ServiceStateLogic.java | 2 +-
.../entity/effector/AddChildrenEffector.java | 2 +-
.../brooklyn/entity/effector/AddEffector.java | 2 +-
.../brooklyn/entity/effector/AddSensor.java | 2 +-
.../brooklyn/entity/effector/EffectorBody.java | 10 +-
.../brooklyn/entity/effector/EffectorTasks.java | 10 +-
.../brooklyn/entity/effector/Effectors.java | 4 +-
.../java/brooklyn/entity/group/Cluster.java | 2 +-
.../brooklyn/entity/group/DynamicCluster.java | 2 +-
.../entity/group/DynamicClusterImpl.java | 8 +-
.../brooklyn/entity/group/DynamicFabric.java | 2 +-
.../entity/group/DynamicMultiGroup.java | 2 +-
.../entity/group/QuarantineGroupImpl.java | 4 +-
.../entity/proxying/EntityProxyImpl.java | 6 +-
.../entity/proxying/InternalEntityFactory.java | 4 +-
.../proxying/InternalLocationFactory.java | 4 +-
.../entity/proxying/InternalPolicyFactory.java | 2 +-
.../rebind/BasicCatalogItemRebindSupport.java | 2 +-
.../rebind/BasicEnricherRebindSupport.java | 4 +-
.../entity/rebind/BasicFeedRebindSupport.java | 4 +-
.../rebind/BasicLocationRebindSupport.java | 4 +-
.../entity/rebind/BasicPolicyRebindSupport.java | 4 +-
.../rebind/PeriodicDeltaChangeListener.java | 4 +-
.../brooklyn/entity/rebind/RebindIteration.java | 2 +-
.../entity/rebind/RebindManagerImpl.java | 6 +-
.../entity/rebind/dto/BasicLocationMemento.java | 2 +-
.../entity/rebind/dto/MementosGenerators.java | 4 +-
.../BrooklynMementoPersisterToObjectStore.java | 2 +-
.../persister/BrooklynPersistenceUtils.java | 2 +-
.../rebind/persister/FileBasedObjectStore.java | 2 +-
.../rebind/persister/XmlMementoSerializer.java | 2 +-
.../rebind/transformer/CompoundTransformer.java | 4 +-
.../transformer/CompoundTransformerLoader.java | 4 +-
.../java/brooklyn/entity/trait/Startable.java | 4 +-
.../brooklyn/entity/trait/StartableMethods.java | 6 +-
.../java/brooklyn/event/basic/AttributeMap.java | 2 +-
.../basic/AttributeSensorAndConfigKey.java | 2 +-
.../brooklyn/event/basic/BasicConfigKey.java | 4 +-
.../event/basic/DependentConfiguration.java | 16 +-
.../basic/PortAttributeSensorAndConfigKey.java | 2 +-
...platedStringAttributeSensorAndConfigKey.java | 2 +-
.../event/feed/AttributePollHandler.java | 4 +-
.../main/java/brooklyn/event/feed/Poller.java | 6 +-
.../java/brooklyn/event/feed/http/HttpFeed.java | 6 +-
.../event/feed/http/HttpPollConfig.java | 4 +-
.../brooklyn/event/feed/http/HttpPollValue.java | 2 +-
.../brooklyn/event/feed/http/HttpPolls.java | 5 +-
.../event/feed/http/HttpValueFunctions.java | 3 +-
.../brooklyn/event/feed/shell/ShellFeed.java | 6 +-
.../java/brooklyn/event/feed/ssh/SshFeed.java | 6 +-
.../windows/WindowsPerformanceCounterFeed.java | 4 +-
.../policy/basic/AbstractEntityAdjunct.java | 8 +-
.../brooklyn/policy/basic/ConfigMapImpl.java | 4 +-
.../util/BrooklynLanguageExtensions.java | 48 -
.../brooklyn/util/BrooklynMavenArtifacts.java | 58 -
.../brooklyn/util/BrooklynNetworkUtils.java | 41 -
.../main/java/brooklyn/util/ResourceUtils.java | 639 ----------
.../java/brooklyn/util/config/ConfigBag.java | 588 ----------
.../brooklyn/util/crypto/FluentKeySigner.java | 192 ---
.../java/brooklyn/util/crypto/SecureKeys.java | 184 ---
.../java/brooklyn/util/file/ArchiveBuilder.java | 423 -------
.../java/brooklyn/util/file/ArchiveTasks.java | 58 -
.../java/brooklyn/util/file/ArchiveUtils.java | 351 ------
.../util/flags/ClassCoercionException.java | 39 -
.../java/brooklyn/util/flags/FlagUtils.java | 587 ----------
.../brooklyn/util/flags/MethodCoercions.java | 183 ---
.../java/brooklyn/util/flags/SetFromFlag.java | 71 --
.../java/brooklyn/util/flags/TypeCoercions.java | 879 --------------
.../main/java/brooklyn/util/http/HttpTool.java | 387 -------
.../brooklyn/util/http/HttpToolResponse.java | 185 ---
.../util/internal/ConfigKeySelfExtracting.java | 41 -
.../java/brooklyn/util/internal/Repeater.java | 369 ------
.../ssh/BackoffLimitedRetryHandler.java | 74 --
.../util/internal/ssh/ShellAbstractTool.java | 442 -------
.../brooklyn/util/internal/ssh/ShellTool.java | 113 --
.../util/internal/ssh/SshAbstractTool.java | 172 ---
.../util/internal/ssh/SshException.java | 32 -
.../brooklyn/util/internal/ssh/SshTool.java | 174 ---
.../util/internal/ssh/cli/SshCliTool.java | 316 -----
.../util/internal/ssh/process/ProcessTool.java | 214 ----
.../internal/ssh/sshj/SshjClientConnection.java | 282 -----
.../util/internal/ssh/sshj/SshjTool.java | 1091 ------------------
.../util/javalang/ReflectionScanner.java | 135 ---
.../brooklyn/util/javalang/UrlClassLoader.java | 69 --
.../java/brooklyn/util/mutex/MutexSupport.java | 120 --
.../brooklyn/util/mutex/SemaphoreForTasks.java | 112 --
.../util/mutex/SemaphoreWithOwners.java | 231 ----
.../java/brooklyn/util/mutex/WithMutexes.java | 45 -
.../src/main/java/brooklyn/util/osgi/Osgis.java | 719 ------------
.../util/task/AbstractExecutionContext.java | 75 --
.../util/task/BasicExecutionContext.java | 221 ----
.../util/task/BasicExecutionManager.java | 755 ------------
.../main/java/brooklyn/util/task/BasicTask.java | 892 --------------
.../java/brooklyn/util/task/CanSetName.java | 25 -
.../java/brooklyn/util/task/CompoundTask.java | 131 ---
.../brooklyn/util/task/DeferredSupplier.java | 38 -
.../util/task/DynamicSequentialTask.java | 480 --------
.../java/brooklyn/util/task/DynamicTasks.java | 337 ------
.../brooklyn/util/task/ExecutionListener.java | 31 -
.../java/brooklyn/util/task/ExecutionUtils.java | 49 -
.../java/brooklyn/util/task/ForwardingTask.java | 325 ------
.../util/task/ListenableForwardingFuture.java | 50 -
.../java/brooklyn/util/task/ParallelTask.java | 85 --
.../java/brooklyn/util/task/ScheduledTask.java | 185 ---
.../java/brooklyn/util/task/SequentialTask.java | 58 -
.../util/task/SingleThreadedScheduler.java | 216 ----
.../java/brooklyn/util/task/TaskBuilder.java | 184 ---
.../java/brooklyn/util/task/TaskInternal.java | 125 --
.../java/brooklyn/util/task/TaskScheduler.java | 41 -
.../main/java/brooklyn/util/task/TaskTags.java | 71 --
.../src/main/java/brooklyn/util/task/Tasks.java | 488 --------
.../java/brooklyn/util/task/ValueResolver.java | 426 -------
.../util/task/ssh/SshFetchTaskFactory.java | 89 --
.../util/task/ssh/SshFetchTaskWrapper.java | 135 ---
.../util/task/ssh/SshPutTaskFactory.java | 123 --
.../brooklyn/util/task/ssh/SshPutTaskStub.java | 69 --
.../util/task/ssh/SshPutTaskWrapper.java | 190 ---
.../java/brooklyn/util/task/ssh/SshTasks.java | 236 ----
.../internal/AbstractSshExecTaskFactory.java | 58 -
.../ssh/internal/PlainSshExecTaskFactory.java | 71 --
.../util/task/system/ProcessTaskFactory.java | 65 --
.../util/task/system/ProcessTaskStub.java | 101 --
.../util/task/system/ProcessTaskWrapper.java | 187 ---
.../brooklyn/util/task/system/SystemTasks.java | 29 -
.../internal/AbstractProcessTaskFactory.java | 214 ----
.../system/internal/ExecWithLoggingHelpers.java | 200 ----
.../internal/SystemProcessTaskFactory.java | 131 ---
.../brooklyn/util/text/DataUriSchemeParser.java | 267 -----
.../brooklyn/util/text/TemplateProcessor.java | 397 -------
...ompilerIndependentOuterClassFieldMapper.java | 166 ---
.../xstream/EnumCaseForgivingConverter.java | 60 -
.../EnumCaseForgivingSingleValueConverter.java | 35 -
.../util/xstream/ImmutableListConverter.java | 54 -
.../util/xstream/ImmutableMapConverter.java | 56 -
.../util/xstream/ImmutableSetConverter.java | 54 -
.../util/xstream/Inet4AddressConverter.java | 65 --
.../brooklyn/util/xstream/MapConverter.java | 104 --
.../util/xstream/MutableSetConverter.java | 44 -
.../util/xstream/StringKeyMapConverter.java | 134 ---
.../brooklyn/util/xstream/XmlSerializer.java | 97 --
.../java/brooklyn/util/xstream/XmlUtil.java | 59 -
.../catalog/internal/BasicBrooklynCatalog.java | 2 +-
.../catalog/internal/CatalogClasspathDo.java | 6 +-
.../core/catalog/internal/CatalogDto.java | 2 +-
.../core/catalog/internal/CatalogDtoUtils.java | 2 +-
.../catalog/internal/CatalogInitialization.java | 4 +-
.../internal/CatalogItemDtoAbstract.java | 4 +-
.../catalog/internal/CatalogXmlSerializer.java | 4 +-
.../internal/BrooklynFeatureEnablement.java | 2 +-
.../core/internal/BrooklynInitialization.java | 9 +-
.../management/entitlement/Entitlements.java | 2 +-
.../ha/HighAvailabilityManagerImpl.java | 4 +-
.../core/management/ha/OsgiManager.java | 4 +-
.../internal/AbstractManagementContext.java | 8 +-
.../internal/AsyncCollectionChangeAdapter.java | 4 +-
.../internal/BrooklynGarbageCollector.java | 6 +-
.../core/management/internal/EffectorUtils.java | 4 +-
.../internal/EntityManagementUtils.java | 4 +-
.../management/internal/LocalEntityManager.java | 2 +-
.../internal/LocalLocationManager.java | 4 +-
.../internal/LocalManagementContext.java | 10 +-
.../internal/LocalSubscriptionManager.java | 4 +-
.../management/internal/LocalUsageManager.java | 2 +-
.../internal/ManagementContextInternal.java | 2 +-
.../core/util/BrooklynLanguageExtensions.java | 48 +
.../core/util/BrooklynMavenArtifacts.java | 58 +
.../core/util/BrooklynNetworkUtils.java | 44 +
.../brooklyn/core/util/ResourceUtils.java | 639 ++++++++++
.../brooklyn/core/util/config/ConfigBag.java | 589 ++++++++++
.../core/util/crypto/FluentKeySigner.java | 192 +++
.../brooklyn/core/util/crypto/SecureKeys.java | 186 +++
.../brooklyn/core/util/file/ArchiveBuilder.java | 424 +++++++
.../brooklyn/core/util/file/ArchiveTasks.java | 58 +
.../brooklyn/core/util/file/ArchiveUtils.java | 351 ++++++
.../core/util/flags/ClassCoercionException.java | 39 +
.../brooklyn/core/util/flags/FlagUtils.java | 587 ++++++++++
.../core/util/flags/MethodCoercions.java | 183 +++
.../brooklyn/core/util/flags/SetFromFlag.java | 71 ++
.../brooklyn/core/util/flags/TypeCoercions.java | 879 ++++++++++++++
.../brooklyn/core/util/http/HttpTool.java | 387 +++++++
.../core/util/http/HttpToolResponse.java | 185 +++
.../util/internal/ConfigKeySelfExtracting.java | 41 +
.../brooklyn/core/util/internal/Repeater.java | 370 ++++++
.../ssh/BackoffLimitedRetryHandler.java | 74 ++
.../util/internal/ssh/ShellAbstractTool.java | 442 +++++++
.../core/util/internal/ssh/ShellTool.java | 113 ++
.../core/util/internal/ssh/SshAbstractTool.java | 172 +++
.../core/util/internal/ssh/SshException.java | 32 +
.../core/util/internal/ssh/SshTool.java | 174 +++
.../core/util/internal/ssh/cli/SshCliTool.java | 317 +++++
.../util/internal/ssh/process/ProcessTool.java | 215 ++++
.../internal/ssh/sshj/SshjClientConnection.java | 282 +++++
.../core/util/internal/ssh/sshj/SshjTool.java | 1091 ++++++++++++++++++
.../core/util/javalang/ReflectionScanner.java | 135 +++
.../core/util/javalang/UrlClassLoader.java | 70 ++
.../brooklyn/core/util/mutex/MutexSupport.java | 119 ++
.../core/util/mutex/SemaphoreForTasks.java | 112 ++
.../core/util/mutex/SemaphoreWithOwners.java | 231 ++++
.../brooklyn/core/util/mutex/WithMutexes.java | 45 +
.../apache/brooklyn/core/util/osgi/Osgis.java | 720 ++++++++++++
.../util/task/AbstractExecutionContext.java | 75 ++
.../core/util/task/BasicExecutionContext.java | 221 ++++
.../core/util/task/BasicExecutionManager.java | 755 ++++++++++++
.../brooklyn/core/util/task/BasicTask.java | 892 ++++++++++++++
.../brooklyn/core/util/task/CanSetName.java | 25 +
.../brooklyn/core/util/task/CompoundTask.java | 131 +++
.../core/util/task/DeferredSupplier.java | 38 +
.../core/util/task/DynamicSequentialTask.java | 480 ++++++++
.../brooklyn/core/util/task/DynamicTasks.java | 337 ++++++
.../core/util/task/ExecutionListener.java | 31 +
.../brooklyn/core/util/task/ExecutionUtils.java | 49 +
.../brooklyn/core/util/task/ForwardingTask.java | 325 ++++++
.../util/task/ListenableForwardingFuture.java | 50 +
.../brooklyn/core/util/task/ParallelTask.java | 85 ++
.../brooklyn/core/util/task/ScheduledTask.java | 185 +++
.../brooklyn/core/util/task/SequentialTask.java | 58 +
.../core/util/task/SingleThreadedScheduler.java | 216 ++++
.../brooklyn/core/util/task/TaskBuilder.java | 184 +++
.../brooklyn/core/util/task/TaskInternal.java | 125 ++
.../brooklyn/core/util/task/TaskScheduler.java | 41 +
.../brooklyn/core/util/task/TaskTags.java | 71 ++
.../apache/brooklyn/core/util/task/Tasks.java | 488 ++++++++
.../brooklyn/core/util/task/ValueResolver.java | 426 +++++++
.../core/util/task/ssh/SshFetchTaskFactory.java | 88 ++
.../core/util/task/ssh/SshFetchTaskWrapper.java | 135 +++
.../core/util/task/ssh/SshPutTaskFactory.java | 123 ++
.../core/util/task/ssh/SshPutTaskStub.java | 69 ++
.../core/util/task/ssh/SshPutTaskWrapper.java | 189 +++
.../brooklyn/core/util/task/ssh/SshTasks.java | 236 ++++
.../internal/AbstractSshExecTaskFactory.java | 58 +
.../ssh/internal/PlainSshExecTaskFactory.java | 71 ++
.../util/task/system/ProcessTaskFactory.java | 66 ++
.../core/util/task/system/ProcessTaskStub.java | 102 ++
.../util/task/system/ProcessTaskWrapper.java | 187 +++
.../core/util/task/system/SystemTasks.java | 29 +
.../internal/AbstractProcessTaskFactory.java | 216 ++++
.../system/internal/ExecWithLoggingHelpers.java | 202 ++++
.../internal/SystemProcessTaskFactory.java | 131 +++
.../core/util/text/DataUriSchemeParser.java | 267 +++++
.../core/util/text/TemplateProcessor.java | 398 +++++++
...ompilerIndependentOuterClassFieldMapper.java | 166 +++
.../xstream/EnumCaseForgivingConverter.java | 60 +
.../EnumCaseForgivingSingleValueConverter.java | 35 +
.../util/xstream/ImmutableListConverter.java | 54 +
.../util/xstream/ImmutableMapConverter.java | 56 +
.../util/xstream/ImmutableSetConverter.java | 54 +
.../util/xstream/Inet4AddressConverter.java | 65 ++
.../core/util/xstream/MapConverter.java | 104 ++
.../core/util/xstream/MutableSetConverter.java | 44 +
.../util/xstream/StringKeyMapConverter.java | 134 +++
.../core/util/xstream/XmlSerializer.java | 97 ++
.../brooklyn/core/util/xstream/XmlUtil.java | 59 +
.../location/access/BrooklynAccessUtils.java | 8 +-
.../PortForwardManagerLocationResolver.java | 3 +-
.../location/basic/AbstractLocation.java | 6 +-
.../basic/AbstractLocationResolver.java | 2 +-
.../AggregatingMachineProvisioningLocation.java | 2 +-
.../location/basic/BasicLocationRegistry.java | 2 +-
.../location/basic/BasicMachineDetails.java | 10 +-
.../location/basic/ByonLocationResolver.java | 4 +-
.../FixedListMachineProvisioningLocation.java | 4 +-
.../location/basic/HostLocationResolver.java | 2 +-
.../basic/LocalhostLocationResolver.java | 3 +-
.../LocalhostMachineProvisioningLocation.java | 10 +-
...calhostPropertiesFromBrooklynProperties.java | 3 +-
.../location/basic/LocationConfigUtils.java | 8 +-
.../location/basic/LocationInternal.java | 2 +-
...ocationPropertiesFromBrooklynProperties.java | 4 +-
.../brooklyn/location/basic/MultiLocation.java | 2 +-
.../location/basic/NamedLocationResolver.java | 2 +-
.../brooklyn/location/basic/PortRanges.java | 3 +-
.../basic/SingleMachineLocationResolver.java | 2 +-
.../SingleMachineProvisioningLocation.java | 3 +-
.../location/basic/SshMachineLocation.java | 32 +-
...bstractCloudMachineProvisioningLocation.java | 4 +-
.../location/cloud/CloudLocationConfig.java | 3 +-
.../cloud/names/AbstractCloudMachineNamer.java | 4 +-
.../cloud/names/BasicCloudMachineNamer.java | 4 +-
.../location/cloud/names/CloudMachineNamer.java | 3 +-
.../cloud/names/CustomMachineNamer.java | 6 +-
.../location/dynamic/DynamicLocation.java | 2 +-
.../location/dynamic/LocationOwner.java | 2 +-
.../brooklyn/location/geo/HostGeoInfo.java | 2 +-
.../location/geo/LocalhostExternalIpLoader.java | 2 +-
.../brooklyn/camp/lite/CampYamlLiteTest.java | 4 +-
.../camp/lite/TestAppAssemblyInstantiator.java | 2 +-
.../enricher/basic/BasicEnricherTest.java | 2 +-
.../java/brooklyn/entity/EffectorSayHiTest.java | 2 +-
.../java/brooklyn/entity/SetFromFlagTest.java | 2 +-
.../brooklyn/entity/basic/ConfigMapTest.java | 4 +-
.../basic/DependentConfigurationTest.java | 2 +-
.../brooklyn/entity/basic/EntityConfigTest.java | 2 +-
.../brooklyn/entity/basic/EntitySpecTest.java | 2 +-
...apListAndOtherStructuredConfigKeyTest.groovy | 2 +-
.../brooklyn/entity/basic/SanitizerTest.java | 3 +-
.../entity/effector/EffectorBasicTest.java | 2 +-
.../effector/EffectorConcatenateTest.java | 4 +-
.../entity/effector/EffectorTaskTest.java | 10 +-
.../java/brooklyn/entity/rebind/Dumpers.java | 2 +-
.../entity/rebind/RebindCatalogEntityTest.java | 3 +-
.../entity/rebind/RebindEnricherTest.java | 2 +-
.../rebind/RebindEntityDynamicTypeInfoTest.java | 2 +-
.../entity/rebind/RebindEntityTest.java | 2 +-
.../entity/rebind/RebindFailuresTest.java | 2 +-
.../brooklyn/entity/rebind/RebindFeedTest.java | 4 +-
.../entity/rebind/RebindFeedWithHaTest.java | 4 +-
.../entity/rebind/RebindLocationTest.java | 2 +-
.../entity/rebind/RebindManagerTest.java | 5 +-
.../entity/rebind/RebindPolicyTest.java | 2 +-
.../entity/rebind/RebindTestFixture.java | 2 +-
.../transformer/impl/XsltTransformerTest.java | 4 +-
.../brooklyn/entity/trait/FailingEntity.java | 2 +-
.../entity/trait/FailingEntityImpl.java | 2 +-
.../entity/trait/StartableMethodsTest.java | 3 +-
.../java/brooklyn/event/feed/PollerTest.java | 2 +-
.../brooklyn/event/feed/http/HttpFeedTest.java | 4 +-
.../event/feed/http/HttpValueFunctionsTest.java | 3 +-
.../brooklyn/policy/basic/BasicPolicyTest.java | 2 +-
.../EntityCleanupLongevityTestFixture.java | 4 +-
.../FilePersistencePerformanceTest.java | 2 +-
.../qa/performance/TaskPerformanceTest.java | 4 +-
.../test/java/brooklyn/test/HttpService.java | 4 +-
.../java/brooklyn/test/policy/TestEnricher.java | 2 +-
.../java/brooklyn/test/policy/TestPolicy.java | 2 +-
.../util/BrooklynMavenArtifactsTest.java | 96 --
.../brooklyn/util/ResourceUtilsHttpTest.java | 196 ----
.../java/brooklyn/util/ResourceUtilsTest.java | 189 ---
.../brooklyn/util/config/ConfigBagTest.java | 191 ---
.../util/crypto/SecureKeysAndSignerTest.java | 166 ---
.../brooklyn/util/file/ArchiveBuilderTest.java | 193 ----
.../brooklyn/util/file/ArchiveUtilsTest.java | 135 ---
.../util/flags/MethodCoercionsTest.java | 146 ---
.../brooklyn/util/http/BetterMockWebServer.java | 138 ---
.../util/http/HttpToolIntegrationTest.java | 98 --
.../brooklyn/util/internal/FlagUtilsTest.java | 314 -----
.../brooklyn/util/internal/RepeaterTest.groovy | 255 ----
.../util/internal/TypeCoercionsTest.java | 360 ------
.../util/internal/ssh/RecordingSshTool.java | 95 --
.../internal/ssh/ShellToolAbstractTest.java | 439 -------
.../ssh/SshToolAbstractIntegrationTest.java | 301 -----
.../ssh/SshToolAbstractPerformanceTest.java | 137 ---
.../ssh/cli/SshCliToolIntegrationTest.java | 119 --
.../ssh/cli/SshCliToolPerformanceTest.java | 44 -
.../ssh/process/ProcessToolIntegrationTest.java | 69 --
.../ssh/process/ProcessToolStaticsTest.java | 79 --
.../sshj/SshjToolAsyncStubIntegrationTest.java | 177 ---
.../ssh/sshj/SshjToolIntegrationTest.java | 313 -----
.../ssh/sshj/SshjToolPerformanceTest.java | 44 -
.../brooklyn/util/mutex/WithMutexesTest.java | 126 --
.../test/java/brooklyn/util/osgi/OsgisTest.java | 41 -
.../util/ssh/BashCommandsIntegrationTest.java | 501 --------
.../task/BasicTaskExecutionPerformanceTest.java | 206 ----
.../util/task/BasicTaskExecutionTest.java | 460 --------
.../util/task/BasicTasksFutureTest.java | 224 ----
.../util/task/CompoundTaskExecutionTest.java | 252 ----
.../util/task/DynamicSequentialTaskTest.java | 365 ------
.../util/task/NonBasicTaskExecutionTest.java | 126 --
.../util/task/ScheduledExecutionTest.java | 287 -----
.../util/task/SingleThreadedSchedulerTest.java | 192 ---
.../util/task/TaskFinalizationTest.java | 62 -
.../test/java/brooklyn/util/task/TasksTest.java | 181 ---
.../brooklyn/util/task/ValueResolverTest.java | 132 ---
.../brooklyn/util/task/ssh/SshTasksTest.java | 207 ----
.../util/task/system/SystemTasksTest.java | 134 ---
.../util/text/DataUriSchemeParserTest.java | 52 -
.../util/text/TemplateProcessorTest.java | 179 ---
.../util/xstream/CompilerCompatibilityTest.java | 154 ---
.../util/xstream/ConverterTestFixture.java | 40 -
.../xstream/EnumCaseForgivingConverterTest.java | 52 -
.../xstream/ImmutableListConverterTest.java | 59 -
.../util/xstream/InetAddressConverterTest.java | 41 -
.../util/xstream/StringKeyMapConverterTest.java | 77 --
.../java/brooklyn/util/xstream/XmlUtilTest.java | 33 -
.../core/catalog/internal/CatalogDtoTest.java | 2 +-
.../core/catalog/internal/CatalogLoadTest.java | 3 +-
.../core/catalog/internal/CatalogScanTest.java | 2 +-
.../AcmeEntitlementManagerTestFixture.java | 2 +-
.../entitlement/EntityEntitlementTest.java | 2 +-
.../internal/EntityExecutionManagerTest.java | 8 +-
.../management/osgi/OsgiStandaloneTest.java | 6 +-
.../osgi/OsgiVersionMoreEntityTest.java | 2 +-
.../core/util/BrooklynMavenArtifactsTest.java | 98 ++
.../core/util/ResourceUtilsHttpTest.java | 197 ++++
.../brooklyn/core/util/ResourceUtilsTest.java | 190 +++
.../core/util/config/ConfigBagTest.java | 193 ++++
.../util/crypto/SecureKeysAndSignerTest.java | 169 +++
.../core/util/file/ArchiveBuilderTest.java | 194 ++++
.../core/util/file/ArchiveUtilsTest.java | 139 +++
.../core/util/flags/MethodCoercionsTest.java | 149 +++
.../core/util/http/BetterMockWebServer.java | 138 +++
.../core/util/http/HttpToolIntegrationTest.java | 100 ++
.../core/util/internal/FlagUtilsTest.java | 314 +++++
.../core/util/internal/RepeaterTest.groovy | 257 +++++
.../core/util/internal/TypeCoercionsTest.java | 360 ++++++
.../util/internal/ssh/RecordingSshTool.java | 97 ++
.../internal/ssh/ShellToolAbstractTest.java | 441 +++++++
.../ssh/SshToolAbstractIntegrationTest.java | 304 +++++
.../ssh/SshToolAbstractPerformanceTest.java | 138 +++
.../ssh/cli/SshCliToolIntegrationTest.java | 119 ++
.../ssh/cli/SshCliToolPerformanceTest.java | 44 +
.../ssh/process/ProcessToolIntegrationTest.java | 69 ++
.../ssh/process/ProcessToolStaticsTest.java | 80 ++
.../sshj/SshjToolAsyncStubIntegrationTest.java | 178 +++
.../ssh/sshj/SshjToolIntegrationTest.java | 314 +++++
.../ssh/sshj/SshjToolPerformanceTest.java | 44 +
.../core/util/mutex/WithMutexesTest.java | 129 +++
.../brooklyn/core/util/osgi/OsgisTest.java | 41 +
.../util/ssh/BashCommandsIntegrationTest.java | 504 ++++++++
.../task/BasicTaskExecutionPerformanceTest.java | 209 ++++
.../core/util/task/BasicTaskExecutionTest.java | 462 ++++++++
.../core/util/task/BasicTasksFutureTest.java | 227 ++++
.../util/task/CompoundTaskExecutionTest.java | 258 +++++
.../util/task/DynamicSequentialTaskTest.java | 371 ++++++
.../util/task/NonBasicTaskExecutionTest.java | 130 +++
.../core/util/task/ScheduledExecutionTest.java | 291 +++++
.../util/task/SingleThreadedSchedulerTest.java | 195 ++++
.../core/util/task/TaskFinalizationTest.java | 63 +
.../brooklyn/core/util/task/TasksTest.java | 184 +++
.../core/util/task/ValueResolverTest.java | 134 +++
.../core/util/task/ssh/SshTasksTest.java | 213 ++++
.../core/util/task/system/SystemTasksTest.java | 137 +++
.../core/util/text/DataUriSchemeParserTest.java | 53 +
.../core/util/text/TemplateProcessorTest.java | 180 +++
.../util/xstream/CompilerCompatibilityTest.java | 158 +++
.../core/util/xstream/ConverterTestFixture.java | 40 +
.../xstream/EnumCaseForgivingConverterTest.java | 53 +
.../xstream/ImmutableListConverterTest.java | 60 +
.../util/xstream/InetAddressConverterTest.java | 42 +
.../util/xstream/StringKeyMapConverterTest.java | 78 ++
.../brooklyn/core/util/xstream/XmlUtilTest.java | 34 +
.../location/basic/AbstractLocationTest.java | 2 +-
.../basic/LegacyAbstractLocationTest.java | 2 +-
.../location/basic/LocationConfigTest.java | 2 +-
.../location/basic/LocationConfigUtilsTest.java | 3 +-
.../brooklyn/location/basic/PortRangesTest.java | 3 +-
.../SshMachineLocationIntegrationTest.java | 9 +-
.../SshMachineLocationPerformanceTest.java | 2 +-
.../SshMachineLocationReuseIntegrationTest.java | 4 +-
.../location/basic/SshMachineLocationTest.java | 14 +-
.../location/cloud/CloudMachineNamerTest.java | 4 +-
.../location/cloud/CustomMachineNamerTest.java | 3 +-
.../brooklyn/test/entity/BlockingEntity.java | 2 +-
.../apache/brooklyn/test/entity/TestEntity.java | 2 +-
.../rebind/compiler_compatibility_eclipse.xml | 20 +-
.../rebind/compiler_compatibility_oracle.xml | 18 +-
.../brooklyn/demo/GlobalWebFabricExample.java | 6 +-
.../brooklyn/demo/CumulusRDFApplication.java | 8 +-
.../demo/WebClusterDatabaseExampleApp.java | 6 +-
.../brooklyn/policy/os/CreateUserPolicy.java | 4 +-
.../location/jclouds/BrooklynMachinePool.java | 2 +-
.../jclouds/ComputeServiceRegistry.java | 3 +-
.../jclouds/ComputeServiceRegistryImpl.java | 2 +-
.../jclouds/JcloudsByonLocationResolver.java | 2 +-
.../location/jclouds/JcloudsLocation.java | 18 +-
.../location/jclouds/JcloudsLocationConfig.java | 3 +-
.../jclouds/JcloudsLocationCustomizer.java | 3 +-
.../location/jclouds/JcloudsMachineNamer.java | 2 +-
...JcloudsPropertiesFromBrooklynProperties.java | 4 +-
.../jclouds/JcloudsSshMachineLocation.java | 2 +-
.../brooklyn/location/jclouds/JcloudsUtil.java | 2 +-
.../jclouds/JcloudsWinRmMachineLocation.java | 2 +-
.../jclouds/SudoTtyFixingCustomizer.java | 7 +-
.../JcloudsLocationSecurityGroupCustomizer.java | 4 +-
.../persister/jclouds/BlobStoreExpiryTest.java | 6 +-
.../policy/os/CreateUserPolicyLiveTest.java | 2 +-
.../policy/os/CreateUserPolicyTest.java | 3 +-
.../jclouds/AbstractJcloudsStubbedLiveTest.java | 3 +-
.../jclouds/BailOutJcloudsLocation.java | 2 +-
...ationTemplateOptionsCustomisersLiveTest.java | 4 +-
.../location/jclouds/JcloudsLocationTest.java | 2 +-
.../jclouds/JcloudsMachineNamerTest.java | 2 +-
.../jclouds/RebindJcloudsLocationLiveTest.java | 2 +-
.../jclouds/RebindJcloudsLocationTest.java | 3 +-
.../java/brooklyn/enricher/DeltaEnricher.java | 2 +-
.../brooklyn/enricher/HttpLatencyDetector.java | 2 +-
.../brooklyn/enricher/RollingMeanEnricher.java | 2 +-
.../enricher/RollingTimeWindowMeanEnricher.java | 2 +-
.../enricher/TimeFractionDeltaEnricher.java | 2 +-
.../enricher/TimeWeightedDeltaEnricher.java | 2 +-
.../entity/brooklyn/BrooklynMetrics.java | 2 +-
.../entity/brooklyn/BrooklynMetricsImpl.java | 2 +-
.../policy/autoscaling/AutoScalerPolicy.java | 6 +-
.../policy/followthesun/FollowTheSunPolicy.java | 2 +-
.../policy/ha/AbstractFailureDetector.java | 6 +-
.../policy/ha/ConditionalSuspendPolicy.java | 2 +-
.../policy/ha/ConnectionFailureDetector.java | 2 +-
.../policy/ha/ServiceFailureDetector.java | 8 +-
.../brooklyn/policy/ha/ServiceReplacer.java | 4 +-
.../brooklyn/policy/ha/ServiceRestarter.java | 4 +-
.../policy/ha/SshMachineFailureDetector.java | 4 +-
.../loadbalancing/ItemsInContainersGroup.java | 2 +-
.../loadbalancing/LoadBalancingPolicy.java | 2 +-
.../brooklyn/policy/loadbalancing/Movable.java | 2 +-
.../enricher/HttpLatencyDetectorTest.java | 4 +-
.../brooklyn/enricher/RebindEnricherTest.java | 2 +-
.../brooklyn/policy/ha/ServiceReplacerTest.java | 2 +-
.../policy/ha/ServiceRestarterTest.java | 2 +-
.../loadbalancing/MockContainerEntity.java | 2 +-
.../basic/AbstractSoftwareProcessDriver.java | 8 +-
.../basic/AbstractSoftwareProcessSshDriver.java | 12 +-
.../SameServerDriverLifecycleEffectorTasks.java | 4 +-
.../brooklyn/entity/basic/SameServerEntity.java | 2 +-
.../entity/basic/SameServerEntityImpl.java | 6 +-
.../brooklyn/entity/basic/SoftwareProcess.java | 2 +-
...wareProcessDriverLifecycleEffectorTasks.java | 4 +-
.../entity/basic/SoftwareProcessImpl.java | 8 +-
.../basic/VanillaSoftwareProcessSshDriver.java | 4 +-
.../basic/lifecycle/NaiveScriptRunner.java | 2 +-
.../entity/basic/lifecycle/ScriptHelper.java | 12 +-
.../brooklynnode/BrooklynEntityMirrorImpl.java | 8 +-
.../entity/brooklynnode/BrooklynNode.java | 2 +-
.../entity/brooklynnode/BrooklynNodeImpl.java | 12 +-
.../brooklynnode/BrooklynNodeSshDriver.java | 10 +-
.../entity/brooklynnode/EntityHttpClient.java | 4 +-
.../brooklynnode/EntityHttpClientImpl.java | 6 +-
.../brooklynnode/RemoteEffectorBuilder.java | 2 +-
.../BrooklynClusterUpgradeEffectorBody.java | 6 +-
.../BrooklynNodeUpgradeEffectorBody.java | 6 +-
.../effector/SelectMasterEffectorBody.java | 4 +-
.../SetHighAvailabilityModeEffectorBody.java | 4 +-
...SetHighAvailabilityPriorityEffectorBody.java | 4 +-
.../brooklyn/entity/chef/ChefAttributeFeed.java | 4 +-
.../java/brooklyn/entity/chef/ChefConfig.java | 3 +-
.../entity/chef/ChefLifecycleEffectorTasks.java | 10 +-
.../brooklyn/entity/chef/ChefServerTasks.java | 2 +-
.../brooklyn/entity/chef/ChefSoloDriver.java | 3 +-
.../java/brooklyn/entity/chef/ChefTasks.java | 10 +-
.../entity/chef/KnifeConvergeTaskFactory.java | 4 +-
.../brooklyn/entity/chef/KnifeTaskFactory.java | 10 +-
.../java/JavaSoftwareProcessSshDriver.java | 16 +-
.../java/brooklyn/entity/java/JmxSupport.java | 8 +-
.../brooklyn/entity/java/JmxmpSslSupport.java | 7 +-
.../java/brooklyn/entity/java/UsesJava.java | 3 +-
.../brooklyn/entity/java/UsesJavaMXBeans.java | 2 +-
.../main/java/brooklyn/entity/java/UsesJmx.java | 3 +-
.../brooklyn/entity/java/VanillaJavaApp.java | 2 +-
.../entity/java/VanillaJavaAppImpl.java | 2 +-
.../entity/java/VanillaJavaAppSshDriver.java | 10 +-
.../entity/machine/MachineEntityImpl.java | 6 +-
.../brooklyn/entity/pool/ServerPoolImpl.java | 2 +-
.../entity/pool/ServerPoolLocation.java | 3 +-
.../entity/service/EntityLaunchListener.java | 2 +-
.../entity/service/InitdServiceInstaller.java | 12 +-
.../entity/service/SystemServiceEnricher.java | 14 +-
.../entity/software/MachineInitTasks.java | 8 +-
.../software/MachineLifecycleEffectorTasks.java | 8 +-
.../software/ProvidesProvisioningFlags.java | 3 +-
.../entity/software/SshEffectorTasks.java | 24 +-
.../brooklyn/entity/software/StaticSensor.java | 6 +-
.../entity/software/http/HttpRequestSensor.java | 2 +-
.../software/java/JmxAttributeSensor.java | 6 +-
.../entity/software/ssh/SshCommandEffector.java | 2 +-
.../entity/software/ssh/SshCommandSensor.java | 4 +-
.../winrm/WindowsPerformanceCounterSensors.java | 2 +-
.../java/brooklyn/event/feed/jmx/JmxHelper.java | 2 +-
.../basic/SoftwareProcessEntityLatchTest.java | 2 +-
.../basic/SoftwareProcessEntityRebindTest.java | 3 +-
.../entity/basic/SoftwareProcessEntityTest.java | 6 +-
...SoftwareProcessSshDriverIntegrationTest.java | 2 +-
...ftwareProcessAndChildrenIntegrationTest.java | 2 +-
.../entity/basic/lifecycle/MyEntityImpl.java | 6 +-
.../basic/lifecycle/NaiveScriptRunnerTest.java | 6 +-
.../basic/lifecycle/StartStopSshDriverTest.java | 8 +-
.../BrooklynNodeIntegrationTest.java | 8 +-
.../brooklynnode/CallbackEntityHttpClient.java | 4 +-
.../entity/chef/ChefLiveTestSupport.java | 2 +-
.../chef/ChefServerTasksIntegrationTest.java | 2 +-
.../ChefSoloDriverMySqlEntityLiveTest.java | 2 +-
.../java/brooklyn/entity/java/JavaOptsTest.java | 6 +-
.../brooklyn/entity/java/JmxSupportTest.java | 4 +-
.../brooklyn/entity/java/SslKeyConfigTest.java | 5 +-
.../entity/java/VanillaJavaAppRebindTest.java | 2 +-
.../entity/java/VanillaJavaAppTest.java | 8 +-
.../MachineLifecycleEffectorTasksTest.java | 4 +-
.../entity/software/SoftwareEffectorTest.java | 5 +-
.../entity/software/SshEffectorTasksTest.java | 6 +-
.../entity/software/StaticSensorTest.java | 2 +-
.../software/http/HttpRequestSensorTest.java | 2 +-
.../mysql/AbstractToyMySqlEntityTest.java | 2 +-
.../mysql/DynamicToyMySqlEntityBuilder.java | 8 +-
.../software/ssh/SshCommandIntegrationTest.java | 2 +-
.../entity/database/DatastoreMixins.java | 4 +-
.../entity/database/crate/CrateNode.java | 3 +-
.../entity/database/mariadb/MariaDbDriver.java | 3 +-
.../entity/database/mariadb/MariaDbNode.java | 3 +-
.../database/mariadb/MariaDbNodeImpl.java | 4 +-
.../database/mariadb/MariaDbSshDriver.java | 4 +-
.../entity/database/mysql/MySqlClusterImpl.java | 4 +-
.../entity/database/mysql/MySqlDriver.java | 3 +-
.../entity/database/mysql/MySqlNode.java | 3 +-
.../entity/database/mysql/MySqlNodeImpl.java | 4 +-
.../entity/database/mysql/MySqlSshDriver.java | 4 +-
.../database/postgresql/PostgreSqlDriver.java | 3 +-
.../database/postgresql/PostgreSqlNode.java | 3 +-
.../PostgreSqlNodeChefImplFromScratch.java | 8 +-
.../database/postgresql/PostgreSqlNodeImpl.java | 2 +-
.../postgresql/PostgreSqlSshDriver.java | 8 +-
.../entity/database/rubyrep/RubyRepNode.java | 2 +-
.../database/postgresql/PostgreSqlChefTest.java | 2 +-
.../messaging/activemq/ActiveMQBroker.java | 2 +-
.../entity/messaging/amqp/AmqpExchange.java | 2 +-
.../brooklyn/entity/messaging/kafka/Kafka.java | 3 +-
.../entity/messaging/kafka/KafkaBroker.java | 4 +-
.../entity/messaging/kafka/KafkaCluster.java | 2 +-
.../entity/messaging/kafka/KafkaZooKeeper.java | 2 +-
.../entity/messaging/qpid/QpidBroker.java | 2 +-
.../messaging/qpid/QpidDestinationImpl.java | 2 +-
.../entity/messaging/rabbit/RabbitBroker.java | 2 +-
.../brooklyn/entity/messaging/storm/Storm.java | 2 +-
.../entity/messaging/storm/StormDeployment.java | 2 +-
.../messaging/storm/StormDeploymentImpl.java | 2 +-
.../entity/zookeeper/ZooKeeperEnsemble.java | 2 +-
.../entity/zookeeper/ZooKeeperNode.java | 2 +-
.../storm/StormAbstractCloudLiveTest.java | 4 +-
.../entity/monitoring/monit/MonitNode.java | 2 +-
.../entity/network/bind/BindDnsServer.java | 4 +-
.../nosql/cassandra/CassandraDatacenter.java | 2 +-
.../cassandra/CassandraDatacenterImpl.java | 4 +-
.../entity/nosql/cassandra/CassandraNode.java | 4 +-
.../nosql/cassandra/CassandraNodeDriver.java | 3 +-
.../nosql/cassandra/CassandraNodeImpl.java | 4 +-
.../nosql/cassandra/CassandraNodeSshDriver.java | 8 +-
.../nosql/couchbase/CouchbaseCluster.java | 2 +-
.../nosql/couchbase/CouchbaseClusterImpl.java | 10 +-
.../entity/nosql/couchbase/CouchbaseNode.java | 2 +-
.../nosql/couchbase/CouchbaseNodeImpl.java | 8 +-
.../nosql/couchbase/CouchbaseNodeSshDriver.java | 12 +-
.../nosql/couchbase/CouchbaseSyncGateway.java | 2 +-
.../entity/nosql/couchdb/CouchDBCluster.java | 2 +-
.../entity/nosql/couchdb/CouchDBNode.java | 2 +-
.../entity/nosql/couchdb/CouchDBNodeImpl.java | 2 +-
.../elasticsearch/ElasticSearchCluster.java | 2 +-
.../nosql/elasticsearch/ElasticSearchNode.java | 3 +-
.../elasticsearch/ElasticSearchNodeImpl.java | 4 +-
.../nosql/mongodb/AbstractMongoDBServer.java | 2 +-
.../entity/nosql/mongodb/MongoDBClient.java | 3 +-
.../entity/nosql/mongodb/MongoDBReplicaSet.java | 2 +-
.../entity/nosql/mongodb/MongoDBServer.java | 2 +-
.../sharding/CoLocatedMongoDBRouter.java | 2 +-
.../sharding/MongoDBShardedDeployment.java | 2 +-
.../brooklyn/entity/nosql/redis/RedisSlave.java | 2 +-
.../brooklyn/entity/nosql/redis/RedisStore.java | 2 +-
.../brooklyn/entity/nosql/riak/RiakCluster.java | 2 +-
.../entity/nosql/riak/RiakClusterImpl.java | 2 +-
.../brooklyn/entity/nosql/riak/RiakNode.java | 2 +-
.../entity/nosql/riak/RiakNodeImpl.java | 2 +-
.../entity/nosql/riak/RiakNodeSshDriver.java | 4 +-
.../brooklyn/entity/nosql/solr/SolrServer.java | 4 +-
.../entity/nosql/solr/SolrServerSshDriver.java | 2 +-
.../cassandra/CassandraDatacenterTest.java | 4 +-
.../ElasticSearchClusterIntegrationTest.java | 4 +-
.../ElasticSearchNodeIntegrationTest.java | 5 +-
.../entity/osgi/karaf/KarafContainer.java | 2 +-
.../entity/dns/AbstractGeoDnsServiceImpl.java | 2 +-
.../dns/geoscaling/GeoscalingDnsService.java | 2 +-
.../geoscaling/GeoscalingDnsServiceImpl.java | 4 +-
.../geoscaling/GeoscalingScriptGenerator.java | 3 +-
.../dns/geoscaling/GeoscalingWebClient.java | 2 +-
.../entity/proxy/AbstractController.java | 2 +-
.../entity/proxy/AbstractControllerImpl.java | 2 +-
.../brooklyn/entity/proxy/LoadBalancer.java | 2 +-
.../brooklyn/entity/proxy/ProxySslConfig.java | 5 +-
.../entity/proxy/nginx/NginxController.java | 2 +-
.../entity/proxy/nginx/NginxControllerImpl.java | 8 +-
.../entity/proxy/nginx/NginxSshDriver.java | 8 +-
.../nginx/NginxTemplateConfigGenerator.java | 4 +-
.../brooklyn/entity/proxy/nginx/UrlMapping.java | 2 +-
.../webapp/ControlledDynamicWebAppCluster.java | 2 +-
.../entity/webapp/DynamicWebAppClusterImpl.java | 8 +-
.../entity/webapp/JavaWebAppService.java | 2 +-
.../entity/webapp/JavaWebAppSshDriver.java | 8 +-
.../entity/webapp/WebAppServiceConstants.java | 2 +-
.../entity/webapp/jboss/JBoss6Server.java | 2 +-
.../entity/webapp/jboss/JBoss7Server.java | 2 +-
.../entity/webapp/jetty/Jetty6Server.java | 2 +-
.../webapp/nodejs/NodeJsWebAppService.java | 3 +-
.../webapp/nodejs/NodeJsWebAppSshDriver.java | 4 +-
.../entity/webapp/tomcat/Tomcat8Server.java | 2 +-
.../entity/webapp/tomcat/TomcatServer.java | 4 +-
.../GeoscalingScriptGeneratorTest.java | 3 +-
.../dns/geoscaling/GeoscalingWebClientTest.java | 2 +-
.../entity/proxy/AbstractControllerTest.java | 2 +-
.../entity/proxy/ProxySslConfigTest.java | 2 +-
.../nginx/NginxRebindWithHaIntegrationTest.java | 4 +-
.../AbstractWebAppFixtureIntegrationTest.java | 4 +-
.../entity/webapp/HttpsSslConfigTest.java | 2 +-
.../webapp/WebAppConcurrentDeployTest.java | 4 +-
.../test/entity/TestJavaWebAppEntity.java | 2 +-
.../test/entity/TestJavaWebAppEntityImpl.java | 2 +-
.../app/SampleLocalhostIntegrationTest.java | 2 +-
.../camp/brooklyn/YamlLauncherAbstract.java | 2 +-
.../BrooklynAssemblyTemplateInstantiator.java | 4 +-
.../BrooklynComponentTemplateResolver.java | 10 +-
.../BrooklynEntityDecorationResolver.java | 2 +-
.../creation/BrooklynYamlTypeInstantiator.java | 2 +-
.../spi/dsl/BrooklynDslDeferredSupplier.java | 2 +-
.../camp/brooklyn/spi/dsl/DslUtils.java | 2 +-
.../spi/dsl/methods/BrooklynDslCommon.java | 10 +-
.../brooklyn/spi/dsl/methods/DslComponent.java | 4 +-
.../camp/brooklyn/AbstractYamlRebindTest.java | 4 +-
.../camp/brooklyn/AbstractYamlTest.java | 4 +-
.../camp/brooklyn/DslAndRebindYamlTest.java | 2 +-
.../camp/brooklyn/EntitiesYamlTest.java | 2 +-
...aWebAppWithDslYamlRebindIntegrationTest.java | 2 +-
.../brooklyn/JavaWebAppsIntegrationTest.java | 2 +-
.../camp/brooklyn/JavaWebAppsMatchingTest.java | 4 +-
.../camp/brooklyn/MapReferenceYamlTest.java | 2 +-
.../brooklyn/camp/brooklyn/ObjectsYamlTest.java | 6 +-
.../brooklyn/ReloadBrooklynPropertiesTest.java | 2 +-
.../TestSensorAndEffectorInitializer.java | 2 +-
.../catalog/AbstractCatalogXmlTest.java | 2 +-
.../CatalogOsgiVersionMoreEntityTest.java | 2 +-
.../brooklyn/catalog/CatalogYamlEntityTest.java | 2 +-
.../org/apache/brooklyn/cli/ItemLister.java | 4 +-
.../main/java/org/apache/brooklyn/cli/Main.java | 2 +-
.../apache/brooklyn/cli/lister/ClassFinder.java | 4 +-
.../java/org/apache/brooklyn/cli/CliTest.java | 2 +-
.../brooklyn/launcher/BrooklynWebServer.java | 14 +-
.../launcher/config/CustomResourceLocator.java | 2 +-
.../entity/basic/VanillaSoftwareYamlTest.java | 2 +-
.../brooklynnode/BrooklynNodeRestTest.java | 6 +-
.../database/mssql/MssqlBlueprintLiveTest.java | 5 +-
.../BrooklynLauncherRebindCatalogTest.java | 2 +-
.../launcher/BrooklynWebServerTest.java | 4 +-
.../blueprints/AbstractBlueprintTest.java | 2 +-
.../qa/load/SimulatedMySqlNodeImpl.java | 6 +-
.../brooklyn/qa/longevity/MonitorUtils.java | 4 +-
.../SoftlayerObtainPrivateLiveTest.java | 2 +-
.../resources/AbstractBrooklynRestResource.java | 2 +-
.../rest/resources/ApplicationResource.java | 2 +-
.../rest/resources/CatalogResource.java | 2 +-
.../rest/resources/EntityConfigResource.java | 4 +-
.../brooklyn/rest/resources/EntityResource.java | 2 +-
.../rest/resources/PolicyConfigResource.java | 3 +-
.../brooklyn/rest/resources/SensorResource.java | 2 +-
.../brooklyn/rest/resources/ServerResource.java | 6 +-
.../rest/transform/EffectorTransformer.java | 4 +-
.../rest/transform/LocationTransformer.java | 2 +-
.../rest/transform/TaskTransformer.java | 2 +-
.../rest/util/BrooklynRestResourceUtils.java | 2 +-
.../rest/util/DefaultExceptionMapper.java | 2 +-
.../BrooklynPropertiesSecurityFilterTest.java | 6 +-
.../brooklyn/rest/HaMasterCheckFilterTest.java | 4 +-
.../rest/resources/CatalogResetTest.java | 2 +-
.../SensorResourceIntegrationTest.java | 4 +-
.../ServerResourceIntegrationTest.java | 7 +-
.../testing/mocks/RestMockSimpleEntity.java | 3 +-
.../testing/mocks/RestMockSimplePolicy.java | 2 +-
.../json/BrooklynJacksonSerializerTest.java | 2 +-
.../util/jmx/jmxmp/JmxmpAgentSslTest.java | 5 +-
.../brooklyn/util/jmx/jmxmp/JmxmpClient.java | 3 +-
.../brooklyn/osgi/tests/SimpleLocation.java | 3 +-
.../java/brooklyn/osgi/tests/SimplePolicy.java | 3 +-
.../osgi/tests/more/MoreEntityImpl.java | 3 +-
.../osgi/tests/more/MoreEntityImpl.java | 2 +-
.../osgi/tests/more/MoreEntityImpl.java | 2 +-
795 files changed, 28078 insertions(+), 27902 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/BrooklynVersion.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/BrooklynVersion.java b/core/src/main/java/brooklyn/BrooklynVersion.java
index dbc7869..bf45a99 100644
--- a/core/src/main/java/brooklyn/BrooklynVersion.java
+++ b/core/src/main/java/brooklyn/BrooklynVersion.java
@@ -45,11 +45,11 @@ import com.google.common.collect.Maps;
import org.apache.brooklyn.api.catalog.CatalogItem;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.core.management.classloading.OsgiBrooklynClassLoadingContext;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.osgi.Osgis;
+import org.apache.brooklyn.core.util.osgi.Osgis.ManifestHelper;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.osgi.Osgis;
-import brooklyn.util.osgi.Osgis.ManifestHelper;
import brooklyn.util.stream.Streams;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java b/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java
index c990ed9..76641bf 100644
--- a/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java
+++ b/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java
@@ -25,14 +25,14 @@ import java.util.Set;
import org.apache.brooklyn.api.basic.internal.ApiObjectsFactory;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.entity.basic.AbstractEntity;
import brooklyn.entity.proxying.InternalFactory;
import brooklyn.entity.rebind.RebindManagerImpl;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.text.Identifiers;
import com.google.common.collect.ImmutableSet;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/basic/BasicConfigurableObject.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/basic/BasicConfigurableObject.java b/core/src/main/java/brooklyn/basic/BasicConfigurableObject.java
index d02f1bd..0604f3a 100644
--- a/core/src/main/java/brooklyn/basic/BasicConfigurableObject.java
+++ b/core/src/main/java/brooklyn/basic/BasicConfigurableObject.java
@@ -23,13 +23,13 @@ import org.apache.brooklyn.api.entity.trait.Identifiable;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.core.management.ManagementContextInjectable;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.camp.brooklyn.api.HasBrooklynManagementContext;
import brooklyn.config.ConfigKey;
import brooklyn.config.ConfigKey.HasConfigKey;
import brooklyn.config.ConfigMap;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.text.Identifiers;
/**
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/basic/BrooklynDynamicType.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/basic/BrooklynDynamicType.java b/core/src/main/java/brooklyn/basic/BrooklynDynamicType.java
index dbf8bbc..52d1413 100644
--- a/core/src/main/java/brooklyn/basic/BrooklynDynamicType.java
+++ b/core/src/main/java/brooklyn/basic/BrooklynDynamicType.java
@@ -34,13 +34,13 @@ import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.brooklyn.api.basic.BrooklynObject;
import org.apache.brooklyn.api.basic.BrooklynType;
+import org.apache.brooklyn.core.util.flags.FlagUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.config.ConfigKey;
import brooklyn.config.ConfigKey.HasConfigKey;
import brooklyn.event.basic.BasicConfigKey.BasicConfigKeyOverwriting;
-import brooklyn.util.flags.FlagUtils;
import brooklyn.util.javalang.Reflections;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/basic/BrooklynObjectInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/basic/BrooklynObjectInternal.java b/core/src/main/java/brooklyn/basic/BrooklynObjectInternal.java
index 038013f..ef9212a 100644
--- a/core/src/main/java/brooklyn/basic/BrooklynObjectInternal.java
+++ b/core/src/main/java/brooklyn/basic/BrooklynObjectInternal.java
@@ -24,10 +24,10 @@ import org.apache.brooklyn.api.basic.BrooklynObject;
import org.apache.brooklyn.api.entity.rebind.RebindSupport;
import org.apache.brooklyn.api.entity.rebind.Rebindable;
import org.apache.brooklyn.api.entity.trait.Configurable;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import brooklyn.config.ConfigKey;
import brooklyn.config.ConfigKey.HasConfigKey;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.guava.Maybe;
import com.google.common.annotations.Beta;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/basic/internal/ApiObjectsFactoryImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/basic/internal/ApiObjectsFactoryImpl.java b/core/src/main/java/brooklyn/basic/internal/ApiObjectsFactoryImpl.java
index 8e0f5a4..654c51a 100644
--- a/core/src/main/java/brooklyn/basic/internal/ApiObjectsFactoryImpl.java
+++ b/core/src/main/java/brooklyn/basic/internal/ApiObjectsFactoryImpl.java
@@ -21,9 +21,9 @@ package brooklyn.basic.internal;
import org.apache.brooklyn.api.basic.internal.ApiObjectsFactoryInterface;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.task.Tasks;
import brooklyn.entity.basic.BrooklynTaskTags;
-import brooklyn.util.task.Tasks;
public class ApiObjectsFactoryImpl implements ApiObjectsFactoryInterface {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/config/BrooklynProperties.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/config/BrooklynProperties.java b/core/src/main/java/brooklyn/config/BrooklynProperties.java
index 2c76b21..921fe22 100644
--- a/core/src/main/java/brooklyn/config/BrooklynProperties.java
+++ b/core/src/main/java/brooklyn/config/BrooklynProperties.java
@@ -33,15 +33,15 @@ import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Properties;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.config.ConfigKey.HasConfigKey;
import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.guava.Maybe;
import brooklyn.util.os.Os;
import brooklyn.util.text.StringFunctions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/config/BrooklynServerPaths.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/config/BrooklynServerPaths.java b/core/src/main/java/brooklyn/config/BrooklynServerPaths.java
index a865d5b..0e0a5c9 100644
--- a/core/src/main/java/brooklyn/config/BrooklynServerPaths.java
+++ b/core/src/main/java/brooklyn/config/BrooklynServerPaths.java
@@ -25,6 +25,7 @@ import javax.annotation.Nullable;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.util.text.TemplateProcessor;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -36,7 +37,6 @@ import brooklyn.util.net.Urls;
import brooklyn.util.os.Os;
import brooklyn.util.text.Identifiers;
import brooklyn.util.text.Strings;
-import brooklyn.util.text.TemplateProcessor;
import brooklyn.util.time.Time;
import com.google.common.base.Objects;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/config/internal/AbstractConfigMapImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/config/internal/AbstractConfigMapImpl.java b/core/src/main/java/brooklyn/config/internal/AbstractConfigMapImpl.java
index defb5bc..c648654 100644
--- a/core/src/main/java/brooklyn/config/internal/AbstractConfigMapImpl.java
+++ b/core/src/main/java/brooklyn/config/internal/AbstractConfigMapImpl.java
@@ -23,6 +23,8 @@ import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.Future;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
+import org.apache.brooklyn.core.util.task.DeferredSupplier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -31,8 +33,6 @@ import brooklyn.config.ConfigKey.HasConfigKey;
import brooklyn.config.ConfigMap;
import brooklyn.entity.basic.ConfigMapViewWithStringKeys;
import brooklyn.event.basic.StructuredConfigKey;
-import brooklyn.util.flags.TypeCoercions;
-import brooklyn.util.task.DeferredSupplier;
public abstract class AbstractConfigMapImpl implements ConfigMap {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/enricher/CustomAggregatingEnricher.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/enricher/CustomAggregatingEnricher.java b/core/src/main/java/brooklyn/enricher/CustomAggregatingEnricher.java
index 1089ae4..4924684 100644
--- a/core/src/main/java/brooklyn/enricher/CustomAggregatingEnricher.java
+++ b/core/src/main/java/brooklyn/enricher/CustomAggregatingEnricher.java
@@ -26,12 +26,12 @@ import java.util.Map;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.event.SensorEventListener;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.enricher.basic.AbstractAggregatingEnricher;
import brooklyn.util.GroovyJavaMethods;
-import brooklyn.util.flags.TypeCoercions;
import com.google.common.base.Function;
import com.google.common.base.Throwables;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/enricher/Enrichers.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/enricher/Enrichers.java b/core/src/main/java/brooklyn/enricher/Enrichers.java
index 54af8d1..00aa03f 100644
--- a/core/src/main/java/brooklyn/enricher/Enrichers.java
+++ b/core/src/main/java/brooklyn/enricher/Enrichers.java
@@ -32,6 +32,7 @@ import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.EnricherSpec;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import brooklyn.enricher.basic.AbstractEnricher;
import brooklyn.enricher.basic.Aggregator;
@@ -43,7 +44,6 @@ import brooklyn.enricher.basic.UpdatingMap;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.text.StringPredicates;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/enricher/basic/AbstractEnricher.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/enricher/basic/AbstractEnricher.java b/core/src/main/java/brooklyn/enricher/basic/AbstractEnricher.java
index da5e822..5bca143 100644
--- a/core/src/main/java/brooklyn/enricher/basic/AbstractEnricher.java
+++ b/core/src/main/java/brooklyn/enricher/basic/AbstractEnricher.java
@@ -29,6 +29,7 @@ import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.mementos.EnricherMemento;
import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.EnricherType;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
@@ -36,7 +37,6 @@ import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.rebind.BasicEnricherRebindSupport;
import brooklyn.policy.basic.AbstractEntityAdjunct;
-import brooklyn.util.flags.TypeCoercions;
import com.google.common.base.Objects;
import com.google.common.collect.Maps;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/enricher/basic/AbstractMultipleSensorAggregator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/enricher/basic/AbstractMultipleSensorAggregator.java b/core/src/main/java/brooklyn/enricher/basic/AbstractMultipleSensorAggregator.java
index af47c59..84db77f 100644
--- a/core/src/main/java/brooklyn/enricher/basic/AbstractMultipleSensorAggregator.java
+++ b/core/src/main/java/brooklyn/enricher/basic/AbstractMultipleSensorAggregator.java
@@ -30,12 +30,12 @@ import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.config.BrooklynLogging;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.flags.TypeCoercions;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/enricher/basic/AbstractTypeTransformingEnricher.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/enricher/basic/AbstractTypeTransformingEnricher.java b/core/src/main/java/brooklyn/enricher/basic/AbstractTypeTransformingEnricher.java
index 7bf0ef6..cd9a33f 100644
--- a/core/src/main/java/brooklyn/enricher/basic/AbstractTypeTransformingEnricher.java
+++ b/core/src/main/java/brooklyn/enricher/basic/AbstractTypeTransformingEnricher.java
@@ -23,9 +23,9 @@ import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.event.SensorEventListener;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.event.basic.BasicSensorEvent;
-import brooklyn.util.flags.SetFromFlag;
/**
* Convenience base for transforming a single sensor into a single new sensor of the same type
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/enricher/basic/Aggregator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/enricher/basic/Aggregator.java b/core/src/main/java/brooklyn/enricher/basic/Aggregator.java
index c14487b..5512c28 100644
--- a/core/src/main/java/brooklyn/enricher/basic/Aggregator.java
+++ b/core/src/main/java/brooklyn/enricher/basic/Aggregator.java
@@ -30,6 +30,7 @@ import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -40,7 +41,6 @@ import brooklyn.entity.basic.ConfigKeys;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.text.StringPredicates;
import com.google.common.base.Function;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/enricher/basic/Joiner.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/enricher/basic/Joiner.java b/core/src/main/java/brooklyn/enricher/basic/Joiner.java
index 8c65681..f9e9d4e 100644
--- a/core/src/main/java/brooklyn/enricher/basic/Joiner.java
+++ b/core/src/main/java/brooklyn/enricher/basic/Joiner.java
@@ -26,6 +26,7 @@ import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,7 +34,6 @@ import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.event.basic.BasicSensorEvent;
import brooklyn.util.collections.MutableList;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.text.StringEscapes;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/enricher/basic/Propagator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/enricher/basic/Propagator.java b/core/src/main/java/brooklyn/enricher/basic/Propagator.java
index 187ad8d..f6d2ee8 100644
--- a/core/src/main/java/brooklyn/enricher/basic/Propagator.java
+++ b/core/src/main/java/brooklyn/enricher/basic/Propagator.java
@@ -28,6 +28,9 @@ import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.core.util.task.ValueResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -35,9 +38,6 @@ import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.Attributes;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.flags.SetFromFlag;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.task.ValueResolver;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/enricher/basic/Transformer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/enricher/basic/Transformer.java b/core/src/main/java/brooklyn/enricher/basic/Transformer.java
index 7e331ba..705c626 100644
--- a/core/src/main/java/brooklyn/enricher/basic/Transformer.java
+++ b/core/src/main/java/brooklyn/enricher/basic/Transformer.java
@@ -21,14 +21,14 @@ package brooklyn.enricher.basic;
import static com.google.common.base.Preconditions.checkArgument;
import org.apache.brooklyn.api.event.SensorEvent;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.core.util.task.ValueResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.util.collections.MutableSet;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.task.ValueResolver;
import com.google.common.base.Function;
import com.google.common.reflect.TypeToken;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/enricher/basic/UpdatingMap.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/enricher/basic/UpdatingMap.java b/core/src/main/java/brooklyn/enricher/basic/UpdatingMap.java
index a973774..a396e6c 100644
--- a/core/src/main/java/brooklyn/enricher/basic/UpdatingMap.java
+++ b/core/src/main/java/brooklyn/enricher/basic/UpdatingMap.java
@@ -25,6 +25,7 @@ import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,7 +34,6 @@ import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.Entities;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.base.Function;
import com.google.common.collect.Maps;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/enricher/basic/YamlTimeWeightedDeltaEnricher.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/enricher/basic/YamlTimeWeightedDeltaEnricher.java b/core/src/main/java/brooklyn/enricher/basic/YamlTimeWeightedDeltaEnricher.java
index 65df607..f94c203 100644
--- a/core/src/main/java/brooklyn/enricher/basic/YamlTimeWeightedDeltaEnricher.java
+++ b/core/src/main/java/brooklyn/enricher/basic/YamlTimeWeightedDeltaEnricher.java
@@ -19,13 +19,13 @@
package brooklyn.enricher.basic;
import org.apache.brooklyn.api.event.SensorEvent;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.config.ConfigKey;
import brooklyn.enricher.basic.AbstractTransformer;
import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.time.Duration;
import com.google.common.base.Function;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/basic/AbstractEffector.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/AbstractEffector.java b/core/src/main/java/brooklyn/entity/basic/AbstractEffector.java
index bf29732..2988aeb 100644
--- a/core/src/main/java/brooklyn/entity/basic/AbstractEffector.java
+++ b/core/src/main/java/brooklyn/entity/basic/AbstractEffector.java
@@ -27,14 +27,14 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.ParameterType;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.core.management.internal.EffectorUtils;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.task.DynamicSequentialTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.entity.effector.EffectorBase;
import brooklyn.entity.effector.EffectorTasks.EffectorTaskFactory;
import brooklyn.entity.effector.EffectorWithBody;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.task.DynamicSequentialTask;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java b/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
index 1d21a7e..4bdae46 100644
--- a/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
+++ b/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
@@ -60,6 +60,10 @@ import org.apache.brooklyn.core.management.internal.EffectorUtils;
import org.apache.brooklyn.core.management.internal.EntityManagementSupport;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.core.management.internal.SubscriptionTracker;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.FlagUtils;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
+import org.apache.brooklyn.core.util.task.DeferredSupplier;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -91,12 +95,8 @@ import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
import brooklyn.util.collections.SetFromLiveMap;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.flags.FlagUtils;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.guava.Maybe;
import brooklyn.util.javalang.Equals;
-import brooklyn.util.task.DeferredSupplier;
import brooklyn.util.text.Strings;
import com.google.common.annotations.Beta;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/basic/BasicGroup.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/BasicGroup.java b/core/src/main/java/brooklyn/entity/basic/BasicGroup.java
index 0bb67b6..05606af 100644
--- a/core/src/main/java/brooklyn/entity/basic/BasicGroup.java
+++ b/core/src/main/java/brooklyn/entity/basic/BasicGroup.java
@@ -19,10 +19,10 @@
package brooklyn.entity.basic;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.util.flags.SetFromFlag;
@ImplementedBy(BasicGroupImpl.class)
public interface BasicGroup extends AbstractGroup {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/basic/BrooklynConfigKeys.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/BrooklynConfigKeys.java b/core/src/main/java/brooklyn/entity/basic/BrooklynConfigKeys.java
index 7910267..d9e4903 100644
--- a/core/src/main/java/brooklyn/entity/basic/BrooklynConfigKeys.java
+++ b/core/src/main/java/brooklyn/entity/basic/BrooklynConfigKeys.java
@@ -26,9 +26,9 @@ import brooklyn.event.basic.AttributeSensorAndConfigKey;
import brooklyn.event.basic.TemplatedStringAttributeSensorAndConfigKey;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.util.internal.ssh.ShellTool;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
-import brooklyn.util.internal.ssh.ShellTool;
-import brooklyn.util.internal.ssh.SshTool;
import brooklyn.util.time.Duration;
import com.google.common.base.Preconditions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/basic/BrooklynShutdownHooks.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/BrooklynShutdownHooks.java b/core/src/main/java/brooklyn/entity/basic/BrooklynShutdownHooks.java
index 6032fff..79fe68f 100644
--- a/core/src/main/java/brooklyn/entity/basic/BrooklynShutdownHooks.java
+++ b/core/src/main/java/brooklyn/entity/basic/BrooklynShutdownHooks.java
@@ -27,6 +27,7 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -36,7 +37,6 @@ import brooklyn.util.collections.MutableSet;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.exceptions.RuntimeInterruptedException;
import brooklyn.util.javalang.Threads;
-import brooklyn.util.task.Tasks;
import brooklyn.util.time.CountdownTimer;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/basic/BrooklynTaskTags.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/BrooklynTaskTags.java b/core/src/main/java/brooklyn/entity/basic/BrooklynTaskTags.java
index 3cdfc39..2904ff5 100644
--- a/core/src/main/java/brooklyn/entity/basic/BrooklynTaskTags.java
+++ b/core/src/main/java/brooklyn/entity/basic/BrooklynTaskTags.java
@@ -33,16 +33,16 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.management.ExecutionManager;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.management.entitlement.EntitlementContext;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.task.TaskTags;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.codehaus.jackson.annotate.JsonProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.guava.Maybe;
import brooklyn.util.javalang.MemoryUsageTracker;
import brooklyn.util.stream.Streams;
-import brooklyn.util.task.TaskTags;
-import brooklyn.util.task.Tasks;
import brooklyn.util.text.StringEscapes.BashStringEscapes;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/basic/ConfigKeys.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/ConfigKeys.java b/core/src/main/java/brooklyn/entity/basic/ConfigKeys.java
index 2b22a90..a50c800 100644
--- a/core/src/main/java/brooklyn/entity/basic/ConfigKeys.java
+++ b/core/src/main/java/brooklyn/entity/basic/ConfigKeys.java
@@ -22,6 +22,7 @@ import java.util.Map;
import javax.annotation.Nonnull;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -32,7 +33,6 @@ import brooklyn.event.basic.BasicConfigKey;
import brooklyn.event.basic.TemplatedStringAttributeSensorAndConfigKey;
import brooklyn.event.basic.BasicConfigKey.BasicConfigKeyOverwriting;
import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/basic/DataEntity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/DataEntity.java b/core/src/main/java/brooklyn/entity/basic/DataEntity.java
index 27f1c33..534e125 100644
--- a/core/src/main/java/brooklyn/entity/basic/DataEntity.java
+++ b/core/src/main/java/brooklyn/entity/basic/DataEntity.java
@@ -23,10 +23,10 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.trait.Startable;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.base.Supplier;
import com.google.common.reflect.TypeToken;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/basic/DynamicGroup.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/DynamicGroup.java b/core/src/main/java/brooklyn/entity/basic/DynamicGroup.java
index 078fc88..9ad8c83 100644
--- a/core/src/main/java/brooklyn/entity/basic/DynamicGroup.java
+++ b/core/src/main/java/brooklyn/entity/basic/DynamicGroup.java
@@ -23,6 +23,7 @@ import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.event.SensorEvent;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import com.google.common.base.Predicate;
import com.google.common.reflect.TypeToken;
@@ -31,7 +32,6 @@ import brooklyn.config.ConfigKey;
import brooklyn.entity.annotation.Effector;
import brooklyn.entity.trait.Startable;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
import groovy.lang.Closure;
@ImplementedBy(DynamicGroupImpl.class)
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/basic/DynamicGroupImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/DynamicGroupImpl.java b/core/src/main/java/brooklyn/entity/basic/DynamicGroupImpl.java
index 7ffe8a0..3b1eb47 100644
--- a/core/src/main/java/brooklyn/entity/basic/DynamicGroupImpl.java
+++ b/core/src/main/java/brooklyn/entity/basic/DynamicGroupImpl.java
@@ -30,6 +30,7 @@ import org.apache.brooklyn.api.event.SensorEventListener;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.core.management.internal.CollectionChangeListener;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -37,7 +38,6 @@ import brooklyn.config.BrooklynLogging;
import brooklyn.config.BrooklynLogging.LoggingLevel;
import brooklyn.util.GroovyJavaMethods;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.task.Tasks;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/basic/EffectorStartableImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/EffectorStartableImpl.java b/core/src/main/java/brooklyn/entity/basic/EffectorStartableImpl.java
index 0abb90c..f60f408 100644
--- a/core/src/main/java/brooklyn/entity/basic/EffectorStartableImpl.java
+++ b/core/src/main/java/brooklyn/entity/basic/EffectorStartableImpl.java
@@ -29,8 +29,7 @@ import brooklyn.entity.annotation.EffectorParam;
import brooklyn.entity.trait.Startable;
import org.apache.brooklyn.api.location.Location;
-
-import brooklyn.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import com.google.common.reflect.TypeToken;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/basic/Entities.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/Entities.java b/core/src/main/java/brooklyn/entity/basic/Entities.java
index c768726..635e99c 100644
--- a/core/src/main/java/brooklyn/entity/basic/Entities.java
+++ b/core/src/main/java/brooklyn/entity/basic/Entities.java
@@ -64,6 +64,15 @@ import org.apache.brooklyn.core.management.internal.EntityManagerInternal;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.core.management.internal.NonDeploymentManagementContext;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.FlagUtils;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.ParallelTask;
+import org.apache.brooklyn.core.util.task.TaskTags;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
+import org.apache.brooklyn.core.util.task.system.SystemTasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -80,20 +89,11 @@ import brooklyn.event.basic.DependentConfiguration;
import org.apache.brooklyn.location.basic.LocationInternal;
import org.apache.brooklyn.location.basic.Locations;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.FlagUtils;
import brooklyn.util.guava.Maybe;
import brooklyn.util.repeat.Repeater;
import brooklyn.util.stream.Streams;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.ParallelTask;
-import brooklyn.util.task.TaskTags;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.task.system.ProcessTaskWrapper;
-import brooklyn.util.task.system.SystemTasks;
import brooklyn.util.time.Duration;
import com.google.common.annotations.Beta;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/basic/EntityConfigMap.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/EntityConfigMap.java b/core/src/main/java/brooklyn/entity/basic/EntityConfigMap.java
index 988d6d7..8a7a9f0 100644
--- a/core/src/main/java/brooklyn/entity/basic/EntityConfigMap.java
+++ b/core/src/main/java/brooklyn/entity/basic/EntityConfigMap.java
@@ -28,6 +28,11 @@ import java.util.Set;
import org.apache.brooklyn.api.management.ExecutionContext;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.FlagUtils;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
+import org.apache.brooklyn.core.util.internal.ConfigKeySelfExtracting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -36,12 +41,7 @@ import brooklyn.config.ConfigKey;
import brooklyn.config.internal.AbstractConfigMapImpl;
import brooklyn.event.basic.StructuredConfigKey;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.flags.FlagUtils;
-import brooklyn.util.flags.SetFromFlag;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.guava.Maybe;
-import brooklyn.util.internal.ConfigKeySelfExtracting;
import com.google.common.base.Predicate;
import com.google.common.collect.Maps;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/basic/EntityFunctions.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/EntityFunctions.java b/core/src/main/java/brooklyn/entity/basic/EntityFunctions.java
index 4e02948..d9afc44 100644
--- a/core/src/main/java/brooklyn/entity/basic/EntityFunctions.java
+++ b/core/src/main/java/brooklyn/entity/basic/EntityFunctions.java
@@ -30,9 +30,9 @@ import org.apache.brooklyn.api.entity.trait.Identifiable;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import brooklyn.config.ConfigKey;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.guava.Functionals;
import com.google.common.base.Function;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/basic/EntityInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/EntityInternal.java b/core/src/main/java/brooklyn/entity/basic/EntityInternal.java
index 085079f..36e6907 100644
--- a/core/src/main/java/brooklyn/entity/basic/EntityInternal.java
+++ b/core/src/main/java/brooklyn/entity/basic/EntityInternal.java
@@ -33,10 +33,10 @@ import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.SubscriptionContext;
import org.apache.brooklyn.api.mementos.EntityMemento;
import org.apache.brooklyn.core.management.internal.EntityManagementSupport;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import brooklyn.basic.BrooklynObjectInternal;
import brooklyn.config.ConfigKey;
-import brooklyn.util.config.ConfigBag;
import com.google.common.annotations.Beta;
[37/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/internal/ssh/ShellAbstractTool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/internal/ssh/ShellAbstractTool.java b/core/src/main/java/brooklyn/util/internal/ssh/ShellAbstractTool.java
deleted file mode 100644
index 5c839a9..0000000
--- a/core/src/main/java/brooklyn/util/internal/ssh/ShellAbstractTool.java
+++ /dev/null
@@ -1,442 +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 brooklyn.util.internal.ssh;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-import java.io.ByteArrayInputStream;
-import java.io.Closeable;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.flags.TypeCoercions;
-import brooklyn.util.os.Os;
-import brooklyn.util.ssh.BashCommands;
-import brooklyn.util.text.Identifiers;
-import brooklyn.util.text.StringEscapes.BashStringEscapes;
-import brooklyn.util.text.Strings;
-import brooklyn.util.time.Duration;
-import brooklyn.util.time.Time;
-
-import com.google.common.base.Joiner;
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
-
-public abstract class ShellAbstractTool implements ShellTool {
-
- private static final Logger LOG = LoggerFactory.getLogger(ShellAbstractTool.class);
-
- protected final File localTempDir;
-
- public ShellAbstractTool(String localTempDir) {
- this(localTempDir == null ? null : new File(Os.tidyPath(localTempDir)));
- }
-
- public ShellAbstractTool(File localTempDir) {
- if (localTempDir == null) {
- localTempDir = new File(Os.tmp(), "tmpssh-"+Os.user());
- if (!localTempDir.exists()) localTempDir.mkdir();
- Os.deleteOnExitEmptyParentsUpTo(localTempDir, new File(Os.tmp()));
- }
- this.localTempDir = localTempDir;
- }
-
- public ShellAbstractTool() {
- this((File)null);
- }
-
- protected static void warnOnDeprecated(Map<String, ?> props, String deprecatedKey, String correctKey) {
- if (props.containsKey(deprecatedKey)) {
- if (correctKey != null && props.containsKey(correctKey)) {
- Object dv = props.get(deprecatedKey);
- Object cv = props.get(correctKey);
- if (!Objects.equal(cv, dv)) {
- LOG.warn("SshTool detected deprecated key '"+deprecatedKey+"' with different value ("+dv+") "+
- "than new key '"+correctKey+"' ("+cv+"); ambiguous which will be used");
- } else {
- // ignore, the deprecated key populated for legacy reasons
- }
- } else {
- Object dv = props.get(deprecatedKey);
- LOG.warn("SshTool detected deprecated key '"+deprecatedKey+"' used, with value ("+dv+")");
- }
- }
- }
-
- protected static Boolean hasVal(Map<String,?> map, ConfigKey<?> keyC) {
- String key = keyC.getName();
- return map.containsKey(key);
- }
-
- protected static <T> T getMandatoryVal(Map<String,?> map, ConfigKey<T> keyC) {
- String key = keyC.getName();
- checkArgument(map.containsKey(key), "must contain key '"+keyC+"'");
- return TypeCoercions.coerce(map.get(key), keyC.getTypeToken());
- }
-
- public static <T> T getOptionalVal(Map<String,?> map, ConfigKey<T> keyC) {
- if (keyC==null) return null;
- String key = keyC.getName();
- if (map!=null && map.containsKey(key) && map.get(key) != null) {
- return TypeCoercions.coerce(map.get(key), keyC.getTypeToken());
- } else {
- return keyC.getDefaultValue();
- }
- }
-
- /** returns the value of the key if specified, otherwise defaultValue */
- protected static <T> T getOptionalVal(Map<String,?> map, ConfigKey<T> keyC, T defaultValue) {
- String key = keyC.getName();
- if (map!=null && map.containsKey(key) && map.get(key) != null) {
- return TypeCoercions.coerce(map.get(key), keyC.getTypeToken());
- } else {
- return defaultValue;
- }
- }
-
- protected void closeWhispering(Closeable closeable, Object context) {
- closeWhispering(closeable, this, context);
- }
-
- /**
- * Similar to Guava's Closeables.closeQuitely, except logs exception at debug with context in message.
- */
- protected static void closeWhispering(Closeable closeable, Object context1, Object context2) {
- if (closeable != null) {
- try {
- closeable.close();
- } catch (IOException e) {
- if (LOG.isDebugEnabled()) {
- String msg = String.format("<< exception during close, for %s -> %s (%s); continuing.",
- context1, context2, closeable);
- if (LOG.isTraceEnabled())
- LOG.debug(msg + ": " + e);
- else
- LOG.trace(msg, e);
- }
- }
- }
- }
-
- protected File writeTempFile(InputStream contents) {
- File tempFile = Os.writeToTempFile(contents, localTempDir, "sshcopy", "data");
- tempFile.setReadable(false, false);
- tempFile.setReadable(true, true);
- tempFile.setWritable(false);
- tempFile.setExecutable(false);
- return tempFile;
- }
-
- protected File writeTempFile(String contents) {
- return writeTempFile(contents.getBytes());
- }
-
- protected File writeTempFile(byte[] contents) {
- return writeTempFile(new ByteArrayInputStream(contents));
- }
-
- protected String toScript(Map<String,?> props, List<String> commands, Map<String,?> env) {
- List<String> allcmds = toCommandSequence(commands, env);
- StringBuilder result = new StringBuilder();
- result.append(getOptionalVal(props, PROP_SCRIPT_HEADER)).append('\n');
-
- for (String cmd : allcmds) {
- result.append(cmd).append('\n');
- }
-
- return result.toString();
- }
-
- /**
- * Merges the commands and env, into a single set of commands. Also escapes the commands as required.
- *
- * Not all ssh servers handle "env", so instead convert env into exported variables
- */
- protected List<String> toCommandSequence(List<String> commands, Map<String,?> env) {
- List<String> result = new ArrayList<String>((env!=null ? env.size() : 0) + commands.size());
-
- if (env!=null) {
- for (Entry<String,?> entry : env.entrySet()) {
- if (entry.getKey() == null || entry.getValue() == null) {
- LOG.warn("env key-values must not be null; ignoring: key="+entry.getKey()+"; value="+entry.getValue());
- continue;
- }
- String escapedVal = BashStringEscapes.escapeLiteralForDoubleQuotedBash(entry.getValue().toString());
- result.add("export "+entry.getKey()+"=\""+escapedVal+"\"");
- }
- }
- for (CharSequence cmd : commands) { // objects in commands can be groovy GString so can't treat as String here
- result.add(cmd.toString());
- }
-
- return result;
- }
-
- @Override
- public int execScript(Map<String,?> props, List<String> commands) {
- return execScript(props, commands, Collections.<String,Object>emptyMap());
- }
-
- @Override
- public int execCommands(Map<String,?> props, List<String> commands) {
- return execCommands(props, commands, Collections.<String,Object>emptyMap());
- }
-
- protected static int asInt(Integer input, int valueIfInputNull) {
- return input != null ? input : valueIfInputNull;
- }
-
- protected abstract class ToolAbstractExecScript {
- protected final Map<String, ?> props;
- protected final String separator;
- protected final OutputStream out;
- protected final OutputStream err;
- protected final String scriptDir;
- protected final Boolean runAsRoot;
- protected final Boolean noExtraOutput;
- protected final Boolean noDeleteAfterExec;
- protected final String scriptNameWithoutExtension;
- protected final String scriptPath;
- protected final Duration execTimeout;
-
- public ToolAbstractExecScript(Map<String,?> props) {
- this.props = props;
- this.separator = getOptionalVal(props, PROP_SEPARATOR);
- this.out = getOptionalVal(props, PROP_OUT_STREAM);
- this.err = getOptionalVal(props, PROP_ERR_STREAM);
-
- this.scriptDir = getOptionalVal(props, PROP_SCRIPT_DIR);
- this.runAsRoot = getOptionalVal(props, PROP_RUN_AS_ROOT);
- this.noExtraOutput = getOptionalVal(props, PROP_NO_EXTRA_OUTPUT);
- this.noDeleteAfterExec = getOptionalVal(props, PROP_NO_DELETE_SCRIPT);
- this.execTimeout = getOptionalVal(props, PROP_EXEC_TIMEOUT);
-
- String summary = getOptionalVal(props, PROP_SUMMARY);
- if (summary!=null) {
- summary = Strings.makeValidFilename(summary);
- if (summary.length()>30)
- summary = summary.substring(0,30);
- }
- this.scriptNameWithoutExtension = "brooklyn-"+
- Time.makeDateStampString()+"-"+Identifiers.makeRandomId(4)+
- (Strings.isBlank(summary) ? "" : "-"+summary);
- this.scriptPath = Os.mergePathsUnix(scriptDir, scriptNameWithoutExtension+".sh");
- }
-
- /** builds the command to run the given script;
- * note that some modes require \$RESULT passed in order to access a variable, whereas most just need $ */
- protected List<String> buildRunScriptCommand() {
- MutableList.Builder<String> cmds = MutableList.<String>builder()
- .add((runAsRoot ? BashCommands.sudo(scriptPath) : scriptPath) + " < /dev/null")
- .add("RESULT=$?");
- if (noExtraOutput==null || !noExtraOutput)
- cmds.add("echo Executed "+scriptPath+", result $RESULT");
- if (noDeleteAfterExec!=Boolean.TRUE) {
- // use "-f" because some systems have "rm" aliased to "rm -i"
- // use "< /dev/null" to guarantee doesn't hang
- cmds.add("rm -f "+scriptPath+" < /dev/null");
- }
- cmds.add("exit $RESULT");
- return cmds.build();
- }
-
- protected String getSummary() {
- String summary = getOptionalVal(props, PROP_SUMMARY);
- return (summary != null) ? summary : scriptPath;
- }
-
- public abstract int run();
- }
-
- protected abstract class ToolAbstractAsyncExecScript extends ToolAbstractExecScript {
- protected final String stdoutPath;
- protected final String stderrPath;
- protected final String exitStatusPath;
- protected final String pidPath;
-
- public ToolAbstractAsyncExecScript(Map<String,?> props) {
- super(props);
-
- stdoutPath = Os.mergePathsUnix(scriptDir, scriptNameWithoutExtension + ".stdout");
- stderrPath = Os.mergePathsUnix(scriptDir, scriptNameWithoutExtension + ".stderr");
- exitStatusPath = Os.mergePathsUnix(scriptDir, scriptNameWithoutExtension + ".exitstatus");
- pidPath = Os.mergePathsUnix(scriptDir, scriptNameWithoutExtension + ".pid");
- }
-
- /**
- * Builds the command to run the given script, asynchronously.
- * The executed command will return immediately, but the output from the script
- * will continue to be written
- * note that some modes require \$RESULT passed in order to access a variable, whereas most just need $ */
- @Override
- protected List<String> buildRunScriptCommand() {
- String touchCmd = String.format("touch %s %s %s %s", stdoutPath, stderrPath, exitStatusPath, pidPath);
- String cmd = String.format("nohup sh -c \"( %s > %s 2> %s < /dev/null ) ; echo \\$? > %s \" > /dev/null 2>&1 < /dev/null &", scriptPath, stdoutPath, stderrPath, exitStatusPath);
- MutableList.Builder<String> cmds = MutableList.<String>builder()
- .add(runAsRoot ? BashCommands.sudo(touchCmd) : touchCmd)
- .add(runAsRoot ? BashCommands.sudo(cmd) : cmd)
- .add("echo $! > "+pidPath)
- .add("RESULT=$?");
- if (noExtraOutput==null || !noExtraOutput) {
- cmds.add("echo Executing async "+scriptPath);
- }
- cmds.add("exit $RESULT");
- return cmds.build();
- }
-
- /**
- * Builds the command to retrieve the exit status of the command, written to stdout.
- */
- protected List<String> buildRetrieveStatusCommand() {
- // Retrieve exit status from file (writtent to stdout), if populated;
- // if not found and pid still running, then return empty string; else exit code 1.
- List<String> cmdParts = ImmutableList.of(
- "# Retrieve status", // comment is to aid testing - see SshjToolAsyncStubIntegrationTest
- "if test -s "+exitStatusPath+"; then",
- " cat "+exitStatusPath,
- "elif test -s "+pidPath+"; then",
- " pid=`cat "+pidPath+"`",
- " if ! ps -p $pid > /dev/null < /dev/null; then",
- " # no exit status, and not executing; give a few seconds grace in case just about to write exit status",
- " sleep 3",
- " if test -s "+exitStatusPath+"; then",
- " cat "+exitStatusPath+"",
- " else",
- " echo \"No exit status in "+exitStatusPath+", and pid in "+pidPath+" ($pid) not executing\"",
- " exit 1",
- " fi",
- " fi",
- "else",
- " echo \"No exit status in "+exitStatusPath+", and "+pidPath+" is empty\"",
- " exit 1",
- "fi"+"\n");
- String cmd = Joiner.on("\n").join(cmdParts);
-
- MutableList.Builder<String> cmds = MutableList.<String>builder()
- .add((runAsRoot ? BashCommands.sudo(cmd) : cmd))
- .add("RESULT=$?");
- cmds.add("exit $RESULT");
- return cmds.build();
- }
-
- /**
- * Builds the command to retrieve the stdout and stderr of the async command.
- * An offset can be given, to only retrieve data starting at a particular character (indexed from 0).
- */
- protected List<String> buildRetrieveStdoutAndStderrCommand(int stdoutPosition, int stderrPosition) {
- // Note that `tail -c +1` means start at the *first* character (i.e. start counting from 1, not 0)
- String catStdoutCmd = "tail -c +"+(stdoutPosition+1)+" "+stdoutPath+" 2> /dev/null";
- String catStderrCmd = "tail -c +"+(stderrPosition+1)+" "+stderrPath+" 2>&1 > /dev/null";
- MutableList.Builder<String> cmds = MutableList.<String>builder()
- .add((runAsRoot ? BashCommands.sudo(catStdoutCmd) : catStdoutCmd))
- .add((runAsRoot ? BashCommands.sudo(catStderrCmd) : catStderrCmd))
- .add("RESULT=$?");
- cmds.add("exit $RESULT");
- return cmds.build();
- }
-
- /**
- * Builds the command to retrieve the stdout and stderr of the async command.
- * An offset can be given, to only retrieve data starting at a particular character (indexed from 0).
- */
- protected List<String> buildLongPollCommand(int stdoutPosition, int stderrPosition, Duration timeout) {
- long maxTime = Math.max(1, timeout.toSeconds());
-
- // Note that `tail -c +1` means start at the *first* character (i.e. start counting from 1, not 0)
- List<String> waitForExitStatusParts = ImmutableList.of(
- //Should be careful here because any output will be part of the stdout/stderr streams
- "# Long poll", // comment is to aid testing - see SshjToolAsyncStubIntegrationTest
- // disown to avoid Terminated message after killing the process
- // redirect error output to avoid "file truncated" messages
- "tail -c +"+(stdoutPosition+1)+" -f "+stdoutPath+" 2> /dev/null & export TAIL_STDOUT_PID=$!; disown",
- "tail -c +"+(stderrPosition+1)+" -f "+stderrPath+" 1>&2 2> /dev/null & export TAIL_STDERR_PID=$!; disown",
- "EXIT_STATUS_PATH="+exitStatusPath,
- "PID_PATH="+pidPath,
- "MAX_TIME="+maxTime,
- "COUNTER=0",
- "while [ \"$COUNTER\" -lt $MAX_TIME ]; do",
- " if test -s $EXIT_STATUS_PATH; then",
- " EXIT_STATUS=`cat $EXIT_STATUS_PATH`",
- " kill ${TAIL_STDERR_PID} ${TAIL_STDOUT_PID} 2> /dev/null",
- " exit $EXIT_STATUS",
- " elif test -s $PID_PATH; then",
- " PID=`cat $PID_PATH`",
- " if ! ps -p $PID > /dev/null 2>&1 < /dev/null; then",
- " # no exit status, and not executing; give a few seconds grace in case just about to write exit status",
- " sleep 3",
- " if test -s $EXIT_STATUS_PATH; then",
- " EXIT_STATUS=`cat $EXIT_STATUS_PATH`",
- " kill ${TAIL_STDERR_PID} ${TAIL_STDOUT_PID} 2> /dev/null",
- " exit $EXIT_STATUS",
- " else",
- " echo \"No exit status in $EXIT_STATUS_PATH, and pid in $PID_PATH ($PID) not executing\"",
- " kill ${TAIL_STDERR_PID} ${TAIL_STDOUT_PID} 2> /dev/null",
- " exit 126",
- " fi",
- " fi",
- " fi",
- " # No exit status in $EXIT_STATUS_PATH; keep waiting",
- " sleep 1",
- " COUNTER+=1",
- "done",
- "kill ${TAIL_STDERR_PID} ${TAIL_STDOUT_PID} 2> /dev/null",
- "exit 125"+"\n");
- String waitForExitStatus = Joiner.on("\n").join(waitForExitStatusParts);
-
- return ImmutableList.of(runAsRoot ? BashCommands.sudo(waitForExitStatus) : waitForExitStatus);
- }
-
- protected List<String> deleteTemporaryFilesCommand() {
- ImmutableList.Builder<String> cmdParts = ImmutableList.builder();
-
- if (!Boolean.TRUE.equals(noDeleteAfterExec)) {
- // use "-f" because some systems have "rm" aliased to "rm -i"
- // use "< /dev/null" to guarantee doesn't hang
- cmdParts.add(
- "rm -f "+scriptPath+" "+stdoutPath+" "+stderrPath+" "+exitStatusPath+" "+pidPath+" < /dev/null");
- }
-
- // If the buildLongPollCommand didn't complete properly then it might have left tail command running;
- // ensure they are killed.
- cmdParts.add(
- //ignore error output for the case where there are no running processes and kill is called without arguments
- "ps aux | grep \"tail -c\" | grep \""+stdoutPath+"\" | grep -v grep | awk '{ printf $2 }' | xargs kill 2> /dev/null",
- "ps aux | grep \"tail -c\" | grep \""+stderrPath+"\" | grep -v grep | awk '{ printf $2 }' | xargs kill 2> /dev/null");
-
- String cmd = Joiner.on("\n").join(cmdParts.build());
-
- return ImmutableList.of(runAsRoot ? BashCommands.sudo(cmd) : cmd);
- }
-
- @Override
- public abstract int run();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/internal/ssh/ShellTool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/internal/ssh/ShellTool.java b/core/src/main/java/brooklyn/util/internal/ssh/ShellTool.java
deleted file mode 100644
index 0555039..0000000
--- a/core/src/main/java/brooklyn/util/internal/ssh/ShellTool.java
+++ /dev/null
@@ -1,113 +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 brooklyn.util.internal.ssh;
-
-import static brooklyn.entity.basic.ConfigKeys.newConfigKey;
-import static brooklyn.entity.basic.ConfigKeys.newStringConfigKey;
-
-import java.io.OutputStream;
-import java.util.List;
-import java.util.Map;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.util.os.Os;
-import brooklyn.util.time.Duration;
-
-/** Methods for executing things in an environment (localhost process, or ssh) */
-public interface ShellTool {
-
- // config which applies to sessions
-
- public static final ConfigKey<String> PROP_LOCAL_TEMP_DIR = newStringConfigKey(
- "localTempDir",
- "The directory on the local machine (i.e. running brooklyn) for writing temp files",
- Os.mergePaths(Os.tmp(), "brooklyn-"+Os.user()+"-ssh-tmp"));
-
- // config which applies to calls:
-
- public static final ConfigKey<Boolean> PROP_RUN_AS_ROOT = newConfigKey("runAsRoot", "When running a script, whether to run as root", Boolean.FALSE);
-
- public static final ConfigKey<OutputStream> PROP_OUT_STREAM = newConfigKey(OutputStream.class, "out", "Stream to which to capture stdout");
- public static final ConfigKey<OutputStream> PROP_ERR_STREAM = newConfigKey(OutputStream.class, "err", "Stream to which to capture stderr");
-
- public static final ConfigKey<Boolean> PROP_NO_EXTRA_OUTPUT = newConfigKey("noExtraOutput", "Suppresses any decorative output such as result code which some tool commands insert", false);
-
- public static final ConfigKey<String> PROP_SEPARATOR = newConfigKey("separator", "string to insert between caller-supplied commands being executed as commands", " ; ");
-
- public static final ConfigKey<String> PROP_SCRIPT_DIR = newConfigKey("scriptDir", "directory where scripts should be copied", "/tmp");
- public static final ConfigKey<String> PROP_SCRIPT_HEADER = newConfigKey("scriptHeader", "lines to insert at the start of scripts generated for caller-supplied commands for script execution", "#!/bin/bash -e\n");
- public static final ConfigKey<String> PROP_DIRECT_HEADER = newConfigKey("directHeader", "commands to run at the target before any caller-supplied commands for direct execution", "exec bash -e");
-
- ConfigKey<Boolean> PROP_NO_DELETE_SCRIPT = newConfigKey("noDeleteAfterExec", "Retains the generated script file after executing the commands instead of deleting it", false);
-
- ConfigKey<String> PROP_SUMMARY = ConfigKeys.newStringConfigKey("summary", "Provides a human-readable summary, used in file generation etc");
-
- ConfigKey<Duration> PROP_EXEC_TIMEOUT = newConfigKey("execTimeout", "Timeout when executing a script", Duration.PRACTICALLY_FOREVER);
-
- ConfigKey<Boolean> PROP_EXEC_ASYNC = newConfigKey("execAsync", "Executes the script asynchronously, and then polls for the result (and for stdout/stderr)", false);
-
- ConfigKey<Duration> PROP_EXEC_ASYNC_POLLING_TIMEOUT = newConfigKey("execAsyncPollTimeout", "Timeout per poll when executing a script asynchronously", Duration.ONE_MINUTE);
-
- /**
- * Executes the set of commands in a shell script. Blocks until completion.
- * <p>
- *
- * Optional properties are the same common ones as for {@link #execCommands(Map, List, Map)} with the addition of:
- * <ul>
- * <li>{@link #PROP_RUN_AS_ROOT}
- * <li>{@link #PROP_SCRIPT_DIR}
- * </ul>
- *
- * @return exit status of script
- */
- public int execScript(Map<String,?> props, List<String> commands, Map<String,?> env);
-
- /**
- * @see #execScript(Map, List, Map)
- */
- public int execScript(Map<String,?> props, List<String> commands);
-
- /**
- * Executes the set of commands using ssh exec.
- *
- * This is generally more efficient than ssh shell mode (cf {@link #execScript(Map, List, Map)}),
- * but is not suitable if you need env values which are only set on a fully-fledged shell,
- * or if you want the entire block executed with root permission.
- *
- * Common optional properties (which also apply to {@link #execScript(Map, List, Map)}) are:
- * <ul>
- * <li>{@link #PROP_OUT_STREAM}
- * <li>{@link #PROP_ERR_STREAM}
- * <li>{@link #PROP_SEPARATOR} (for some modes)
- * <li>{@link #PROP_NO_EXTRA_OUTPUT} (often there is no extra output here)
- * </ul>
- *
- * Note that {@link #PROP_RUN_AS_ROOT} is <i>not</i> typically supported here. Prefer {@link #execScript(Map, List, Map)}).
- *
- * @return exit status of commands
- */
- public int execCommands(Map<String,?> properties, List<String> commands, Map<String,?> env);
-
- /**
- * @see #execCommands(Map, List, Map)
- */
- public int execCommands(Map<String,?> properties, List<String> commands);
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/internal/ssh/SshAbstractTool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/internal/ssh/SshAbstractTool.java b/core/src/main/java/brooklyn/util/internal/ssh/SshAbstractTool.java
deleted file mode 100644
index eb0222a..0000000
--- a/core/src/main/java/brooklyn/util/internal/ssh/SshAbstractTool.java
+++ /dev/null
@@ -1,172 +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 brooklyn.util.internal.ssh;
-
-import static brooklyn.util.net.Networking.checkPortValid;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.io.File;
-import java.util.Map;
-import java.util.Set;
-
-import brooklyn.util.os.Os;
-
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Sets;
-
-public abstract class SshAbstractTool extends ShellAbstractTool implements SshTool {
-
- protected final String toString;
-
- protected final String host;
- protected final String user;
- protected final String password;
- protected final int port;
- protected String privateKeyPassphrase;
- protected String privateKeyData;
- protected File privateKeyFile;
- protected boolean strictHostKeyChecking;
- protected boolean allocatePTY;
-
- public static interface SshAction<T> {
- void clear() throws Exception;
- T create() throws Exception;
- }
-
- public static abstract class AbstractSshToolBuilder<T extends SshTool, B extends AbstractSshToolBuilder<T,B>> {
- protected String host;
- protected int port = 22;
- protected String user = System.getProperty("user.name");
- protected String password;
- protected String privateKeyData;
- protected String privateKeyPassphrase;
- protected Set<String> privateKeyFiles = Sets.newLinkedHashSet();
- protected boolean strictHostKeyChecking = false;
- protected boolean allocatePTY = false;
- protected File localTempDir = null;
-
- @SuppressWarnings("unchecked")
- protected B self() {
- return (B) this;
- }
-
- public B from(Map<String,?> props) {
- host = getMandatoryVal(props, PROP_HOST);
- port = getOptionalVal(props, PROP_PORT);
- user = getOptionalVal(props, PROP_USER);
-
- password = getOptionalVal(props, PROP_PASSWORD);
-
- warnOnDeprecated(props, "privateKey", "privateKeyData");
- privateKeyData = getOptionalVal(props, PROP_PRIVATE_KEY_DATA);
- privateKeyPassphrase = getOptionalVal(props, PROP_PRIVATE_KEY_PASSPHRASE);
-
- // for backwards compatibility accept keyFiles and privateKey
- // but sshj accepts only a single privateKeyFile; leave blank to use defaults (i.e. ~/.ssh/id_rsa and id_dsa)
- warnOnDeprecated(props, "keyFiles", null);
- String privateKeyFile = getOptionalVal(props, PROP_PRIVATE_KEY_FILE);
- if (privateKeyFile != null) privateKeyFiles.add(privateKeyFile);
-
- strictHostKeyChecking = getOptionalVal(props, PROP_STRICT_HOST_KEY_CHECKING);
- allocatePTY = getOptionalVal(props, PROP_ALLOCATE_PTY);
-
- String localTempDirPath = getOptionalVal(props, PROP_LOCAL_TEMP_DIR);
- localTempDir = (localTempDirPath == null) ? null : new File(Os.tidyPath(localTempDirPath));
-
- return self();
- }
- public B host(String val) {
- this.host = val; return self();
- }
- public B user(String val) {
- this.user = val; return self();
- }
- public B password(String val) {
- this.password = val; return self();
- }
- public B port(int val) {
- this.port = val; return self();
- }
- public B privateKeyPassphrase(String val) {
- this.privateKeyPassphrase = val; return self();
- }
- /** @deprecated 1.4.0, use privateKeyData */
- public B privateKey(String val) {
- this.privateKeyData = val; return self();
- }
- public B privateKeyData(String val) {
- this.privateKeyData = val; return self();
- }
- public B privateKeyFile(String val) {
- this.privateKeyFiles.add(val); return self();
- }
- public B localTempDir(File val) {
- this.localTempDir = val; return self();
- }
- public abstract T build();
- }
-
- protected SshAbstractTool(AbstractSshToolBuilder<?,?> builder) {
- super(builder.localTempDir);
-
- host = checkNotNull(builder.host, "host");
- port = builder.port;
- user = builder.user;
- password = builder.password;
- strictHostKeyChecking = builder.strictHostKeyChecking;
- allocatePTY = builder.allocatePTY;
- privateKeyPassphrase = builder.privateKeyPassphrase;
- privateKeyData = builder.privateKeyData;
-
- if (builder.privateKeyFiles.size() > 1) {
- throw new IllegalArgumentException("sshj supports only a single private key-file; " +
- "for defaults of ~/.ssh/id_rsa and ~/.ssh/id_dsa leave blank");
- } else if (builder.privateKeyFiles.size() == 1) {
- String privateKeyFileStr = Iterables.get(builder.privateKeyFiles, 0);
- String amendedKeyFile = privateKeyFileStr.startsWith("~") ? (System.getProperty("user.home")+privateKeyFileStr.substring(1)) : privateKeyFileStr;
- privateKeyFile = new File(amendedKeyFile);
- } else {
- privateKeyFile = null;
- }
-
- checkArgument(host.length() > 0, "host value must not be an empty string");
- checkPortValid(port, "ssh port");
-
- toString = String.format("%s@%s:%d", user, host, port);
- }
-
- @Override
- public String toString() {
- return toString;
- }
-
- public String getHostAddress() {
- return this.host;
- }
-
- public String getUsername() {
- return this.user;
- }
-
- protected SshException propagate(Exception e, String message) throws SshException {
- throw new SshException("(" + toString() + ") " + message + ": " + e.getMessage(), e);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/internal/ssh/SshException.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/internal/ssh/SshException.java b/core/src/main/java/brooklyn/util/internal/ssh/SshException.java
deleted file mode 100644
index 20653bb..0000000
--- a/core/src/main/java/brooklyn/util/internal/ssh/SshException.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 brooklyn.util.internal.ssh;
-
-public class SshException extends RuntimeException {
-
- private static final long serialVersionUID = -5690230838066860965L;
-
- public SshException(String msg) {
- super(msg);
- }
-
- public SshException(String msg, Throwable cause) {
- super(msg, cause);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/internal/ssh/SshTool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/internal/ssh/SshTool.java b/core/src/main/java/brooklyn/util/internal/ssh/SshTool.java
deleted file mode 100644
index a676599..0000000
--- a/core/src/main/java/brooklyn/util/internal/ssh/SshTool.java
+++ /dev/null
@@ -1,174 +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 brooklyn.util.internal.ssh;
-
-import static brooklyn.entity.basic.ConfigKeys.newConfigKey;
-import static brooklyn.entity.basic.ConfigKeys.newStringConfigKey;
-
-import java.io.File;
-import java.io.InputStream;
-import java.util.List;
-import java.util.Map;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.util.stream.KnownSizeInputStream;
-import brooklyn.util.time.Duration;
-
-/**
- * Defines the methods available on the various different implementations of SSH,
- * and configuration options which are also generally available.
- * <p>
- * The config keys in this class can be supplied (or their string equivalents, where the flags/props take {@code Map<String,?>})
- * to influence configuration, either for the tool/session itself or for individual commands.
- * <p>
- * To specify some of these properties on a global basis, use the variants of the keys here
- * contained in {@link ConfigKeys}
- * (which are generally {@value #BROOKLYN_CONFIG_KEY_PREFIX} prefixed to the names of keys here).
- */
-public interface SshTool extends ShellTool {
-
- /** Public-facing global config keys for Brooklyn are defined in ConfigKeys,
- * and have this prefix pre-prended to the config keys in this class.
- * These keys are detected from entity/global config and automatically applied to ssh executions. */
- public static final String BROOKLYN_CONFIG_KEY_PREFIX = "brooklyn.ssh.config.";
-
- public static final ConfigKey<String> PROP_TOOL_CLASS = newStringConfigKey("tool.class", "SshTool implementation to use", null);
-
- public static final ConfigKey<String> PROP_HOST = newStringConfigKey("host", "Host to connect to (required)", null);
- public static final ConfigKey<Integer> PROP_PORT = newConfigKey("port", "Port on host to connect to", 22);
- public static final ConfigKey<String> PROP_USER = newConfigKey("user", "User to connect as", System.getProperty("user.name"));
- public static final ConfigKey<String> PROP_PASSWORD = newStringConfigKey("password", "Password to use to connect", null);
-
- public static final ConfigKey<String> PROP_PRIVATE_KEY_FILE = newStringConfigKey("privateKeyFile", "the path of an ssh private key file; leave blank to use defaults (i.e. ~/.ssh/id_rsa and id_dsa)", null);
- public static final ConfigKey<String> PROP_PRIVATE_KEY_DATA = newStringConfigKey("privateKeyData", "the private ssh key (e.g. contents of an id_rsa or id_dsa file)", null);
- public static final ConfigKey<String> PROP_PRIVATE_KEY_PASSPHRASE = newStringConfigKey("privateKeyPassphrase", "the passphrase for the ssh private key", null);
- public static final ConfigKey<Boolean> PROP_STRICT_HOST_KEY_CHECKING = newConfigKey("strictHostKeyChecking", "whether to check the remote host's identification; defaults to false", false);
- public static final ConfigKey<Boolean> PROP_ALLOCATE_PTY = newConfigKey("allocatePTY", "whether to allocate PTY (vt100); if true then stderr is sent to stdout, but sometimes required for sudo'ing due to requiretty", false);
-
- public static final ConfigKey<Long> PROP_CONNECT_TIMEOUT = newConfigKey("connectTimeout", "Timeout in millis when establishing an SSH connection; if 0 then uses default (usually 30s)", 0L);
- public static final ConfigKey<Long> PROP_SESSION_TIMEOUT = newConfigKey("sessionTimeout", "Timeout in millis for an ssh session; if 0 then uses default", 0L);
- public static final ConfigKey<Integer> PROP_SSH_TRIES = newConfigKey("sshTries", "Max number of times to attempt ssh operations", 4);
- public static final ConfigKey<Long> PROP_SSH_TRIES_TIMEOUT = newConfigKey("sshTriesTimeout", "Time limit for attempting retries; will not interrupt tasks, but stops retrying after a total amount of elapsed time", Duration.TWO_MINUTES.toMilliseconds());
- public static final ConfigKey<Long> PROP_SSH_RETRY_DELAY = newConfigKey("sshRetryDelay", "Time (in milliseconds) before first ssh-retry, after which it will do exponential backoff", 50L);
-
- // NB -- items above apply for _session_ (a tool), below apply for a _call_
- // TODO would be nice to track which arguments are used, so we can indicate whether extras are supplied
-
- public static final ConfigKey<String> PROP_PERMISSIONS = newConfigKey("permissions", "Default permissions for files copied/created on remote machine; must be four-digit octal string, default '0644'", "0644");
- public static final ConfigKey<Long> PROP_LAST_MODIFICATION_DATE = newConfigKey("lastModificationDate", "Last-modification-date to be set on files copied/created (should be UTC/1000, ie seconds since 1970; default 0 usually means current)", 0L);
- public static final ConfigKey<Long> PROP_LAST_ACCESS_DATE = newConfigKey("lastAccessDate", "Last-access-date to be set on files copied/created (should be UTC/1000, ie seconds since 1970; default 0 usually means lastModificationDate)", 0L);
- public static final ConfigKey<Integer> PROP_OWNER_UID = newConfigKey("ownerUid", "Default owner UID (not username) for files created on remote machine; default is unset", -1);
-
- // TODO remove unnecessary "public static final" modifiers
-
- // TODO Could define the following in SshMachineLocation, or some such?
- //public static ConfigKey<String> PROP_LOG_PREFIX = newStringKey("logPrefix", "???", ???);
- //public static ConfigKey<Boolean> PROP_NO_STDOUT_LOGGING = newStringKey("noStdoutLogging", "???", ???);
- //public static ConfigKey<Boolean> PROP_NO_STDOUT_LOGGING = newStringKey("noStdoutLogging", "???", ???);
-
- /**
- * @throws SshException
- */
- public void connect();
-
- /**
- * @deprecated since 0.7.0; (since much earlier) this ignores the argument in favour of {@link #PROP_SSH_TRIES}
- *
- * @param maxAttempts
- * @throws SshException
- */
- public void connect(int maxAttempts);
-
- public void disconnect();
-
- public boolean isConnected();
-
- /**
- * @see super{@link #execScript(Map, List, Map)}
- * @throws SshException If failed to connect
- */
- @Override
- public int execScript(Map<String,?> props, List<String> commands, Map<String,?> env);
-
- /**
- * @see #execScript(Map, List, Map)
- */
- @Override
- public int execScript(Map<String,?> props, List<String> commands);
-
- /**
- * @see super{@link #execCommands(Map, List, Map)}
- * @throws SshException If failed to connect
- */
- @Override
- public int execCommands(Map<String,?> properties, List<String> commands, Map<String,?> env);
-
- /**
- * @see #execCommands(Map, List, Map)
- */
- @Override
- public int execCommands(Map<String,?> properties, List<String> commands);
-
- /**
- * Copies the file to the server at the given path.
- * If path is null, empty, '.', '..', or ends with '/' then file name is used.
- * <p>
- * The file will not preserve the permission of last _access_ date.
- *
- * Optional properties are:
- * <ul>
- * <li>'permissions' (e.g. "0644") - see {@link #PROP_PERMISSIONS}
- * <li>'lastModificationDate' see {@link #PROP_LAST_MODIFICATION_DATE}; not supported by all SshTool implementations
- * <li>'lastAccessDate' see {@link #PROP_LAST_ACCESS_DATE}; not supported by all SshTool implementations
- * </ul>
- *
- * @return exit code (not supported by all SshTool implementations, usually throwing on error;
- * sometimes possibly returning 0 even on error (?) )
- */
- public int copyToServer(Map<String,?> props, File localFile, String pathAndFileOnRemoteServer);
-
- /**
- * Closes the given input stream before returning.
- * Consider using {@link KnownSizeInputStream} for efficiency when the size of the stream is known.
- *
- * @see #copyToServer(Map, File, String)
- */
- public int copyToServer(Map<String,?> props, InputStream contents, String pathAndFileOnRemoteServer);
-
- /**
- * @see #copyToServer(Map, File, String)
- */
- public int copyToServer(Map<String,?> props, byte[] contents, String pathAndFileOnRemoteServer);
-
- /**
- * Copies the file from the server at the given path.
- *
- * @return exit code (not supported by all SshTool implementations, usually throwing on error;
- * sometimes possibly returning 0 even on error (?) )
- */
- public int copyFromServer(Map<String,?> props, String pathAndFileOnRemoteServer, File local);
-
- // TODO might be more efficicent than copyFrom by way of temp file
-// /**
-// * Reads from the file at the given path on the remote server.
-// */
-// public InputStream streamFromServer(Map<String,?> props, String pathAndFileOnRemoteServer);
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/internal/ssh/cli/SshCliTool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/internal/ssh/cli/SshCliTool.java b/core/src/main/java/brooklyn/util/internal/ssh/cli/SshCliTool.java
deleted file mode 100644
index 91b5d91..0000000
--- a/core/src/main/java/brooklyn/util/internal/ssh/cli/SshCliTool.java
+++ /dev/null
@@ -1,316 +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 brooklyn.util.internal.ssh.cli;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.io.File;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.internal.ssh.SshAbstractTool;
-import brooklyn.util.internal.ssh.SshTool;
-import brooklyn.util.internal.ssh.process.ProcessTool;
-import brooklyn.util.text.StringEscapes.BashStringEscapes;
-import brooklyn.util.text.Strings;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
-
-/**
- * For ssh and scp commands, delegating to system calls.
- */
-public class SshCliTool extends SshAbstractTool implements SshTool {
-
- // TODO No retry support, with backoffLimitedRetryHandler
-
- private static final Logger LOG = LoggerFactory.getLogger(SshCliTool.class);
-
- public static final ConfigKey<String> PROP_SSH_EXECUTABLE = ConfigKeys.newStringConfigKey("sshExecutable", "command to execute for ssh (defaults to \"ssh\", but could be overridden to sshg3 for Tectia for example)", "ssh");
- public static final ConfigKey<String> PROP_SSH_FLAGS = ConfigKeys.newStringConfigKey("sshFlags", "flags to pass to ssh, as a space separated list", "");
- public static final ConfigKey<String> PROP_SCP_EXECUTABLE = ConfigKeys.newStringConfigKey("scpExecutable", "command to execute for scp (defaults to \"scp\", but could be overridden to scpg3 for Tectia for example)", "scp");
-
- public static Builder<SshCliTool,?> builder() {
- return new ConcreteBuilder();
- }
-
- private static class ConcreteBuilder extends Builder<SshCliTool, ConcreteBuilder> {
- }
-
- public static class Builder<T extends SshCliTool, B extends Builder<T,B>> extends AbstractSshToolBuilder<T,B> {
- private String sshExecutable;
- private String sshFlags;
- private String scpExecutable;
-
- @Override
- public B from(Map<String,?> props) {
- super.from(props);
- sshExecutable = getOptionalVal(props, PROP_SSH_EXECUTABLE);
- sshFlags = getOptionalVal(props, PROP_SSH_FLAGS);
- scpExecutable = getOptionalVal(props, PROP_SCP_EXECUTABLE);
- return self();
- }
- public B sshExecutable(String val) {
- this.sshExecutable = val; return self();
- }
- public B scpExecutable(String val) {
- this.scpExecutable = val; return self();
- }
- @SuppressWarnings("unchecked")
- public T build() {
- return (T) new SshCliTool(this);
- }
- }
-
- private final String sshExecutable;
- private final String sshFlags;
- private final String scpExecutable;
-
- public SshCliTool(Map<String,?> map) {
- this(builder().from(map));
- }
-
- private SshCliTool(Builder<?,?> builder) {
- super(builder);
- sshExecutable = checkNotNull(builder.sshExecutable);
- sshFlags = checkNotNull(builder.sshFlags);
- scpExecutable = checkNotNull(builder.scpExecutable);
- if (LOG.isTraceEnabled()) LOG.trace("Created SshCliTool {} ({})", this, System.identityHashCode(this));
- }
-
- @Override
- public void connect() {
- // no-op
- }
-
- @Override
- public void connect(int maxAttempts) {
- // no-op
- }
-
- @Override
- public void disconnect() {
- if (LOG.isTraceEnabled()) LOG.trace("Disconnecting SshCliTool {} ({}) - no-op", this, System.identityHashCode(this));
- // no-op
- }
-
- @Override
- public boolean isConnected() {
- // TODO Always pretends to be connected
- return true;
- }
-
- @Override
- public int copyToServer(java.util.Map<String,?> props, byte[] contents, String pathAndFileOnRemoteServer) {
- return copyTempFileToServer(props, writeTempFile(contents), pathAndFileOnRemoteServer);
- }
-
- @Override
- public int copyToServer(java.util.Map<String,?> props, InputStream contents, String pathAndFileOnRemoteServer) {
- return copyTempFileToServer(props, writeTempFile(contents), pathAndFileOnRemoteServer);
- }
-
- @Override
- public int copyToServer(Map<String,?> props, File f, String pathAndFileOnRemoteServer) {
- if (hasVal(props, PROP_LAST_MODIFICATION_DATE)) {
- LOG.warn("Unsupported ssh feature, setting lastModificationDate for {}:{}", this, pathAndFileOnRemoteServer);
- }
- if (hasVal(props, PROP_LAST_ACCESS_DATE)) {
- LOG.warn("Unsupported ssh feature, setting lastAccessDate for {}:{}", this, pathAndFileOnRemoteServer);
- }
- String permissions = getOptionalVal(props, PROP_PERMISSIONS);
-
- int uid = getOptionalVal(props, PROP_OWNER_UID);
-
- int result = scpToServer(props, f, pathAndFileOnRemoteServer);
- if (result == 0) {
- result = chmodOnServer(props, permissions, pathAndFileOnRemoteServer);
- if (result == 0) {
- if (uid != -1) {
- result = chownOnServer(props, uid, pathAndFileOnRemoteServer);
- if (result != 0) {
- LOG.warn("Error setting file owner to {}, after copying file {} to {}:{}; exit code {}", new Object[] { uid, pathAndFileOnRemoteServer, this, f, result });
- }
- }
- } else {
- LOG.warn("Error setting file permissions to {}, after copying file {} to {}:{}; exit code {}", new Object[] { permissions, pathAndFileOnRemoteServer, this, f, result });
- }
- } else {
- LOG.warn("Error copying file {} to {}:{}; exit code {}", new Object[] {pathAndFileOnRemoteServer, this, f, result});
- }
- return result;
- }
-
- private int chownOnServer(Map<String,?> props, int uid, String remote) {
- return sshExec(props, "chown "+uid+" "+remote);
- }
-
- private int copyTempFileToServer(Map<String,?> props, File f, String pathAndFileOnRemoteServer) {
- try {
- return copyToServer(props, f, pathAndFileOnRemoteServer);
- } finally {
- f.delete();
- }
- }
-
- @Override
- public int copyFromServer(Map<String,?> props, String pathAndFileOnRemoteServer, File localFile) {
- return scpFromServer(props, pathAndFileOnRemoteServer, localFile);
- }
-
- @Override
- public int execScript(final Map<String,?> props, final List<String> commands, final Map<String,?> env) {
- return new ToolAbstractExecScript(props) {
- public int run() {
- String scriptContents = toScript(props, commands, env);
- if (LOG.isTraceEnabled()) LOG.trace("Running shell command at {} as script: {}", host, scriptContents);
- copyTempFileToServer(ImmutableMap.of("permissions", "0700"), writeTempFile(scriptContents), scriptPath);
-
- String cmd = Strings.join(buildRunScriptCommand(), separator);
- return asInt(sshExec(props, cmd), -1);
- }
- }.run();
- }
-
- @Override
- public int execCommands(Map<String,?> props, List<String> commands, Map<String,?> env) {
- Map<String,Object> props2 = new MutableMap<String,Object>();
- if (props!=null) props2.putAll(props);
- props2.put(SshTool.PROP_NO_EXTRA_OUTPUT.getName(), true);
- return execScript(props2, commands, env);
- }
-
- private int scpToServer(Map<String,?> props, File local, String remote) {
- String to = (Strings.isEmpty(getUsername()) ? "" : getUsername()+"@")+getHostAddress()+":"+remote;
- return scpExec(props, local.getAbsolutePath(), to);
- }
-
- private int scpFromServer(Map<String,?> props, String remote, File local) {
- String from = (Strings.isEmpty(getUsername()) ? "" : getUsername()+"@")+getHostAddress()+":"+remote;
- return scpExec(props, from, local.getAbsolutePath());
- }
-
- private int chmodOnServer(Map<String,?> props, String permissions, String remote) {
- return sshExec(props, "chmod "+permissions+" "+remote);
- }
-
- private int scpExec(Map<String,?> props, String from, String to) {
- File tempFile = null;
- try {
- List<String> cmd = Lists.newArrayList();
- cmd.add(getOptionalVal(props, PROP_SCP_EXECUTABLE, scpExecutable));
- if (privateKeyFile != null) {
- cmd.add("-i");
- cmd.add(privateKeyFile.getAbsolutePath());
- } else if (privateKeyData != null) {
- tempFile = writeTempFile(privateKeyData);
- cmd.add("-i");
- cmd.add(tempFile.getAbsolutePath());
- }
- if (!strictHostKeyChecking) {
- cmd.add("-o");
- cmd.add("StrictHostKeyChecking=no");
- }
- if (port != 22) {
- cmd.add("-P");
- cmd.add(""+port);
- }
- cmd.add(from);
- cmd.add(to);
-
- if (LOG.isTraceEnabled()) LOG.trace("Executing with command: {}", cmd);
- int result = execProcess(props, cmd);
-
- if (LOG.isTraceEnabled()) LOG.trace("Executed command: {}; exit code {}", cmd, result);
- return result;
-
- } finally {
- if (tempFile != null) tempFile.delete();
- }
- }
-
- private int sshExec(Map<String,?> props, String command) {
- File tempKeyFile = null;
- try {
- List<String> cmd = Lists.newArrayList();
- cmd.add(getOptionalVal(props, PROP_SSH_EXECUTABLE, sshExecutable));
- String propsFlags = getOptionalVal(props, PROP_SSH_FLAGS, sshFlags);
- if (propsFlags!=null && propsFlags.trim().length()>0)
- cmd.addAll(Arrays.asList(propsFlags.trim().split(" ")));
- if (privateKeyFile != null) {
- cmd.add("-i");
- cmd.add(privateKeyFile.getAbsolutePath());
- } else if (privateKeyData != null) {
- tempKeyFile = writeTempFile(privateKeyData);
- cmd.add("-i");
- cmd.add(tempKeyFile.getAbsolutePath());
- }
- if (!strictHostKeyChecking) {
- cmd.add("-o");
- cmd.add("StrictHostKeyChecking=no");
- }
- if (port != 22) {
- cmd.add("-P");
- cmd.add(""+port);
- }
- if (allocatePTY) {
- // have to be careful with double -tt as it can leave a shell session active
- // when done from bash (ie ssh -tt localhost < /tmp/myscript.sh);
- // hover that doesn't seem to be a problem the way we use it from brooklyn
- // (and note single -t doesn't work _programmatically_ since the input isn't a terminal)
- cmd.add("-tt");
- }
- cmd.add((Strings.isEmpty(getUsername()) ? "" : getUsername()+"@")+getHostAddress());
-
- cmd.add("bash -c "+BashStringEscapes.wrapBash(command));
- // previously we tried these approaches:
- //cmd.add("$(<"+tempCmdFile.getAbsolutePath()+")");
- // only pays attention to the first word; the "; echo Executing ..." get treated as arguments
- // to the script in the first word, when invoked from java (when invoked from prompt the behaviour is as desired)
- //cmd.add("\""+command+"\"");
- // only works if command is a single word
- //cmd.add(tempCmdFile.getAbsolutePath());
- // above of course only works if the metafile is copied across
-
- if (LOG.isTraceEnabled()) LOG.trace("Executing ssh with command: {} (with {})", command, cmd);
- int result = execProcess(props, cmd);
-
- if (LOG.isTraceEnabled()) LOG.trace("Executed command: {}; exit code {}", cmd, result);
- return result;
-
- } finally {
- if (tempKeyFile != null) tempKeyFile.delete();
- }
- }
-
- private int execProcess(Map<String,?> props, List<String> cmdWords) {
- OutputStream out = getOptionalVal(props, PROP_OUT_STREAM);
- OutputStream err = getOptionalVal(props, PROP_ERR_STREAM);
- return ProcessTool.execSingleProcess(cmdWords, null, (File)null, out, err, this);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/internal/ssh/process/ProcessTool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/internal/ssh/process/ProcessTool.java b/core/src/main/java/brooklyn/util/internal/ssh/process/ProcessTool.java
deleted file mode 100644
index 90de9f2..0000000
--- a/core/src/main/java/brooklyn/util/internal/ssh/process/ProcessTool.java
+++ /dev/null
@@ -1,214 +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 brooklyn.util.internal.ssh.process;
-
-import static brooklyn.entity.basic.ConfigKeys.newConfigKey;
-import static brooklyn.entity.basic.ConfigKeys.newStringConfigKey;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.List;
-import java.util.Map;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.internal.ssh.ShellAbstractTool;
-import brooklyn.util.internal.ssh.ShellTool;
-import brooklyn.util.internal.ssh.SshException;
-import brooklyn.util.os.Os;
-import brooklyn.util.stream.StreamGobbler;
-import brooklyn.util.text.Strings;
-
-import com.google.common.base.Joiner;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Throwables;
-import com.google.common.io.ByteSource;
-import com.google.common.io.ByteStreams;
-import com.google.common.io.Files;
-
-/** Implementation of {@link ShellTool} which runs locally. */
-public class ProcessTool extends ShellAbstractTool implements ShellTool {
-
- private static final Logger LOG = LoggerFactory.getLogger(ProcessTool.class);
-
- // applies to calls
-
- public static final ConfigKey<Boolean> PROP_LOGIN_SHELL = newConfigKey("loginShell", "Causes the commands to be invoked with bash arguments to forcea login shell", Boolean.FALSE);
-
- public static final ConfigKey<String> PROP_DIRECTORY = newStringConfigKey("directory", "the working directory, for executing commands", null);
-
- public ProcessTool() {
- this(null);
- }
-
- public ProcessTool(Map<String,?> flags) {
- super(getOptionalVal(flags, PROP_LOCAL_TEMP_DIR));
- if (flags!=null) {
- MutableMap<String, Object> flags2 = MutableMap.copyOf(flags);
- // TODO should remember other flags here? (e.g. NO_EXTRA_OUTPUT, RUN_AS_ROOT, etc)
- flags2.remove(PROP_LOCAL_TEMP_DIR.getName());
- if (!flags2.isEmpty())
- LOG.warn(""+this+" ignoring unsupported constructor flags: "+flags);
- }
- }
-
- @Override
- public int execScript(final Map<String,?> props, final List<String> commands, final Map<String,?> env) {
- return new ToolAbstractExecScript(props) {
- public int run() {
- try {
- String directory = getOptionalVal(props, PROP_DIRECTORY);
- File directoryDir = (directory != null) ? new File(Os.tidyPath(directory)) : null;
-
- String scriptContents = toScript(props, commands, env);
-
- if (LOG.isTraceEnabled()) LOG.trace("Running shell process (process) as script:\n{}", scriptContents);
- File to = new File(scriptPath);
- Files.createParentDirs(to);
- ByteSource.wrap(scriptContents.getBytes()).copyTo(Files.asByteSink(to));
-
- List<String> cmds = buildRunScriptCommand();
- cmds.add(0, "chmod +x "+scriptPath);
- return asInt(execProcesses(cmds, null, directoryDir, out, err, separator, getOptionalVal(props, PROP_LOGIN_SHELL), this), -1);
- } catch (IOException e) {
- throw Throwables.propagate(e);
- }
- }
- }.run();
- }
-
- @Override
- public int execCommands(Map<String,?> props, List<String> commands, Map<String,?> env) {
- if (Boolean.FALSE.equals(props.get("blocks"))) {
- throw new IllegalArgumentException("Cannot exec non-blocking: command="+commands);
- }
- OutputStream out = getOptionalVal(props, PROP_OUT_STREAM);
- OutputStream err = getOptionalVal(props, PROP_ERR_STREAM);
- String separator = getOptionalVal(props, PROP_SEPARATOR);
- String directory = getOptionalVal(props, PROP_DIRECTORY);
- File directoryDir = (directory != null) ? new File(Os.tidyPath(directory)) : null;
-
- List<String> allcmds = toCommandSequence(commands, null);
-
- String singlecmd = Joiner.on(separator).join(allcmds);
- if (Boolean.TRUE.equals(getOptionalVal(props, PROP_RUN_AS_ROOT))) {
- LOG.warn("Cannot run as root when executing as command; run as a script instead (will run as normal user): "+singlecmd);
- }
- if (LOG.isTraceEnabled()) LOG.trace("Running shell command (process): {}", singlecmd);
-
- return asInt(execProcesses(allcmds, env, directoryDir, out, err, separator, getOptionalVal(props, PROP_LOGIN_SHELL), this), -1);
- }
-
- /**
- * as {@link #execProcesses(List, Map, OutputStream, OutputStream, String, boolean, Object)} but not using a login shell
- * @deprecated since 0.7; use {@link #execProcesses(List, Map, File, OutputStream, OutputStream, String, boolean, Object)}
- */
- @Deprecated
- public static int execProcesses(List<String> cmds, Map<String,?> env, OutputStream out, OutputStream err, String separator, Object contextForLogging) {
- return execProcesses(cmds, env, (File)null, out, err, separator, false, contextForLogging);
- }
-
- /**
- * @deprecated since 0.7; use {@link #execProcesses(List, Map, File, OutputStream, OutputStream, String, boolean, Object)}
- */
- @Deprecated
- public static int execProcesses(List<String> cmds, Map<String,?> env, OutputStream out, OutputStream err, String separator, boolean asLoginShell, Object contextForLogging) {
- return execProcesses(cmds, env, (File)null, out, err, separator, asLoginShell, contextForLogging);
- }
-
- /** executes a set of commands by sending them as a single process to `bash -c`
- * (single command argument of all the commands, joined with separator)
- * <p>
- * consequence of this is that you should not normally need to escape things oddly in your commands,
- * type them just as you would into a bash shell (if you find exceptions please note them here!)
- */
- public static int execProcesses(List<String> cmds, Map<String,?> env, File directory, OutputStream out, OutputStream err, String separator, boolean asLoginShell, Object contextForLogging) {
- MutableList<String> commands = new MutableList<String>().append("bash");
- if (asLoginShell) commands.append("-l");
- commands.append("-c", Strings.join(cmds, Preconditions.checkNotNull(separator, "separator")));
- return execSingleProcess(commands, env, directory, out, err, contextForLogging);
- }
-
- /**
- * @deprecated since 0.7; use {@link #execSingleProcess(List, Map, File, OutputStream, OutputStream, Object)}
- */
- @Deprecated
- public static int execSingleProcess(List<String> cmdWords, Map<String,?> env, OutputStream out, OutputStream err, Object contextForLogging) {
- return execSingleProcess(cmdWords, env, (File)null, out, err, contextForLogging);
- }
-
- /** executes a single process made up of the given command words (*not* bash escaped);
- * should be portable across OS's */
- public static int execSingleProcess(List<String> cmdWords, Map<String,?> env, File directory, OutputStream out, OutputStream err, Object contextForLogging) {
- StreamGobbler errgobbler = null;
- StreamGobbler outgobbler = null;
-
- ProcessBuilder pb = new ProcessBuilder(cmdWords);
- if (env!=null) {
- for (Map.Entry<String,?> kv: env.entrySet()) pb.environment().put(kv.getKey(), String.valueOf(kv.getValue()));
- }
- if (directory != null) {
- pb.directory(directory);
- }
-
- try {
- Process p = pb.start();
-
- if (out != null) {
- InputStream outstream = p.getInputStream();
- outgobbler = new StreamGobbler(outstream, out, (Logger) null);
- outgobbler.start();
- }
- if (err != null) {
- InputStream errstream = p.getErrorStream();
- errgobbler = new StreamGobbler(errstream, err, (Logger) null);
- errgobbler.start();
- }
-
- int result = p.waitFor();
-
- if (outgobbler != null) outgobbler.blockUntilFinished();
- if (errgobbler != null) errgobbler.blockUntilFinished();
-
- if (result==255)
- // this is not definitive, but tests (and code?) expects throw exception if can't connect;
- // only return exit code when it is exit code from underlying process;
- // we have no way to distinguish 255 from ssh failure from 255 from the command run through ssh ...
- // but probably 255 is from CLI ssh
- throw new SshException("exit code 255 from CLI ssh; probably failed to connect");
-
- return result;
- } catch (InterruptedException e) {
- throw Exceptions.propagate(e);
- } catch (IOException e) {
- throw Exceptions.propagate(e);
- } finally {
- closeWhispering(outgobbler, contextForLogging, "execProcess");
- closeWhispering(errgobbler, contextForLogging, "execProcess");
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/internal/ssh/sshj/SshjClientConnection.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/internal/ssh/sshj/SshjClientConnection.java b/core/src/main/java/brooklyn/util/internal/ssh/sshj/SshjClientConnection.java
deleted file mode 100644
index 982022a..0000000
--- a/core/src/main/java/brooklyn/util/internal/ssh/sshj/SshjClientConnection.java
+++ /dev/null
@@ -1,282 +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 brooklyn.util.internal.ssh.sshj;
-
-import static com.google.common.base.Objects.equal;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.io.File;
-import java.io.IOException;
-
-import net.schmizz.sshj.SSHClient;
-import net.schmizz.sshj.transport.verification.PromiscuousVerifier;
-import net.schmizz.sshj.userauth.keyprovider.OpenSSHKeyFile;
-import net.schmizz.sshj.userauth.password.PasswordUtils;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.util.GroovyJavaMethods;
-import brooklyn.util.internal.ssh.SshAbstractTool.SshAction;
-
-import com.google.common.base.Objects;
-import com.google.common.net.HostAndPort;
-
-/** based on code from jclouds */
-public class SshjClientConnection implements SshAction<SSHClient> {
-
- private static final Logger LOG = LoggerFactory.getLogger(SshjClientConnection.class);
-
- public static Builder builder() {
- return new Builder();
- }
-
- public static class Builder {
-
- protected HostAndPort hostAndPort;
- protected String username;
- protected String password;
- protected String privateKeyPassphrase;
- protected String privateKeyData;
- protected File privateKeyFile;
- protected long connectTimeout;
- protected long sessionTimeout;
- protected boolean strictHostKeyChecking;
-
- public Builder hostAndPort(HostAndPort hostAndPort) {
- this.hostAndPort = hostAndPort;
- return this;
- }
-
- public Builder username(String username) {
- this.username = username;
- return this;
- }
-
- public Builder password(String val) {
- this.password = val;
- return this;
- }
-
- /** @deprecated use privateKeyData */
- public Builder privateKey(String val) {
- this.privateKeyData = val;
- return this;
- }
-
- public Builder privateKeyPassphrase(String val) {
- this.privateKeyPassphrase = val;
- return this;
- }
-
- public Builder privateKeyData(String val) {
- this.privateKeyData = val;
- return this;
- }
-
- public Builder privateKeyFile(File val) {
- this.privateKeyFile = val;
- return this;
- }
-
- public Builder strictHostKeyChecking(boolean val) {
- this.strictHostKeyChecking = val;
- return this;
- }
-
- public Builder connectTimeout(long connectTimeout) {
- this.connectTimeout = connectTimeout;
- return this;
- }
-
- public Builder sessionTimeout(long sessionTimeout) {
- this.sessionTimeout = sessionTimeout;
- return this;
- }
-
- public SshjClientConnection build() {
- return new SshjClientConnection(this);
- }
-
- protected static Builder fromSSHClientConnection(SshjClientConnection in) {
- return new Builder().hostAndPort(in.getHostAndPort()).connectTimeout(in.getConnectTimeout()).sessionTimeout(
- in.getSessionTimeout()).username(in.username).password(in.password).privateKey(in.privateKeyData).privateKeyFile(in.privateKeyFile);
- }
- }
-
- private final HostAndPort hostAndPort;
- private final String username;
- private final String password;
- private final String privateKeyPassphrase;
- private final String privateKeyData;
- private final File privateKeyFile;
- private final boolean strictHostKeyChecking;
- private final int connectTimeout;
- private final int sessionTimeout;
-
- SSHClient ssh;
-
- private SshjClientConnection(Builder builder) {
- this.hostAndPort = checkNotNull(builder.hostAndPort);
- this.username = builder.username;
- this.password = builder.password;
- this.privateKeyPassphrase = builder.privateKeyPassphrase;
- this.privateKeyData = builder.privateKeyData;
- this.privateKeyFile = builder.privateKeyFile;
- this.strictHostKeyChecking = builder.strictHostKeyChecking;
- this.connectTimeout = checkInt("connectTimeout", builder.connectTimeout, Integer.MAX_VALUE);
- this.sessionTimeout = checkInt("sessionTimeout", builder.sessionTimeout, Integer.MAX_VALUE);
- }
-
- static Integer checkInt(String context, long value, Integer ifTooLarge) {
- if (value > Integer.MAX_VALUE) {
- LOG.warn("Value '"+value+"' for "+context+" too large in SshjClientConnection; using "+value);
- return ifTooLarge;
- }
- return (int)value;
- }
-
- public boolean isConnected() {
- return ssh != null && ssh.isConnected();
- }
-
- public boolean isAuthenticated() {
- return ssh != null && ssh.isAuthenticated();
- }
-
- @Override
- public void clear() {
- if (ssh != null && ssh.isConnected()) {
- try {
- if (LOG.isTraceEnabled()) LOG.trace("Disconnecting SshjClientConnection {} ({})", this, System.identityHashCode(this));
- ssh.disconnect();
- } catch (IOException e) {
- if (LOG.isDebugEnabled()) LOG.debug("<< exception disconnecting from {}: {}", e, e.getMessage());
- }
- }
- ssh = null;
- }
-
- @Override
- public SSHClient create() throws Exception {
- if (LOG.isTraceEnabled()) LOG.trace("Connecting SshjClientConnection {} ({})", this, System.identityHashCode(this));
- ssh = new net.schmizz.sshj.SSHClient();
- if (!strictHostKeyChecking) {
- ssh.addHostKeyVerifier(new PromiscuousVerifier());
- }
- if (connectTimeout != 0) {
- ssh.setConnectTimeout(connectTimeout);
- }
- if (sessionTimeout != 0) {
- ssh.setTimeout(sessionTimeout);
- }
- ssh.connect(hostAndPort.getHostText(), hostAndPort.getPortOrDefault(22));
-
- if (password != null) {
- ssh.authPassword(username, password);
- } else if (privateKeyData != null) {
- OpenSSHKeyFile key = new OpenSSHKeyFile();
- key.init(privateKeyData, null,
- GroovyJavaMethods.truth(privateKeyPassphrase) ?
- PasswordUtils.createOneOff(privateKeyPassphrase.toCharArray())
- : null);
- ssh.authPublickey(username, key);
- } else if (privateKeyFile != null) {
- OpenSSHKeyFile key = new OpenSSHKeyFile();
- key.init(privateKeyFile,
- GroovyJavaMethods.truth(privateKeyPassphrase) ?
- PasswordUtils.createOneOff(privateKeyPassphrase.toCharArray())
- : null);
- ssh.authPublickey(username, key);
- } else {
- // Accept defaults (in ~/.ssh)
- ssh.authPublickey(username);
- }
-
- return ssh;
- }
-
- /**
- * @return host and port, where port if not present defaults to {@code 22}
- */
- public HostAndPort getHostAndPort() {
- return hostAndPort;
- }
-
- /**
- * @return username used in this ssh
- */
- public String getUsername() {
- return username;
- }
-
- /**
- *
- * @return how long to wait for the initial connection to be made
- */
- public int getConnectTimeout() {
- return connectTimeout;
- }
-
- /**
- *
- * @return how long to keep the ssh open, or {@code 0} for indefinitely
- */
- public int getSessionTimeout() {
- return sessionTimeout;
- }
-
- /**
- *
- * @return the current ssh or {@code null} if not connected
- */
- public SSHClient getSSHClient() {
- return ssh;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o)
- return true;
- if (o == null || getClass() != o.getClass())
- return false;
- SshjClientConnection that = SshjClientConnection.class.cast(o);
- return equal(this.hostAndPort, that.hostAndPort) && equal(this.username, that.username)
- && equal(this.password, that.password) && equal(this.privateKeyData, that.privateKeyData)
- && equal(this.privateKeyFile, that.privateKeyFile) && equal(this.ssh, that.ssh);
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(hostAndPort, username, password, privateKeyData, ssh);
- }
-
- @Override
- public String toString() {
- return Objects.toStringHelper("")
- .add("hostAndPort", hostAndPort)
- .add("user", username)
- .add("ssh", ssh != null ? ssh.hashCode() : null)
- .add("password", (password != null ? "xxxxxx" : null))
- .add("privateKeyFile", privateKeyFile)
- .add("privateKey", (privateKeyData != null ? "xxxxxx" : null))
- .add("connectTimeout", connectTimeout)
- .add("sessionTimeout", sessionTimeout).toString();
- }
-}
[17/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/internal/RepeaterTest.groovy
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/internal/RepeaterTest.groovy b/core/src/test/java/brooklyn/util/internal/RepeaterTest.groovy
deleted file mode 100644
index 65976e1..0000000
--- a/core/src/test/java/brooklyn/util/internal/RepeaterTest.groovy
+++ /dev/null
@@ -1,255 +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 brooklyn.util.internal
-
-import static java.util.concurrent.TimeUnit.*
-import static org.testng.Assert.*
-
-import java.util.concurrent.Callable;
-import java.util.concurrent.TimeUnit
-
-import org.testng.annotations.Test
-
-import brooklyn.util.time.Duration;
-
-import com.google.common.base.Stopwatch
-
-public class RepeaterTest {
- static { TimeExtras.init() }
-
- @Test
- public void sanityTest() {
- new Repeater("Sanity test")
- .repeat()
- .until { true }
- .every(10 * MILLISECONDS);
- }
-
- @Test
- public void sanityTestDescription() {
- new Repeater()
- .repeat()
- .until { true }
- .every(10 * MILLISECONDS);
- }
-
- @Test
- public void sanityTestBuilder() {
- Repeater.create("Sanity test")
- .repeat()
- .until { true }
- .every(10 * MILLISECONDS);
- }
-
- @Test
- public void sanityTestBuilderDescription() {
- Repeater.create()
- .repeat()
- .until { true }
- .every(10 * MILLISECONDS);
- }
-
- @Test(expectedExceptions = [ NullPointerException.class ])
- public void repeatFailsIfClosureIsNull() {
- new Repeater("repeatFailsIfClosureIsNull").repeat((Callable<?>)null);
- fail "Expected exception was not thrown"
- }
-
- @Test
- public void repeatSucceedsIfClosureIsNonNull() {
- new Repeater("repeatSucceedsIfClosureIsNonNull").repeat { true };
- }
-
- @Test(expectedExceptions = [ NullPointerException.class ])
- public void untilFailsIfClosureIsNull() {
- new Repeater("untilFailsIfClosureIsNull").until(null);
- fail "Expected exception was not thrown"
- }
-
- @Test
- public void untilSucceedsIfClosureIsNonNull() {
- new Repeater("untilSucceedsIfClosureIsNonNull").until { true };
- }
-
- @Test(expectedExceptions = [ IllegalArgumentException.class ])
- public void everyFailsIfPeriodIsZero() {
- new Repeater("everyFailsIfPeriodIsZero").every(0 * MILLISECONDS);
- fail "Expected exception was not thrown"
- }
-
- @Test(expectedExceptions = [ IllegalArgumentException.class ])
- public void everyFailsIfPeriodIsNegative() {
- new Repeater("everyFailsIfPeriodIsNegative").every(-1 * MILLISECONDS);
- fail "Expected exception was not thrown"
- }
-
- @Test(expectedExceptions = [ NullPointerException.class ])
- public void everyFailsIfUnitsIsNull() {
- new Repeater("everyFailsIfUnitsIsNull").every(10, null);
- fail "Expected exception was not thrown"
- }
-
- @Test
- public void everySucceedsIfPeriodIsPositiveAndUnitsIsNonNull() {
- new Repeater("repeatSucceedsIfClosureIsNonNull").every(10 * MILLISECONDS);
- }
-
- @Test(expectedExceptions = [ IllegalArgumentException.class ])
- public void limitTimeToFailsIfPeriodIsZero() {
- new Repeater("limitTimeToFailsIfPeriodIsZero").limitTimeTo(0, TimeUnit.MILLISECONDS);
- fail "Expected exception was not thrown"
- }
-
- @Test(expectedExceptions = [ IllegalArgumentException.class ])
- public void limitTimeToFailsIfPeriodIsNegative() {
- new Repeater("limitTimeToFailsIfPeriodIsNegative").limitTimeTo(-1, TimeUnit.MILLISECONDS);
- fail "Expected exception was not thrown"
- }
-
- @Test(expectedExceptions = [ NullPointerException.class ])
- public void limitTimeToFailsIfUnitsIsNull() {
- new Repeater("limitTimeToFailsIfUnitsIsNull").limitTimeTo(10, null);
- fail "Expected exception was not thrown"
- }
-
- @Test
- public void limitTimeToSucceedsIfPeriodIsPositiveAndUnitsIsNonNull() {
- new Repeater("limitTimeToSucceedsIfClosureIsNonNull").limitTimeTo(10, TimeUnit.MILLISECONDS);
- }
-
- @Test
- public void everyAcceptsDuration() {
- new Repeater("everyAcceptsDuration").every(Duration.ONE_SECOND);
- }
-
- @Test
- public void everyAcceptsLong() {
- new Repeater("everyAcceptsLong").every(1000L);
- }
-
- @Test
- public void everyAcceptsTimeUnit() {
- new Repeater("everyAcceptsTimeUnit").every(1000000L, TimeUnit.MICROSECONDS);
- }
-
- @Test
- public void runReturnsTrueIfExitConditionIsTrue() {
- assertTrue new Repeater("runReturnsTrueIfExitConditionIsTrue")
- .repeat()
- .every(1 * MILLISECONDS)
- .until { true }
- .run();
- }
-
- @Test
- public void runRespectsMaximumIterationLimitAndReturnsFalseIfReached() {
- int iterations = 0;
- assertFalse new Repeater("runRespectsMaximumIterationLimitAndReturnsFalseIfReached")
- .repeat { iterations++ }
- .every(1 * MILLISECONDS)
- .until { false }
- .limitIterationsTo(5)
- .run();
- assertEquals 5, iterations;
- }
-
- /**
- * Check that the {@link Repeater} will stop after a time limit.
- *
- * The repeater is configured to run every 100ms and never stop until the limit is reached.
- * This is given as {@link Repeater#limitTimeTo(groovy.time.Duration)} and the execution time
- * is then checked to ensure it is between 100% and 400% of the specified value. Due to scheduling
- * delays and other factors in a non RTOS system it is expected that the repeater will take much
- * longer to exit occasionally.
- *
- * @see #runRespectsMaximumIterationLimitAndReturnsFalseIfReached()
- */
- @Test(groups="Integration")
- public void runRespectsTimeLimitAndReturnsFalseIfReached() {
- final long LIMIT = 2000l;
- Repeater repeater = new Repeater("runRespectsTimeLimitAndReturnsFalseIfReached")
- .repeat()
- .every(100 * MILLISECONDS)
- .until { false }
- .limitTimeTo(LIMIT, TimeUnit.MILLISECONDS);
-
- Stopwatch stopwatch = new Stopwatch().start();
- boolean result = repeater.run();
- stopwatch.stop();
-
- assertFalse result;
-
- long difference = stopwatch.elapsed(TimeUnit.MILLISECONDS);
- assertTrue(difference >= LIMIT, "Difference was: " + difference);
- assertTrue(difference < 4 * LIMIT, "Difference was: " + difference);
- }
-
- @Test(expectedExceptions = [ IllegalStateException.class ])
- public void runFailsIfUntilWasNotSet() {
- new Repeater("runFailsIfUntilWasNotSet")
- .repeat()
- .every(10 * MILLISECONDS)
- .run();
- fail "Expected exception was not thrown"
- }
-
- @Test(expectedExceptions = [ IllegalStateException.class ])
- public void runFailsIfEveryWasNotSet() {
- new Repeater("runFailsIfEveryWasNotSet")
- .repeat()
- .until { true }
- .run();
- fail "Expected exception was not thrown"
- }
-
- @Test(expectedExceptions = [ UnsupportedOperationException.class ])
- public void testRethrowsException() {
- boolean result = new Repeater("throwRuntimeException")
- .repeat()
- .every(10 * MILLISECONDS)
- .until { throw new UnsupportedOperationException("fail") }
- .rethrowException()
- .limitIterationsTo(2)
- .run();
- fail "Expected exception was not thrown"
- }
-
- @Test
- public void testNoRethrowsException() {
- try {
- boolean result = new Repeater("throwRuntimeException")
- .repeat()
- .every(10 * MILLISECONDS)
- .until { throw new UnsupportedOperationException("fail") }
- .limitIterationsTo(2)
- .run();
- assertFalse result
- } catch (RuntimeException re) {
- fail "Exception should not have been thrown: " + re.getMessage()
- }
- }
-
- public void testFlags() {
- int count=0;
- new Repeater(period: 5*MILLISECONDS, timeout: 100*MILLISECONDS).repeat({ count++ }).until({ count>100}).run();
- assertTrue count>10
- assertTrue count<30
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/internal/TypeCoercionsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/internal/TypeCoercionsTest.java b/core/src/test/java/brooklyn/util/internal/TypeCoercionsTest.java
deleted file mode 100644
index ecb8c7c..0000000
--- a/core/src/test/java/brooklyn/util/internal/TypeCoercionsTest.java
+++ /dev/null
@@ -1,360 +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 brooklyn.util.internal;
-
-import static org.testng.Assert.assertEquals;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.codehaus.groovy.runtime.GStringImpl;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-import brooklyn.entity.basic.Lifecycle;
-import brooklyn.util.collections.MutableSet;
-import brooklyn.util.flags.ClassCoercionException;
-import brooklyn.util.flags.TypeCoercions;
-import brooklyn.util.text.StringPredicates;
-
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.reflect.TypeToken;
-
-public class TypeCoercionsTest {
-
- private static final Logger log = LoggerFactory.getLogger(TypeCoercionsTest.class);
-
- @Test
- public void testCoerceCharSequenceToString() {
- assertEquals(TypeCoercions.coerce(new StringBuilder("abc"), String.class), "abc");
- assertEquals(TypeCoercions.coerce(new GStringImpl(new Object[0], new String[0]), String.class), "");
- }
-
- @Test
- public void testCoerceStringToPrimitive() {
- assertEquals(TypeCoercions.coerce("1", Character.class), (Character)'1');
- assertEquals(TypeCoercions.coerce(" ", Character.class), (Character)' ');
- assertEquals(TypeCoercions.coerce("1", Short.class), (Short)((short)1));
- assertEquals(TypeCoercions.coerce("1", Integer.class), (Integer)1);
- assertEquals(TypeCoercions.coerce("1", Long.class), (Long)1l);
- assertEquals(TypeCoercions.coerce("1", Float.class), (Float)1f);
- assertEquals(TypeCoercions.coerce("1", Double.class), (Double)1d);
- assertEquals(TypeCoercions.coerce("true", Boolean.class), (Boolean)true);
- assertEquals(TypeCoercions.coerce("False", Boolean.class), (Boolean)false);
- assertEquals(TypeCoercions.coerce("true ", Boolean.class), (Boolean)true);
-
- assertEquals(TypeCoercions.coerce("1", char.class), (Character)'1');
- assertEquals(TypeCoercions.coerce("1", short.class), (Short)((short)1));
- assertEquals(TypeCoercions.coerce("1", int.class), (Integer)1);
- assertEquals(TypeCoercions.coerce("1", long.class), (Long)1l);
- assertEquals(TypeCoercions.coerce("1", float.class), (Float)1f);
- assertEquals(TypeCoercions.coerce("1", double.class), (Double)1d);
- assertEquals(TypeCoercions.coerce("TRUE", boolean.class), (Boolean)true);
- assertEquals(TypeCoercions.coerce("false", boolean.class), (Boolean)false);
- }
-
- @Test
- public void testCoercePrimitivesToSameType() {
- assertEquals(TypeCoercions.coerce('1', Character.class), (Character)'1');
- assertEquals(TypeCoercions.coerce((short)1, Short.class), (Short)((short)1));
- assertEquals(TypeCoercions.coerce(1, Integer.class), (Integer)1);
- assertEquals(TypeCoercions.coerce(1l, Long.class), (Long)1l);
- assertEquals(TypeCoercions.coerce(1f, Float.class), (Float)1f);
- assertEquals(TypeCoercions.coerce(1d, Double.class), (Double)1d);
- assertEquals(TypeCoercions.coerce(true, Boolean.class), (Boolean)true);
- }
-
- @Test
- public void testCastPrimitives() {
- assertEquals(TypeCoercions.coerce(1L, Character.class), (Character)(char)1);
- assertEquals(TypeCoercions.coerce(1L, Byte.class), (Byte)(byte)1);
- assertEquals(TypeCoercions.coerce(1L, Short.class), (Short)(short)1);
- assertEquals(TypeCoercions.coerce(1L, Integer.class), (Integer)1);
- assertEquals(TypeCoercions.coerce(1L, Long.class), (Long)(long)1);
- assertEquals(TypeCoercions.coerce(1L, Float.class), (Float)(float)1);
- assertEquals(TypeCoercions.coerce(1L, Double.class), (Double)(double)1);
-
- assertEquals(TypeCoercions.coerce(1L, char.class), (Character)(char)1);
- assertEquals(TypeCoercions.coerce(1L, byte.class), (Byte)(byte)1);
- assertEquals(TypeCoercions.coerce(1L, short.class), (Short)(short)1);
- assertEquals(TypeCoercions.coerce(1L, int.class), (Integer)1);
- assertEquals(TypeCoercions.coerce(1L, long.class), (Long)(long)1);
- assertEquals(TypeCoercions.coerce(1L, float.class), (Float)(float)1);
- assertEquals(TypeCoercions.coerce(1L, double.class), (Double)(double)1);
-
- assertEquals(TypeCoercions.coerce((char)1, Integer.class), (Integer)1);
- assertEquals(TypeCoercions.coerce((byte)1, Integer.class), (Integer)1);
- assertEquals(TypeCoercions.coerce((short)1, Integer.class), (Integer)1);
- assertEquals(TypeCoercions.coerce((int)1, Integer.class), (Integer)1);
- assertEquals(TypeCoercions.coerce((long)1, Integer.class), (Integer)1);
- assertEquals(TypeCoercions.coerce((float)1, Integer.class), (Integer)1);
- assertEquals(TypeCoercions.coerce((double)1, Integer.class), (Integer)1);
- }
-
- @Test
- public void testCoercePrimitiveFailures() {
- // error messages don't have to be this exactly, but they should include sufficient information...
- assertCoercionFailsWithErrorMatching("maybe", boolean.class, StringPredicates.containsAllLiterals("String", "boolean", "maybe"));
- assertCoercionFailsWithErrorMatching("NaN", int.class, StringPredicates.containsAllLiterals("int", "NaN"));
- assertCoercionFailsWithErrorMatching('c', boolean.class, StringPredicates.containsAllLiterals("boolean", "(c)")); // will say 'string' rather than 'char'
- assertCoercionFailsWithErrorMatching(0, boolean.class, StringPredicates.containsAllLiterals("Integer", "boolean", "0"));
- }
-
- protected void assertCoercionFailsWithErrorMatching(Object input, Class<?> type, Predicate<? super String> errorMessageRequirement) {
- try {
- Object result = TypeCoercions.coerce(input, type);
- Assert.fail("Should have failed type coercion of "+input+" to "+type+", instead got: "+result);
- } catch (Exception e) {
- if (errorMessageRequirement==null || errorMessageRequirement.apply(e.toString()))
- log.info("Primitive coercion failed as expected, with: "+e);
- else
- Assert.fail("Error from type coercion of "+input+" to "+type+" failed with wrong exception; expected match of "+errorMessageRequirement+" but got: "+e);
- }
-
- }
-
- @Test
- public void testCastToNumericPrimitives() {
- assertEquals(TypeCoercions.coerce(BigInteger.ONE, Integer.class), (Integer)1);
- assertEquals(TypeCoercions.coerce(BigInteger.ONE, int.class), (Integer)1);
- assertEquals(TypeCoercions.coerce(BigInteger.valueOf(Long.MAX_VALUE), Long.class), (Long)Long.MAX_VALUE);
- assertEquals(TypeCoercions.coerce(BigInteger.valueOf(Long.MAX_VALUE), long.class), (Long)Long.MAX_VALUE);
-
- assertEquals(TypeCoercions.coerce(BigDecimal.valueOf(0.5), Double.class), 0.5d, 0.00001d);
- assertEquals(TypeCoercions.coerce(BigDecimal.valueOf(0.5), double.class), 0.5d, 0.00001d);
- }
-
- @Test
- public void testCoerceStringToBigNumber() {
- assertEquals(TypeCoercions.coerce("0.5", BigDecimal.class), BigDecimal.valueOf(0.5));
- assertEquals(TypeCoercions.coerce("1", BigInteger.class), BigInteger.valueOf(1));
- }
-
- @Test
- public void testCoerceStringToEnum() {
- assertEquals(TypeCoercions.coerce("STARTING", Lifecycle.class), Lifecycle.STARTING);
- assertEquals(TypeCoercions.coerce("Starting", Lifecycle.class), Lifecycle.STARTING);
- assertEquals(TypeCoercions.coerce("starting", Lifecycle.class), Lifecycle.STARTING);
-
- assertEquals(TypeCoercions.coerce("LOWERCASE", PerverseEnum.class), PerverseEnum.lowercase);
- assertEquals(TypeCoercions.coerce("CAMELCASE", PerverseEnum.class), PerverseEnum.camelCase);
- assertEquals(TypeCoercions.coerce("upper", PerverseEnum.class), PerverseEnum.UPPER);
- assertEquals(TypeCoercions.coerce("upper_with_underscore", PerverseEnum.class), PerverseEnum.UPPER_WITH_UNDERSCORE);
- assertEquals(TypeCoercions.coerce("LOWER_WITH_UNDERSCORE", PerverseEnum.class), PerverseEnum.lower_with_underscore);
- }
- public static enum PerverseEnum {
- lowercase,
- camelCase,
- UPPER,
- UPPER_WITH_UNDERSCORE,
- lower_with_underscore;
- }
-
- @Test(expectedExceptions = ClassCoercionException.class)
- public void testCoerceStringToEnumFailure() {
- TypeCoercions.coerce("scrambled-eggs", Lifecycle.class);
- }
-
- @Test
- public void testListToSetCoercion() {
- Set<?> s = TypeCoercions.coerce(ImmutableList.of(1), Set.class);
- Assert.assertEquals(s, ImmutableSet.of(1));
- }
-
- @Test
- public void testSetToListCoercion() {
- List<?> s = TypeCoercions.coerce(ImmutableSet.of(1), List.class);
- Assert.assertEquals(s, ImmutableList.of(1));
- }
-
- @Test
- public void testIterableToArrayCoercion() {
- String[] s = TypeCoercions.coerce(ImmutableList.of("a", "b"), String[].class);
- Assert.assertTrue(Arrays.equals(s, new String[] {"a", "b"}), "result="+Arrays.toString(s));
-
- Integer[] i = TypeCoercions.coerce(ImmutableList.of(1, 2), Integer[].class);
- Assert.assertTrue(Arrays.equals(i, new Integer[] {1, 2}), "result="+Arrays.toString(i));
-
- int[] i2 = TypeCoercions.coerce(ImmutableList.of(1, 2), int[].class);
- Assert.assertTrue(Arrays.equals(i2, new int[] {1, 2}), "result="+Arrays.toString(i2));
-
- int[] i3 = TypeCoercions.coerce(MutableSet.of("1", 2), int[].class);
- Assert.assertTrue(Arrays.equals(i3, new int[] {1, 2}), "result="+Arrays.toString(i3));
- }
-
- @Test
- public void testListEntryCoercion() {
- List<?> s = TypeCoercions.coerce(ImmutableList.of("java.lang.Integer", "java.lang.Double"), new TypeToken<List<Class<?>>>() { });
- Assert.assertEquals(s, ImmutableList.of(Integer.class, Double.class));
- }
-
- @Test
- public void testListEntryToSetCoercion() {
- Set<?> s = TypeCoercions.coerce(ImmutableList.of("java.lang.Integer", "java.lang.Double"), new TypeToken<Set<Class<?>>>() { });
- Assert.assertEquals(s, ImmutableSet.of(Integer.class, Double.class));
- }
-
- @Test
- public void testListEntryToCollectionCoercion() {
- Collection<?> s = TypeCoercions.coerce(ImmutableList.of("java.lang.Integer", "java.lang.Double"), new TypeToken<Collection<Class<?>>>() { });
- Assert.assertEquals(s, ImmutableList.of(Integer.class, Double.class));
- }
-
- @Test
- public void testMapValueCoercion() {
- Map<?,?> s = TypeCoercions.coerce(ImmutableMap.of("int", "java.lang.Integer", "double", "java.lang.Double"), new TypeToken<Map<String, Class<?>>>() { });
- Assert.assertEquals(s, ImmutableMap.of("int", Integer.class, "double", Double.class));
- }
-
- @Test
- public void testMapKeyCoercion() {
- Map<?,?> s = TypeCoercions.coerce(ImmutableMap.of("java.lang.Integer", "int", "java.lang.Double", "double"), new TypeToken<Map<Class<?>, String>>() { });
- Assert.assertEquals(s, ImmutableMap.of(Integer.class, "int", Double.class, "double"));
- }
-
- @Test
- public void testStringToListCoercion() {
- List<?> s = TypeCoercions.coerce("a,b,c", List.class);
- Assert.assertEquals(s, ImmutableList.of("a", "b", "c"));
- }
-
- @Test
- @SuppressWarnings("serial")
- public void testCoerceRecursivelyStringToGenericsCollection() {
- assertEquals(TypeCoercions.coerce("1,2", new TypeToken<List<Integer>>() {}), ImmutableList.of(1, 2));
- }
-
- @Test
- public void testJsonStringToMapCoercion() {
- Map<?,?> s = TypeCoercions.coerce("{ \"a\" : \"1\", b : 2 }", Map.class);
- Assert.assertEquals(s, ImmutableMap.of("a", "1", "b", 2));
- }
-
- @Test
- public void testJsonStringWithoutQuotesToMapCoercion() {
- Map<?,?> s = TypeCoercions.coerce("{ a : 1 }", Map.class);
- Assert.assertEquals(s, ImmutableMap.of("a", 1));
- }
-
- @Test
- public void testJsonComplexTypesToMapCoercion() {
- Map<?,?> s = TypeCoercions.coerce("{ a : [1, \"2\", '\"3\"'], b: { c: d, 'e': \"f\" } }", Map.class);
- Assert.assertEquals(s, ImmutableMap.of("a", ImmutableList.<Object>of(1, "2", "\"3\""),
- "b", ImmutableMap.of("c", "d", "e", "f")));
- }
-
- @Test
- public void testJsonStringWithoutBracesToMapCoercion() {
- Map<?,?> s = TypeCoercions.coerce("a : 1", Map.class);
- Assert.assertEquals(s, ImmutableMap.of("a", 1));
- }
-
- @Test
- public void testJsonStringWithoutBracesWithMultipleToMapCoercion() {
- Map<?,?> s = TypeCoercions.coerce("a : 1, b : 2", Map.class);
- Assert.assertEquals(s, ImmutableMap.of("a", 1, "b", 2));
- }
-
- @Test
- public void testKeyEqualsValueStringToMapCoercion() {
- Map<?,?> s = TypeCoercions.coerce("a=1,b=2", Map.class);
- Assert.assertEquals(s, ImmutableMap.of("a", "1", "b", "2"));
- }
-
- @Test(expectedExceptions=IllegalArgumentException.class)
- public void testJsonStringWithoutBracesOrSpaceDisallowedAsMapCoercion() {
- // yaml requires spaces after the colon
- Map<?,?> s = TypeCoercions.coerce("a:1,b:2", Map.class);
- Assert.assertEquals(s, ImmutableMap.of("a", 1, "b", 2));
- }
-
- @Test
- public void testEqualsInBracesMapCoercion() {
- Map<?,?> s = TypeCoercions.coerce("{ a = 1, b = '2' }", Map.class);
- Assert.assertEquals(s, ImmutableMap.of("a", 1, "b", "2"));
- }
-
- @Test
- public void testKeyEqualsOrColonValueWithBracesStringToMapCoercion() {
- Map<?,?> s = TypeCoercions.coerce("{ a=1, b: 2 }", Map.class);
- Assert.assertEquals(s, ImmutableMap.of("a", "1", "b", 2));
- }
-
- @Test
- public void testKeyEqualsOrColonValueWithoutBracesStringToMapCoercion() {
- Map<?,?> s = TypeCoercions.coerce("a=1, b: 2", Map.class);
- Assert.assertEquals(s, ImmutableMap.of("a", "1", "b", 2));
- }
-
- @Test
- public void testAs() {
- Integer x = TypeCoercions.coerce(new WithAs("3"), Integer.class);
- Assert.assertEquals(x, (Integer)3);
- }
-
- @Test
- public void testFrom() {
- WithFrom x = TypeCoercions.coerce("3", WithFrom.class);
- Assert.assertEquals(x.value, 3);
- }
-
- @Test
- public void testCoerceStringToNumber() {
- assertEquals(TypeCoercions.coerce("1", Number.class), (Number) Double.valueOf(1));
- assertEquals(TypeCoercions.coerce("1.0", Number.class), (Number) Double.valueOf(1.0));
- }
-
- @Test(expectedExceptions = ClassCoercionException.class)
- public void testInvalidCoercionThrowsClassCoercionException() {
- TypeCoercions.coerce(new Object(), TypeToken.of(Integer.class));
- }
-
- @Test
- public void testCoercionFunction() {
- assertEquals(TypeCoercions.function(Double.class).apply("1"), Double.valueOf(1));
- }
-
- public static class WithAs {
- String value;
- public WithAs(Object x) { value = ""+x; }
- public Integer asInteger() {
- return Integer.parseInt(value);
- }
- }
-
- public static class WithFrom {
- int value;
- public static WithFrom fromString(String s) {
- WithFrom result = new WithFrom();
- result.value = Integer.parseInt(s);
- return result;
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/internal/ssh/RecordingSshTool.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/internal/ssh/RecordingSshTool.java b/core/src/test/java/brooklyn/util/internal/ssh/RecordingSshTool.java
deleted file mode 100644
index 8c556a6..0000000
--- a/core/src/test/java/brooklyn/util/internal/ssh/RecordingSshTool.java
+++ /dev/null
@@ -1,95 +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 brooklyn.util.internal.ssh;
-
-import java.io.File;
-import java.io.InputStream;
-import java.util.List;
-import java.util.Map;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
-
-/** Mock tool */
-public class RecordingSshTool implements SshTool {
-
- public static class ExecCmd {
- public final Map<String,?> props;
- public final String summaryForLogging;
- public final List<String> commands;
- public final Map<?,?> env;
-
- ExecCmd(Map<String,?> props, String summaryForLogging, List<String> commands, Map env) {
- this.props = props;
- this.summaryForLogging = summaryForLogging;
- this.commands = commands;
- this.env = env;
- }
-
- @Override
- public String toString() {
- return "ExecCmd["+summaryForLogging+": "+commands+"; "+props+"; "+env+"]";
- }
- }
-
- public static List<ExecCmd> execScriptCmds = Lists.newCopyOnWriteArrayList();
-
- private boolean connected;
-
- public RecordingSshTool(Map<?,?> props) {
- }
- @Override public void connect() {
- connected = true;
- }
- @Override public void connect(int maxAttempts) {
- connected = true;
- }
- @Override public void disconnect() {
- connected = false;
- }
- @Override public boolean isConnected() {
- return connected;
- }
- @Override public int execScript(Map<String, ?> props, List<String> commands, Map<String, ?> env) {
- execScriptCmds.add(new ExecCmd(props, "", commands, env));
- return 0;
- }
- @Override public int execScript(Map<String, ?> props, List<String> commands) {
- return execScript(props, commands, ImmutableMap.<String,Object>of());
- }
- @Override public int execCommands(Map<String, ?> props, List<String> commands, Map<String, ?> env) {
- execScriptCmds.add(new ExecCmd(props, "", commands, env));
- return 0;
- }
- @Override public int execCommands(Map<String, ?> props, List<String> commands) {
- return execCommands(props, commands, ImmutableMap.<String,Object>of());
- }
- @Override public int copyToServer(Map<String, ?> props, File localFile, String pathAndFileOnRemoteServer) {
- return 0;
- }
- @Override public int copyToServer(Map<String, ?> props, InputStream contents, String pathAndFileOnRemoteServer) {
- return 0;
- }
- @Override public int copyToServer(Map<String, ?> props, byte[] contents, String pathAndFileOnRemoteServer) {
- return 0;
- }
- @Override public int copyFromServer(Map<String, ?> props, String pathAndFileOnRemoteServer, File local) {
- return 0;
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/internal/ssh/ShellToolAbstractTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/internal/ssh/ShellToolAbstractTest.java b/core/src/test/java/brooklyn/util/internal/ssh/ShellToolAbstractTest.java
deleted file mode 100644
index b8b394b..0000000
--- a/core/src/test/java/brooklyn/util/internal/ssh/ShellToolAbstractTest.java
+++ /dev/null
@@ -1,439 +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 brooklyn.util.internal.ssh;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertNotEquals;
-import static org.testng.Assert.assertTrue;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.text.Identifiers;
-import brooklyn.util.time.Time;
-
-import com.google.common.base.Stopwatch;
-import com.google.common.base.Strings;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
-
-public abstract class ShellToolAbstractTest {
-
- protected List<ShellTool> tools = Lists.newArrayList();
- protected List<String> filesCreated;
- protected String localFilePath;
-
- protected ShellTool tool;
-
- protected ShellTool newTool() {
- return newTool(MutableMap.<String,Object>of());
- }
-
- protected ShellTool newTool(Map<String,?> flags) {
- ShellTool t = newUnregisteredTool(flags);
- tools.add(t);
- return t;
- }
-
- protected abstract ShellTool newUnregisteredTool(Map<String,?> flags);
-
- protected ShellTool tool() { return tool; }
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() throws Exception {
- localFilePath = "/tmp/ssh-test-local-"+Identifiers.makeRandomId(8);
- filesCreated = new ArrayList<String>();
- filesCreated.add(localFilePath);
-
- tool = newTool();
- connect(tool);
- }
-
- @AfterMethod(alwaysRun=true)
- public void afterMethod() throws Exception {
- for (ShellTool t : tools) {
- if (t instanceof SshTool) ((SshTool)t).disconnect();
- }
- for (String fileCreated : filesCreated) {
- new File(fileCreated).delete();
- }
- }
-
- protected static void connect(ShellTool tool) {
- if (tool instanceof SshTool)
- ((SshTool)tool).connect();
- }
-
- @Test(groups = {"Integration"})
- public void testExecConsecutiveCommands() throws Exception {
- String out = execScript("echo run1");
- String out2 = execScript("echo run2");
-
- assertTrue(out.contains("run1"), "out="+out);
- assertTrue(out2.contains("run2"), "out="+out);
- }
-
- @Test(groups = {"Integration"})
- public void testExecScriptChainOfCommands() throws Exception {
- String out = execScript("export MYPROP=abc", "echo val is $MYPROP");
-
- assertTrue(out.contains("val is abc"), "out="+out);
- }
-
- @Test(groups = {"Integration"})
- public void testExecScriptReturningNonZeroExitCode() throws Exception {
- int exitcode = tool.execScript(MutableMap.<String,Object>of(), ImmutableList.of("exit 123"));
- assertEquals(exitcode, 123);
- }
-
- @Test(groups = {"Integration"})
- public void testExecScriptReturningZeroExitCode() throws Exception {
- int exitcode = tool.execScript(MutableMap.<String,Object>of(), ImmutableList.of("date"));
- assertEquals(exitcode, 0);
- }
-
- @Test(groups = {"Integration"})
- public void testExecScriptCommandWithEnvVariables() throws Exception {
- String out = execScript(ImmutableList.of("echo val is $MYPROP2"), ImmutableMap.of("MYPROP2", "myval"));
-
- assertTrue(out.contains("val is myval"), "out="+out);
- }
-
- @Test(groups = {"Integration"})
- public void testScriptDataNotLost() throws Exception {
- String out = execScript("echo `echo foo``echo bar`");
-
- assertTrue(out.contains("foobar"), "out="+out);
- }
-
- @Test(groups = {"Integration"})
- public void testExecScriptWithSleepThenExit() throws Exception {
- Stopwatch watch = Stopwatch.createStarted();
- execScript("sleep 1", "exit 0");
- assertTrue(watch.elapsed(TimeUnit.MILLISECONDS) > 900, "only slept "+Time.makeTimeStringRounded(watch));
- }
-
- // Really just tests that it returns; the command will be echo'ed automatically so this doesn't assert the command will have been executed
- @Test(groups = {"Integration"})
- public void testExecScriptBigCommand() throws Exception {
- String bigstring = Strings.repeat("a", 10000);
- String out = execScript("echo "+bigstring);
-
- assertTrue(out.contains(bigstring), "out="+out);
- }
-
- @Test(groups = {"Integration"})
- public void testExecScriptBigChainOfCommand() throws Exception {
- String bigstring = Strings.repeat("abcdefghij", 100); // 1KB
- List<String> cmds = Lists.newArrayList();
- for (int i = 0; i < 10; i++) {
- cmds.add("export MYPROP"+i+"="+bigstring);
- cmds.add("echo val"+i+" is $MYPROP"+i);
- }
- String out = execScript(cmds);
-
- for (int i = 0; i < 10; i++) {
- assertTrue(out.contains("val"+i+" is "+bigstring), "out="+out);
- }
- }
-
- @Test(groups = {"Integration"})
- public void testExecScriptAbortsOnCommandFailure() throws Exception {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- int exitcode = tool.execScript(ImmutableMap.of("out", out), ImmutableList.of("export MYPROP=myval", "acmdthatdoesnotexist", "echo val is $MYPROP"));
- String outstr = new String(out.toByteArray());
-
- assertFalse(outstr.contains("val is myval"), "out="+out);
- assertNotEquals(exitcode, 0);
- }
-
- @Test(groups = {"Integration"})
- public void testExecScriptWithSleepThenBigCommand() throws Exception {
- String bigstring = Strings.repeat("abcdefghij", 1000); // 10KB
- String out = execScript("sleep 2", "export MYPROP="+bigstring, "echo val is $MYPROP");
- assertTrue(out.contains("val is "+bigstring), "out="+out);
- }
-
- @Test(groups = {"WIP", "Integration"})
- public void testExecScriptBigConcurrentCommand() throws Exception {
- ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
- List<ListenableFuture<?>> futures = new ArrayList<ListenableFuture<?>>();
- try {
- for (int i = 0; i < 10; i++) {
- final ShellTool localtool = newTool();
- connect(localtool);
-
- futures.add(executor.submit(new Runnable() {
- public void run() {
- String bigstring = Strings.repeat("abcdefghij", 1000); // 10KB
- String out = execScript(localtool, ImmutableList.of("export MYPROP="+bigstring, "echo val is $MYPROP"));
- assertTrue(out.contains("val is "+bigstring), "outSize="+out.length()+"; out="+out);
- }}));
- }
- Futures.allAsList(futures).get();
- } finally {
- executor.shutdownNow();
- }
- }
-
- @Test(groups = {"WIP", "Integration"})
- public void testExecScriptBigConcurrentSleepyCommand() throws Exception {
- ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
- List<ListenableFuture<?>> futures = new ArrayList<ListenableFuture<?>>();
- try {
- long starttime = System.currentTimeMillis();
- for (int i = 0; i < 10; i++) {
- final ShellTool localtool = newTool();
- connect(localtool);
-
- futures.add(executor.submit(new Runnable() {
- public void run() {
- String bigstring = Strings.repeat("abcdefghij", 1000); // 10KB
- String out = execScript(localtool, ImmutableList.of("sleep 2", "export MYPROP="+bigstring, "echo val is $MYPROP"));
- assertTrue(out.contains("val is "+bigstring), "out="+out);
- }}));
- }
- Futures.allAsList(futures).get();
- long runtime = System.currentTimeMillis() - starttime;
-
- long OVERHEAD = 20*1000;
- assertTrue(runtime < 2000+OVERHEAD, "runtime="+runtime);
-
- } finally {
- executor.shutdownNow();
- }
- }
-
- @Test(groups = {"Integration"})
- public void testExecChainOfCommands() throws Exception {
- String out = execCommands("MYPROP=abc", "echo val is $MYPROP");
-
- assertEquals(out, "val is abc\n");
- }
-
- @Test(groups = {"Integration"})
- public void testExecReturningNonZeroExitCode() throws Exception {
- int exitcode = tool.execCommands(MutableMap.<String,Object>of(), ImmutableList.of("exit 123"));
- assertEquals(exitcode, 123);
- }
-
- @Test(groups = {"Integration"})
- public void testExecReturningZeroExitCode() throws Exception {
- int exitcode = tool.execCommands(MutableMap.<String,Object>of(), ImmutableList.of("date"));
- assertEquals(exitcode, 0);
- }
-
- @Test(groups = {"Integration"})
- public void testExecCommandWithEnvVariables() throws Exception {
- String out = execCommands(ImmutableList.of("echo val is $MYPROP2"), ImmutableMap.of("MYPROP2", "myval"));
-
- assertEquals(out, "val is myval\n");
- }
-
- @Test(groups = {"Integration"})
- public void testExecBigCommand() throws Exception {
- String bigstring = Strings.repeat("abcdefghij", 1000); // 10KB
- String out = execCommands("echo "+bigstring);
-
- assertEquals(out, bigstring+"\n", "actualSize="+out.length()+"; expectedSize="+bigstring.length());
- }
-
- @Test(groups = {"Integration"})
- public void testExecBigConcurrentCommand() throws Exception {
- runExecBigConcurrentCommand(10, 0L);
- }
-
- // TODO Fails I believe due to synchronization model in SshjTool of calling connect/disconnect.
- // Even with a retry-count of 4, it still fails because some commands are calling disconnect
- // while another concurrently executing command expects to be still connected.
- @Test(groups = {"Integration", "WIP"})
- public void testExecBigConcurrentCommandWithStaggeredStart() throws Exception {
- // This test is to vary the concurrency of concurrent actions
- runExecBigConcurrentCommand(50, 100L);
- }
-
- protected void runExecBigConcurrentCommand(int numCommands, long staggeredDelayBeforeStart) throws Exception {
- ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
- List<ListenableFuture<?>> futures = new ArrayList<ListenableFuture<?>>();
- try {
- for (int i = 0; i < numCommands; i++) {
- long delay = (long) (Math.random() * staggeredDelayBeforeStart);
- if (i > 0) Time.sleep(delay);
-
- futures.add(executor.submit(new Runnable() {
- public void run() {
- String bigstring = Strings.repeat("abcdefghij", 1000); // 10KB
- String out = execCommands("echo "+bigstring);
- assertEquals(out, bigstring+"\n", "actualSize="+out.length()+"; expectedSize="+bigstring.length());
- }}));
- }
- Futures.allAsList(futures).get();
- } finally {
- executor.shutdownNow();
- }
- }
-
- // fails if terminal enabled
- @Test(groups = {"Integration"})
- @Deprecated // tests deprecated code
- public void testExecScriptCapturesStderr() throws Exception {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ByteArrayOutputStream err = new ByteArrayOutputStream();
- String nonExistantCmd = "acmdthatdoesnotexist";
- tool.execScript(ImmutableMap.of("out", out, "err", err), ImmutableList.of(nonExistantCmd));
- assertTrue(new String(err.toByteArray()).contains(nonExistantCmd+": command not found"), "out="+out+"; err="+err);
- }
-
- // fails if terminal enabled
- @Test(groups = {"Integration"})
- @Deprecated // tests deprecated code
- public void testExecCapturesStderr() throws Exception {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ByteArrayOutputStream err = new ByteArrayOutputStream();
- String nonExistantCmd = "acmdthatdoesnotexist";
- tool.execCommands(ImmutableMap.of("out", out, "err", err), ImmutableList.of(nonExistantCmd));
- String errMsg = new String(err.toByteArray());
- assertTrue(errMsg.contains(nonExistantCmd+": command not found\n"), "errMsg="+errMsg+"; out="+out+"; err="+err);
-
- }
-
- @Test(groups = {"Integration"})
- public void testScriptHeader() {
- final ShellTool localtool = newTool();
- String out = execScript(MutableMap.of("scriptHeader", "#!/bin/bash -e\necho hello world\n"),
- localtool, Arrays.asList("echo goodbye world"), null);
- assertTrue(out.contains("goodbye world"), "no goodbye in output: "+out);
- assertTrue(out.contains("hello world"), "no hello in output: "+out);
- }
-
- @Test(groups = {"Integration"})
- public void testStdErr() {
- final ShellTool localtool = newTool();
- Map<String,Object> props = new LinkedHashMap<String, Object>();
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ByteArrayOutputStream err = new ByteArrayOutputStream();
- props.put("out", out);
- props.put("err", err);
- int exitcode = localtool.execScript(props, Arrays.asList("echo hello err > /dev/stderr"), null);
- assertFalse(out.toString().contains("hello err"), "hello found where it shouldn't have been, in stdout: "+out);
- assertTrue(err.toString().contains("hello err"), "no hello in stderr: "+err);
- assertEquals(0, exitcode);
- }
-
- @Test(groups = {"Integration"})
- public void testRunAsRoot() {
- final ShellTool localtool = newTool();
- Map<String,Object> props = new LinkedHashMap<String, Object>();
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ByteArrayOutputStream err = new ByteArrayOutputStream();
- props.put("out", out);
- props.put("err", err);
- props.put(SshTool.PROP_RUN_AS_ROOT.getName(), true);
- int exitcode = localtool.execScript(props, Arrays.asList("whoami"), null);
- assertTrue(out.toString().contains("root"), "not running as root; whoami is: "+out+" (err is '"+err+"')");
- assertEquals(0, exitcode);
- }
-
- @Test(groups = {"Integration"})
- public void testExecScriptEchosExecute() throws Exception {
- String out = execScript("date");
- assertTrue(out.toString().contains("Executed"), "Executed did not display: "+out);
- }
-
- @Test(groups = {"Integration"})
- public void testExecScriptEchosDontExecuteWhenToldNoExtraOutput() throws Exception {
- final ShellTool localtool = newTool();
- Map<String,Object> props = new LinkedHashMap<String, Object>();
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ByteArrayOutputStream err = new ByteArrayOutputStream();
- props.put("out", out);
- props.put("err", err);
- props.put(SshTool.PROP_NO_EXTRA_OUTPUT.getName(), true);
- int exitcode = localtool.execScript(props, Arrays.asList("echo hello world"), null);
- assertFalse(out.toString().contains("Executed"), "Executed should not have displayed: "+out);
- assertEquals(out.toString().trim(), "hello world");
- assertEquals(0, exitcode);
- }
-
- protected String execCommands(String... cmds) {
- return execCommands(Arrays.asList(cmds));
- }
-
- protected String execCommands(List<String> cmds) {
- return execCommands(cmds, ImmutableMap.<String,Object>of());
- }
-
- protected String execCommands(List<String> cmds, Map<String,?> env) {
- return execCommands(null, cmds, env);
- }
-
- protected String execCommands(ConfigBag config, List<String> cmds, Map<String,?> env) {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- MutableMap<String,Object> flags = MutableMap.<String,Object>of("out", out);
- if (config!=null) flags.add(config.getAllConfig());
- tool.execCommands(flags, cmds, env);
- return new String(out.toByteArray());
- }
-
- protected String execScript(String... cmds) {
- return execScript(tool, Arrays.asList(cmds));
- }
-
- protected String execScript(ShellTool t, List<String> cmds) {
- return execScript(ImmutableMap.<String,Object>of(), t, cmds, ImmutableMap.<String,Object>of());
- }
-
- protected String execScript(List<String> cmds) {
- return execScript(cmds, ImmutableMap.<String,Object>of());
- }
-
- protected String execScript(List<String> cmds, Map<String,?> env) {
- return execScript(MutableMap.<String,Object>of(), tool, cmds, env);
- }
-
- protected String execScript(Map<String, ?> props, ShellTool tool, List<String> cmds, Map<String,?> env) {
- Map<String, Object> props2 = new LinkedHashMap<String, Object>(props);
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- props2.put("out", out);
- int exitcode = tool.execScript(props2, cmds, env);
- String outstr = new String(out.toByteArray());
- assertEquals(exitcode, 0, outstr);
- return outstr;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/internal/ssh/SshToolAbstractIntegrationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/internal/ssh/SshToolAbstractIntegrationTest.java b/core/src/test/java/brooklyn/util/internal/ssh/SshToolAbstractIntegrationTest.java
deleted file mode 100644
index 84b1029..0000000
--- a/core/src/test/java/brooklyn/util/internal/ssh/SshToolAbstractIntegrationTest.java
+++ /dev/null
@@ -1,301 +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 brooklyn.util.internal.ssh;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.Assert;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.os.Os;
-import brooklyn.util.text.Identifiers;
-import brooklyn.util.text.Strings;
-
-import com.google.common.base.Charsets;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.io.Files;
-
-/**
- * Test the operation of the {@link SshTool} utility class; to be extended to test concrete implementations.
- *
- * Requires keys set up, e.g. running:
- *
- * <pre>
- * cd ~/.ssh
- * ssh-keygen
- * id_rsa_with_passphrase
- * mypassphrase
- * mypassphrase
- * </pre>
- *
- */
-public abstract class SshToolAbstractIntegrationTest extends ShellToolAbstractTest {
-
- private static final Logger log = LoggerFactory.getLogger(SshToolAbstractIntegrationTest.class);
-
- // FIXME need tests which take properties set in entities and brooklyn.properties;
- // but not in this class because it is lower level than entities, Aled would argue.
-
- // TODO No tests for retry logic and exception handing yet
-
- public static final String SSH_KEY_WITH_PASSPHRASE = System.getProperty("sshPrivateKeyWithPassphrase", "~/.ssh/id_rsa_with_passphrase");
- public static final String SSH_PASSPHRASE = System.getProperty("sshPrivateKeyPassphrase", "mypassphrase");
-
- protected String remoteFilePath;
-
- protected SshTool tool() { return (SshTool)tool; }
-
- protected abstract SshTool newUnregisteredTool(Map<String,?> flags);
-
- @Override
- protected SshTool newTool() {
- return newTool(ImmutableMap.of("host", "localhost", "privateKeyFile", "~/.ssh/id_rsa"));
- }
-
- @Override
- protected SshTool newTool(Map<String,?> flags) {
- return (SshTool) super.newTool(flags);
- }
-
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() throws Exception {
- super.setUp();
- remoteFilePath = "/tmp/ssh-test-remote-"+Identifiers.makeRandomId(8);
- filesCreated.add(remoteFilePath);
- }
-
- protected void assertRemoteFileContents(String remotePath, String expectedContents) {
- String catout = execCommands("cat "+remotePath);
- assertEquals(catout, expectedContents);
- }
-
- /**
- * @param remotePath
- * @param expectedPermissions Of the form, for example, "-rw-r--r--"
- */
- protected void assertRemoteFilePermissions(String remotePath, String expectedPermissions) {
- String lsout = execCommands("ls -l "+remotePath);
- assertTrue(lsout.contains(expectedPermissions), lsout);
- }
-
- protected void assertRemoteFileLastModifiedIsNow(String remotePath) {
- // Check default last-modified time is `now`.
- // Be lenient in assertion, in case unlucky that clock ticked over to next hour/minute as test was running.
- // TODO Code could be greatly improved, but low priority!
- // Output format:
- // -rw-r--r-- 1 aled wheel 18 Apr 24 15:03 /tmp/ssh-test-remote-CvFN9zQA
- // [0] [1] [2] [3] [4] [5] [6] [7] [8]
-
- String lsout = execCommands("ls -l "+remotePath);
-
- String[] lsparts = lsout.split("\\s+");
- int day = Integer.parseInt(lsparts[6]);
- int hour = Integer.parseInt(lsparts[7].split(":")[0]);
- int minute = Integer.parseInt(lsparts[7].split(":")[1]);
-
- Calendar expected = Calendar.getInstance();
- int expectedDay = expected.get(Calendar.DAY_OF_MONTH);
- int expectedHour = expected.get(Calendar.HOUR_OF_DAY);
- int expectedMinute = expected.get(Calendar.MINUTE);
-
- assertEquals(day, expectedDay, "ls="+lsout+"; lsparts="+Arrays.toString(lsparts)+"; expected="+expected+"; expectedDay="+expectedDay+"; day="+day+"; zone="+expected.getTimeZone());
- assertTrue(Math.abs(hour - expectedHour) <= 1, "ls="+lsout+"; lsparts="+Arrays.toString(lsparts)+"; expected="+expected+"; expectedHour="+expectedHour+"; hour="+hour+"; zone="+expected.getTimeZone());
- assertTrue(Math.abs(minute - expectedMinute) <= 1, "ls="+lsout+"; lsparts="+Arrays.toString(lsparts)+"; expected="+expected+"; expectedMinute="+expectedMinute+"; minute="+minute+"; zone="+expected.getTimeZone());
- }
-
- @Test(groups = {"Integration"})
- public void testCopyToServerFromBytes() throws Exception {
- String contents = "echo hello world!\n";
- byte[] contentBytes = contents.getBytes();
- tool().copyToServer(MutableMap.<String,Object>of(), contentBytes, remoteFilePath);
-
- assertRemoteFileContents(remoteFilePath, contents);
- assertRemoteFilePermissions(remoteFilePath, "-rw-r--r--");
-
- // TODO would like to also assert lastModified time, but on jenkins the jvm locale
- // and the OS locale are different (i.e. different timezones) so the file time-stamp
- // is several hours out.
- //assertRemoteFileLastModifiedIsNow(remoteFilePath);
- }
-
- @Test(groups = {"Integration"})
- public void testCopyToServerFromInputStream() throws Exception {
- String contents = "echo hello world!\n";
- ByteArrayInputStream contentsStream = new ByteArrayInputStream(contents.getBytes());
- tool().copyToServer(MutableMap.<String,Object>of(), contentsStream, remoteFilePath);
-
- assertRemoteFileContents(remoteFilePath, contents);
- }
-
- @Test(groups = {"Integration"})
- public void testCopyToServerWithPermissions() throws Exception {
- tool().copyToServer(ImmutableMap.of("permissions","0754"), "echo hello world!\n".getBytes(), remoteFilePath);
-
- assertRemoteFilePermissions(remoteFilePath, "-rwxr-xr--");
- }
-
- @Test(groups = {"Integration"})
- public void testCopyToServerWithLastModifiedDate() throws Exception {
- long lastModificationTime = 1234567;
- tool().copyToServer(ImmutableMap.of("lastModificationDate", lastModificationTime), "echo hello world!\n".getBytes(), remoteFilePath);
-
- String lsout = execCommands("ls -l "+remoteFilePath);//+" | awk '{print \$6 \" \" \$7 \" \" \$8}'"])
- //execCommands([ "ls -l "+remoteFilePath+" | awk '{print \$6 \" \" \$7 \" \" \$8}'"])
- //varies depending on timezone
- assertTrue(lsout.contains("Jan 15 1970") || lsout.contains("Jan 14 1970") || lsout.contains("Jan 16 1970"), lsout);
- //assertLastModified(lsout, lastModifiedDate)
- }
-
- @Test(groups = {"Integration"})
- public void testCopyFileToServerWithPermissions() throws Exception {
- String contents = "echo hello world!\n";
- Files.write(contents, new File(localFilePath), Charsets.UTF_8);
- tool().copyToServer(ImmutableMap.of("permissions", "0754"), new File(localFilePath), remoteFilePath);
-
- assertRemoteFileContents(remoteFilePath, contents);
-
- String lsout = execCommands("ls -l "+remoteFilePath);
- assertTrue(lsout.contains("-rwxr-xr--"), lsout);
- }
-
- @Test(groups = {"Integration"})
- public void testCopyFromServer() throws Exception {
- String contentsWithoutLineBreak = "echo hello world!";
- String contents = contentsWithoutLineBreak+"\n";
- tool().copyToServer(MutableMap.<String,Object>of(), contents.getBytes(), remoteFilePath);
-
- tool().copyFromServer(MutableMap.<String,Object>of(), remoteFilePath, new File(localFilePath));
-
- List<String> actual = Files.readLines(new File(localFilePath), Charsets.UTF_8);
- assertEquals(actual, ImmutableList.of(contentsWithoutLineBreak));
- }
-
- // TODO No config options in sshj or scp for auto-creating the parent directories
- @Test(enabled=false, groups = {"Integration"})
- public void testCopyFileToNonExistantDir() throws Exception {
- String contents = "echo hello world!\n";
- String remoteFileDirPath = "/tmp/ssh-test-remote-dir-"+Identifiers.makeRandomId(8);
- String remoteFileInDirPath = remoteFileDirPath + File.separator + "ssh-test-remote-"+Identifiers.makeRandomId(8);
- filesCreated.add(remoteFileInDirPath);
- filesCreated.add(remoteFileDirPath);
-
- tool().copyToServer(MutableMap.<String,Object>of(), contents.getBytes(), remoteFileInDirPath);
-
- assertRemoteFileContents(remoteFileInDirPath, contents);
- }
-
-
- @Test(groups = {"Integration"})
- public void testAllocatePty() {
- final ShellTool localtool = newTool(MutableMap.of("host", "localhost", SshTool.PROP_ALLOCATE_PTY.getName(), true));
- Map<String,Object> props = new LinkedHashMap<String, Object>();
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ByteArrayOutputStream err = new ByteArrayOutputStream();
- props.put("out", out);
- props.put("err", err);
- int exitcode = localtool.execScript(props, Arrays.asList("echo hello err > /dev/stderr"), null);
- assertTrue(out.toString().contains("hello err"), "no hello in output: "+out+" (err is '"+err+"')");
- assertFalse(err.toString().contains("hello err"), "hello found in stderr: "+err);
- assertEquals(0, exitcode);
- }
-
- // Requires setting up an extra ssh key, with a passphrase, and adding it to ~/.ssh/authorized_keys
- @Test(groups = {"Integration"})
- public void testSshKeyWithPassphrase() throws Exception {
- final SshTool localtool = newTool(ImmutableMap.<String,Object>builder()
- .put(SshTool.PROP_HOST.getName(), "localhost")
- .put(SshTool.PROP_PRIVATE_KEY_FILE.getName(), SSH_KEY_WITH_PASSPHRASE)
- .put(SshTool.PROP_PRIVATE_KEY_PASSPHRASE.getName(), SSH_PASSPHRASE)
- .build());
- localtool.connect();
-
- assertEquals(tool.execScript(MutableMap.<String,Object>of(), ImmutableList.of("date")), 0);
-
- // Also needs the negative test to prove that we're really using an ssh-key with a passphrase
- try {
- final SshTool localtool2 = newTool(ImmutableMap.<String,Object>builder()
- .put(SshTool.PROP_HOST.getName(), "localhost")
- .put(SshTool.PROP_PRIVATE_KEY_FILE.getName(), SSH_KEY_WITH_PASSPHRASE)
- .build());
- localtool2.connect();
- fail();
- } catch (Exception e) {
- SshException se = Exceptions.getFirstThrowableOfType(e, SshException.class);
- if (se == null) throw e;
- }
- }
-
- @Test(groups = {"Integration"})
- public void testConnectWithInvalidUserThrowsException() throws Exception {
- final ShellTool localtool = newTool(ImmutableMap.of("user", "wronguser", "host", "localhost", "privateKeyFile", "~/.ssh/id_rsa"));
- tools.add(localtool);
- try {
- connect(localtool);
- fail();
- } catch (SshException e) {
- if (!e.toString().contains("failed to connect")) throw e;
- }
- }
-
- @Test(groups = {"Integration"})
- public void testOutputAsExpected() throws Exception {
- final String CONTENTS = "hello world\n"
- + "bye bye\n";
- execCommands("cat > "+Os.mergePaths(Os.tmp(), "test1")+" << X\n"
- + CONTENTS
- + "X\n");
- String read = execCommands("echo START_FOO", "cat "+Os.mergePaths(Os.tmp(), "test1"), "echo END_FOO");
- log.debug("read back data written, as:\n"+read);
- String contents = Strings.getFragmentBetween(read, "START_FOO", "END_FOO");
- Assert.assertEquals(CONTENTS.trim(), contents.trim());
- }
-
- @Test(groups = {"Integration"})
- public void testScriptDirPropertiesIsRespected() {
- // For explanation of (some of) the magic behind this command, see http://stackoverflow.com/a/229606/68898
- final String command = "if [[ \"$0\" == \"/var/tmp/\"* ]]; then true; else false; fi";
-
- SshTool sshTool = newTool(ImmutableMap.<String, Object>builder()
- .put(SshTool.PROP_HOST.getName(), "localhost")
- .build());
- int rc = sshTool.execScript(ImmutableMap.<String, Object>builder()
- .put(SshTool.PROP_SCRIPT_DIR.getName(), "/var/tmp")
- .build(), ImmutableList.of(command));
- assertEquals(rc, 0);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/internal/ssh/SshToolAbstractPerformanceTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/internal/ssh/SshToolAbstractPerformanceTest.java b/core/src/test/java/brooklyn/util/internal/ssh/SshToolAbstractPerformanceTest.java
deleted file mode 100644
index be1441a..0000000
--- a/core/src/test/java/brooklyn/util/internal/ssh/SshToolAbstractPerformanceTest.java
+++ /dev/null
@@ -1,137 +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 brooklyn.util.internal.ssh;
-
-import java.io.ByteArrayOutputStream;
-import java.lang.management.ManagementFactory;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.text.Identifiers;
-import brooklyn.util.time.Time;
-
-import com.google.common.base.Stopwatch;
-import com.google.common.collect.ImmutableList;
-
-/**
- * Test the performance of different variants of invoking the sshj tool.
- *
- * Intended for human-invocation and inspection, to see which parts are most expensive.
- */
-public abstract class SshToolAbstractPerformanceTest {
-
- private static final Logger LOG = LoggerFactory.getLogger(SshToolAbstractPerformanceTest.class);
-
- private SshTool tool;
-
- protected abstract SshTool newSshTool(Map<String,?> flags);
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() throws Exception {
- }
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws Exception {
- if (tool != null) tool.disconnect();
- }
-
- @Test(groups = {"Integration"})
- public void testConsecutiveConnectAndDisconnect() throws Exception {
- Runnable task = new Runnable() {
- public void run() {
- tool = newSshTool(MutableMap.of("host", "localhost"));
- tool.connect();
- tool.disconnect();
- }
- };
- runMany(task, "connect-disconnect", 10);
- }
-
- @Test(groups = {"Integration"})
- public void testConsecutiveSmallCommands() throws Exception {
- runExecManyCommands(ImmutableList.of("true"), false, "small-cmd", 10);
- }
-
- @Test(groups = {"Integration"})
- public void testConsecutiveSmallCommandsWithStdouterr() throws Exception {
- runExecManyCommands(ImmutableList.of("true"), true, "small-cmd-with-stdout", 10);
- }
-
- @Test(groups = {"Integration"})
- public void testConsecutiveBigStdoutCommands() throws Exception {
- runExecManyCommands(ImmutableList.of("head -c 100000 /dev/urandom"), true, "big-stdout", 10);
- }
-
- @Test(groups = {"Integration"})
- public void testConsecutiveBigStdinCommands() throws Exception {
- String bigstr = Identifiers.makeRandomId(100000);
- runExecManyCommands(ImmutableList.of("echo "+bigstr+" | wc -c"), true, "big-stdin", 10);
- }
-
- private void runExecManyCommands(final List<String> cmds, final boolean captureOutAndErr, String context, int iterations) throws Exception {
- Runnable task = new Runnable() {
- @Override public void run() {
- execScript(cmds, captureOutAndErr);
- }};
- runMany(task, context, iterations);
- }
-
- private void runMany(Runnable task, String context, int iterations) throws Exception {
- MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
- ObjectName osMBeanName = ObjectName.getInstance(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME);
- long preCpuTime = (Long) mbeanServer.getAttribute(osMBeanName, "ProcessCpuTime");
- Stopwatch stopwatch = Stopwatch.createStarted();
-
- for (int i = 0; i < iterations; i++) {
- task.run();
-
- long postCpuTime = (Long) mbeanServer.getAttribute(osMBeanName, "ProcessCpuTime");
- long elapsedTime = stopwatch.elapsed(TimeUnit.MILLISECONDS);
- double fractionCpu = (elapsedTime > 0) ? ((double)postCpuTime-preCpuTime) / TimeUnit.MILLISECONDS.toNanos(elapsedTime) : -1;
- LOG.info("Executing {}; completed {}; took {}; fraction cpu {}", new Object[] {context, (i+1), Time.makeTimeStringRounded(elapsedTime), fractionCpu});
- }
- }
-
- private int execScript(List<String> cmds, boolean captureOutandErr) {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ByteArrayOutputStream err = new ByteArrayOutputStream();
- MutableMap<String,?> flags = (captureOutandErr) ? MutableMap.of("out", out, "err", err) : MutableMap.<String,Object>of();
-
- tool = newSshTool(MutableMap.of("host", "localhost"));
- tool.connect();
- int result = tool.execScript(flags, cmds);
- tool.disconnect();
-
- int outlen = out.toByteArray().length;
- int errlen = out.toByteArray().length;
- if (LOG.isTraceEnabled()) LOG.trace("Executed: result={}; stdout={}; stderr={}", new Object[] {result, outlen, errlen});
- return result;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/internal/ssh/cli/SshCliToolIntegrationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/internal/ssh/cli/SshCliToolIntegrationTest.java b/core/src/test/java/brooklyn/util/internal/ssh/cli/SshCliToolIntegrationTest.java
deleted file mode 100644
index c8640e7..0000000
--- a/core/src/test/java/brooklyn/util/internal/ssh/cli/SshCliToolIntegrationTest.java
+++ /dev/null
@@ -1,119 +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 brooklyn.util.internal.ssh.cli;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
-
-import java.io.ByteArrayOutputStream;
-import java.util.Arrays;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.internal.ssh.SshException;
-import brooklyn.util.internal.ssh.SshTool;
-import brooklyn.util.internal.ssh.SshToolAbstractIntegrationTest;
-import brooklyn.util.internal.ssh.cli.SshCliTool;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-
-/**
- * Test the operation of the {@link SshJschTool} utility class.
- */
-public class SshCliToolIntegrationTest extends SshToolAbstractIntegrationTest {
-
- private static final Logger log = LoggerFactory.getLogger(SshCliToolIntegrationTest.class);
-
- protected SshTool newUnregisteredTool(Map<String,?> flags) {
- return new SshCliTool(flags);
- }
-
- @Test(groups = {"Integration"})
- public void testFlags() throws Exception {
- final SshTool localtool = newTool(ImmutableMap.of("sshFlags", "-vvv -tt", "host", "localhost"));
- tools.add(localtool);
- try {
- localtool.connect();
- Map<String,Object> props = new LinkedHashMap<String, Object>();
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ByteArrayOutputStream err = new ByteArrayOutputStream();
- props.put("out", out);
- props.put("err", err);
- int exitcode = localtool.execScript(props, Arrays.asList("echo hello err > /dev/stderr"), null);
- Assert.assertEquals(0, exitcode, "exitCode="+exitcode+", but expected 0");
- log.debug("OUT from ssh -vvv command is: "+out);
- log.debug("ERR from ssh -vvv command is: "+err);
- assertFalse(err.toString().contains("hello err"), "hello found where it shouldn't have been, in stderr (should have been tty merged to stdout): "+err);
- assertTrue(out.toString().contains("hello err"), "no hello in stdout: "+err);
- // look for word 'ssh' to confirm we got verbose output
- assertTrue(err.toString().toLowerCase().contains("ssh"), "no mention of ssh in stderr: "+err);
- } catch (SshException e) {
- if (!e.toString().contains("failed to connect")) throw e;
- }
- }
-
- // Need to have at least one test method here (rather than just inherited) for eclipse to recognize it
- @Test(enabled = false)
- public void testDummy() throws Exception {
- }
-
- // TODO When running mvn on the command line (for Aled), this test hangs when prompting for a password (but works in the IDE!)
- // Doing .connect() isn't enough; need to cause ssh or scp to be invoked
- @Test(enabled=false, groups = {"Integration"})
- public void testConnectWithInvalidUserThrowsException() throws Exception {
- final SshTool localtool = newTool(ImmutableMap.of("user", "wronguser", "host", "localhost", "privateKeyFile", "~/.ssh/id_rsa"));
- tools.add(localtool);
- try {
- localtool.connect();
- int result = localtool.execScript(ImmutableMap.<String,Object>of(), ImmutableList.of("date"));
- fail("exitCode="+result+", but expected exception");
- } catch (SshException e) {
- if (!e.toString().contains("failed to connect")) throw e;
- }
- }
-
- // TODO ssh-cli doesn't support pass-phrases yet
- @Test(enabled=false, groups = {"Integration"})
- public void testSshKeyWithPassphrase() throws Exception {
- super.testSshKeyWithPassphrase();
- }
-
- // Setting last modified date not yet supported for cli-based ssh
- @Override
- @Test(enabled=false, groups = {"Integration"})
- public void testCopyToServerWithLastModifiedDate() throws Exception {
- super.testCopyToServerWithLastModifiedDate();
- }
-
- @Test(groups = {"Integration"})
- public void testExecReturningNonZeroExitCode() throws Exception {
- int exitcode = tool.execCommands(MutableMap.<String,Object>of(), ImmutableList.of("exit 123"));
- assertEquals(exitcode, 123);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/internal/ssh/cli/SshCliToolPerformanceTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/internal/ssh/cli/SshCliToolPerformanceTest.java b/core/src/test/java/brooklyn/util/internal/ssh/cli/SshCliToolPerformanceTest.java
deleted file mode 100644
index 4d2ba20..0000000
--- a/core/src/test/java/brooklyn/util/internal/ssh/cli/SshCliToolPerformanceTest.java
+++ /dev/null
@@ -1,44 +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 brooklyn.util.internal.ssh.cli;
-
-import java.util.Map;
-
-import org.testng.annotations.Test;
-
-import brooklyn.util.internal.ssh.SshTool;
-import brooklyn.util.internal.ssh.SshToolAbstractPerformanceTest;
-
-/**
- * Test the performance of different variants of invoking the sshj tool.
- *
- * Intended for human-invocation and inspection, to see which parts are most expensive.
- */
-public class SshCliToolPerformanceTest extends SshToolAbstractPerformanceTest {
-
- @Override
- protected SshTool newSshTool(Map<String,?> flags) {
- return new SshCliTool(flags);
- }
-
- // Need to have at least one test method here (rather than just inherited) for eclipse to recognize it
- @Test(enabled = false)
- public void testDummy() throws Exception {
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/internal/ssh/process/ProcessToolIntegrationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/internal/ssh/process/ProcessToolIntegrationTest.java b/core/src/test/java/brooklyn/util/internal/ssh/process/ProcessToolIntegrationTest.java
deleted file mode 100644
index 64054ba..0000000
--- a/core/src/test/java/brooklyn/util/internal/ssh/process/ProcessToolIntegrationTest.java
+++ /dev/null
@@ -1,69 +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 brooklyn.util.internal.ssh.process;
-
-import static org.testng.Assert.assertTrue;
-
-import java.util.Arrays;
-import java.util.Map;
-
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.internal.ssh.ShellToolAbstractTest;
-
-/**
- * Test the operation of the {@link ProcessTool} utility class.
- */
-public class ProcessToolIntegrationTest extends ShellToolAbstractTest {
-
- @Override
- protected ProcessTool newUnregisteredTool(Map<String,?> flags) {
- return new ProcessTool(flags);
- }
-
- // ones here included as *non*-integration tests. must run on windows and linux.
- // (also includes integration tests from parent)
-
- @Test(groups="UNIX")
- public void testPortableCommand() throws Exception {
- String out = execScript("echo hello world");
- assertTrue(out.contains("hello world"), "out="+out);
- }
-
- @Test(groups="Integration")
- public void testLoginShell() {
- // this detection scheme only works for commands; can't test whether it works for scripts without
- // requiring stuff in bash_profile / profile / etc, which gets hard to make portable;
- // it is nearly the same code path on the impl so this is probably enough
-
- final String LOGIN_SHELL_CHECK = "shopt -q login_shell && echo 'yes, login shell' || echo 'no, not login shell'";
- ConfigBag config = ConfigBag.newInstance().configure(ProcessTool.PROP_NO_EXTRA_OUTPUT, true);
- String out;
-
- out = execCommands(config, Arrays.asList(LOGIN_SHELL_CHECK), null);
- Assert.assertEquals(out.trim(), "no, not login shell", "out = "+out);
-
- config.configure(ProcessTool.PROP_LOGIN_SHELL, true);
- out = execCommands(config, Arrays.asList(LOGIN_SHELL_CHECK), null);
- Assert.assertEquals(out.trim(), "yes, login shell", "out = "+out);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/internal/ssh/process/ProcessToolStaticsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/internal/ssh/process/ProcessToolStaticsTest.java b/core/src/test/java/brooklyn/util/internal/ssh/process/ProcessToolStaticsTest.java
deleted file mode 100644
index 787c776..0000000
--- a/core/src/test/java/brooklyn/util/internal/ssh/process/ProcessToolStaticsTest.java
+++ /dev/null
@@ -1,79 +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 brooklyn.util.internal.ssh.process;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.util.Arrays;
-import java.util.List;
-
-import org.testng.Assert;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.os.Os;
-
-public class ProcessToolStaticsTest {
-
- ByteArrayOutputStream out;
- ByteArrayOutputStream err;
-
- @BeforeMethod(alwaysRun=true)
- public void clear() {
- out = new ByteArrayOutputStream();
- err = new ByteArrayOutputStream();
- }
-
- private List<String> getTestCommand() {
- if(Os.isMicrosoftWindows()) {
- return Arrays.asList("cmd", "/c", "echo", "hello", "world");
- } else {
- return Arrays.asList("echo", "hello", "world");
- }
- }
-
- @Test
- public void testRunsWithStdout() throws Exception {
- int code = ProcessTool.execSingleProcess(getTestCommand(), null, (File)null, out, err, this);
- Assert.assertEquals(err.toString().trim(), "");
- Assert.assertEquals(out.toString().trim(), "hello world");
- Assert.assertEquals(code, 0);
- }
-
- @Test(groups="Integration") // *nix only
- public void testRunsWithBashEnvVarAndStderr() throws Exception {
- int code = ProcessTool.execSingleProcess(Arrays.asList("/bin/bash", "-c", "echo hello $NAME | tee /dev/stderr"),
- MutableMap.of("NAME", "BOB"), (File)null, out, err, this);
- Assert.assertEquals(err.toString().trim(), "hello BOB", "err is: "+err);
- Assert.assertEquals(out.toString().trim(), "hello BOB", "out is: "+out);
- Assert.assertEquals(code, 0);
- }
-
- @Test(groups="Integration") // *nix only
- public void testRunsManyCommandsWithBashEnvVarAndStderr() throws Exception {
- int code = ProcessTool.execProcesses(Arrays.asList("echo hello $NAME", "export NAME=JOHN", "echo goodbye $NAME | tee /dev/stderr"),
- MutableMap.of("NAME", "BOB"), (File)null, out, err, " ; ", false, this);
- Assert.assertEquals(err.toString().trim(), "goodbye JOHN", "err is: "+err);
- Assert.assertEquals(out.toString().trim(), "hello BOB\ngoodbye JOHN", "out is: "+out);
- Assert.assertEquals(code, 0);
- }
-
-
-}
[21/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/ValueResolver.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/ValueResolver.java b/core/src/main/java/org/apache/brooklyn/core/util/task/ValueResolver.java
new file mode 100644
index 0000000..7fc112b
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/ValueResolver.java
@@ -0,0 +1,426 @@
+/*
+ * 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.util.task;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.management.ExecutionContext;
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.api.management.TaskAdaptable;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.entity.basic.BrooklynTaskTags;
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.guava.Maybe;
+import brooklyn.util.javalang.JavaClassNames;
+import brooklyn.util.repeat.Repeater;
+import brooklyn.util.time.CountdownTimer;
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Durations;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.common.reflect.TypeToken;
+
+/**
+ * Resolves a given object, as follows:
+ * <li> If it is a {@link Tasks} or a {@link DeferredSupplier} then get its contents
+ * <li> If it's a map and {@link #deep(boolean)} is requested, it applies resolution to contents
+ * <li> It applies coercion
+ * <p>
+ * Fluent-style API exposes a number of other options.
+ */
+public class ValueResolver<T> implements DeferredSupplier<T> {
+
+ /**
+ * Period to wait if we're expected to return real quick
+ * but we want fast things to have time to finish.
+ * <p>
+ * Timings are always somewhat arbitrary but this at least
+ * allows some intention to be captured in code rather than arbitrary values. */
+ public static Duration REAL_QUICK_WAIT = Duration.millis(50);
+ /**
+ * Period to wait if we're expected to return quickly
+ * but we want to be a bit more generous for things to finish,
+ * without letting a caller get annoyed.
+ * <p>
+ * See {@link #REAL_QUICK_WAIT}. */
+ public static Duration PRETTY_QUICK_WAIT = Duration.millis(200);
+
+ /** Period to wait when we have to poll but want to give the illusion of no wait.
+ * See {@link Repeater#DEFAULT_REAL_QUICK_PERIOD} */
+ public static Duration REAL_QUICK_PERIOD = Repeater.DEFAULT_REAL_QUICK_PERIOD;
+
+ private static final Logger log = LoggerFactory.getLogger(ValueResolver.class);
+
+ final Object value;
+ final Class<T> type;
+ ExecutionContext exec;
+ String description;
+ boolean forceDeep;
+ /** null means do it if you can; true means always, false means never */
+ Boolean embedResolutionInTask;
+ /** timeout on execution, if possible, or if embedResolutionInTask is true */
+ Duration timeout;
+ boolean isTransientTask = true;
+
+ T defaultValue = null;
+ boolean returnDefaultOnGet = false;
+ boolean swallowExceptions = false;
+
+ // internal fields
+ final Object parentOriginalValue;
+ final CountdownTimer parentTimer;
+ AtomicBoolean started = new AtomicBoolean(false);
+ boolean expired;
+
+ ValueResolver(Object v, Class<T> type) {
+ this.value = v;
+ this.type = type;
+ checkTypeNotNull();
+ parentOriginalValue = null;
+ parentTimer = null;
+ }
+
+ ValueResolver(Object v, Class<T> type, ValueResolver<?> parent) {
+ this.value = v;
+ this.type = type;
+ checkTypeNotNull();
+
+ exec = parent.exec;
+ description = parent.description;
+ forceDeep = parent.forceDeep;
+ embedResolutionInTask = parent.embedResolutionInTask;
+
+ parentOriginalValue = parent.getOriginalValue();
+
+ timeout = parent.timeout;
+ parentTimer = parent.parentTimer;
+ if (parentTimer!=null && parentTimer.isExpired())
+ expired = true;
+
+ // default value and swallow exceptions do not need to be nested
+ }
+
+ public static class ResolverBuilderPretype {
+ final Object v;
+ public ResolverBuilderPretype(Object v) {
+ this.v = v;
+ }
+ public <T> ValueResolver<T> as(Class<T> type) {
+ return new ValueResolver<T>(v, type);
+ }
+ }
+
+ /** returns a copy of this resolver which can be queried, even if the original (single-use instance) has already been copied */
+ public ValueResolver<T> clone() {
+ ValueResolver<T> result = new ValueResolver<T>(value, type)
+ .context(exec).description(description)
+ .embedResolutionInTask(embedResolutionInTask)
+ .deep(forceDeep)
+ .timeout(timeout);
+ if (returnDefaultOnGet) result.defaultValue(defaultValue);
+ if (swallowExceptions) result.swallowExceptions();
+ return result;
+ }
+
+ /** execution context to use when resolving; required if resolving unsubmitted tasks or running with a time limit */
+ public ValueResolver<T> context(ExecutionContext exec) {
+ this.exec = exec;
+ return this;
+ }
+ /** as {@link #context(ExecutionContext)} for use from an entity */
+ public ValueResolver<T> context(Entity entity) {
+ return context(entity!=null ? ((EntityInternal)entity).getExecutionContext() : null);
+ }
+
+ /** sets a message which will be displayed in status reports while it waits (e.g. the name of the config key being looked up) */
+ public ValueResolver<T> description(String description) {
+ this.description = description;
+ return this;
+ }
+
+ /** sets a default value which will be returned on a call to {@link #get()} if the task does not complete
+ * or completes with an error
+ * <p>
+ * note that {@link #getMaybe()} returns an absent object even in the presence of
+ * a default, so that any error can still be accessed */
+ public ValueResolver<T> defaultValue(T defaultValue) {
+ this.defaultValue = defaultValue;
+ this.returnDefaultOnGet = true;
+ return this;
+ }
+
+ /** indicates that no default value should be returned on a call to {@link #get()}, and instead it should throw
+ * (this is the default; this method is provided to undo a call to {@link #defaultValue(Object)}) */
+ public ValueResolver<T> noDefaultValue() {
+ this.returnDefaultOnGet = false;
+ this.defaultValue = null;
+ return this;
+ }
+
+ /** indicates that exceptions in resolution should not be thrown on a call to {@link #getMaybe()},
+ * but rather used as part of the {@link Maybe#get()} if it's absent,
+ * and swallowed altogether on a call to {@link #get()} in the presence of a {@link #defaultValue(Object)} */
+ public ValueResolver<T> swallowExceptions() {
+ this.swallowExceptions = true;
+ return this;
+ }
+
+ /** whether the task should be marked as transient; defaults true */
+ public ValueResolver<T> transientTask(boolean isTransientTask) {
+ this.isTransientTask = isTransientTask;
+ return this;
+ }
+
+ public Maybe<T> getDefault() {
+ if (returnDefaultOnGet) return Maybe.of(defaultValue);
+ else return Maybe.absent("No default value set");
+ }
+
+ /** causes nested structures (maps, lists) to be descended and nested unresolved values resolved */
+ public ValueResolver<T> deep(boolean forceDeep) {
+ this.forceDeep = forceDeep;
+ return this;
+ }
+
+ /** if true, forces execution of a deferred supplier to be run in a task;
+ * if false, it prevents it (meaning time limits may not be applied);
+ * if null, the default, it runs in a task if a time limit is applied.
+ * <p>
+ * running inside a task is required for some {@link DeferredSupplier}
+ * instances which look up a task {@link ExecutionContext}. */
+ public ValueResolver<T> embedResolutionInTask(Boolean embedResolutionInTask) {
+ this.embedResolutionInTask = embedResolutionInTask;
+ return this;
+ }
+
+ /** sets a time limit on executions
+ * <p>
+ * used for {@link Task} and {@link DeferredSupplier} instances.
+ * may require an execution context at runtime. */
+ public ValueResolver<T> timeout(Duration timeout) {
+ this.timeout = timeout;
+ return this;
+ }
+
+ protected void checkTypeNotNull() {
+ if (type==null)
+ throw new NullPointerException("type must be set to resolve, for '"+value+"'"+(description!=null ? ", "+description : ""));
+ }
+
+ public T get() {
+ Maybe<T> m = getMaybe();
+ if (m.isPresent()) return m.get();
+ if (returnDefaultOnGet) return defaultValue;
+ return m.get();
+ }
+
+ public Maybe<T> getMaybe() {
+ Maybe<T> result = getMaybeInternal();
+ if (log.isTraceEnabled()) {
+ log.trace(this+" evaluated as "+result);
+ }
+ return result;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ protected Maybe<T> getMaybeInternal() {
+ if (started.getAndSet(true))
+ throw new IllegalStateException("ValueResolver can only be used once");
+
+ if (expired) return Maybe.absent("Nested resolution of "+getOriginalValue()+" did not complete within "+timeout);
+
+ ExecutionContext exec = this.exec;
+ if (exec==null) {
+ // if execution context not specified, take it from the current task if present
+ exec = BasicExecutionContext.getCurrentExecutionContext();
+ }
+
+ CountdownTimer timerU = parentTimer;
+ if (timerU==null && timeout!=null)
+ timerU = timeout.countdownTimer();
+ final CountdownTimer timer = timerU;
+ if (timer!=null && !timer.isRunning())
+ timer.start();
+
+ checkTypeNotNull();
+ Object v = this.value;
+
+ //if the expected type is a closure or map and that's what we have, we're done (or if it's null);
+ //but not allowed to return a future or DeferredSupplier as the resolved value
+ if (v==null || (!forceDeep && type.isInstance(v) && !Future.class.isInstance(v) && !DeferredSupplier.class.isInstance(v)))
+ return Maybe.of((T) v);
+
+ try {
+ //if it's a task or a future, we wait for the task to complete
+ if (v instanceof TaskAdaptable<?>) {
+ //if it's a task, we make sure it is submitted
+ if (!((TaskAdaptable<?>) v).asTask().isSubmitted() ) {
+ if (exec==null)
+ return Maybe.absent("Value for unsubmitted task '"+getDescription()+"' requested but no execution context available");
+ exec.submit(((TaskAdaptable<?>) v).asTask());
+ }
+ }
+
+ if (v instanceof Future) {
+ final Future<?> vfuture = (Future<?>) v;
+
+ //including tasks, above
+ if (!vfuture.isDone()) {
+ Callable<Maybe> callable = new Callable<Maybe>() {
+ public Maybe call() throws Exception {
+ return Durations.get(vfuture, timer);
+ } };
+
+ String description = getDescription();
+ Maybe vm = Tasks.withBlockingDetails("Waiting for "+description, callable);
+ if (vm.isAbsent()) return vm;
+ v = vm.get();
+
+ } else {
+ v = vfuture.get();
+
+ }
+
+ } else if (v instanceof DeferredSupplier<?>) {
+ final Object vf = v;
+
+ if ((!Boolean.FALSE.equals(embedResolutionInTask) && (exec!=null || timeout!=null)) || Boolean.TRUE.equals(embedResolutionInTask)) {
+ if (exec==null)
+ return Maybe.absent("Embedding in task needed for '"+getDescription()+"' but no execution context available");
+
+ Callable<Object> callable = new Callable<Object>() {
+ public Object call() throws Exception {
+ try {
+ Tasks.setBlockingDetails("Retrieving "+vf);
+ return ((DeferredSupplier<?>) vf).get();
+ } finally {
+ Tasks.resetBlockingDetails();
+ }
+ } };
+ String description = getDescription();
+ TaskBuilder<Object> vb = Tasks.<Object>builder().body(callable).name("Resolving dependent value").description(description);
+ if (isTransientTask) vb.tag(BrooklynTaskTags.TRANSIENT_TASK_TAG);
+ Task<Object> vt = exec.submit(vb.build());
+ // TODO to handle immediate resolution, it would be nice to be able to submit
+ // so it executes in the current thread,
+ // or put a marker in the target thread or task while it is running that the task
+ // should never wait on anything other than another value being resolved
+ // (though either could recurse infinitely)
+ Maybe<Object> vm = Durations.get(vt, timer);
+ vt.cancel(true);
+ if (vm.isAbsent()) return (Maybe<T>)vm;
+ v = vm.get();
+
+ } else {
+ try {
+ Tasks.setBlockingDetails("Retrieving (non-task) "+vf);
+ v = ((DeferredSupplier<?>) vf).get();
+ } finally {
+ Tasks.resetBlockingDetails();
+ }
+ }
+
+ } else if (v instanceof Map) {
+ //and if a map or list we look inside
+ Map result = Maps.newLinkedHashMap();
+ for (Map.Entry<?,?> entry : ((Map<?,?>)v).entrySet()) {
+ Maybe<?> kk = new ValueResolver(entry.getKey(), type, this)
+ .description( (description!=null ? description+", " : "") + "map key "+entry.getKey() )
+ .getMaybe();
+ if (kk.isAbsent()) return (Maybe<T>)kk;
+ Maybe<?> vv = new ValueResolver(entry.getValue(), type, this)
+ .description( (description!=null ? description+", " : "") + "map value for key "+kk.get() )
+ .getMaybe();
+ if (vv.isAbsent()) return (Maybe<T>)vv;
+ result.put(kk.get(), vv.get());
+ }
+ return Maybe.of((T) result);
+
+ } else if (v instanceof Set) {
+ Set result = Sets.newLinkedHashSet();
+ int count = 0;
+ for (Object it : (Set)v) {
+ Maybe<?> vv = new ValueResolver(it, type, this)
+ .description( (description!=null ? description+", " : "") + "entry "+count )
+ .getMaybe();
+ if (vv.isAbsent()) return (Maybe<T>)vv;
+ result.add(vv.get());
+ count++;
+ }
+ return Maybe.of((T) result);
+
+ } else if (v instanceof Iterable) {
+ List result = Lists.newArrayList();
+ int count = 0;
+ for (Object it : (Iterable)v) {
+ Maybe<?> vv = new ValueResolver(it, type, this)
+ .description( (description!=null ? description+", " : "") + "entry "+count )
+ .getMaybe();
+ if (vv.isAbsent()) return (Maybe<T>)vv;
+ result.add(vv.get());
+ count++;
+ }
+ return Maybe.of((T) result);
+
+ } else {
+ return TypeCoercions.tryCoerce(v, TypeToken.of(type));
+ }
+
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+
+ IllegalArgumentException problem = new IllegalArgumentException("Error resolving "+(description!=null ? description+", " : "")+v+", in "+exec+": "+e, e);
+ if (swallowExceptions) {
+ if (log.isDebugEnabled())
+ log.debug("Resolution of "+this+" failed, swallowing and returning: "+e);
+ return Maybe.absent(problem);
+ }
+ if (log.isDebugEnabled())
+ log.debug("Resolution of "+this+" failed, throwing: "+e);
+ throw problem;
+ }
+
+ return new ValueResolver(v, type, this).getMaybe();
+ }
+
+ protected String getDescription() {
+ return description!=null ? description : ""+value;
+ }
+ protected Object getOriginalValue() {
+ if (parentOriginalValue!=null) return parentOriginalValue;
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ return JavaClassNames.cleanSimpleClassName(this)+"["+JavaClassNames.cleanSimpleClassName(type)+" "+value+"]";
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/SshFetchTaskFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/SshFetchTaskFactory.java b/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/SshFetchTaskFactory.java
new file mode 100644
index 0000000..a38e305
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/SshFetchTaskFactory.java
@@ -0,0 +1,88 @@
+/*
+ * 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.util.task.ssh;
+
+import org.apache.brooklyn.api.management.TaskFactory;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.brooklyn.location.basic.SshMachineLocation;
+
+// cannot be (cleanly) instantiated due to nested generic self-referential type; however trivial subclasses do allow it
+public class SshFetchTaskFactory implements TaskFactory<SshFetchTaskWrapper> {
+
+ private static final Logger log = LoggerFactory.getLogger(SshFetchTaskFactory.class);
+
+ private boolean dirty = false;
+
+ protected SshMachineLocation machine;
+ protected String remoteFile;
+ protected final ConfigBag config = ConfigBag.newInstance();
+
+ /** constructor where machine will be added later */
+ public SshFetchTaskFactory(String remoteFile) {
+ remoteFile(remoteFile);
+ }
+
+ /** convenience constructor to supply machine immediately */
+ public SshFetchTaskFactory(SshMachineLocation machine, String remoteFile) {
+ machine(machine);
+ remoteFile(remoteFile);
+ }
+
+ protected SshFetchTaskFactory self() { return this; }
+
+ protected void markDirty() {
+ dirty = true;
+ }
+
+ public SshFetchTaskFactory machine(SshMachineLocation machine) {
+ markDirty();
+ this.machine = machine;
+ return self();
+ }
+
+ public SshMachineLocation getMachine() {
+ return machine;
+ }
+
+ public SshFetchTaskFactory remoteFile(String remoteFile) {
+ this.remoteFile = remoteFile;
+ return self();
+ }
+
+ public ConfigBag getConfig() {
+ return config;
+ }
+
+ @Override
+ public SshFetchTaskWrapper newTask() {
+ dirty = false;
+ return new SshFetchTaskWrapper(this);
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ // help let people know of API usage error
+ if (dirty)
+ log.warn("Task "+this+" was modified but modification was never used");
+ super.finalize();
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/SshFetchTaskWrapper.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/SshFetchTaskWrapper.java b/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/SshFetchTaskWrapper.java
new file mode 100644
index 0000000..b6c2931
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/SshFetchTaskWrapper.java
@@ -0,0 +1,135 @@
+/*
+ * 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.util.task.ssh;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.concurrent.Callable;
+
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.api.management.TaskWrapper;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.task.TaskBuilder;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.brooklyn.location.basic.SshMachineLocation;
+
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.os.Os;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+
+/**
+ * As {@link ProcessTaskWrapper}, but putting a file on the remote machine
+ *
+ * @since 0.6.0
+ */
+@Beta
+public class SshFetchTaskWrapper implements TaskWrapper<String> {
+
+ private final Task<String> task;
+
+ private final String remoteFile;
+ private final SshMachineLocation machine;
+ private File backingFile;
+ private final ConfigBag config;
+
+
+ // package private as only AbstractSshTaskFactory should invoke
+ SshFetchTaskWrapper(SshFetchTaskFactory factory) {
+ this.remoteFile = Preconditions.checkNotNull(factory.remoteFile, "remoteFile");
+ this.machine = Preconditions.checkNotNull(factory.machine, "machine");
+ TaskBuilder<String> tb = TaskBuilder.<String>builder().dynamic(false).name("ssh fetch "+factory.remoteFile);
+ task = tb.body(new SshFetchJob()).build();
+ config = factory.getConfig();
+ }
+
+ @Override
+ public Task<String> asTask() {
+ return getTask();
+ }
+
+ @Override
+ public Task<String> getTask() {
+ return task;
+ }
+
+ public String getRemoteFile() {
+ return remoteFile;
+ }
+
+ public SshMachineLocation getMachine() {
+ return machine;
+ }
+
+ private class SshFetchJob implements Callable<String> {
+ @Override
+ public String call() throws Exception {
+ int result = -1;
+ try {
+ Preconditions.checkNotNull(getMachine(), "machine");
+ backingFile = Os.newTempFile("brooklyn-ssh-fetch-", FilenameUtils.getName(remoteFile));
+ backingFile.deleteOnExit();
+
+ result = getMachine().copyFrom(config.getAllConfig(), remoteFile, backingFile.getPath());
+ } catch (Exception e) {
+ throw new IllegalStateException("SSH fetch "+getRemoteFile()+" from "+getMachine()+" returned threw exception, in "+Tasks.current()+": "+e, e);
+ }
+ if (result!=0) {
+ throw new IllegalStateException("SSH fetch "+getRemoteFile()+" from "+getMachine()+" returned non-zero exit code "+result+", in "+Tasks.current());
+ }
+ return FileUtils.readFileToString(backingFile);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return super.toString()+"["+task+"]";
+ }
+
+ /** blocks, returns the fetched file as a string, throwing if there was an exception */
+ public String get() {
+ return getTask().getUnchecked();
+ }
+
+ /** blocks, returns the fetched file as bytes, throwing if there was an exception */
+ public byte[] getBytes() {
+ block();
+ try {
+ return FileUtils.readFileToByteArray(backingFile);
+ } catch (IOException e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ /** blocks until the task completes; does not throw */
+ public SshFetchTaskWrapper block() {
+ getTask().blockUntilEnded();
+ return this;
+ }
+
+ /** true iff the ssh job has completed (with or without failure) */
+ public boolean isDone() {
+ return getTask().isDone();
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/SshPutTaskFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/SshPutTaskFactory.java b/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/SshPutTaskFactory.java
new file mode 100644
index 0000000..05cc42e
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/SshPutTaskFactory.java
@@ -0,0 +1,123 @@
+/*
+ * 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.util.task.ssh;
+
+import java.io.InputStream;
+import java.io.Reader;
+
+import org.apache.brooklyn.api.management.TaskFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.brooklyn.location.basic.SshMachineLocation;
+import brooklyn.util.stream.KnownSizeInputStream;
+import brooklyn.util.stream.ReaderInputStream;
+
+import com.google.common.base.Suppliers;
+
+// cannot be (cleanly) instantiated due to nested generic self-referential type; however trivial subclasses do allow it
+public class SshPutTaskFactory extends SshPutTaskStub implements TaskFactory<SshPutTaskWrapper> {
+
+ private static final Logger log = LoggerFactory.getLogger(SshPutTaskFactory.class);
+
+ private boolean dirty = false;
+
+ /** constructor where machine will be added later */
+ public SshPutTaskFactory(String remoteFile) {
+ remoteFile(remoteFile);
+ }
+
+ /** convenience constructor to supply machine immediately */
+ public SshPutTaskFactory(SshMachineLocation machine, String remoteFile) {
+ machine(machine);
+ remoteFile(remoteFile);
+ }
+
+ protected SshPutTaskFactory self() { return this; }
+
+ protected void markDirty() {
+ dirty = true;
+ }
+
+ public SshPutTaskFactory machine(SshMachineLocation machine) {
+ markDirty();
+ this.machine = machine;
+ return self();
+ }
+
+ public SshPutTaskFactory remoteFile(String remoteFile) {
+ this.remoteFile = remoteFile;
+ return self();
+ }
+
+ public SshPutTaskFactory summary(String summary) {
+ markDirty();
+ this.summary = summary;
+ return self();
+ }
+
+ public SshPutTaskFactory contents(String contents) {
+ markDirty();
+ this.contents = Suppliers.ofInstance(KnownSizeInputStream.of(contents));
+ return self();
+ }
+
+ public SshPutTaskFactory contents(byte[] contents) {
+ markDirty();
+ this.contents = Suppliers.ofInstance(KnownSizeInputStream.of(contents));
+ return self();
+ }
+
+ public SshPutTaskFactory contents(InputStream stream) {
+ markDirty();
+ this.contents = Suppliers.ofInstance(stream);
+ return self();
+ }
+
+ public SshPutTaskFactory contents(Reader reader) {
+ markDirty();
+ this.contents = Suppliers.ofInstance(new ReaderInputStream(reader));
+ return self();
+ }
+
+ public SshPutTaskFactory allowFailure() {
+ markDirty();
+ allowFailure = true;
+ return self();
+ }
+
+ public SshPutTaskFactory createDirectory() {
+ markDirty();
+ createDirectory = true;
+ return self();
+ }
+
+ public SshPutTaskWrapper newTask() {
+ dirty = false;
+ return new SshPutTaskWrapper(this);
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ // help let people know of API usage error
+ if (dirty)
+ log.warn("Task "+this+" was modified but modification was never used");
+ super.finalize();
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/SshPutTaskStub.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/SshPutTaskStub.java b/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/SshPutTaskStub.java
new file mode 100644
index 0000000..4e3a024
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/SshPutTaskStub.java
@@ -0,0 +1,69 @@
+/*
+ * 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.util.task.ssh;
+
+import java.io.InputStream;
+
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.location.basic.SshMachineLocation;
+
+import com.google.common.base.Supplier;
+
+public class SshPutTaskStub {
+
+ protected String remoteFile;
+ protected SshMachineLocation machine;
+ protected Supplier<? extends InputStream> contents;
+ protected String summary;
+ protected String permissions;
+ protected boolean allowFailure = false;
+ protected boolean createDirectory = false;
+ protected final ConfigBag config = ConfigBag.newInstance();
+
+ protected SshPutTaskStub() {
+ }
+
+ protected SshPutTaskStub(SshPutTaskStub constructor) {
+ this.remoteFile = constructor.remoteFile;
+ this.machine = constructor.machine;
+ this.contents = constructor.contents;
+ this.summary = constructor.summary;
+ this.allowFailure = constructor.allowFailure;
+ this.createDirectory = constructor.createDirectory;
+ this.permissions = constructor.permissions;
+ this.config.copy(constructor.config);
+ }
+
+ public String getRemoteFile() {
+ return remoteFile;
+ }
+
+ public String getSummary() {
+ if (summary!=null) return summary;
+ return "scp put: "+remoteFile;
+ }
+
+ public SshMachineLocation getMachine() {
+ return machine;
+ }
+
+ protected ConfigBag getConfig() {
+ return config;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/SshPutTaskWrapper.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/SshPutTaskWrapper.java b/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/SshPutTaskWrapper.java
new file mode 100644
index 0000000..13449d0
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/SshPutTaskWrapper.java
@@ -0,0 +1,189 @@
+/*
+ * 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.util.task.ssh;
+
+import java.util.Arrays;
+import java.util.concurrent.Callable;
+
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.api.management.TaskWrapper;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
+import org.apache.brooklyn.core.util.task.TaskBuilder;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+
+/** As {@link ProcessTaskWrapper}, but putting a file on the remote machine */
+@Beta
+public class SshPutTaskWrapper extends SshPutTaskStub implements TaskWrapper<Void> {
+
+ private static final Logger log = LoggerFactory.getLogger(SshPutTaskWrapper.class);
+
+ private final Task<Void> task;
+
+ protected Integer exitCodeOfCopy = null;
+ protected Exception exception = null;
+ protected boolean successful = false;
+
+ // package private as only AbstractSshTaskFactory should invoke
+ SshPutTaskWrapper(SshPutTaskFactory constructor) {
+ super(constructor);
+ TaskBuilder<Void> tb = TaskBuilder.<Void>builder().dynamic(false).name(getSummary());
+ task = tb.body(new SshPutJob()).build();
+ }
+
+ @Override
+ public Task<Void> asTask() {
+ return getTask();
+ }
+
+ @Override
+ public Task<Void> getTask() {
+ return task;
+ }
+
+ // TODO:
+ // verify
+ // copyAsRoot
+ // owner
+ // lastModificationDate - see {@link #PROP_LAST_MODIFICATION_DATE}; not supported by all SshTool implementations
+ // lastAccessDate - see {@link #PROP_LAST_ACCESS_DATE}; not supported by all SshTool implementations
+
+ private class SshPutJob implements Callable<Void> {
+ @Override
+ public Void call() throws Exception {
+ try {
+ Preconditions.checkNotNull(getMachine(), "machine");
+
+ String remoteFile = getRemoteFile();
+
+ if (createDirectory) {
+ String remoteDir = remoteFile;
+ int exitCodeOfCreate = -1;
+ try {
+ int li = remoteDir.lastIndexOf("/");
+ if (li>=0) {
+ remoteDir = remoteDir.substring(0, li+1);
+ exitCodeOfCreate = getMachine().execCommands("creating directory for "+getSummary(),
+ Arrays.asList("mkdir -p "+remoteDir));
+ } else {
+ // nothing to create
+ exitCodeOfCreate = 0;
+ }
+ } catch (Exception e) {
+ if (log.isDebugEnabled())
+ log.debug("SSH put "+getRemoteFile()+" (create dir, in task "+getSummary()+") to "+getMachine()+" threw exception: "+e);
+ exception = e;
+ }
+ if (exception!=null || !((Integer)0).equals(exitCodeOfCreate)) {
+ if (!allowFailure) {
+ if (exception != null) {
+ throw new IllegalStateException(getSummary()+" (creating dir "+remoteDir+" for SSH put task) ended with exception, in "+Tasks.current()+": "+exception, exception);
+ }
+ if (exitCodeOfCreate!=0) {
+ exception = new IllegalStateException(getSummary()+" (creating dir "+remoteDir+" SSH put task) ended with exit code "+exitCodeOfCreate+", in "+Tasks.current());
+ throw exception;
+ }
+ }
+ // not successful, but allowed
+ return null;
+ }
+ }
+
+ ConfigBag config = ConfigBag.newInstanceCopying(getConfig());
+ if (permissions!=null) config.put(SshTool.PROP_PERMISSIONS, permissions);
+
+ exitCodeOfCopy = getMachine().copyTo(config.getAllConfig(), contents.get(), remoteFile);
+
+ if (log.isDebugEnabled())
+ log.debug("SSH put "+getRemoteFile()+" (task "+getSummary()+") to "+getMachine()+" completed with exit code "+exitCodeOfCopy);
+ } catch (Exception e) {
+ if (log.isDebugEnabled())
+ log.debug("SSH put "+getRemoteFile()+" (task "+getSummary()+") to "+getMachine()+" threw exception: "+e);
+ exception = e;
+ }
+
+ if (exception!=null || !((Integer)0).equals(exitCodeOfCopy)) {
+ if (!allowFailure) {
+ if (exception != null) {
+ throw new IllegalStateException(getSummary()+" (SSH put task) ended with exception, in "+Tasks.current()+": "+exception, exception);
+ }
+ if (exitCodeOfCopy!=0) {
+ exception = new IllegalStateException(getSummary()+" (SSH put task) ended with exit code "+exitCodeOfCopy+", in "+Tasks.current());
+ throw exception;
+ }
+ }
+ // not successful, but allowed
+ return null;
+ }
+
+ // TODO verify
+
+ successful = (exception==null && ((Integer)0).equals(exitCodeOfCopy));
+ return null;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return super.toString()+"["+task+"]";
+ }
+
+ /** blocks, throwing if there was an exception */
+ public Void get() {
+ return getTask().getUnchecked();
+ }
+
+ /** returns the exit code from the copy, 0 on success;
+ * null if it has not completed or threw exception
+ * (not sure if this is ever a non-zero integer or if it is meaningful)
+ * <p>
+ * most callers will want the simpler {@link #isSuccessful()} */
+ public Integer getExitCode() {
+ return exitCodeOfCopy;
+ }
+
+ /** returns any exception encountered in the operation */
+ public Exception getException() {
+ return exception;
+ }
+
+ /** blocks until the task completes; does not throw */
+ public SshPutTaskWrapper block() {
+ getTask().blockUntilEnded();
+ return this;
+ }
+
+ /** true iff the ssh job has completed (with or without failure) */
+ public boolean isDone() {
+ return getTask().isDone();
+ }
+
+ /** true iff the scp has completed successfully; guaranteed to be set before {@link #isDone()} or {@link #block()} are satisfied */
+ public boolean isSuccessful() {
+ return successful;
+ }
+
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/SshTasks.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/SshTasks.java b/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/SshTasks.java
new file mode 100644
index 0000000..5f8d735
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/SshTasks.java
@@ -0,0 +1,236 @@
+/*
+ * 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.util.task.ssh;
+
+import java.util.Map;
+
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.api.management.TaskAdaptable;
+import org.apache.brooklyn.api.management.TaskFactory;
+import org.apache.brooklyn.api.management.TaskQueueingContext;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.core.util.task.ssh.internal.PlainSshExecTaskFactory;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskFactory;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.config.ConfigUtils;
+import brooklyn.entity.basic.BrooklynTaskTags;
+import brooklyn.entity.basic.ConfigKeys;
+
+import org.apache.brooklyn.location.basic.AbstractLocation;
+import org.apache.brooklyn.location.basic.LocationInternal;
+import org.apache.brooklyn.location.basic.SshMachineLocation;
+
+import brooklyn.util.net.Urls;
+import brooklyn.util.ssh.BashCommands;
+import brooklyn.util.stream.Streams;
+import brooklyn.util.text.Identifiers;
+import brooklyn.util.text.Strings;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+
+/**
+ * Conveniences for generating {@link Task} instances to perform SSH activities on an {@link SshMachineLocation}.
+ * <p>
+ * To infer the {@link SshMachineLocation} and take properties from entities and global management context the
+ * {@link SshEffectorTasks} should be preferred over this class.
+ *
+ * @see SshEffectorTasks
+ * @since 0.6.0
+ */
+@Beta
+public class SshTasks {
+
+ private static final Logger log = LoggerFactory.getLogger(SshTasks.class);
+
+ public static ProcessTaskFactory<Integer> newSshExecTaskFactory(SshMachineLocation machine, String ...commands) {
+ return newSshExecTaskFactory(machine, true, commands);
+ }
+
+ public static ProcessTaskFactory<Integer> newSshExecTaskFactory(SshMachineLocation machine, final boolean useMachineConfig, String ...commands) {
+ return new PlainSshExecTaskFactory<Integer>(machine, commands) {
+ {
+ if (useMachineConfig)
+ config.putIfAbsent(getSshFlags(machine));
+ }
+ };
+ }
+
+ public static SshPutTaskFactory newSshPutTaskFactory(SshMachineLocation machine, String remoteFile) {
+ return newSshPutTaskFactory(machine, true, remoteFile);
+ }
+
+ public static SshPutTaskFactory newSshPutTaskFactory(SshMachineLocation machine, final boolean useMachineConfig, String remoteFile) {
+ return new SshPutTaskFactory(machine, remoteFile) {
+ {
+ if (useMachineConfig)
+ config.putIfAbsent(getSshFlags(machine));
+ }
+ };
+ }
+
+ public static SshFetchTaskFactory newSshFetchTaskFactory(SshMachineLocation machine, String remoteFile) {
+ return newSshFetchTaskFactory(machine, true, remoteFile);
+ }
+
+ public static SshFetchTaskFactory newSshFetchTaskFactory(SshMachineLocation machine, final boolean useMachineConfig, String remoteFile) {
+ return new SshFetchTaskFactory(machine, remoteFile) {
+ {
+ if (useMachineConfig)
+ config.putIfAbsent(getSshFlags(machine));
+ }
+ };
+ }
+
+ private static Map<String, Object> getSshFlags(Location location) {
+ ConfigBag allConfig = ConfigBag.newInstance();
+
+ if (location instanceof AbstractLocation) {
+ ManagementContext mgmt = ((AbstractLocation)location).getManagementContext();
+ if (mgmt!=null)
+ allConfig.putAll(mgmt.getConfig().getAllConfig());
+ }
+
+ allConfig.putAll(((LocationInternal)location).config().getBag());
+
+ Map<String, Object> result = Maps.newLinkedHashMap();
+ for (String keyS : allConfig.getAllConfig().keySet()) {
+ ConfigKey<?> key = ConfigKeys.newConfigKey(Object.class, keyS);
+ if (key.getName().startsWith(SshTool.BROOKLYN_CONFIG_KEY_PREFIX)) {
+ result.put(ConfigUtils.unprefixedKey(SshTool.BROOKLYN_CONFIG_KEY_PREFIX, key).getName(), allConfig.get(key));
+ }
+ }
+ return result;
+ }
+
+ @Beta
+ public static enum OnFailingTask {
+ FAIL,
+ /** issues a warning, sometimes implemented as marking the task inessential and failing it if it appears
+ * we are in a dynamic {@link TaskQueueingContext};
+ * useful because this way the warning appears to the user;
+ * but note that the check is done against the calling thread so use with some care
+ * (and thus this enum is currently here rather then elsewhere) */
+ WARN_OR_IF_DYNAMIC_FAIL_MARKING_INESSENTIAL,
+ /** issues a warning in the log if the task fails, otherwise swallows it */
+ WARN_IN_LOG_ONLY,
+ /** not even a warning if the task fails (the caller is expected to handle it as appropriate) */
+ IGNORE }
+
+ public static ProcessTaskFactory<Boolean> dontRequireTtyForSudo(SshMachineLocation machine, final boolean failIfCantSudo) {
+ return dontRequireTtyForSudo(machine, failIfCantSudo ? OnFailingTask.FAIL : OnFailingTask.WARN_IN_LOG_ONLY);
+ }
+ /** creates a task which returns modifies sudoers to ensure non-tty access is permitted;
+ * also gives nice warnings if sudo is not permitted */
+ public static ProcessTaskFactory<Boolean> dontRequireTtyForSudo(SshMachineLocation machine, OnFailingTask onFailingTaskRequested) {
+ final OnFailingTask onFailingTask;
+ if (onFailingTaskRequested==OnFailingTask.WARN_OR_IF_DYNAMIC_FAIL_MARKING_INESSENTIAL) {
+ if (DynamicTasks.getTaskQueuingContext()!=null)
+ onFailingTask = onFailingTaskRequested;
+ else
+ onFailingTask = OnFailingTask.WARN_IN_LOG_ONLY;
+ } else {
+ onFailingTask = onFailingTaskRequested;
+ }
+
+ final String id = Identifiers.makeRandomId(6);
+ return newSshExecTaskFactory(machine,
+ BashCommands.dontRequireTtyForSudo(),
+ // strange quotes are to ensure we don't match against echoed stdin
+ BashCommands.sudo("echo \"sudo\"-is-working-"+id))
+ .summary("setting up sudo")
+ .configure(SshTool.PROP_ALLOCATE_PTY, true)
+ .allowingNonZeroExitCode()
+ .returning(new Function<ProcessTaskWrapper<?>,Boolean>() { public Boolean apply(ProcessTaskWrapper<?> task) {
+ if (task.getExitCode()==0 && task.getStdout().contains("sudo-is-working-"+id)) return true;
+ Entity entity = BrooklynTaskTags.getTargetOrContextEntity(Tasks.current());
+
+
+ if (onFailingTask!=OnFailingTask.IGNORE) {
+ // TODO if in a queueing context can we mark this task inessential and throw?
+ // that way user sees the message...
+ String message = "Error setting up sudo for "+task.getMachine().getUser()+"@"+task.getMachine().getAddress().getHostName()+" "+
+ " (exit code "+task.getExitCode()+(entity!=null ? ", entity "+entity : "")+")";
+ DynamicTasks.queueIfPossible(Tasks.warning(message, null));
+ }
+ Streams.logStreamTail(log, "STDERR of sudo setup problem", Streams.byteArrayOfString(task.getStderr()), 1024);
+
+ if (onFailingTask==OnFailingTask.WARN_OR_IF_DYNAMIC_FAIL_MARKING_INESSENTIAL) {
+ Tasks.markInessential();
+ }
+ if (onFailingTask==OnFailingTask.FAIL || onFailingTask==OnFailingTask.WARN_OR_IF_DYNAMIC_FAIL_MARKING_INESSENTIAL) {
+ throw new IllegalStateException("Passwordless sudo is required for "+task.getMachine().getUser()+"@"+task.getMachine().getAddress().getHostName()+
+ (entity!=null ? " ("+entity+")" : ""));
+ }
+ return false;
+ } });
+ }
+
+ /** Function for use in {@link ProcessTaskFactory#returning(Function)} which logs all information, optionally requires zero exit code,
+ * and then returns stdout */
+ public static Function<ProcessTaskWrapper<?>, String> returningStdoutLoggingInfo(final Logger logger, final boolean requireZero) {
+ return new Function<ProcessTaskWrapper<?>, String>() {
+ public String apply(@Nullable ProcessTaskWrapper<?> input) {
+ if (logger!=null) logger.info(input+" COMMANDS:\n"+Strings.join(input.getCommands(),"\n"));
+ if (logger!=null) logger.info(input+" STDOUT:\n"+input.getStdout());
+ if (logger!=null) logger.info(input+" STDERR:\n"+input.getStderr());
+ if (requireZero && input.getExitCode()!=0)
+ throw new IllegalStateException("non-zero exit code in "+input.getSummary()+": see log for more details!");
+ return input.getStdout();
+ }
+ };
+ }
+
+ /** task to install a file given a url, where the url is resolved remotely first then locally */
+ public static TaskFactory<?> installFromUrl(final SshMachineLocation location, final String url, final String destPath) {
+ return installFromUrl(ResourceUtils.create(SshTasks.class), ImmutableMap.<String,Object>of(), location, url, destPath);
+ }
+ /** task to install a file given a url, where the url is resolved remotely first then locally */
+ public static TaskFactory<?> installFromUrl(final ResourceUtils utils, final Map<String, ?> props, final SshMachineLocation location, final String url, final String destPath) {
+ return new TaskFactory<TaskAdaptable<?>>() {
+ @Override
+ public TaskAdaptable<?> newTask() {
+ return Tasks.<Void>builder().name("installing "+Urls.getBasename(url)).description("installing "+url+" to "+destPath).body(new Runnable() {
+ @Override
+ public void run() {
+ int result = location.installTo(utils, props, url, destPath);
+ if (result!=0)
+ throw new IllegalStateException("Failed to install '"+url+"' to '"+destPath+"' at "+location+": exit code "+result);
+ }
+ }).build();
+ }
+ };
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/internal/AbstractSshExecTaskFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/internal/AbstractSshExecTaskFactory.java b/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/internal/AbstractSshExecTaskFactory.java
new file mode 100644
index 0000000..45600d5
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/internal/AbstractSshExecTaskFactory.java
@@ -0,0 +1,58 @@
+/*
+ * 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.util.task.ssh.internal;
+
+import com.google.common.base.Preconditions;
+
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskFactory;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
+import org.apache.brooklyn.core.util.task.system.internal.AbstractProcessTaskFactory;
+import org.apache.brooklyn.location.basic.SshMachineLocation;
+
+// cannot be (cleanly) instantiated due to nested generic self-referential type; however trivial subclasses do allow it
+public abstract class AbstractSshExecTaskFactory<T extends AbstractProcessTaskFactory<T,RET>,RET> extends AbstractProcessTaskFactory<T,RET> implements ProcessTaskFactory<RET> {
+
+ /** constructor where machine will be added later */
+ public AbstractSshExecTaskFactory(String ...commands) {
+ super(commands);
+ }
+
+ /** convenience constructor to supply machine immediately */
+ public AbstractSshExecTaskFactory(SshMachineLocation machine, String ...commands) {
+ this(commands);
+ machine(machine);
+ }
+
+ @Override
+ public ProcessTaskWrapper<RET> newTask() {
+ dirty = false;
+ return new ProcessTaskWrapper<RET>(this) {
+ protected void run(ConfigBag config) {
+ Preconditions.checkNotNull(getMachine(), "machine");
+ if (Boolean.FALSE.equals(this.runAsScript)) {
+ this.exitCode = getMachine().execCommands(config.getAllConfig(), getSummary(), commands, shellEnvironment);
+ } else { // runScript = null or TRUE
+ this.exitCode = getMachine().execScript(config.getAllConfig(), getSummary(), commands, shellEnvironment);
+ }
+ }
+ protected String taskTypeShortName() { return "SSH"; }
+ };
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/internal/PlainSshExecTaskFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/internal/PlainSshExecTaskFactory.java b/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/internal/PlainSshExecTaskFactory.java
new file mode 100644
index 0000000..4d5dfce
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/ssh/internal/PlainSshExecTaskFactory.java
@@ -0,0 +1,71 @@
+/*
+ * 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.util.task.ssh.internal;
+
+import java.util.List;
+
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
+import org.apache.brooklyn.location.basic.SshMachineLocation;
+
+import com.google.common.base.Function;
+
+/** the "Plain" class exists purely so we can massage return types for callers' convenience */
+public class PlainSshExecTaskFactory<RET> extends AbstractSshExecTaskFactory<PlainSshExecTaskFactory<RET>,RET> {
+ /** constructor where machine will be added later */
+ public PlainSshExecTaskFactory(String ...commands) {
+ super(commands);
+ }
+
+ /** convenience constructor to supply machine immediately */
+ public PlainSshExecTaskFactory(SshMachineLocation machine, String ...commands) {
+ this(commands);
+ machine(machine);
+ }
+
+ /** Constructor where machine will be added later */
+ public PlainSshExecTaskFactory(List<String> commands) {
+ this(commands.toArray(new String[commands.size()]));
+ }
+
+ /** Convenience constructor to supply machine immediately */
+ public PlainSshExecTaskFactory(SshMachineLocation machine, List<String> commands) {
+ this(machine, commands.toArray(new String[commands.size()]));
+ }
+
+ @Override
+ public <T2> PlainSshExecTaskFactory<T2> returning(ScriptReturnType type) {
+ return (PlainSshExecTaskFactory<T2>) super.<T2>returning(type);
+ }
+
+ @Override
+ public <RET2> PlainSshExecTaskFactory<RET2> returning(Function<ProcessTaskWrapper<?>, RET2> resultTransformation) {
+ return (PlainSshExecTaskFactory<RET2>) super.returning(resultTransformation);
+ }
+
+ @Override
+ public PlainSshExecTaskFactory<Boolean> returningIsExitCodeZero() {
+ return (PlainSshExecTaskFactory<Boolean>) super.returningIsExitCodeZero();
+ }
+
+ @Override
+ public PlainSshExecTaskFactory<String> requiringZeroAndReturningStdout() {
+ return (PlainSshExecTaskFactory<String>) super.requiringZeroAndReturningStdout();
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/system/ProcessTaskFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/system/ProcessTaskFactory.java b/core/src/main/java/org/apache/brooklyn/core/util/task/system/ProcessTaskFactory.java
new file mode 100644
index 0000000..f66e1ea
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/system/ProcessTaskFactory.java
@@ -0,0 +1,66 @@
+/*
+ * 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.util.task.system;
+
+import java.util.Map;
+
+import org.apache.brooklyn.api.management.TaskFactory;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskStub.ScriptReturnType;
+
+import brooklyn.config.ConfigKey;
+
+import org.apache.brooklyn.location.basic.SshMachineLocation;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Function;
+
+public interface ProcessTaskFactory<T> extends TaskFactory<ProcessTaskWrapper<T>> {
+ public ProcessTaskFactory<T> machine(SshMachineLocation machine);
+ public ProcessTaskFactory<T> add(String ...commandsToAdd);
+ public ProcessTaskFactory<T> add(Iterable<String> commandsToAdd);
+ public ProcessTaskFactory<T> requiringExitCodeZero();
+ public ProcessTaskFactory<T> requiringExitCodeZero(String extraErrorMessage);
+ public ProcessTaskFactory<T> allowingNonZeroExitCode();
+ public ProcessTaskFactory<String> requiringZeroAndReturningStdout();
+ public ProcessTaskFactory<Boolean> returningIsExitCodeZero();
+ public <RET2> ProcessTaskFactory<RET2> returning(ScriptReturnType type);
+ public <RET2> ProcessTaskFactory<RET2> returning(Function<ProcessTaskWrapper<?>, RET2> resultTransformation);
+ public ProcessTaskFactory<T> runAsCommand();
+ public ProcessTaskFactory<T> runAsScript();
+ public ProcessTaskFactory<T> runAsRoot();
+ public ProcessTaskFactory<T> environmentVariable(String key, String val);
+ public ProcessTaskFactory<T> environmentVariables(Map<String,String> vars);
+ public ProcessTaskFactory<T> summary(String summary);
+
+ /** allows setting config-key based properties for specific underlying tools */
+ @Beta
+ public <V> ProcessTaskFactory<T> configure(ConfigKey<V> key, V value);
+
+ /** allows setting config-key/flag based properties for specific underlying tools;
+ * but note that if any are prefixed with {@link SshTool#BROOKLYN_CONFIG_KEY_PREFIX}
+ * these should normally be filtered out */
+ @Beta
+ public ProcessTaskFactory<T> configure(Map<?,?> flags);
+
+ /** adds a listener which will be notified of (otherwise) successful completion,
+ * typically used to invalidate the result (ie throw exception, to promote a string in the output to an exception);
+ * invoked even if return code is zero, so a better error can be thrown */
+ public ProcessTaskFactory<T> addCompletionListener(Function<ProcessTaskWrapper<?>, Void> function);
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/system/ProcessTaskStub.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/system/ProcessTaskStub.java b/core/src/main/java/org/apache/brooklyn/core/util/task/system/ProcessTaskStub.java
new file mode 100644
index 0000000..1937d15
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/system/ProcessTaskStub.java
@@ -0,0 +1,102 @@
+/*
+ * 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.util.task.system;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.location.basic.SshMachineLocation;
+
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.text.Strings;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+public class ProcessTaskStub {
+
+ protected final List<String> commands = new ArrayList<String>();
+ /** null for localhost */
+ protected SshMachineLocation machine;
+
+ // config data
+ protected String summary;
+ protected final ConfigBag config = ConfigBag.newInstance();
+
+ public static enum ScriptReturnType { CUSTOM, EXIT_CODE, STDOUT_STRING, STDOUT_BYTES, STDERR_STRING, STDERR_BYTES }
+ protected Function<ProcessTaskWrapper<?>, ?> returnResultTransformation = null;
+ protected ScriptReturnType returnType = ScriptReturnType.EXIT_CODE;
+
+ protected Boolean runAsScript = null;
+ protected boolean runAsRoot = false;
+ protected Boolean requireExitCodeZero = null;
+ protected String extraErrorMessage = null;
+ protected Map<String,String> shellEnvironment = new MutableMap<String, String>();
+ protected final List<Function<ProcessTaskWrapper<?>, Void>> completionListeners = new ArrayList<Function<ProcessTaskWrapper<?>,Void>>();
+
+ public ProcessTaskStub() {}
+
+ protected ProcessTaskStub(ProcessTaskStub source) {
+ commands.addAll(source.getCommands());
+ machine = source.getMachine();
+ summary = source.getSummary();
+ config.copy(source.getConfig());
+ returnResultTransformation = source.returnResultTransformation;
+ returnType = source.returnType;
+ runAsScript = source.runAsScript;
+ runAsRoot = source.runAsRoot;
+ requireExitCodeZero = source.requireExitCodeZero;
+ extraErrorMessage = source.extraErrorMessage;
+ shellEnvironment.putAll(source.getShellEnvironment());
+ completionListeners.addAll(source.getCompletionListeners());
+ }
+
+ public String getSummary() {
+ if (summary!=null) return summary;
+ return Strings.maxlen(Strings.join(commands, " ; "), 160);
+ }
+
+ /** null for localhost */
+ public SshMachineLocation getMachine() {
+ return machine;
+ }
+
+ public Map<String, String> getShellEnvironment() {
+ return ImmutableMap.copyOf(shellEnvironment);
+ }
+
+ @Override
+ public String toString() {
+ return super.toString()+"["+getSummary()+"]";
+ }
+
+ public List<String> getCommands() {
+ return ImmutableList.copyOf(commands);
+ }
+
+ public List<Function<ProcessTaskWrapper<?>, Void>> getCompletionListeners() {
+ return completionListeners;
+ }
+
+ protected ConfigBag getConfig() { return config; }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/system/ProcessTaskWrapper.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/system/ProcessTaskWrapper.java b/core/src/main/java/org/apache/brooklyn/core/util/task/system/ProcessTaskWrapper.java
new file mode 100644
index 0000000..045b3c9
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/system/ProcessTaskWrapper.java
@@ -0,0 +1,187 @@
+/*
+ * 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.util.task.system;
+
+import java.io.ByteArrayOutputStream;
+import java.util.concurrent.Callable;
+
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.api.management.TaskWrapper;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.internal.ssh.ShellTool;
+import org.apache.brooklyn.core.util.task.TaskBuilder;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.core.util.task.system.internal.AbstractProcessTaskFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.entity.basic.BrooklynTaskTags;
+import brooklyn.util.stream.Streams;
+import brooklyn.util.text.Strings;
+
+import com.google.common.base.Function;
+
+/** Wraps a fully constructed process task, and allows callers to inspect status.
+ * Note that methods in here such as {@link #getStdout()} will return partially completed streams while the task is ongoing
+ * (and exit code will be null). You can {@link #block()} or {@link #get()} as conveniences on the underlying {@link #getTask()}. */
+public abstract class ProcessTaskWrapper<RET> extends ProcessTaskStub implements TaskWrapper<RET> {
+
+ private static final Logger log = LoggerFactory.getLogger(ProcessTaskWrapper.class);
+
+ private final Task<RET> task;
+
+ // execution details
+ protected ByteArrayOutputStream stdout = new ByteArrayOutputStream();
+ protected ByteArrayOutputStream stderr = new ByteArrayOutputStream();
+ protected Integer exitCode = null;
+
+ @SuppressWarnings("unchecked")
+ protected ProcessTaskWrapper(AbstractProcessTaskFactory<?,RET> constructor) {
+ super(constructor);
+ TaskBuilder<Object> tb = constructor.constructCustomizedTaskBuilder();
+ if (stdout!=null) tb.tag(BrooklynTaskTags.tagForStreamSoft(BrooklynTaskTags.STREAM_STDOUT, stdout));
+ if (stderr!=null) tb.tag(BrooklynTaskTags.tagForStreamSoft(BrooklynTaskTags.STREAM_STDERR, stderr));
+ task = (Task<RET>) tb.body(new ProcessTaskInternalJob()).build();
+ }
+
+ @Override
+ public Task<RET> asTask() {
+ return getTask();
+ }
+
+ @Override
+ public Task<RET> getTask() {
+ return task;
+ }
+
+ public Integer getExitCode() {
+ return exitCode;
+ }
+
+ public byte[] getStdoutBytes() {
+ if (stdout==null) return null;
+ return stdout.toByteArray();
+ }
+
+ public byte[] getStderrBytes() {
+ if (stderr==null) return null;
+ return stderr.toByteArray();
+ }
+
+ public String getStdout() {
+ if (stdout==null) return null;
+ return stdout.toString();
+ }
+
+ public String getStderr() {
+ if (stderr==null) return null;
+ return stderr.toString();
+ }
+
+ protected class ProcessTaskInternalJob implements Callable<Object> {
+ @Override
+ public Object call() throws Exception {
+ run( getConfigForRunning() );
+
+ for (Function<ProcessTaskWrapper<?>, Void> listener: completionListeners) {
+ try {
+ listener.apply(ProcessTaskWrapper.this);
+ } catch (Exception e) {
+ logWithDetailsAndThrow("Error in "+taskTypeShortName()+" task "+getSummary()+": "+e, e);
+ }
+ }
+
+ if (exitCode!=0 && !Boolean.FALSE.equals(requireExitCodeZero)) {
+ if (Boolean.TRUE.equals(requireExitCodeZero)) {
+ logWithDetailsAndThrow(taskTypeShortName()+" task ended with exit code "+exitCode+" when 0 was required, in "+Tasks.current()+": "+getSummary(), null);
+ } else {
+ // warn, but allow, on non-zero not explicitly allowed
+ log.warn(taskTypeShortName()+" task ended with exit code "+exitCode+" when non-zero was not explicitly allowed (error may be thrown in future), in "
+ +Tasks.current()+": "+getSummary());
+ }
+ }
+ switch (returnType) {
+ case CUSTOM: return returnResultTransformation.apply(ProcessTaskWrapper.this);
+ case STDOUT_STRING: return stdout.toString();
+ case STDOUT_BYTES: return stdout.toByteArray();
+ case STDERR_STRING: return stderr.toString();
+ case STDERR_BYTES: return stderr.toByteArray();
+ case EXIT_CODE: return exitCode;
+ }
+
+ throw new IllegalStateException("Unknown return type for "+taskTypeShortName()+" job "+getSummary()+": "+returnType);
+ }
+
+ protected void logWithDetailsAndThrow(String message, Throwable optionalCause) {
+ message = (extraErrorMessage!=null ? extraErrorMessage+": " : "") + message;
+ log.warn(message+" (throwing)");
+ logProblemDetails("STDERR", stderr, 1024);
+ logProblemDetails("STDOUT", stdout, 1024);
+ logProblemDetails("STDIN", Streams.byteArrayOfString(Strings.join(commands,"\n")), 4096);
+ if (optionalCause!=null) throw new IllegalStateException(message, optionalCause);
+ throw new IllegalStateException(message);
+ }
+
+ protected void logProblemDetails(String streamName, ByteArrayOutputStream stream, int max) {
+ Streams.logStreamTail(log, streamName+" for problem in "+Tasks.current(), stream, max);
+ }
+
+ }
+
+ @Override
+ public String toString() {
+ return super.toString()+"["+task+"]";
+ }
+
+ /** blocks and gets the result, throwing if there was an exception */
+ public RET get() {
+ return getTask().getUnchecked();
+ }
+
+ /** blocks until the task completes; does not throw */
+ public ProcessTaskWrapper<RET> block() {
+ getTask().blockUntilEnded();
+ return this;
+ }
+
+ /** true iff the process has completed (with or without failure) */
+ public boolean isDone() {
+ return getTask().isDone();
+ }
+
+ /** for overriding */
+ protected ConfigBag getConfigForRunning() {
+ ConfigBag config = ConfigBag.newInstanceCopying(ProcessTaskWrapper.this.config);
+ if (stdout!=null) config.put(ShellTool.PROP_OUT_STREAM, stdout);
+ if (stderr!=null) config.put(ShellTool.PROP_ERR_STREAM, stderr);
+
+ if (!config.containsKey(ShellTool.PROP_NO_EXTRA_OUTPUT))
+ // by default no extra output (so things like cat, etc work as expected)
+ config.put(ShellTool.PROP_NO_EXTRA_OUTPUT, true);
+
+ if (runAsRoot)
+ config.put(ShellTool.PROP_RUN_AS_ROOT, true);
+ return config;
+ }
+
+ protected abstract void run(ConfigBag config);
+
+ protected abstract String taskTypeShortName();
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/system/SystemTasks.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/system/SystemTasks.java b/core/src/main/java/org/apache/brooklyn/core/util/task/system/SystemTasks.java
new file mode 100644
index 0000000..d05b09c
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/system/SystemTasks.java
@@ -0,0 +1,29 @@
+/*
+ * 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.util.task.system;
+
+import org.apache.brooklyn.core.util.task.system.internal.SystemProcessTaskFactory.ConcreteSystemProcessTaskFactory;
+
+public class SystemTasks {
+
+ public static ProcessTaskFactory<Integer> exec(String ...commands) {
+ return new ConcreteSystemProcessTaskFactory<Integer>(commands);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/system/internal/AbstractProcessTaskFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/system/internal/AbstractProcessTaskFactory.java b/core/src/main/java/org/apache/brooklyn/core/util/task/system/internal/AbstractProcessTaskFactory.java
new file mode 100644
index 0000000..8b90263
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/system/internal/AbstractProcessTaskFactory.java
@@ -0,0 +1,216 @@
+/*
+ * 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.util.task.system.internal;
+
+import java.util.Arrays;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.basic.BrooklynTaskTags;
+
+import org.apache.brooklyn.core.util.task.TaskBuilder;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskFactory;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskStub;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
+import org.apache.brooklyn.location.basic.SshMachineLocation;
+
+import brooklyn.util.stream.Streams;
+import brooklyn.util.text.Strings;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+
+public abstract class AbstractProcessTaskFactory<T extends AbstractProcessTaskFactory<T,RET>,RET> extends ProcessTaskStub implements ProcessTaskFactory<RET> {
+
+ private static final Logger log = LoggerFactory.getLogger(AbstractProcessTaskFactory.class);
+
+ protected boolean dirty = false;
+
+ public AbstractProcessTaskFactory(String ...commands) {
+ this.commands.addAll(Arrays.asList(commands));
+ }
+
+ @SuppressWarnings("unchecked")
+ protected T self() { return (T)this; }
+
+ protected void markDirty() {
+ dirty = true;
+ }
+
+ @Override
+ public T add(String ...commandsToAdd) {
+ markDirty();
+ for (String commandToAdd: commandsToAdd) this.commands.add(commandToAdd);
+ return self();
+ }
+
+ @Override
+ public T add(Iterable<String> commandsToAdd) {
+ Iterables.addAll(this.commands, commandsToAdd);
+ return self();
+ }
+
+ @Override
+ public T machine(SshMachineLocation machine) {
+ markDirty();
+ this.machine = machine;
+ return self();
+ }
+
+ @Override
+ public T requiringExitCodeZero() {
+ markDirty();
+ requireExitCodeZero = true;
+ return self();
+ }
+
+ @Override
+ public T requiringExitCodeZero(String extraErrorMessage) {
+ markDirty();
+ requireExitCodeZero = true;
+ this.extraErrorMessage = extraErrorMessage;
+ return self();
+ }
+
+ @Override
+ public T allowingNonZeroExitCode() {
+ markDirty();
+ requireExitCodeZero = false;
+ return self();
+ }
+
+ @Override
+ public ProcessTaskFactory<Boolean> returningIsExitCodeZero() {
+ if (requireExitCodeZero==null) allowingNonZeroExitCode();
+ return returning(new Function<ProcessTaskWrapper<?>,Boolean>() {
+ public Boolean apply(ProcessTaskWrapper<?> input) {
+ return input.getExitCode()==0;
+ }
+ });
+ }
+
+ @Override
+ public ProcessTaskFactory<String> requiringZeroAndReturningStdout() {
+ requiringExitCodeZero();
+ return this.<String>returning(ScriptReturnType.STDOUT_STRING);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <RET2> ProcessTaskFactory<RET2> returning(ScriptReturnType type) {
+ markDirty();
+ returnType = Preconditions.checkNotNull(type);
+ return (ProcessTaskFactory<RET2>) self();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <RET2> ProcessTaskFactory<RET2> returning(Function<ProcessTaskWrapper<?>, RET2> resultTransformation) {
+ markDirty();
+ returnType = ScriptReturnType.CUSTOM;
+ this.returnResultTransformation = resultTransformation;
+ return (ProcessTaskFactory<RET2>) self();
+ }
+
+ @Override
+ public T runAsCommand() {
+ markDirty();
+ runAsScript = false;
+ return self();
+ }
+
+ @Override
+ public T runAsScript() {
+ markDirty();
+ runAsScript = true;
+ return self();
+ }
+
+ @Override
+ public T runAsRoot() {
+ markDirty();
+ runAsRoot = true;
+ return self();
+ }
+
+ @Override
+ public T environmentVariable(String key, String val) {
+ markDirty();
+ shellEnvironment.put(key, val);
+ return self();
+ }
+
+ @Override
+ public T environmentVariables(Map<String,String> vars) {
+ if (vars!=null) {
+ markDirty();
+ shellEnvironment.putAll(vars);
+ }
+ return self();
+ }
+
+ /** creates the TaskBuilder which can be further customized; typically invoked by the initial {@link #newTask()} */
+ public TaskBuilder<Object> constructCustomizedTaskBuilder() {
+ TaskBuilder<Object> tb = TaskBuilder.builder().dynamic(false).name("ssh: "+getSummary());
+
+ tb.tag(BrooklynTaskTags.tagForStream(BrooklynTaskTags.STREAM_STDIN,
+ Streams.byteArrayOfString(Strings.join(commands, "\n"))));
+ tb.tag(BrooklynTaskTags.tagForEnvStream(BrooklynTaskTags.STREAM_ENV, shellEnvironment));
+
+ return tb;
+ }
+
+ @Override
+ public T summary(String summary) {
+ markDirty();
+ this.summary = summary;
+ return self();
+ }
+
+ @Override
+ public <V> T configure(ConfigKey<V> key, V value) {
+ config.configure(key, value);
+ return self();
+ }
+
+ @Override
+ public T configure(Map<?, ?> flags) {
+ if (flags!=null)
+ config.putAll(flags);
+ return self();
+ }
+
+ @Override
+ public T addCompletionListener(Function<ProcessTaskWrapper<?>, Void> listener) {
+ completionListeners.add(listener);
+ return self();
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ // help let people know of API usage error
+ if (dirty)
+ log.warn("Task "+this+" was modified but modification was never used");
+ super.finalize();
+ }
+}
[34/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/BasicTask.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/BasicTask.java b/core/src/main/java/brooklyn/util/task/BasicTask.java
deleted file mode 100644
index 57b2bb2..0000000
--- a/core/src/main/java/brooklyn/util/task/BasicTask.java
+++ /dev/null
@@ -1,892 +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 brooklyn.util.task;
-
-import static brooklyn.util.JavaGroovyEquivalents.asString;
-import static brooklyn.util.JavaGroovyEquivalents.elvisString;
-import groovy.lang.Closure;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.lang.management.LockInfo;
-import java.lang.management.ManagementFactory;
-import java.lang.management.ThreadInfo;
-import java.util.Collections;
-import java.util.ConcurrentModificationException;
-import java.util.LinkedHashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-import org.apache.brooklyn.api.management.HasTaskChildren;
-import org.apache.brooklyn.api.management.Task;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.util.GroovyJavaMethods;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.guava.Maybe;
-import brooklyn.util.text.Identifiers;
-import brooklyn.util.text.Strings;
-import brooklyn.util.time.Duration;
-import brooklyn.util.time.Time;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Function;
-import com.google.common.base.Objects;
-import com.google.common.base.Throwables;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Sets;
-import com.google.common.util.concurrent.Callables;
-import com.google.common.util.concurrent.ExecutionList;
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * The basic concrete implementation of a {@link Task} to be executed.
- *
- * A {@link Task} is a wrapper for an executable unit, such as a {@link Closure} or a {@link Runnable} or
- * {@link Callable} and will run in its own {@link Thread}.
- * <p>
- * The task can be given an optional displayName and description in its constructor (as named
- * arguments in the first {@link Map} parameter). It is guaranteed to have {@link Object#notify()} called
- * once whenever the task starts running and once again when the task is about to complete. Due to
- * the way executors work it is ugly to guarantee notification <em>after</em> completion, so instead we
- * notify just before then expect the user to call {@link #get()} - which will throw errors if the underlying job
- * did so - or {@link #blockUntilEnded()} which will not throw errors.
- */
-public class BasicTask<T> implements TaskInternal<T> {
- private static final Logger log = LoggerFactory.getLogger(BasicTask.class);
-
- private String id = Identifiers.makeRandomId(8);
- protected Callable<T> job;
- public final String displayName;
- public final String description;
-
- protected final Set<Object> tags = Sets.newConcurrentHashSet();
- // for debugging, to record where tasks were created
-// { tags.add(new Throwable("Creation stack trace")); }
-
- protected Task<?> proxyTargetTask = null;
-
- protected String blockingDetails = null;
- protected Task<?> blockingTask = null;
- Object extraStatusText = null;
-
- /** listeners attached at task level; these are stored here, but run on the underlying ListenableFuture */
- protected final ExecutionList listeners = new ExecutionList();
-
- /**
- * Constructor needed to prevent confusion in groovy stubs when looking for default constructor,
- *
- * The generics on {@link Closure} break it if that is first constructor.
- */
- protected BasicTask() { this(Collections.emptyMap()); }
- protected BasicTask(Map<?,?> flags) { this(flags, (Callable<T>) null); }
-
- public BasicTask(Callable<T> job) { this(Collections.emptyMap(), job); }
-
- public BasicTask(Map<?,?> flags, Callable<T> job) {
- this.job = job;
-
- if (flags.containsKey("tag")) tags.add(flags.remove("tag"));
- Object ftags = flags.remove("tags");
- if (ftags!=null) {
- if (ftags instanceof Iterable) Iterables.addAll(tags, (Iterable<?>)ftags);
- else {
- log.info("deprecated use of non-collection argument for 'tags' ("+ftags+") in "+this, new Throwable("trace of discouraged use of non-colleciton tags argument"));
- tags.add(ftags);
- }
- }
-
- description = elvisString(flags.remove("description"), "");
- String d = asString(flags.remove("displayName"));
- displayName = (d==null ? "" : d);
- }
-
- public BasicTask(Runnable job) { this(GroovyJavaMethods.<T>callableFromRunnable(job)); }
- public BasicTask(Map<?,?> flags, Runnable job) { this(flags, GroovyJavaMethods.<T>callableFromRunnable(job)); }
- public BasicTask(Closure<T> job) { this(GroovyJavaMethods.callableFromClosure(job)); }
- public BasicTask(Map<?,?> flags, Closure<T> job) { this(flags, GroovyJavaMethods.callableFromClosure(job)); }
-
- @Override
- public String getId() {
- return id;
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(id);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj instanceof Task)
- return ((Task<?>)obj).getId().equals(getId());
- return false;
- }
-
- @Override
- public String toString() {
- // give display name plus id, or job and tags plus id; some jobs have been extended to include nice tostrings
- return "Task["+
- (Strings.isNonEmpty(displayName) ?
- displayName :
- (job + (tags!=null && !tags.isEmpty() ? ";"+tags : "")) ) +
- ":"+getId()+"]";
- }
-
- @Override
- public Task<T> asTask() {
- return this;
- }
-
- // housekeeping --------------------
-
- /*
- * These flags are set by BasicExecutionManager.submit.
- *
- * Order is guaranteed to be as shown below, in order of #. Within each # line it is currently in the order specified by commas but this is not guaranteed.
- * (The spaces between the # section indicate longer delays / logical separation ... it should be clear!)
- *
- * # submitter, submit time set, tags and other submit-time fields set
- *
- * # thread set, ThreadLocal getCurrentTask set
- * # start time set, isBegun is true
- * # task end callback run, if supplied
- *
- * # task runs
- *
- * # task end callback run, if supplied
- * # end time set
- * # thread cleared, ThreadLocal getCurrentTask set
- * # Task.notifyAll()
- * # Task.get() (result.get()) available, Task.isDone is true
- *
- * Few _consumers_ should care, but internally we rely on this so that, for example, status is displayed correctly.
- * Tests should catch most things, but be careful if you change any of the above semantics.
- */
-
- protected long queuedTimeUtc = -1;
- protected long submitTimeUtc = -1;
- protected long startTimeUtc = -1;
- protected long endTimeUtc = -1;
- protected Maybe<Task<?>> submittedByTask;
-
- protected volatile Thread thread = null;
- private volatile boolean cancelled = false;
- /** normally a {@link ListenableFuture}, except for scheduled tasks when it may be a {@link ScheduledFuture} */
- protected volatile Future<T> internalFuture = null;
-
- @Override
- public synchronized void initInternalFuture(ListenableFuture<T> result) {
- if (this.internalFuture != null)
- throw new IllegalStateException("task "+this+" is being given a result twice");
- this.internalFuture = result;
- notifyAll();
- }
-
- // metadata accessors ------------
-
- @Override
- public Set<Object> getTags() { return Collections.unmodifiableSet(new LinkedHashSet<Object>(tags)); }
-
- /** if the job is queued for submission (e.g. by another task) it can indicate that fact (and time) here;
- * note tasks can (and often are) submitted without any queueing, in which case this value may be -1 */
- @Override
- public long getQueuedTimeUtc() { return queuedTimeUtc; }
-
- @Override
- public long getSubmitTimeUtc() { return submitTimeUtc; }
-
- @Override
- public long getStartTimeUtc() { return startTimeUtc; }
-
- @Override
- public long getEndTimeUtc() { return endTimeUtc; }
-
- @Override
- public Future<T> getInternalFuture() { return internalFuture; }
-
- @Override
- public Task<?> getSubmittedByTask() {
- if (submittedByTask==null) return null;
- return submittedByTask.orNull();
- }
-
- /** the thread where the task is running, if it is running */
- @Override
- public Thread getThread() { return thread; }
-
- // basic fields --------------------
-
- @Override
- public boolean isQueued() {
- return (queuedTimeUtc >= 0);
- }
-
- @Override
- public boolean isQueuedOrSubmitted() {
- return isQueued() || isSubmitted();
- }
-
- @Override
- public boolean isQueuedAndNotSubmitted() {
- return isQueued() && (!isSubmitted());
- }
-
- @Override
- public boolean isSubmitted() {
- return submitTimeUtc >= 0;
- }
-
- @Override
- public boolean isBegun() {
- return startTimeUtc >= 0;
- }
-
- /** marks the task as queued for execution */
- @Override
- public void markQueued() {
- if (queuedTimeUtc<0)
- queuedTimeUtc = System.currentTimeMillis();
- }
-
- @Override
- public final synchronized boolean cancel() { return cancel(true); }
-
- /** doesn't resume it, just means if something was cancelled but not submitted it could now be submitted;
- * probably going to be removed and perhaps some mechanism for running again made available
- * @since 0.7.0 */
- @Beta
- public synchronized boolean uncancel() {
- boolean wasCancelled = cancelled;
- cancelled = false;
- return wasCancelled;
- }
-
- @Override
- public synchronized boolean cancel(boolean mayInterruptIfRunning) {
- if (isDone()) return false;
- boolean cancel = true;
- cancelled = true;
- if (internalFuture!=null) {
- cancel = internalFuture.cancel(mayInterruptIfRunning);
- }
- notifyAll();
- return cancel;
- }
-
- @Override
- public boolean isCancelled() {
- return cancelled || (internalFuture!=null && internalFuture.isCancelled());
- }
-
- @Override
- public boolean isDone() {
- // if endTime is set, result might not be completed yet, but it will be set very soon
- // (the two values are set close in time, result right after the endTime;
- // but callback hooks might not see the result yet)
- return cancelled || (internalFuture!=null && internalFuture.isDone()) || endTimeUtc>0;
- }
-
- /**
- * Returns true if the task has had an error.
- *
- * Only true if calling {@link #get()} will throw an exception when it completes (including cancel).
- * Implementations may set this true before completion if they have that insight, or
- * (the default) they may compute it lazily after completion (returning false before completion).
- */
- @Override
- public boolean isError() {
- if (!isDone()) return false;
- if (isCancelled()) return true;
- try {
- get();
- return false;
- } catch (Throwable t) {
- return true;
- }
- }
-
- // future value --------------------
-
- @Override
- public T get() throws InterruptedException, ExecutionException {
- try {
- if (!isDone())
- Tasks.setBlockingTask(this);
- blockUntilStarted();
- return internalFuture.get();
- } finally {
- Tasks.resetBlockingTask();
- }
- }
-
- @Override
- public T getUnchecked() {
- try {
- return get();
- } catch (Exception e) {
- throw Exceptions.propagate(e);
- }
- }
-
- @Override
- public synchronized void blockUntilStarted() {
- blockUntilStarted(null);
- }
-
- @Override
- public synchronized boolean blockUntilStarted(Duration timeout) {
- Long endTime = timeout==null ? null : System.currentTimeMillis() + timeout.toMillisecondsRoundingUp();
- while (true) {
- if (cancelled) throw new CancellationException();
- if (internalFuture==null)
- try {
- if (timeout==null) {
- wait();
- } else {
- long remaining = endTime - System.currentTimeMillis();
- if (remaining>0)
- wait(remaining);
- else
- return false;
- }
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- Throwables.propagate(e);
- }
- if (internalFuture!=null) return true;
- }
- }
-
- @Override
- public void blockUntilEnded() {
- blockUntilEnded(null);
- }
-
- @Override
- public boolean blockUntilEnded(Duration timeout) {
- Long endTime = timeout==null ? null : System.currentTimeMillis() + timeout.toMillisecondsRoundingUp();
- try {
- boolean started = blockUntilStarted(timeout);
- if (!started) return false;
- if (timeout==null) {
- internalFuture.get();
- } else {
- long remaining = endTime - System.currentTimeMillis();
- if (remaining>0)
- internalFuture.get(remaining, TimeUnit.MILLISECONDS);
- }
- return isDone();
- } catch (Throwable t) {
- Exceptions.propagateIfFatal(t);
- if (!(t instanceof TimeoutException) && log.isDebugEnabled())
- log.debug("call from "+Thread.currentThread()+", blocking until '"+this+"' finishes, ended with error: "+t);
- return isDone();
- }
- }
-
- @Override
- public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
- return get(new Duration(timeout, unit));
- }
-
- @Override
- public T get(Duration duration) throws InterruptedException, ExecutionException, TimeoutException {
- long start = System.currentTimeMillis();
- Long end = duration==null ? null : start + duration.toMillisecondsRoundingUp();
- while (end==null || end > System.currentTimeMillis()) {
- if (cancelled) throw new CancellationException();
- if (internalFuture == null) {
- synchronized (this) {
- long remaining = end - System.currentTimeMillis();
- if (internalFuture==null && remaining>0)
- wait(remaining);
- }
- }
- if (internalFuture != null) break;
- }
- Long remaining = end==null ? null : end - System.currentTimeMillis();
- if (isDone()) {
- return internalFuture.get(1, TimeUnit.MILLISECONDS);
- } else if (remaining == null) {
- return internalFuture.get();
- } else if (remaining > 0) {
- return internalFuture.get(remaining, TimeUnit.MILLISECONDS);
- } else {
- throw new TimeoutException();
- }
- }
-
- @Override
- public T getUnchecked(Duration duration) {
- try {
- return get(duration);
- } catch (Exception e) {
- throw Exceptions.propagate(e);
- }
- }
-
- // ------------------ status ---------------------------
-
- /**
- * Returns a brief status string
- *
- * Plain-text format. Reported status if there is one, otherwise state which will be one of:
- * <ul>
- * <li>Not submitted
- * <li>Submitted for execution
- * <li>Ended by error
- * <li>Ended by cancellation
- * <li>Ended normally
- * <li>Running
- * <li>Waiting
- * </ul>
- */
- @Override
- public String getStatusSummary() {
- return getStatusString(0);
- }
-
- /**
- * Returns detailed status, suitable for a hover
- *
- * Plain-text format, with new-lines (and sometimes extra info) if multiline enabled.
- */
- @Override
- public String getStatusDetail(boolean multiline) {
- return getStatusString(multiline?2:1);
- }
-
- /**
- * This method is useful for callers to see the status of a task.
- *
- * Also for developers to see best practices for examining status fields etc
- *
- * @param verbosity 0 = brief, 1 = one-line with some detail, 2 = lots of detail
- */
- protected String getStatusString(int verbosity) {
-// Thread t = getThread();
- String rv;
- if (submitTimeUtc <= 0) rv = "Not submitted";
- else if (!isCancelled() && startTimeUtc <= 0) {
- rv = "Submitted for execution";
- if (verbosity>0) {
- long elapsed = System.currentTimeMillis() - submitTimeUtc;
- rv += " "+Time.makeTimeStringRoundedSince(elapsed)+" ago";
- }
- if (verbosity >= 2 && getExtraStatusText()!=null) {
- rv += "\n\n"+getExtraStatusText();
- }
- } else if (isDone()) {
- long elapsed = endTimeUtc - submitTimeUtc;
- String duration = Time.makeTimeStringRounded(elapsed);
- if (isCancelled()) {
- rv = "Cancelled";
- if (verbosity >= 1) rv+=" after "+duration;
-
- if (verbosity >= 2 && getExtraStatusText()!=null) {
- rv += "\n\n"+getExtraStatusText();
- }
- } else if (isError()) {
- rv = "Failed";
- if (verbosity >= 1) {
- rv += " after "+duration;
- Throwable error = Tasks.getError(this);
-
- if (verbosity >= 2 && getExtraStatusText()!=null) {
- rv += "\n\n"+getExtraStatusText();
- }
-
- //remove outer ExecException which is reported by the get(), we want the exception the task threw
- while (error instanceof ExecutionException) error = error.getCause();
- String errorMessage = Exceptions.collapseText(error);
-
- if (verbosity == 1) rv += ": "+abbreviate(errorMessage);
- if (verbosity >= 2) {
- rv += ": "+errorMessage;
- StringWriter sw = new StringWriter();
- ((Throwable)error).printStackTrace(new PrintWriter(sw));
- rv += "\n\n"+sw.getBuffer();
- }
- }
- } else {
- rv = "Completed";
- if (verbosity>=1) {
- if (verbosity==1) {
- try {
- Object v = get();
- rv += ", " +(v==null ? "no return value (null)" : "result: "+abbreviate(v.toString()));
- } catch (Exception e) {
- rv += ", but error accessing result ["+e+"]"; //shouldn't happen
- }
- } else {
- rv += " after "+duration;
- try {
- Object v = get();
- rv += "\n\n" + (v==null ? "No return value (null)" : "Result: "+v);
- } catch (Exception e) {
- rv += " at first\n" +
- "Error accessing result ["+e+"]"; //shouldn't happen
- }
- if (verbosity >= 2 && getExtraStatusText()!=null) {
- rv += "\n\n"+getExtraStatusText();
- }
- }
- }
- }
- } else {
- rv = getActiveTaskStatusString(verbosity);
- }
- return rv;
- }
-
- private static String abbreviate(String s) {
- s = Strings.getFirstLine(s);
- if (s.length()>255) s = s.substring(0, 252)+ "...";
- return s;
- }
-
- protected String getActiveTaskStatusString(int verbosity) {
- String rv = "";
- Thread t = getThread();
-
- // Normally, it's not possible for thread==null as we were started and not ended
-
- // However, there is a race where the task starts sand completes between the calls to getThread()
- // at the start of the method and this call to getThread(), so both return null even though
- // the intermediate checks returned started==true isDone()==false.
- if (t == null) {
- if (isDone()) {
- return getStatusString(verbosity);
- } else {
- //should only happen for repeating task which is not active
- return "Sleeping";
- }
- }
-
- ThreadInfo ti = ManagementFactory.getThreadMXBean().getThreadInfo(t.getId(), (verbosity<=0 ? 0 : verbosity==1 ? 1 : Integer.MAX_VALUE));
- if (getThread()==null)
- //thread might have moved on to a new task; if so, recompute (it should now say "done")
- return getStatusString(verbosity);
-
- if (verbosity >= 1 && Strings.isNonBlank(blockingDetails)) {
- if (verbosity==1)
- // short status string will just show blocking details
- return blockingDetails;
- //otherwise show the blocking details, then a new line, then additional information
- rv = blockingDetails + "\n\n";
- }
-
- if (verbosity >= 1 && blockingTask!=null) {
- if (verbosity==1)
- // short status string will just show blocking details
- return "Waiting on "+blockingTask;
- //otherwise show the blocking details, then a new line, then additional information
- rv = "Waiting on "+blockingTask + "\n\n";
- }
-
- if (verbosity>=2) {
- if (getExtraStatusText()!=null) {
- rv += getExtraStatusText()+"\n\n";
- }
-
- rv += ""+toString()+"\n";
- if (submittedByTask!=null) {
- rv += "Submitted by "+submittedByTask+"\n";
- }
-
- if (this instanceof HasTaskChildren) {
- // list children tasks for compound tasks
- try {
- Iterable<Task<?>> childrenTasks = ((HasTaskChildren)this).getChildren();
- if (childrenTasks.iterator().hasNext()) {
- rv += "Children:\n";
- for (Task<?> child: childrenTasks) {
- rv += " "+child+": "+child.getStatusDetail(false)+"\n";
- }
- }
- } catch (ConcurrentModificationException exc) {
- rv += " (children not available - currently being modified)\n";
- }
- }
- rv += "\n";
- }
-
- LockInfo lock = ti.getLockInfo();
- rv += "In progress";
- if (verbosity>=1) {
- if (lock==null && ti.getThreadState()==Thread.State.RUNNABLE) {
- //not blocked
- if (ti.isSuspended()) {
- // when does this happen?
- rv += ", thread suspended";
- } else {
- if (verbosity >= 2) rv += " ("+ti.getThreadState()+")";
- }
- } else {
- rv +=", thread waiting ";
- if (ti.getThreadState() == Thread.State.BLOCKED) {
- rv += "(mutex) on "+lookup(lock);
- //TODO could say who holds it
- } else if (ti.getThreadState() == Thread.State.WAITING) {
- rv += "(notify) on "+lookup(lock);
- } else if (ti.getThreadState() == Thread.State.TIMED_WAITING) {
- rv += "(timed) on "+lookup(lock);
- } else {
- rv = "("+ti.getThreadState()+") on "+lookup(lock);
- }
- }
- }
- if (verbosity>=2) {
- StackTraceElement[] st = ti.getStackTrace();
- st = brooklyn.util.javalang.StackTraceSimplifier.cleanStackTrace(st);
- if (st!=null && st.length>0)
- rv += "\n" +"At: "+st[0];
- for (int ii=1; ii<st.length; ii++) {
- rv += "\n" +" "+st[ii];
- }
- }
- return rv;
- }
-
- protected String lookup(LockInfo info) {
- return info!=null ? ""+info : "unknown (sleep)";
- }
-
- @Override
- public String getDisplayName() {
- return displayName;
- }
-
- @Override
- public String getDescription() {
- return description;
- }
-
-
- /** allows a task user to specify why a task is blocked; for use immediately before a blocking/wait,
- * and typically cleared immediately afterwards; referenced by management api to inspect a task
- * which is blocking
- */
- @Override
- public String setBlockingDetails(String blockingDetails) {
- String old = this.blockingDetails;
- this.blockingDetails = blockingDetails;
- return old;
- }
-
- @Override
- public Task<?> setBlockingTask(Task<?> blockingTask) {
- Task<?> old = this.blockingTask;
- this.blockingTask = blockingTask;
- return old;
- }
-
- @Override
- public void resetBlockingDetails() {
- this.blockingDetails = null;
- }
-
- @Override
- public void resetBlockingTask() {
- this.blockingTask = null;
- }
-
- /** returns a textual message giving details while the task is blocked */
- @Override
- public String getBlockingDetails() {
- return blockingDetails;
- }
-
- /** returns a task that this task is blocked on */
- @Override
- public Task<?> getBlockingTask() {
- return blockingTask;
- }
-
- @Override
- public void setExtraStatusText(Object extraStatus) {
- this.extraStatusText = extraStatus;
- }
-
- @Override
- public Object getExtraStatusText() {
- return extraStatusText;
- }
-
- // ---- add a way to warn if task is not run
-
- public interface TaskFinalizer {
- public void onTaskFinalization(Task<?> t);
- }
-
- public static final TaskFinalizer WARN_IF_NOT_RUN = new TaskFinalizer() {
- @Override
- public void onTaskFinalization(Task<?> t) {
- if (!Tasks.isAncestorCancelled(t) && !t.isSubmitted()) {
- log.warn(t+" was never submitted; did the code create it and forget to run it? ('cancel' the task to suppress this message)");
- log.debug("Detail of unsubmitted task "+t+":\n"+t.getStatusDetail(true));
- return;
- }
- if (!t.isDone()) {
- // shouldn't happen
- // TODO But does happen if management context was terminated (e.g. running test suite).
- // Should check if Execution Manager is running, and only log if it was not terminated?
- log.warn("Task "+t+" is being finalized before completion");
- return;
- }
- }
- };
-
- public static final TaskFinalizer NO_OP = new TaskFinalizer() {
- @Override
- public void onTaskFinalization(Task<?> t) {
- }
- };
-
- public void ignoreIfNotRun() {
- setFinalizer(NO_OP);
- }
-
- public void setFinalizer(TaskFinalizer f) {
- TaskFinalizer finalizer = Tasks.tag(this, TaskFinalizer.class, false);
- if (finalizer!=null && finalizer!=f)
- throw new IllegalStateException("Cannot apply multiple finalizers");
- if (isDone())
- throw new IllegalStateException("Finalizer cannot be set on task "+this+" after it is finished");
- tags.add(f);
- }
-
- @Override
- protected void finalize() throws Throwable {
- TaskFinalizer finalizer = Tasks.tag(this, TaskFinalizer.class, false);
- if (finalizer==null) finalizer = WARN_IF_NOT_RUN;
- finalizer.onTaskFinalization(this);
- }
-
- public static class SubmissionErrorCatchingExecutor implements Executor {
- final Executor target;
- public SubmissionErrorCatchingExecutor(Executor target) {
- this.target = target;
- }
- @Override
- public void execute(Runnable command) {
- if (isShutdown()) {
- log.debug("Skipping execution of task callback hook "+command+" because executor is shutdown.");
- return;
- }
- try {
- target.execute(command);
- } catch (Exception e) {
- if (isShutdown()) {
- log.debug("Ignoring failed execution of task callback hook "+command+" because executor is shutdown.");
- } else {
- log.warn("Execution of task callback hook "+command+" failed: "+e, e);
- }
- }
- }
- protected boolean isShutdown() {
- return target instanceof ExecutorService && ((ExecutorService)target).isShutdown();
- }
- }
-
- @Override
- public void addListener(Runnable listener, Executor executor) {
- listeners.add(listener, new SubmissionErrorCatchingExecutor(executor));
- }
-
- @Override
- public void runListeners() {
- listeners.execute();
- }
-
- @Override
- public void setEndTimeUtc(long val) {
- endTimeUtc = val;
- }
-
- @Override
- public void setThread(Thread thread) {
- this.thread = thread;
- }
-
- @Override
- public Callable<T> getJob() {
- return job;
- }
-
- @Override
- public void setJob(Callable<T> job) {
- this.job = job;
- }
-
- @Override
- public ExecutionList getListeners() {
- return listeners;
- }
-
- @Override
- public void setSubmitTimeUtc(long val) {
- submitTimeUtc = val;
- }
-
- private static <T> Task<T> newGoneTaskFor(Task<?> task) {
- Task<T> t = Tasks.<T>builder().dynamic(false).name(task.getDisplayName())
- .description("Details of the original task "+task+" have been forgotten.")
- .body(Callables.returning((T)null)).build();
- ((BasicTask<T>)t).ignoreIfNotRun();
- return t;
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- @Override
- public void setSubmittedByTask(Task<?> task) {
- submittedByTask = (Maybe)Maybe.softThen((Task)task, (Maybe)Maybe.of(BasicTask.newGoneTaskFor(task)));
- }
-
- @Override
- public Set<Object> getMutableTags() {
- return tags;
- }
-
- @Override
- public void setStartTimeUtc(long val) {
- startTimeUtc = val;
- }
-
- @Override
- public void applyTagModifier(Function<Set<Object>,Void> modifier) {
- modifier.apply(tags);
- }
-
- @Override
- public Task<?> getProxyTarget() {
- return proxyTargetTask;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/CanSetName.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/CanSetName.java b/core/src/main/java/brooklyn/util/task/CanSetName.java
deleted file mode 100644
index 760c99e..0000000
--- a/core/src/main/java/brooklyn/util/task/CanSetName.java
+++ /dev/null
@@ -1,25 +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 brooklyn.util.task;
-
-public interface CanSetName {
-
- void setName(String name);
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/CompoundTask.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/CompoundTask.java b/core/src/main/java/brooklyn/util/task/CompoundTask.java
deleted file mode 100644
index e33120c..0000000
--- a/core/src/main/java/brooklyn/util/task/CompoundTask.java
+++ /dev/null
@@ -1,131 +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 brooklyn.util.task;
-
-import groovy.lang.Closure;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-
-import org.apache.brooklyn.api.management.HasTaskChildren;
-import org.apache.brooklyn.api.management.Task;
-import org.apache.brooklyn.api.management.TaskAdaptable;
-import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.entity.basic.BrooklynTaskTags;
-import brooklyn.util.collections.MutableMap;
-
-
-/**
- * A {@link Task} that is comprised of other units of work: possibly a heterogeneous mix of {@link Task},
- * {@link Runnable}, {@link Callable} and {@link Closure} instances.
- *
- * This class holds the collection of child tasks, but subclasses have the responsibility of executing them in a
- * sensible manner by implementing the abstract {@link #runJobs} method.
- */
-public abstract class CompoundTask<T> extends BasicTask<List<T>> implements HasTaskChildren {
-
- @SuppressWarnings("unused")
- private static final Logger log = LoggerFactory.getLogger(CompoundTask.class);
-
- protected final List<Task<? extends T>> children;
- protected final List<Object> result;
-
- /**
- * Constructs a new compound task containing the specified units of work.
- *
- * @param jobs A potentially heterogeneous mixture of {@link Runnable}, {@link Callable}, {@link Closure} and {@link Task} can be provided.
- * @throws IllegalArgumentException if any of the passed child jobs is not one of the above types
- */
- public CompoundTask(Object... jobs) {
- this( Arrays.asList(jobs) );
- }
-
- /**
- * Constructs a new compound task containing the specified units of work.
- *
- * @param jobs A potentially heterogeneous mixture of {@link Runnable}, {@link Callable}, {@link Closure} and {@link Task} can be provided.
- * @throws IllegalArgumentException if any of the passed child jobs is not one of the above types
- */
- public CompoundTask(Collection<?> jobs) {
- this(MutableMap.of("tag", "compound"), jobs);
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public CompoundTask(Map<String,?> flags, Collection<?> jobs) {
- super(flags);
- super.job = new Callable<List<T>>() {
- @Override public List<T> call() throws Exception {
- return runJobs();
- }
- };
-
- this.result = new ArrayList<Object>(jobs.size());
- this.children = new ArrayList<Task<? extends T>>(jobs.size());
- for (Object job : jobs) {
- Task subtask;
- if (job instanceof TaskAdaptable) { subtask = ((TaskAdaptable)job).asTask(); }
- else if (job instanceof Closure) { subtask = new BasicTask<T>((Closure) job); }
- else if (job instanceof Callable) { subtask = new BasicTask<T>((Callable) job); }
- else if (job instanceof Runnable) { subtask = new BasicTask<T>((Runnable) job); }
-
- else throw new IllegalArgumentException("Invalid child "+(job == null ? null : job.getClass() + " ("+job+")")+
- " passed to compound task; must be Runnable, Callable, Closure or Task");
-
- BrooklynTaskTags.addTagDynamically(subtask, ManagementContextInternal.SUB_TASK_TAG);
- children.add(subtask);
- }
-
- for (Task<?> t: getChildren()) {
- ((TaskInternal<?>)t).markQueued();
- }
- }
-
- /** return value needs to be specified by subclass; subclass should also setBlockingDetails
- * @throws ExecutionException
- * @throws InterruptedException */
- protected abstract List<T> runJobs() throws InterruptedException, ExecutionException;
-
- protected void submitIfNecessary(TaskAdaptable<?> task) {
- if (!task.asTask().isSubmitted()) {
- if (BasicExecutionContext.getCurrentExecutionContext() == null) {
- throw new IllegalStateException("Compound task ("+task+") launched from "+this+" missing required execution context");
- } else {
- BasicExecutionContext.getCurrentExecutionContext().submit(task);
- }
- }
- }
-
- public List<Task<? extends T>> getChildrenTyped() {
- return children;
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public List<Task<?>> getChildren() {
- return (List) getChildrenTyped();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/DeferredSupplier.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/DeferredSupplier.java b/core/src/main/java/brooklyn/util/task/DeferredSupplier.java
deleted file mode 100644
index d82b3fb..0000000
--- a/core/src/main/java/brooklyn/util/task/DeferredSupplier.java
+++ /dev/null
@@ -1,38 +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 brooklyn.util.task;
-
-import com.google.common.base.Supplier;
-
-/**
- * A class that supplies objects of a single type. When used as a ConfigKey value,
- * the evaluation is deferred until getConfig() is called. The returned value will then
- * be coerced to the correct type.
- *
- * Subsequent calls to getConfig will result in further calls to deferredProvider.get(),
- * rather than reusing the result. If you want to reuse the result, consider instead
- * using a Future.
- *
- * Note that this functionality replaces the ues of Closure in brooklyn 0.4.0, which
- * served the same purpose.
- */
-public interface DeferredSupplier<T> extends Supplier<T> {
- @Override
- T get();
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/DynamicSequentialTask.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/DynamicSequentialTask.java b/core/src/main/java/brooklyn/util/task/DynamicSequentialTask.java
deleted file mode 100644
index 455a889..0000000
--- a/core/src/main/java/brooklyn/util/task/DynamicSequentialTask.java
+++ /dev/null
@@ -1,480 +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 brooklyn.util.task;
-
-import groovy.lang.Closure;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Queue;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ConcurrentLinkedQueue;
-
-import org.apache.brooklyn.api.management.HasTaskChildren;
-import org.apache.brooklyn.api.management.Task;
-import org.apache.brooklyn.api.management.TaskQueueingContext;
-import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.entity.basic.BrooklynTaskTags;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.time.CountdownTimer;
-import brooklyn.util.time.Duration;
-
-import com.google.common.annotations.Beta;
-import com.google.common.collect.ImmutableList;
-
-/** Represents a task whose run() method can create other tasks
- * which are run sequentially, but that sequence runs in parallel to this task
- * <p>
- * There is an optional primary job run with this task, along with multiple secondary children.
- * If any secondary task fails (assuming it isn't {@link Tasks#markInessential()} then by default
- * subsequent tasks are not submitted and the primary task fails (but no tasks are cancelled or interrupted).
- * You can change the behavior of this task with fields in {@link FailureHandlingConfig},
- * or the convenience {@link TaskQueueingContext#swallowChildrenFailures()}
- * (and {@link DynamicTasks#swallowChildrenFailures()} if you are inside the task).
- * <p>
- * This synchronizes on secondary tasks when submitting them, in case they may be manually submitted
- * and the submitter wishes to ensure it is only submitted once.
- * <p>
- * Improvements which would be nice to have:
- * <li> unqueued tasks not visible in api; would like that
- * <li> uses an extra thread (submitted as background task) to monitor the secondary jobs; would be nice to remove this,
- * and rely on {@link BasicExecutionManager} to run the jobs sequentially (combined with fix to item above)
- * <li> would be nice to have cancel, resume, and possibly skipQueue available as operations (ideally in the REST API and GUI)
- **/
-public class DynamicSequentialTask<T> extends BasicTask<T> implements HasTaskChildren, TaskQueueingContext {
-
- private static final Logger log = LoggerFactory.getLogger(CompoundTask.class);
-
- protected final Queue<Task<?>> secondaryJobsAll = new ConcurrentLinkedQueue<Task<?>>();
- protected final Queue<Task<?>> secondaryJobsRemaining = new ConcurrentLinkedQueue<Task<?>>();
- protected final Object jobTransitionLock = new Object();
- protected volatile boolean primaryStarted = false;
- protected volatile boolean primaryFinished = false;
- protected volatile boolean secondaryQueueAborted = false;
- protected Thread primaryThread;
- protected DstJob dstJob;
- protected FailureHandlingConfig failureHandlingConfig = FailureHandlingConfig.DEFAULT;
-
- // default values for how to handle the various failures
- @Beta
- public static class FailureHandlingConfig {
- /** secondary queue runs independently of primary task (submitting and blocking on each secondary task in order),
- * but can set it up not to submit any more tasks if the primary fails */
- public final boolean abortSecondaryQueueOnPrimaryFailure;
- /** as {@link #abortSecondaryQueueOnPrimaryFailure} but controls cancelling of secondary queue*/
- public final boolean cancelSecondariesOnPrimaryFailure;
- /** secondary queue can continue submitting+blocking tasks even if a secondary task fails (unusual;
- * typically handled by {@link TaskTags#markInessential(Task)} on the secondary tasks, in which case
- * the secondary queue is never aborted */
- public final boolean abortSecondaryQueueOnSecondaryFailure;
- /** unsubmitted secondary tasks (ie those further in the queue) can be cancelled if a secondary task fails */
- public final boolean cancelSecondariesOnSecondaryFailure;
- /** whether to issue cancel against primary task if a secondary task fails */
- public final boolean cancelPrimaryOnSecondaryFailure;
- /** whether to fail this task if a secondary task fails */
- public final boolean failParentOnSecondaryFailure;
-
- @Beta
- public FailureHandlingConfig(
- boolean abortSecondaryQueueOnPrimaryFailure, boolean cancelSecondariesOnPrimaryFailure,
- boolean abortSecondaryQueueOnSecondaryFailure, boolean cancelSecondariesOnSecondaryFailure,
- boolean cancelPrimaryOnSecondaryFailure, boolean failParentOnSecondaryFailure) {
- this.abortSecondaryQueueOnPrimaryFailure = abortSecondaryQueueOnPrimaryFailure;
- this.cancelSecondariesOnPrimaryFailure = cancelSecondariesOnPrimaryFailure;
- this.abortSecondaryQueueOnSecondaryFailure = abortSecondaryQueueOnSecondaryFailure;
- this.cancelSecondariesOnSecondaryFailure = cancelSecondariesOnSecondaryFailure;
- this.cancelPrimaryOnSecondaryFailure = cancelPrimaryOnSecondaryFailure;
- this.failParentOnSecondaryFailure = failParentOnSecondaryFailure;
- }
-
- public static final FailureHandlingConfig DEFAULT = new FailureHandlingConfig(false, false, true, false, false, true);
- public static final FailureHandlingConfig SWALLOWING_CHILDREN_FAILURES = new FailureHandlingConfig(false, false, false, false, false, false);
- }
-
- public static class QueueAbortedException extends IllegalStateException {
- private static final long serialVersionUID = -7569362887826818524L;
-
- public QueueAbortedException(String msg) {
- super(msg);
- }
- public QueueAbortedException(String msg, Throwable cause) {
- super(msg, cause);
- }
- }
-
- /**
- * Constructs a new compound task containing the specified units of work.
- *
- * @param jobs A potentially heterogeneous mixture of {@link Runnable}, {@link Callable}, {@link Closure} and {@link Task} can be provided.
- * @throws IllegalArgumentException if any of the passed child jobs is not one of the above types
- */
- public DynamicSequentialTask() {
- this(null);
- }
-
- public DynamicSequentialTask(Callable<T> mainJob) {
- this(MutableMap.of("tag", "compound"), mainJob);
- }
-
- public DynamicSequentialTask(Map<?,?> flags, Callable<T> mainJob) {
- super(flags);
- this.job = dstJob = new DstJob(mainJob);
- }
-
- @Override
- public void queue(Task<?> t) {
- synchronized (jobTransitionLock) {
- if (primaryFinished)
- throw new IllegalStateException("Cannot add a task to "+this+" which is already finished (trying to add "+t+")");
- if (secondaryQueueAborted)
- throw new QueueAbortedException("Cannot add a task to "+this+" whose queue has been aborted (trying to add "+t+")");
- secondaryJobsAll.add(t);
- secondaryJobsRemaining.add(t);
- BrooklynTaskTags.addTagsDynamically(t, ManagementContextInternal.SUB_TASK_TAG);
- ((TaskInternal<?>)t).markQueued();
- jobTransitionLock.notifyAll();
- }
- }
-
- @Override
- public boolean cancel(boolean mayInterruptIfRunning) {
- return cancel(mayInterruptIfRunning, mayInterruptIfRunning, true);
- }
- public boolean cancel(boolean mayInterruptTask, boolean interruptPrimaryThread, boolean alsoCancelChildren) {
- if (isDone()) return false;
- if (log.isTraceEnabled()) log.trace("cancelling {}", this);
- boolean cancel = super.cancel(mayInterruptTask);
- if (alsoCancelChildren) {
- for (Task<?> t: secondaryJobsAll)
- cancel |= t.cancel(mayInterruptTask);
- }
- synchronized (jobTransitionLock) {
- if (primaryThread!=null) {
- if (interruptPrimaryThread) {
- if (log.isTraceEnabled()) log.trace("cancelling {} - interrupting", this);
- primaryThread.interrupt();
- }
- cancel = true;
- }
- }
- return cancel;
- }
-
- @Override
- public synchronized boolean uncancel() {
- secondaryQueueAborted = false;
- return super.uncancel();
- }
-
- @Override
- public Iterable<Task<?>> getChildren() {
- return Collections.unmodifiableCollection(secondaryJobsAll);
- }
-
- /** submits the indicated task for execution in the current execution context, and returns immediately */
- protected void submitBackgroundInheritingContext(Task<?> task) {
- BasicExecutionContext ec = BasicExecutionContext.getCurrentExecutionContext();
- if (log.isTraceEnabled()) {
- log.trace("task {} - submitting background task {} ({})", new Object[] { Tasks.current(), task, ec });
- }
- if (ec==null) {
- String message = Tasks.current()!=null ?
- // user forgot ExecContext:
- "Task "+this+" submitting background task requires an ExecutionContext (an ExecutionManager is not enough): submitting "+task+" in "+Tasks.current()
- : // should not happen:
- "Cannot submit tasks inside DST when not in a task : submitting "+task+" in "+this;
- log.warn(message+" (rethrowing)");
- throw new IllegalStateException(message);
- }
- synchronized (task) {
- if (task.isSubmitted()) {
- if (log.isTraceEnabled()) {
- log.trace("DST "+this+" skipping submission of child "+task+" because it is already submitted");
- }
- } else {
- try {
- ec.submit(task);
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- // Give some context when the submit fails (happens when the target is already unmanaged)
- throw new IllegalStateException("Failure submitting task "+task+" in "+this+": "+e.getMessage(), e);
- }
- }
- }
- }
-
- public void setFailureHandlingConfig(FailureHandlingConfig failureHandlingConfig) {
- this.failureHandlingConfig = failureHandlingConfig;
- }
- @Override
- public void swallowChildrenFailures() {
- setFailureHandlingConfig(FailureHandlingConfig.SWALLOWING_CHILDREN_FAILURES);
- }
-
- protected class DstJob implements Callable<T> {
- protected Callable<T> primaryJob;
- /** currently executing (or just completed) secondary task, or null if none;
- * with jobTransitionLock notified on change and completion */
- protected volatile Task<?> currentSecondary = null;
- protected volatile boolean finishedSecondaries = false;
-
- public DstJob(Callable<T> mainJob) {
- this.primaryJob = mainJob;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public T call() throws Exception {
-
- synchronized (jobTransitionLock) {
- primaryStarted = true;
- primaryThread = Thread.currentThread();
- for (Task<?> t: secondaryJobsAll)
- ((TaskInternal<?>)t).markQueued();
- }
- // TODO overkill having a thread/task for this, but it works
- // optimisation would either use newTaskEndCallback property on task to submit
- // or use some kind of single threaded executor for the queued tasks
- Task<List<Object>> secondaryJobMaster = Tasks.<List<Object>>builder().dynamic(false)
- .name("DST manager (internal)")
- // TODO marking it transient helps it be GC'd sooner,
- // but ideally we wouldn't have this,
- // or else it would be a child
- .tag(BrooklynTaskTags.TRANSIENT_TASK_TAG)
- .body(new Callable<List<Object>>() {
-
- @Override
- public List<Object> call() throws Exception {
- List<Object> result = new ArrayList<Object>();
- try {
- while (!secondaryQueueAborted && (!primaryFinished || !secondaryJobsRemaining.isEmpty())) {
- synchronized (jobTransitionLock) {
- if (!primaryFinished && secondaryJobsRemaining.isEmpty()) {
- currentSecondary = null;
- jobTransitionLock.wait(1000);
- }
- }
- @SuppressWarnings("rawtypes")
- Task secondaryJob = secondaryJobsRemaining.poll();
- if (secondaryJob != null) {
- synchronized (jobTransitionLock) {
- currentSecondary = secondaryJob;
- submitBackgroundInheritingContext(secondaryJob);
- jobTransitionLock.notifyAll();
- }
- try {
- result.add(secondaryJob.get());
- } catch (Exception e) {
- if (TaskTags.isInessential(secondaryJob)) {
- result.add(Tasks.getError(secondaryJob));
- if (log.isDebugEnabled())
- log.debug("Secondary job queue for "+DynamicSequentialTask.this+" ignoring error in inessential task "+secondaryJob+": "+e);
- } else {
- if (failureHandlingConfig.cancelSecondariesOnSecondaryFailure) {
- if (log.isDebugEnabled())
- log.debug("Secondary job queue for "+DynamicSequentialTask.this+" cancelling "+secondaryJobsRemaining.size()+" remaining, due to error in task "+secondaryJob+": "+e);
- synchronized (jobTransitionLock) {
- for (Task<?> t: secondaryJobsRemaining)
- t.cancel(true);
- jobTransitionLock.notifyAll();
- }
- }
-
- if (failureHandlingConfig.abortSecondaryQueueOnSecondaryFailure) {
- if (log.isDebugEnabled())
- log.debug("Aborting secondary job queue for "+DynamicSequentialTask.this+" due to error in child task "+secondaryJob+" ("+e+", being rethrown)");
- secondaryQueueAborted = true;
- throw e;
- }
-
- if (!primaryFinished && failureHandlingConfig.cancelPrimaryOnSecondaryFailure) {
- cancel(true, false, false);
- }
-
- result.add(Tasks.getError(secondaryJob));
- if (log.isDebugEnabled())
- log.debug("Secondary job queue for "+DynamicSequentialTask.this+" continuing in presence of error in child task "+secondaryJob+" ("+e+", being remembered)");
- }
- }
- }
- }
- } finally {
- synchronized (jobTransitionLock) {
- currentSecondary = null;
- finishedSecondaries = true;
- jobTransitionLock.notifyAll();
- }
- }
- return result;
- }
- }).build();
- ((BasicTask<?>)secondaryJobMaster).proxyTargetTask = DynamicSequentialTask.this;
-
- submitBackgroundInheritingContext(secondaryJobMaster);
-
- T result = null;
- Throwable error = null;
- Throwable uninterestingSelfError = null;
- boolean errorIsFromChild = false;
- try {
- if (log.isTraceEnabled()) log.trace("calling primary job for {}", this);
- if (primaryJob!=null) result = primaryJob.call();
- } catch (Throwable selfException) {
- Exceptions.propagateIfFatal(selfException);
- if (Exceptions.getFirstThrowableOfType(selfException, QueueAbortedException.class) != null) {
- // Error was caused by the task already having failed, and this thread calling queue() to try
- // to queue more work. The underlying cause will be much more interesting.
- // Without this special catch, we record error = "Cannot add a task to ... whose queue has been aborted",
- // which gets propagated instead of the more interesting child exception.
- uninterestingSelfError = selfException;
- } else {
- error = selfException;
- errorIsFromChild = false;
- }
- if (failureHandlingConfig.abortSecondaryQueueOnPrimaryFailure) {
- if (log.isDebugEnabled())
- log.debug("Secondary job queue for "+DynamicSequentialTask.this+" aborting with "+secondaryJobsRemaining.size()+" remaining, due to error in primary task: "+selfException);
- secondaryQueueAborted = true;
- }
- if (failureHandlingConfig.cancelSecondariesOnPrimaryFailure) {
- if (log.isDebugEnabled())
- log.debug(DynamicSequentialTask.this+" cancelling "+secondaryJobsRemaining.size()+" remaining, due to error in primary task: "+selfException);
- synchronized (jobTransitionLock) {
- for (Task<?> t: secondaryJobsRemaining)
- t.cancel(true);
- // do this early to prevent additions; and note we notify very soon below, so not notify is help off until below
- primaryThread = null;
- primaryFinished = true;
- }
- }
- } finally {
- try {
- if (log.isTraceEnabled()) log.trace("cleaning up for {}", this);
- synchronized (jobTransitionLock) {
- // semaphore might be nicer here (aled notes as it is this is a little hard to read)
- primaryThread = null;
- primaryFinished = true;
- jobTransitionLock.notifyAll();
- }
- if (!isCancelled() && !Thread.currentThread().isInterrupted()) {
- if (log.isTraceEnabled()) log.trace("waiting for secondaries for {}", this);
- // wait on tasks sequentially so that blocking information is more interesting
- DynamicTasks.waitForLast();
- List<Object> result2 = secondaryJobMaster.get();
- try {
- if (primaryJob==null) result = (T)result2;
- } catch (ClassCastException e) { /* ignore class cast exception; leave the result as null */ }
- }
- } catch (Throwable childException) {
- Exceptions.propagateIfFatal(childException);
- if (error==null) {
- error = childException;
- errorIsFromChild = true;
- } else {
- if (log.isDebugEnabled()) log.debug("Parent task "+this+" ignoring child error ("+childException+") in presence of our own error ("+error+")");
- }
- }
- }
- if (error!=null) {
- handleException(error, errorIsFromChild);
- }
- if (uninterestingSelfError != null) {
- handleException(uninterestingSelfError, false);
- }
- return result;
- }
-
- @Override
- public String toString() {
- return "DstJob:"+DynamicSequentialTask.this.getId();
- }
-
- /** waits for this job to complete, or the given time to elapse */
- public void join(boolean includePrimary, Duration optionalTimeout) throws InterruptedException {
- CountdownTimer timeLeft = optionalTimeout!=null ? CountdownTimer.newInstanceStarted(optionalTimeout) : null;
- while (true) {
- Task<?> cs;
- Duration remaining;
- synchronized (jobTransitionLock) {
- cs = currentSecondary;
- if (finishedSecondaries) return;
- remaining = timeLeft==null ? Duration.ONE_SECOND : timeLeft.getDurationRemaining();
- if (!remaining.isPositive()) return;
- if (cs==null) {
- if (!includePrimary && secondaryJobsRemaining.isEmpty()) return;
- // parent still running, no children though
- Tasks.setBlockingTask(DynamicSequentialTask.this);
- jobTransitionLock.wait(remaining.toMilliseconds());
- Tasks.resetBlockingDetails();
- }
- }
- if (cs!=null) {
- Tasks.setBlockingTask(cs);
- cs.blockUntilEnded(remaining);
- Tasks.resetBlockingDetails();
- }
- }
- }
- }
-
- @Override
- public List<Task<?>> getQueue() {
- return ImmutableList.copyOf(secondaryJobsAll);
- }
-
- public void handleException(Throwable throwable, boolean fromChild) throws Exception {
- Exceptions.propagateIfFatal(throwable);
- if (fromChild && !failureHandlingConfig.failParentOnSecondaryFailure) {
- log.debug("Parent task "+this+" swallowing child error: "+throwable);
- return;
- }
- handleException(throwable);
- }
- public void handleException(Throwable throwable) throws Exception {
- Exceptions.propagateIfFatal(throwable);
- if (throwable instanceof Exception) {
- // allow checked exceptions to be passed through
- throw (Exception)throwable;
- }
- throw Exceptions.propagate(throwable);
- }
-
- @Override
- public void drain(Duration optionalTimeout, boolean includePrimary, boolean throwFirstError) {
- try {
- dstJob.join(includePrimary, optionalTimeout);
- } catch (InterruptedException e) {
- throw Exceptions.propagate(e);
- }
- if (throwFirstError) {
- if (isError())
- getUnchecked();
- for (Task<?> t: getQueue())
- if (t.isError() && !TaskTags.isInessential(t))
- t.getUnchecked();
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/DynamicTasks.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/DynamicTasks.java b/core/src/main/java/brooklyn/util/task/DynamicTasks.java
deleted file mode 100644
index 9d552c6..0000000
--- a/core/src/main/java/brooklyn/util/task/DynamicTasks.java
+++ /dev/null
@@ -1,337 +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 brooklyn.util.task;
-
-import java.util.List;
-import java.util.concurrent.Callable;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.management.ExecutionContext;
-import org.apache.brooklyn.api.management.Task;
-import org.apache.brooklyn.api.management.TaskAdaptable;
-import org.apache.brooklyn.api.management.TaskFactory;
-import org.apache.brooklyn.api.management.TaskQueueingContext;
-import org.apache.brooklyn.api.management.TaskWrapper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.entity.basic.EntityInternal;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.time.Duration;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Iterables;
-
-/**
- * Contains static methods which detect and use the current {@link TaskQueueingContext} to execute tasks.
- *
- * @since 0.6.0
- */
-@Beta
-public class DynamicTasks {
-
- private static final Logger log = LoggerFactory.getLogger(DynamicTasks.class);
- private static final ThreadLocal<TaskQueueingContext> taskQueueingContext = new ThreadLocal<TaskQueueingContext>();
-
- public static void setTaskQueueingContext(TaskQueueingContext newTaskQC) {
- taskQueueingContext.set(newTaskQC);
- }
-
- public static TaskQueueingContext getThreadTaskQueuingContext() {
- return taskQueueingContext.get();
- }
-
- public static TaskQueueingContext getTaskQueuingContext() {
- TaskQueueingContext adder = getThreadTaskQueuingContext();
- if (adder!=null) return adder;
- Task<?> t = Tasks.current();
- if (t instanceof TaskQueueingContext) return (TaskQueueingContext) t;
- return null;
- }
-
-
- public static void removeTaskQueueingContext() {
- taskQueueingContext.remove();
- }
-
- public static class TaskQueueingResult<T> implements TaskWrapper<T> {
- private final Task<T> task;
- private final boolean wasQueued;
- private ExecutionContext execContext = null;
-
- private TaskQueueingResult(TaskAdaptable<T> task, boolean wasQueued) {
- this.task = task.asTask();
- this.wasQueued = wasQueued;
- }
- @Override
- public Task<T> asTask() {
- return task;
- }
- @Override
- public Task<T> getTask() {
- return task;
- }
- /** returns true if the task was queued */
- public boolean wasQueued() {
- return wasQueued;
- }
- /** returns true if the task either is currently queued or has been submitted */
- public boolean isQueuedOrSubmitted() {
- return wasQueued || Tasks.isQueuedOrSubmitted(task);
- }
- /** specifies an execContext to use if the task has to be explicitly submitted;
- * if omitted it will attempt to find one based on the current thread's context */
- public TaskQueueingResult<T> executionContext(ExecutionContext execContext) {
- this.execContext = execContext;
- return this;
- }
- /** as {@link #executionContext(ExecutionContext)} but inferring from the entity */
- public TaskQueueingResult<T> executionContext(Entity entity) {
- this.execContext = ((EntityInternal)entity).getManagementSupport().getExecutionContext();
- return this;
- }
- private boolean orSubmitInternal() {
- if (!wasQueued()) {
- if (isQueuedOrSubmitted()) {
- log.warn("Redundant call to execute "+getTask()+"; skipping");
- return false;
- } else {
- ExecutionContext ec = execContext;
- if (ec==null)
- ec = BasicExecutionContext.getCurrentExecutionContext();
- if (ec==null)
- throw new IllegalStateException("Cannot execute "+getTask()+" without an execution context; ensure caller is in an ExecutionContext");
- ec.submit(getTask());
- return true;
- }
- } else {
- return false;
- }
- }
- /** causes the task to be submitted (asynchronously) if it hasn't already been,
- * requiring an entity execution context (will try to find a default if not set) */
- public TaskQueueingResult<T> orSubmitAsync() {
- orSubmitInternal();
- return this;
- }
- /** convenience for setting {@link #executionContext(ExecutionContext)} then submitting async */
- public TaskQueueingResult<T> orSubmitAsync(Entity entity) {
- executionContext(entity);
- return orSubmitAsync();
- }
- /** causes the task to be submitted *synchronously* if it hasn't already been submitted;
- * useful in contexts such as libraries where callers may be either on a legacy call path
- * (which assumes all commands complete immediately);
- * requiring an entity execution context (will try to find a default if not set) */
- public TaskQueueingResult<T> orSubmitAndBlock() {
- if (orSubmitInternal()) task.getUnchecked();
- return this;
- }
- /** convenience for setting {@link #executionContext(ExecutionContext)} then submitting blocking */
- public TaskQueueingResult<T> orSubmitAndBlock(Entity entity) {
- executionContext(entity);
- return orSubmitAndBlock();
- }
- /** blocks for the task to be completed
- * <p>
- * needed in any context where subsequent commands assume the task has completed.
- * not needed in a context where the task is simply being built up and queued.
- * <p>
- * throws if there are any errors
- */
- public T andWaitForSuccess() {
- return task.getUnchecked();
- }
- public void orCancel() {
- if (!wasQueued()) {
- task.cancel(false);
- }
- }
- }
-
- /**
- * Tries to add the task to the current addition context if there is one, otherwise does nothing.
- * <p/>
- * Call {@link TaskQueueingResult#orSubmitAsync() orSubmitAsync()} on the returned
- * {@link TaskQueueingResult TaskQueueingResult} to handle execution of tasks in a
- * {@link BasicExecutionContext}.
- */
- public static <T> TaskQueueingResult<T> queueIfPossible(TaskAdaptable<T> task) {
- TaskQueueingContext adder = getTaskQueuingContext();
- boolean result = false;
- if (adder!=null)
- result = Tasks.tryQueueing(adder, task);
- return new TaskQueueingResult<T>(task, result);
- }
-
- /** @see #queueIfPossible(TaskAdaptable) */
- public static <T> TaskQueueingResult<T> queueIfPossible(TaskFactory<? extends TaskAdaptable<T>> task) {
- return queueIfPossible(task.newTask());
- }
-
- /** adds the given task to the nearest task addition context,
- * either set as a thread-local, or in the current task, or the submitter of the task, etc
- * <p>
- * throws if it cannot add */
- public static <T> Task<T> queueInTaskHierarchy(Task<T> task) {
- Preconditions.checkNotNull(task, "Task to queue cannot be null");
- Preconditions.checkState(!Tasks.isQueuedOrSubmitted(task), "Task to queue must not yet be submitted: {}", task);
-
- TaskQueueingContext adder = getTaskQueuingContext();
- if (adder!=null) {
- if (Tasks.tryQueueing(adder, task)) {
- log.debug("Queued task {} at context {} (no hierarchy)", task, adder);
- return task;
- }
- }
-
- Task<?> t = Tasks.current();
- Preconditions.checkState(t!=null || adder!=null, "No task addition context available for queueing task "+task);
-
- while (t!=null) {
- if (t instanceof TaskQueueingContext) {
- if (Tasks.tryQueueing((TaskQueueingContext)t, task)) {
- log.debug("Queued task {} at hierarchical context {}", task, t);
- return task;
- }
- }
- t = t.getSubmittedByTask();
- }
-
- throw new IllegalStateException("No task addition context available in current task hierarchy for adding task "+task);
- }
-
- /**
- * Queues the given task.
- * <p/>
- * This method is only valid within a dynamic task. Use {@link #queueIfPossible(TaskAdaptable)}
- * and {@link TaskQueueingResult#orSubmitAsync()} if the calling context is a basic task.
- *
- * @param task The task to queue
- * @throws IllegalStateException if no task queueing context is available
- * @return The queued task
- */
- public static <V extends TaskAdaptable<?>> V queue(V task) {
- try {
- Preconditions.checkNotNull(task, "Task to queue cannot be null");
- Preconditions.checkState(!Tasks.isQueued(task), "Task to queue must not yet be queued: %s", task);
- TaskQueueingContext adder = getTaskQueuingContext();
- if (adder==null) {
- throw new IllegalStateException("Task "+task+" cannot be queued here; no queueing context available");
- }
- adder.queue(task.asTask());
- return task;
- } catch (Throwable e) {
- log.warn("Error queueing "+task+" (rethrowing): "+e);
- throw Exceptions.propagate(e);
- }
- }
-
- /** @see #queue(org.apache.brooklyn.api.management.TaskAdaptable) */
- public static void queue(TaskAdaptable<?> task1, TaskAdaptable<?> task2, TaskAdaptable<?> ...tasks) {
- queue(task1);
- queue(task2);
- for (TaskAdaptable<?> task: tasks) queue(task);
- }
-
- /** @see #queue(org.apache.brooklyn.api.management.TaskAdaptable) */
- public static <T extends TaskAdaptable<?>> T queue(TaskFactory<T> taskFactory) {
- return queue(taskFactory.newTask());
- }
-
- /** @see #queue(org.apache.brooklyn.api.management.TaskAdaptable) */
- public static void queue(TaskFactory<?> task1, TaskFactory<?> task2, TaskFactory<?> ...tasks) {
- queue(task1.newTask());
- queue(task2.newTask());
- for (TaskFactory<?> task: tasks) queue(task.newTask());
- }
-
- /** @see #queue(org.apache.brooklyn.api.management.TaskAdaptable) */
- public static <T> Task<T> queue(String name, Callable<T> job) {
- return DynamicTasks.queue(Tasks.<T>builder().name(name).body(job).build());
- }
-
- /** @see #queue(org.apache.brooklyn.api.management.TaskAdaptable) */
- public static <T> Task<T> queue(String name, Runnable job) {
- return DynamicTasks.queue(Tasks.<T>builder().name(name).body(job).build());
- }
-
- /** queues the task if needed, i.e. if it is not yet submitted (so it will run),
- * or if it is submitted but not queued and we are in a queueing context (so it is available for informational purposes) */
- public static <T extends TaskAdaptable<?>> T queueIfNeeded(T task) {
- if (!Tasks.isQueued(task)) {
- if (Tasks.isSubmitted(task) && getTaskQueuingContext()==null) {
- // already submitted and not in a queueing context, don't try to queue
- } else {
- // needs submitting, put it in the queue
- // (will throw an error if we are not a queueing context)
- queue(task);
- }
- }
- return task;
- }
-
- /** submits/queues the given task if needed, and gets the result (unchecked)
- * only permitted in a queueing context (ie a DST main job) if the task is not yet submitted */
- // things get really confusing if you try to queueInTaskHierarchy -- easy to cause deadlocks!
- public static <T> T get(TaskAdaptable<T> t) {
- return queueIfNeeded(t).asTask().getUnchecked();
- }
-
- /** As {@link #drain(Duration, boolean)} waiting forever and throwing the first error
- * (excluding errors in inessential tasks),
- * then returning the last task in the queue (which is guaranteed to have finished without error,
- * if this method returns without throwing) */
- public static Task<?> waitForLast() {
- drain(null, true);
- // this call to last is safe, as the above guarantees everything will have run
- // (on errors the above will throw so we won't come here)
- List<Task<?>> q = DynamicTasks.getTaskQueuingContext().getQueue();
- return q.isEmpty() ? null : Iterables.getLast(q);
- }
-
- /** Calls {@link TaskQueueingContext#drain(Duration, boolean, boolean)} on the current task context */
- public static TaskQueueingContext drain(Duration optionalTimeout, boolean throwFirstError) {
- TaskQueueingContext qc = DynamicTasks.getTaskQueuingContext();
- Preconditions.checkNotNull(qc, "Cannot drain when there is no queueing context");
- qc.drain(optionalTimeout, false, throwFirstError);
- return qc;
- }
-
- /** as {@link Tasks#swallowChildrenFailures()} but requiring a {@link TaskQueueingContext}. */
- @Beta
- public static void swallowChildrenFailures() {
- Preconditions.checkNotNull(DynamicTasks.getTaskQueuingContext(), "Task queueing context required here");
- Tasks.swallowChildrenFailures();
- }
-
- /** same as {@link Tasks#markInessential()}
- * (but included here for convenience as it is often used in conjunction with {@link DynamicTasks}) */
- public static void markInessential() {
- Tasks.markInessential();
- }
-
- /** queues the task if possible, otherwise submits it asynchronously; returns the task for callers to
- * {@link Task#getUnchecked()} or {@link Task#blockUntilEnded()} */
- public static <T> Task<T> submit(TaskAdaptable<T> task, Entity entity) {
- return queueIfPossible(task).orSubmitAsync(entity).asTask();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/ExecutionListener.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/ExecutionListener.java b/core/src/main/java/brooklyn/util/task/ExecutionListener.java
deleted file mode 100644
index 7753588..0000000
--- a/core/src/main/java/brooklyn/util/task/ExecutionListener.java
+++ /dev/null
@@ -1,31 +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 brooklyn.util.task;
-
-import org.apache.brooklyn.api.management.Task;
-
-public interface ExecutionListener {
-
- /** invoked when a task completes:
- * {@link Task#getEndTimeUtc()} and {@link Task#isDone()} are guaranteed to be set,
- * and {@link Task#get()} should return immediately for most Task implementations
- * (care has been taken to avoid potential deadlocks here, waiting for a result!) */
- public void onTaskDone(Task<?> task);
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/ExecutionUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/ExecutionUtils.java b/core/src/main/java/brooklyn/util/task/ExecutionUtils.java
deleted file mode 100644
index 37c19d2..0000000
--- a/core/src/main/java/brooklyn/util/task/ExecutionUtils.java
+++ /dev/null
@@ -1,49 +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 brooklyn.util.task;
-
-import groovy.lang.Closure;
-
-import java.util.concurrent.Callable;
-
-import com.google.common.base.Function;
-import com.google.common.base.Throwables;
-
-public class ExecutionUtils {
- /**
- * Attempts to run/call the given object, with the given arguments if possible, preserving the return value if there is one (null otherwise);
- * throws exception if the callable is a non-null object which cannot be invoked (not a callable or runnable)
- * @deprecated since 0.7.0 ; this super-loose typing should be avoided; if it is needed, let's move it to one of the Groovy compatibility classes
- */
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public static Object invoke(Object callable, Object ...args) {
- if (callable instanceof Closure) return ((Closure<?>)callable).call(args);
- if (callable instanceof Callable) {
- try {
- return ((Callable<?>)callable).call();
- } catch (Throwable t) {
- throw Throwables.propagate(t);
- }
- }
- if (callable instanceof Runnable) { ((Runnable)callable).run(); return null; }
- if (callable instanceof Function && args.length == 1) { return ((Function)callable).apply(args[0]); }
- if (callable==null) return null;
- throw new IllegalArgumentException("Cannot invoke unexpected object "+callable+" of type "+callable.getClass()+", with "+args.length+" args");
- }
-}
[19/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/xstream/XmlUtil.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/xstream/XmlUtil.java b/core/src/main/java/org/apache/brooklyn/core/util/xstream/XmlUtil.java
new file mode 100644
index 0000000..637f078
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/xstream/XmlUtil.java
@@ -0,0 +1,59 @@
+/*
+ * 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.util.xstream;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+import brooklyn.util.exceptions.Exceptions;
+
+public class XmlUtil {
+
+ public static Object xpath(String xml, String xpath) {
+ // TODO Could share factory/doc in thread-local storage; see http://stackoverflow.com/questions/9828254/is-documentbuilderfactory-thread-safe-in-java-5
+ try {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ Document doc = builder.parse(new ByteArrayInputStream(xml.getBytes()));
+ XPathFactory xPathfactory = XPathFactory.newInstance();
+ XPathExpression expr = xPathfactory.newXPath().compile(xpath);
+
+ return expr.evaluate(doc);
+
+ } catch (ParserConfigurationException e) {
+ throw Exceptions.propagate(e);
+ } catch (SAXException e) {
+ throw Exceptions.propagate(e);
+ } catch (IOException e) {
+ throw Exceptions.propagate(e);
+ } catch (XPathExpressionException e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/access/BrooklynAccessUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/access/BrooklynAccessUtils.java b/core/src/main/java/org/apache/brooklyn/location/access/BrooklynAccessUtils.java
index 9daf1c5..c3b6c61 100644
--- a/core/src/main/java/org/apache/brooklyn/location/access/BrooklynAccessUtils.java
+++ b/core/src/main/java/org/apache/brooklyn/location/access/BrooklynAccessUtils.java
@@ -23,6 +23,10 @@ import java.util.Collection;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.MachineLocation;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.core.util.task.ssh.SshTasks;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -37,10 +41,6 @@ import org.apache.brooklyn.location.basic.SupportsPortForwarding;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.guava.Maybe;
import brooklyn.util.net.Cidr;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.task.ssh.SshTasks;
-import brooklyn.util.task.system.ProcessTaskWrapper;
import brooklyn.util.text.Strings;
import com.google.common.base.Supplier;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/access/PortForwardManagerLocationResolver.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/access/PortForwardManagerLocationResolver.java b/core/src/main/java/org/apache/brooklyn/location/access/PortForwardManagerLocationResolver.java
index db35a34..3e23f45 100644
--- a/core/src/main/java/org/apache/brooklyn/location/access/PortForwardManagerLocationResolver.java
+++ b/core/src/main/java/org/apache/brooklyn/location/access/PortForwardManagerLocationResolver.java
@@ -23,6 +23,7 @@ import java.util.Map;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationRegistry;
import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.location.basic.LocationConfigUtils;
import org.apache.brooklyn.location.basic.LocationInternal;
import org.apache.brooklyn.location.basic.LocationPredicates;
@@ -30,8 +31,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.brooklyn.location.basic.AbstractLocationResolver;
-import brooklyn.util.config.ConfigBag;
-
import com.google.common.base.Optional;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/basic/AbstractLocation.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/basic/AbstractLocation.java b/core/src/main/java/org/apache/brooklyn/location/basic/AbstractLocation.java
index 554a781..0a96956 100644
--- a/core/src/main/java/org/apache/brooklyn/location/basic/AbstractLocation.java
+++ b/core/src/main/java/org/apache/brooklyn/location/basic/AbstractLocation.java
@@ -38,6 +38,9 @@ import org.apache.brooklyn.api.mementos.LocationMemento;
import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
import org.apache.brooklyn.core.management.internal.LocalLocationManager;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.FlagUtils;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -56,9 +59,6 @@ import org.apache.brooklyn.location.geo.HasHostGeoInfo;
import org.apache.brooklyn.location.geo.HostGeoInfo;
import brooklyn.util.collections.SetFromLiveMap;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.flags.FlagUtils;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.guava.Maybe;
import brooklyn.util.stream.Streams;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/basic/AbstractLocationResolver.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/basic/AbstractLocationResolver.java b/core/src/main/java/org/apache/brooklyn/location/basic/AbstractLocationResolver.java
index 26f895c..aea65ae 100644
--- a/core/src/main/java/org/apache/brooklyn/location/basic/AbstractLocationResolver.java
+++ b/core/src/main/java/org/apache/brooklyn/location/basic/AbstractLocationResolver.java
@@ -31,12 +31,12 @@ import org.apache.brooklyn.api.location.LocationRegistry;
import org.apache.brooklyn.api.location.LocationResolver;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.brooklyn.location.basic.AbstractLocationResolver.SpecParser.ParsedSpec;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.text.KeyValueParser;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/basic/AggregatingMachineProvisioningLocation.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/basic/AggregatingMachineProvisioningLocation.java b/core/src/main/java/org/apache/brooklyn/location/basic/AggregatingMachineProvisioningLocation.java
index c814209..ae1a534 100644
--- a/core/src/main/java/org/apache/brooklyn/location/basic/AggregatingMachineProvisioningLocation.java
+++ b/core/src/main/java/org/apache/brooklyn/location/basic/AggregatingMachineProvisioningLocation.java
@@ -29,8 +29,8 @@ import java.util.concurrent.atomic.AtomicInteger;
import org.apache.brooklyn.api.location.MachineLocation;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
import org.apache.brooklyn.api.location.NoMachinesAvailableException;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.stream.Streams;
import com.google.common.base.Objects;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/basic/BasicLocationRegistry.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/basic/BasicLocationRegistry.java b/core/src/main/java/org/apache/brooklyn/location/basic/BasicLocationRegistry.java
index 3cb9f14..4f8637e 100644
--- a/core/src/main/java/org/apache/brooklyn/location/basic/BasicLocationRegistry.java
+++ b/core/src/main/java/org/apache/brooklyn/location/basic/BasicLocationRegistry.java
@@ -42,12 +42,12 @@ import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.core.catalog.CatalogPredicates;
import org.apache.brooklyn.core.management.internal.LocalLocationManager;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import brooklyn.config.ConfigMap;
import brooklyn.config.ConfigPredicates;
import brooklyn.config.ConfigUtils;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.guava.Maybe;
import brooklyn.util.guava.Maybe.Absent;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/basic/BasicMachineDetails.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/basic/BasicMachineDetails.java b/core/src/main/java/org/apache/brooklyn/location/basic/BasicMachineDetails.java
index d6b51c6..9404af2 100644
--- a/core/src/main/java/org/apache/brooklyn/location/basic/BasicMachineDetails.java
+++ b/core/src/main/java/org/apache/brooklyn/location/basic/BasicMachineDetails.java
@@ -32,15 +32,15 @@ import org.apache.brooklyn.api.location.HardwareDetails;
import org.apache.brooklyn.api.location.MachineDetails;
import org.apache.brooklyn.api.location.OsDetails;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.TaskTags;
+import org.apache.brooklyn.core.util.task.ssh.internal.PlainSshExecTaskFactory;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.stream.Streams;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.TaskTags;
-import brooklyn.util.task.ssh.internal.PlainSshExecTaskFactory;
-import brooklyn.util.task.system.ProcessTaskWrapper;
import com.google.common.base.CharMatcher;
import com.google.common.base.Function;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/basic/ByonLocationResolver.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/basic/ByonLocationResolver.java b/core/src/main/java/org/apache/brooklyn/location/basic/ByonLocationResolver.java
index 70735e5..c5680ba 100644
--- a/core/src/main/java/org/apache/brooklyn/location/basic/ByonLocationResolver.java
+++ b/core/src/main/java/org/apache/brooklyn/location/basic/ByonLocationResolver.java
@@ -29,6 +29,8 @@ import org.apache.brooklyn.api.location.LocationRegistry;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.location.MachineLocation;
import org.apache.brooklyn.core.management.internal.LocalLocationManager;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -42,8 +44,6 @@ import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.Sanitizer;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.net.UserAndHostAndPort;
import brooklyn.util.text.WildcardGlobs;
import brooklyn.util.text.WildcardGlobs.PhraseTreatment;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/basic/FixedListMachineProvisioningLocation.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/basic/FixedListMachineProvisioningLocation.java b/core/src/main/java/org/apache/brooklyn/location/basic/FixedListMachineProvisioningLocation.java
index 7b9d73e..170867d 100644
--- a/core/src/main/java/org/apache/brooklyn/location/basic/FixedListMachineProvisioningLocation.java
+++ b/core/src/main/java/org/apache/brooklyn/location/basic/FixedListMachineProvisioningLocation.java
@@ -35,6 +35,8 @@ import org.apache.brooklyn.api.location.MachineLocationCustomizer;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
import org.apache.brooklyn.api.location.NoMachinesAvailableException;
import org.apache.brooklyn.api.management.LocationManager;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -56,8 +58,6 @@ import org.apache.brooklyn.location.cloud.CloudLocationConfig;
import brooklyn.util.collections.CollectionFunctionals;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.stream.Streams;
import brooklyn.util.text.WildcardGlobs;
import brooklyn.util.text.WildcardGlobs.PhraseTreatment;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/basic/HostLocationResolver.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/basic/HostLocationResolver.java b/core/src/main/java/org/apache/brooklyn/location/basic/HostLocationResolver.java
index 8eb983c..d1eb838 100644
--- a/core/src/main/java/org/apache/brooklyn/location/basic/HostLocationResolver.java
+++ b/core/src/main/java/org/apache/brooklyn/location/basic/HostLocationResolver.java
@@ -23,9 +23,9 @@ import java.util.Map;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationRegistry;
import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.location.basic.AbstractLocationResolver.SpecParser.ParsedSpec;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.guava.Maybe;
import brooklyn.util.guava.Maybe.Absent;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/basic/LocalhostLocationResolver.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/basic/LocalhostLocationResolver.java b/core/src/main/java/org/apache/brooklyn/location/basic/LocalhostLocationResolver.java
index 859fa99..9e06f58 100644
--- a/core/src/main/java/org/apache/brooklyn/location/basic/LocalhostLocationResolver.java
+++ b/core/src/main/java/org/apache/brooklyn/location/basic/LocalhostLocationResolver.java
@@ -23,8 +23,7 @@ import java.util.Map;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationRegistry;
import org.apache.brooklyn.api.location.LocationResolver;
-
-import brooklyn.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.config.ConfigBag;
/**
* Examples of valid specs:
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/basic/LocalhostMachineProvisioningLocation.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/basic/LocalhostMachineProvisioningLocation.java b/core/src/main/java/org/apache/brooklyn/location/basic/LocalhostMachineProvisioningLocation.java
index cfaf241..b87b85e 100644
--- a/core/src/main/java/org/apache/brooklyn/location/basic/LocalhostMachineProvisioningLocation.java
+++ b/core/src/main/java/org/apache/brooklyn/location/basic/LocalhostMachineProvisioningLocation.java
@@ -32,6 +32,11 @@ import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
import org.apache.brooklyn.api.location.OsDetails;
import org.apache.brooklyn.api.location.PortRange;
+import org.apache.brooklyn.core.util.BrooklynNetworkUtils;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
+import org.apache.brooklyn.core.util.internal.ssh.process.ProcessTool;
+import org.apache.brooklyn.core.util.mutex.MutexSupport;
+import org.apache.brooklyn.core.util.mutex.WithMutexes;
import org.apache.brooklyn.location.geo.HostGeoInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -43,12 +48,7 @@ import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.rebind.persister.FileBasedObjectStore;
import brooklyn.entity.rebind.persister.LocationWithObjectStore;
import brooklyn.entity.rebind.persister.PersistenceObjectStore;
-import brooklyn.util.BrooklynNetworkUtils;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.flags.SetFromFlag;
-import brooklyn.util.internal.ssh.process.ProcessTool;
-import brooklyn.util.mutex.MutexSupport;
-import brooklyn.util.mutex.WithMutexes;
import brooklyn.util.net.Networking;
import brooklyn.util.os.Os;
import brooklyn.util.ssh.BashCommands;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/basic/LocalhostPropertiesFromBrooklynProperties.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/basic/LocalhostPropertiesFromBrooklynProperties.java b/core/src/main/java/org/apache/brooklyn/location/basic/LocalhostPropertiesFromBrooklynProperties.java
index 1830ddd..7a6c8a9 100644
--- a/core/src/main/java/org/apache/brooklyn/location/basic/LocalhostPropertiesFromBrooklynProperties.java
+++ b/core/src/main/java/org/apache/brooklyn/location/basic/LocalhostPropertiesFromBrooklynProperties.java
@@ -20,11 +20,10 @@ package org.apache.brooklyn.location.basic;
import java.util.Map;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import brooklyn.util.config.ConfigBag;
-
import com.google.common.base.Strings;
/**
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/basic/LocationConfigUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/basic/LocationConfigUtils.java b/core/src/main/java/org/apache/brooklyn/location/basic/LocationConfigUtils.java
index d34a199..47784b1 100644
--- a/core/src/main/java/org/apache/brooklyn/location/basic/LocationConfigUtils.java
+++ b/core/src/main/java/org/apache/brooklyn/location/basic/LocationConfigUtils.java
@@ -32,6 +32,10 @@ import java.util.Set;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.crypto.SecureKeys;
+import org.apache.brooklyn.core.util.crypto.SecureKeys.PassphraseProblem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -40,13 +44,9 @@ import brooklyn.entity.basic.ConfigKeys;
import org.apache.brooklyn.location.cloud.CloudLocationConfig;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.crypto.AuthorizedKeysParser;
-import brooklyn.util.crypto.SecureKeys;
-import brooklyn.util.crypto.SecureKeys.PassphraseProblem;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.os.Os;
import brooklyn.util.text.StringFunctions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/basic/LocationInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/basic/LocationInternal.java b/core/src/main/java/org/apache/brooklyn/location/basic/LocationInternal.java
index de3e9a0..4a444c7 100644
--- a/core/src/main/java/org/apache/brooklyn/location/basic/LocationInternal.java
+++ b/core/src/main/java/org/apache/brooklyn/location/basic/LocationInternal.java
@@ -24,12 +24,12 @@ import org.apache.brooklyn.api.entity.rebind.RebindSupport;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.mementos.LocationMemento;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import brooklyn.basic.BrooklynObjectInternal;
import brooklyn.config.ConfigInheritance;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.util.config.ConfigBag;
import com.google.common.annotations.Beta;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/basic/LocationPropertiesFromBrooklynProperties.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/basic/LocationPropertiesFromBrooklynProperties.java b/core/src/main/java/org/apache/brooklyn/location/basic/LocationPropertiesFromBrooklynProperties.java
index e1feb18..2655fc9 100644
--- a/core/src/main/java/org/apache/brooklyn/location/basic/LocationPropertiesFromBrooklynProperties.java
+++ b/core/src/main/java/org/apache/brooklyn/location/basic/LocationPropertiesFromBrooklynProperties.java
@@ -23,6 +23,8 @@ import static com.google.common.base.Preconditions.checkArgument;
import java.io.File;
import java.util.Map;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -30,8 +32,6 @@ import brooklyn.config.BrooklynProperties;
import brooklyn.config.BrooklynServerConfig;
import brooklyn.config.ConfigUtils;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.internal.ssh.SshTool;
import brooklyn.util.os.Os;
import com.google.common.base.Predicates;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/basic/MultiLocation.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/basic/MultiLocation.java b/core/src/main/java/org/apache/brooklyn/location/basic/MultiLocation.java
index b702a92..5740a8f 100644
--- a/core/src/main/java/org/apache/brooklyn/location/basic/MultiLocation.java
+++ b/core/src/main/java/org/apache/brooklyn/location/basic/MultiLocation.java
@@ -32,6 +32,7 @@ import org.apache.brooklyn.api.location.MachineLocation;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
import org.apache.brooklyn.api.location.NoMachinesAvailableException;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.location.cloud.AbstractAvailabilityZoneExtension;
import org.apache.brooklyn.location.cloud.AvailabilityZoneExtension;
@@ -41,7 +42,6 @@ import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.CompoundRuntimeException;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.text.Strings;
import com.google.common.base.Predicate;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/basic/NamedLocationResolver.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/basic/NamedLocationResolver.java b/core/src/main/java/org/apache/brooklyn/location/basic/NamedLocationResolver.java
index a9f6499..d57b681 100644
--- a/core/src/main/java/org/apache/brooklyn/location/basic/NamedLocationResolver.java
+++ b/core/src/main/java/org/apache/brooklyn/location/basic/NamedLocationResolver.java
@@ -28,10 +28,10 @@ import org.apache.brooklyn.api.location.LocationDefinition;
import org.apache.brooklyn.api.location.LocationRegistry;
import org.apache.brooklyn.api.location.LocationResolver;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.text.Strings;
/**
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/basic/PortRanges.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/basic/PortRanges.java b/core/src/main/java/org/apache/brooklyn/location/basic/PortRanges.java
index 2e1bdcc..92c3010 100644
--- a/core/src/main/java/org/apache/brooklyn/location/basic/PortRanges.java
+++ b/core/src/main/java/org/apache/brooklyn/location/basic/PortRanges.java
@@ -30,8 +30,7 @@ import java.util.NoSuchElementException;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.brooklyn.api.location.PortRange;
-
-import brooklyn.util.flags.TypeCoercions;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import com.google.common.base.Function;
import com.google.common.base.Objects;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/basic/SingleMachineLocationResolver.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/basic/SingleMachineLocationResolver.java b/core/src/main/java/org/apache/brooklyn/location/basic/SingleMachineLocationResolver.java
index fb5f676..3db980e 100644
--- a/core/src/main/java/org/apache/brooklyn/location/basic/SingleMachineLocationResolver.java
+++ b/core/src/main/java/org/apache/brooklyn/location/basic/SingleMachineLocationResolver.java
@@ -23,8 +23,8 @@ import java.util.Map;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationRegistry;
import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.core.util.config.ConfigBag;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.guava.Maybe;
import brooklyn.util.guava.Maybe.Absent;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/basic/SingleMachineProvisioningLocation.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/basic/SingleMachineProvisioningLocation.java b/core/src/main/java/org/apache/brooklyn/location/basic/SingleMachineProvisioningLocation.java
index 5f249d2..bac439f 100644
--- a/core/src/main/java/org/apache/brooklyn/location/basic/SingleMachineProvisioningLocation.java
+++ b/core/src/main/java/org/apache/brooklyn/location/basic/SingleMachineProvisioningLocation.java
@@ -23,11 +23,10 @@ import java.util.Map;
import org.apache.brooklyn.api.location.MachineLocation;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
import org.apache.brooklyn.api.location.NoMachinesAvailableException;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import brooklyn.util.flags.SetFromFlag;
-
import com.google.common.collect.ImmutableMap;
public class SingleMachineProvisioningLocation<T extends MachineLocation> extends FixedListMachineProvisioningLocation<T> {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/basic/SshMachineLocation.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/basic/SshMachineLocation.java b/core/src/main/java/org/apache/brooklyn/location/basic/SshMachineLocation.java
index 0a8dd44..7c58194 100644
--- a/core/src/main/java/org/apache/brooklyn/location/basic/SshMachineLocation.java
+++ b/core/src/main/java/org/apache/brooklyn/location/basic/SshMachineLocation.java
@@ -51,6 +51,22 @@ import org.apache.brooklyn.api.location.OsDetails;
import org.apache.brooklyn.api.location.PortRange;
import org.apache.brooklyn.api.location.PortSupplier;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.crypto.SecureKeys;
+import org.apache.brooklyn.core.util.file.ArchiveUtils;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
+import org.apache.brooklyn.core.util.internal.ssh.ShellTool;
+import org.apache.brooklyn.core.util.internal.ssh.SshException;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
+import org.apache.brooklyn.core.util.internal.ssh.sshj.SshjTool;
+import org.apache.brooklyn.core.util.mutex.MutexSupport;
+import org.apache.brooklyn.core.util.mutex.WithMutexes;
+import org.apache.brooklyn.core.util.task.ScheduledTask;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.core.util.task.system.internal.ExecWithLoggingHelpers;
+import org.apache.brooklyn.core.util.task.system.internal.ExecWithLoggingHelpers.ExecRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -87,22 +103,10 @@ import brooklyn.event.basic.MapConfigKey;
import org.apache.brooklyn.location.access.PortForwardManager;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.crypto.SecureKeys;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.exceptions.RuntimeInterruptedException;
-import brooklyn.util.file.ArchiveUtils;
-import brooklyn.util.flags.SetFromFlag;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.guava.KeyTransformingLoadingCache.KeyTransformingSameTypeLoadingCache;
-import brooklyn.util.internal.ssh.ShellTool;
-import brooklyn.util.internal.ssh.SshException;
-import brooklyn.util.internal.ssh.SshTool;
-import brooklyn.util.internal.ssh.sshj.SshjTool;
-import brooklyn.util.mutex.MutexSupport;
-import brooklyn.util.mutex.WithMutexes;
import brooklyn.util.net.Urls;
import brooklyn.util.pool.BasicPool;
import brooklyn.util.pool.Pool;
@@ -110,10 +114,6 @@ import brooklyn.util.ssh.BashCommands;
import brooklyn.util.stream.KnownSizeInputStream;
import brooklyn.util.stream.ReaderInputStream;
import brooklyn.util.stream.StreamGobbler;
-import brooklyn.util.task.ScheduledTask;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.task.system.internal.ExecWithLoggingHelpers;
-import brooklyn.util.task.system.internal.ExecWithLoggingHelpers.ExecRunner;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Duration;
import groovy.lang.Closure;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/cloud/AbstractCloudMachineProvisioningLocation.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/cloud/AbstractCloudMachineProvisioningLocation.java b/core/src/main/java/org/apache/brooklyn/location/cloud/AbstractCloudMachineProvisioningLocation.java
index 437d49b..4b297f8 100644
--- a/core/src/main/java/org/apache/brooklyn/location/cloud/AbstractCloudMachineProvisioningLocation.java
+++ b/core/src/main/java/org/apache/brooklyn/location/cloud/AbstractCloudMachineProvisioningLocation.java
@@ -24,11 +24,11 @@ import java.util.Map;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.location.MachineLocation;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
import org.apache.brooklyn.location.basic.AbstractLocation;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.internal.ssh.SshTool;
public abstract class AbstractCloudMachineProvisioningLocation extends AbstractLocation
implements MachineProvisioningLocation<MachineLocation>, CloudLocationConfig
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/cloud/CloudLocationConfig.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/cloud/CloudLocationConfig.java b/core/src/main/java/org/apache/brooklyn/location/cloud/CloudLocationConfig.java
index a44ca49..ad6a11c 100644
--- a/core/src/main/java/org/apache/brooklyn/location/cloud/CloudLocationConfig.java
+++ b/core/src/main/java/org/apache/brooklyn/location/cloud/CloudLocationConfig.java
@@ -28,10 +28,9 @@ import brooklyn.entity.basic.ConfigKeys;
import brooklyn.event.basic.BasicConfigKey;
import org.apache.brooklyn.api.location.MachineLocationCustomizer;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.location.basic.LocationConfigKeys;
-import brooklyn.util.flags.SetFromFlag;
-
public interface CloudLocationConfig {
public static final ConfigKey<String> CLOUD_ENDPOINT = LocationConfigKeys.CLOUD_ENDPOINT;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/cloud/names/AbstractCloudMachineNamer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/cloud/names/AbstractCloudMachineNamer.java b/core/src/main/java/org/apache/brooklyn/location/cloud/names/AbstractCloudMachineNamer.java
index b06b88a..2df845e 100644
--- a/core/src/main/java/org/apache/brooklyn/location/cloud/names/AbstractCloudMachineNamer.java
+++ b/core/src/main/java/org/apache/brooklyn/location/cloud/names/AbstractCloudMachineNamer.java
@@ -20,9 +20,9 @@ package org.apache.brooklyn.location.cloud.names;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.trait.HasShortName;
-
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.location.cloud.CloudLocationConfig;
-import brooklyn.util.config.ConfigBag;
+
import brooklyn.util.text.Identifiers;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/cloud/names/BasicCloudMachineNamer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/cloud/names/BasicCloudMachineNamer.java b/core/src/main/java/org/apache/brooklyn/location/cloud/names/BasicCloudMachineNamer.java
index 818053d..26c41ee 100644
--- a/core/src/main/java/org/apache/brooklyn/location/cloud/names/BasicCloudMachineNamer.java
+++ b/core/src/main/java/org/apache/brooklyn/location/cloud/names/BasicCloudMachineNamer.java
@@ -20,9 +20,9 @@ package org.apache.brooklyn.location.cloud.names;
import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.entity.Entity;
-
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.location.cloud.CloudLocationConfig;
-import brooklyn.util.config.ConfigBag;
+
import brooklyn.util.text.Identifiers;
import brooklyn.util.text.StringShortener;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/cloud/names/CloudMachineNamer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/cloud/names/CloudMachineNamer.java b/core/src/main/java/org/apache/brooklyn/location/cloud/names/CloudMachineNamer.java
index df7fd8b..b475436 100644
--- a/core/src/main/java/org/apache/brooklyn/location/cloud/names/CloudMachineNamer.java
+++ b/core/src/main/java/org/apache/brooklyn/location/cloud/names/CloudMachineNamer.java
@@ -20,10 +20,9 @@ package org.apache.brooklyn.location.cloud.names;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.location.cloud.CloudLocationConfig;
-import brooklyn.util.config.ConfigBag;
-
/**
* Interface used to construct names for individual cloud machines and for groups of machines.
* <p>
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/cloud/names/CustomMachineNamer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/cloud/names/CustomMachineNamer.java b/core/src/main/java/org/apache/brooklyn/location/cloud/names/CustomMachineNamer.java
index 472adde..0bac6c8 100644
--- a/core/src/main/java/org/apache/brooklyn/location/cloud/names/CustomMachineNamer.java
+++ b/core/src/main/java/org/apache/brooklyn/location/cloud/names/CustomMachineNamer.java
@@ -21,14 +21,16 @@ package org.apache.brooklyn.location.cloud.names;
import java.util.Map;
import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.text.TemplateProcessor;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.EntityInternal;
+
import org.apache.brooklyn.location.cloud.CloudLocationConfig;
-import brooklyn.util.config.ConfigBag;
+
import brooklyn.util.text.Strings;
-import brooklyn.util.text.TemplateProcessor;
import com.google.common.collect.ImmutableMap;
import com.google.common.reflect.TypeToken;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/dynamic/DynamicLocation.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/dynamic/DynamicLocation.java b/core/src/main/java/org/apache/brooklyn/location/dynamic/DynamicLocation.java
index 4c38b7e..5b6fd05 100644
--- a/core/src/main/java/org/apache/brooklyn/location/dynamic/DynamicLocation.java
+++ b/core/src/main/java/org/apache/brooklyn/location/dynamic/DynamicLocation.java
@@ -20,12 +20,12 @@ package org.apache.brooklyn.location.dynamic;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import com.google.common.annotations.Beta;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.util.flags.SetFromFlag;
/**
* A location that is created and owned by an entity at runtime.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/dynamic/LocationOwner.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/dynamic/LocationOwner.java b/core/src/main/java/org/apache/brooklyn/location/dynamic/LocationOwner.java
index b061b69..84348cb 100644
--- a/core/src/main/java/org/apache/brooklyn/location/dynamic/LocationOwner.java
+++ b/core/src/main/java/org/apache/brooklyn/location/dynamic/LocationOwner.java
@@ -24,12 +24,12 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationDefinition;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/geo/HostGeoInfo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/geo/HostGeoInfo.java b/core/src/main/java/org/apache/brooklyn/location/geo/HostGeoInfo.java
index ad05bbd..c85060c 100644
--- a/core/src/main/java/org/apache/brooklyn/location/geo/HostGeoInfo.java
+++ b/core/src/main/java/org/apache/brooklyn/location/geo/HostGeoInfo.java
@@ -26,13 +26,13 @@ import javax.annotation.Nullable;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.location.AddressableLocation;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import org.apache.brooklyn.location.basic.AbstractLocation;
import org.apache.brooklyn.location.basic.LocationConfigKeys;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.guava.Maybe;
import brooklyn.util.internal.BrooklynSystemProperties;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/location/geo/LocalhostExternalIpLoader.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/geo/LocalhostExternalIpLoader.java b/core/src/main/java/org/apache/brooklyn/location/geo/LocalhostExternalIpLoader.java
index cd46bdd..8738817 100644
--- a/core/src/main/java/org/apache/brooklyn/location/geo/LocalhostExternalIpLoader.java
+++ b/core/src/main/java/org/apache/brooklyn/location/geo/LocalhostExternalIpLoader.java
@@ -26,10 +26,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.apache.brooklyn.core.util.ResourceUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.text.StringPredicates;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/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 d5590fc..d6a9ed0 100644
--- a/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
+++ b/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
@@ -55,15 +55,15 @@ import org.apache.brooklyn.core.catalog.internal.CatalogDto;
import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.core.management.osgi.OsgiStandaloneTest;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.config.ConfigBag;
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.util.ResourceUtils;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.stream.Streams;
import com.google.common.base.Joiner;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/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 22d3ab8..2fa3415 100644
--- a/core/src/test/java/brooklyn/camp/lite/TestAppAssemblyInstantiator.java
+++ b/core/src/test/java/brooklyn/camp/lite/TestAppAssemblyInstantiator.java
@@ -32,13 +32,13 @@ import java.util.Set;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestEntity;
import brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator;
import brooklyn.camp.brooklyn.api.HasBrooklynManagementContext;
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
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/enricher/basic/BasicEnricherTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/enricher/basic/BasicEnricherTest.java b/core/src/test/java/brooklyn/enricher/basic/BasicEnricherTest.java
index 396c76a..7ee1177 100644
--- a/core/src/test/java/brooklyn/enricher/basic/BasicEnricherTest.java
+++ b/core/src/test/java/brooklyn/enricher/basic/BasicEnricherTest.java
@@ -25,6 +25,7 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.EnricherSpec;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestApplicationNoEnrichersImpl;
import org.testng.Assert;
@@ -38,7 +39,6 @@ import brooklyn.entity.basic.ApplicationBuilder;
import brooklyn.entity.basic.BrooklynConfigKeys;
import brooklyn.event.basic.BasicConfigKey;
import brooklyn.util.collections.MutableSet;
-import brooklyn.util.flags.SetFromFlag;
/**
* Test that enricher can be created and accessed, by construction and by spec
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/entity/EffectorSayHiTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/EffectorSayHiTest.java b/core/src/test/java/brooklyn/entity/EffectorSayHiTest.java
index 62579e3..80cfe2a 100644
--- a/core/src/test/java/brooklyn/entity/EffectorSayHiTest.java
+++ b/core/src/test/java/brooklyn/entity/EffectorSayHiTest.java
@@ -34,6 +34,7 @@ import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.management.ExecutionContext;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.util.task.BasicTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.BeforeMethod;
@@ -45,7 +46,6 @@ import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.entity.basic.MethodEffector;
import brooklyn.entity.trait.Startable;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.task.BasicTask;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/entity/SetFromFlagTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/SetFromFlagTest.java b/core/src/test/java/brooklyn/entity/SetFromFlagTest.java
index c5cfc0b..08d0428 100644
--- a/core/src/test/java/brooklyn/entity/SetFromFlagTest.java
+++ b/core/src/test/java/brooklyn/entity/SetFromFlagTest.java
@@ -24,6 +24,7 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.location.PortRange;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.testng.annotations.Test;
import brooklyn.entity.basic.AbstractEntity;
@@ -31,7 +32,6 @@ import brooklyn.entity.basic.AbstractEntity;
import org.apache.brooklyn.location.basic.PortRanges;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.flags.SetFromFlag;
public class SetFromFlagTest {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/entity/basic/ConfigMapTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/basic/ConfigMapTest.java b/core/src/test/java/brooklyn/entity/basic/ConfigMapTest.java
index a532d15..f67a193 100644
--- a/core/src/test/java/brooklyn/entity/basic/ConfigMapTest.java
+++ b/core/src/test/java/brooklyn/entity/basic/ConfigMapTest.java
@@ -35,6 +35,8 @@ import java.util.concurrent.atomic.AtomicInteger;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.management.ExecutionManager;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.task.BasicTask;
+import org.apache.brooklyn.core.util.task.DeferredSupplier;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
@@ -46,8 +48,6 @@ import brooklyn.config.ConfigPredicates;
import brooklyn.entity.BrooklynAppUnitTestSupport;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey.IntegerAttributeSensorAndConfigKey;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.task.BasicTask;
-import brooklyn.util.task.DeferredSupplier;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/entity/basic/DependentConfigurationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/basic/DependentConfigurationTest.java b/core/src/test/java/brooklyn/entity/basic/DependentConfigurationTest.java
index 2919055..dd107aa 100644
--- a/core/src/test/java/brooklyn/entity/basic/DependentConfigurationTest.java
+++ b/core/src/test/java/brooklyn/entity/basic/DependentConfigurationTest.java
@@ -31,6 +31,7 @@ import java.util.concurrent.atomic.AtomicReference;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.task.BasicTask;
import org.apache.brooklyn.test.EntityTestUtils;
import org.apache.brooklyn.test.entity.TestEntity;
import org.slf4j.Logger;
@@ -46,7 +47,6 @@ import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.javalang.JavaClassNames;
-import brooklyn.util.task.BasicTask;
import brooklyn.util.text.StringPredicates;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/entity/basic/EntityConfigTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/basic/EntityConfigTest.java b/core/src/test/java/brooklyn/entity/basic/EntityConfigTest.java
index 4878e33..e41e3a3 100644
--- a/core/src/test/java/brooklyn/entity/basic/EntityConfigTest.java
+++ b/core/src/test/java/brooklyn/entity/basic/EntityConfigTest.java
@@ -22,13 +22,13 @@ import static org.testng.Assert.assertEquals;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import brooklyn.config.ConfigKey;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/entity/basic/EntitySpecTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/basic/EntitySpecTest.java b/core/src/test/java/brooklyn/entity/basic/EntitySpecTest.java
index 0bb8c2f..80ebfb7 100644
--- a/core/src/test/java/brooklyn/entity/basic/EntitySpecTest.java
+++ b/core/src/test/java/brooklyn/entity/basic/EntitySpecTest.java
@@ -27,6 +27,7 @@ import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.EnricherSpec;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.test.entity.TestEntity;
import org.apache.brooklyn.test.entity.TestEntityImpl;
import org.apache.brooklyn.test.entity.TestEntityNoEnrichersImpl;
@@ -42,7 +43,6 @@ import org.apache.brooklyn.location.basic.SimulatedLocation;
import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.test.Asserts;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/entity/basic/MapListAndOtherStructuredConfigKeyTest.groovy
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/basic/MapListAndOtherStructuredConfigKeyTest.groovy b/core/src/test/java/brooklyn/entity/basic/MapListAndOtherStructuredConfigKeyTest.groovy
index a52e7d5..86bdc18 100644
--- a/core/src/test/java/brooklyn/entity/basic/MapListAndOtherStructuredConfigKeyTest.groovy
+++ b/core/src/test/java/brooklyn/entity/basic/MapListAndOtherStructuredConfigKeyTest.groovy
@@ -39,7 +39,7 @@ import org.apache.brooklyn.test.entity.TestApplication
import org.apache.brooklyn.test.entity.TestEntity
import brooklyn.util.collections.MutableMap
import brooklyn.util.exceptions.Exceptions
-import brooklyn.util.task.DeferredSupplier
+import org.apache.brooklyn.core.util.task.DeferredSupplier
import com.google.common.collect.ImmutableList
import com.google.common.collect.ImmutableSet
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/entity/basic/SanitizerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/basic/SanitizerTest.java b/core/src/test/java/brooklyn/entity/basic/SanitizerTest.java
index c9d40a5..ed07c75 100644
--- a/core/src/test/java/brooklyn/entity/basic/SanitizerTest.java
+++ b/core/src/test/java/brooklyn/entity/basic/SanitizerTest.java
@@ -22,10 +22,9 @@ import static org.testng.Assert.assertEquals;
import java.util.Map;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.testng.annotations.Test;
-import brooklyn.util.config.ConfigBag;
-
import com.google.common.collect.ImmutableMap;
public class SanitizerTest {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/entity/effector/EffectorBasicTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/effector/EffectorBasicTest.java b/core/src/test/java/brooklyn/entity/effector/EffectorBasicTest.java
index fa963c3..f8f4eb1 100644
--- a/core/src/test/java/brooklyn/entity/effector/EffectorBasicTest.java
+++ b/core/src/test/java/brooklyn/entity/effector/EffectorBasicTest.java
@@ -26,6 +26,7 @@ import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.HasTaskChildren;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.apache.brooklyn.test.TestUtils;
import org.apache.brooklyn.test.entity.TestEntity;
import org.slf4j.Logger;
@@ -43,7 +44,6 @@ import org.apache.brooklyn.location.basic.SimulatedLocation;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.task.Tasks;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/entity/effector/EffectorConcatenateTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/effector/EffectorConcatenateTest.java b/core/src/test/java/brooklyn/entity/effector/EffectorConcatenateTest.java
index 56382d8..63b10da 100644
--- a/core/src/test/java/brooklyn/entity/effector/EffectorConcatenateTest.java
+++ b/core/src/test/java/brooklyn/entity/effector/EffectorConcatenateTest.java
@@ -30,6 +30,8 @@ import java.util.concurrent.atomic.AtomicReference;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.management.ExecutionManager;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.task.BasicExecutionContext;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestApplicationImpl;
import org.slf4j.Logger;
@@ -45,8 +47,6 @@ import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.MethodEffector;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.task.BasicExecutionContext;
-import brooklyn.util.task.Tasks;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/entity/effector/EffectorTaskTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/effector/EffectorTaskTest.java b/core/src/test/java/brooklyn/entity/effector/EffectorTaskTest.java
index 38dd2b8..0f6f041 100644
--- a/core/src/test/java/brooklyn/entity/effector/EffectorTaskTest.java
+++ b/core/src/test/java/brooklyn/entity/effector/EffectorTaskTest.java
@@ -26,6 +26,11 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.HasTaskChildren;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.task.DynamicSequentialTask;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.TaskBuilder;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.apache.brooklyn.test.entity.TestEntity;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -38,12 +43,7 @@ import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.effector.EffectorTasks.EffectorTaskFactory;
import brooklyn.entity.trait.Startable;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.task.DynamicSequentialTask;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.TaskBuilder;
-import brooklyn.util.task.Tasks;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/entity/rebind/Dumpers.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/Dumpers.java b/core/src/test/java/brooklyn/entity/rebind/Dumpers.java
index 12e47ad..934df5c 100644
--- a/core/src/test/java/brooklyn/entity/rebind/Dumpers.java
+++ b/core/src/test/java/brooklyn/entity/rebind/Dumpers.java
@@ -31,11 +31,11 @@ import java.util.Random;
import javax.annotation.Nullable;
+import org.apache.brooklyn.core.util.flags.FlagUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.FlagUtils;
import brooklyn.util.javalang.Serializers;
import brooklyn.util.javalang.Serializers.ObjectReplacer;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/entity/rebind/RebindCatalogEntityTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindCatalogEntityTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindCatalogEntityTest.java
index 3debe30..dc440bc 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindCatalogEntityTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindCatalogEntityTest.java
@@ -45,10 +45,9 @@ import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.ha.ManagementNodeState;
import org.apache.brooklyn.core.catalog.internal.CatalogInitialization;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.util.javalang.UrlClassLoader;
import org.apache.brooklyn.test.TestResourceUnavailableException;
-import brooklyn.util.javalang.UrlClassLoader;
-
import com.google.common.base.Function;
public class RebindCatalogEntityTest extends RebindTestFixture<StartableApplication> {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/entity/rebind/RebindEnricherTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindEnricherTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindEnricherTest.java
index 3102dd2..ea21787 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindEnricherTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindEnricherTest.java
@@ -32,6 +32,7 @@ import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.EnricherSpec;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.test.EntityTestUtils;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestEntity;
@@ -55,7 +56,6 @@ import org.apache.brooklyn.location.basic.SimulatedLocation;
import brooklyn.test.Asserts;
import brooklyn.util.collections.MutableSet;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.text.Identifiers;
import brooklyn.util.text.StringFunctions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/entity/rebind/RebindEntityDynamicTypeInfoTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindEntityDynamicTypeInfoTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindEntityDynamicTypeInfoTest.java
index d7ad132..883b1aa 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindEntityDynamicTypeInfoTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindEntityDynamicTypeInfoTest.java
@@ -27,6 +27,7 @@ import java.util.concurrent.ExecutionException;
import org.apache.brooklyn.api.entity.Effector;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestEntity;
import org.slf4j.Logger;
@@ -38,7 +39,6 @@ import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.effector.EffectorBody;
import brooklyn.entity.effector.Effectors;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.stream.Streams;
public class RebindEntityDynamicTypeInfoTest extends RebindTestFixtureWithApp {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/entity/rebind/RebindEntityTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindEntityTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindEntityTest.java
index 992ca8e..3ece27b 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindEntityTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindEntityTest.java
@@ -53,6 +53,7 @@ import org.apache.brooklyn.api.management.ha.ManagementNodeState;
import org.apache.brooklyn.api.mementos.BrooklynMementoManifest;
import org.apache.brooklyn.api.mementos.EntityMemento;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestEntity;
import org.apache.brooklyn.test.entity.TestEntityImpl;
@@ -79,7 +80,6 @@ import brooklyn.test.Asserts;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
import brooklyn.util.exceptions.RuntimeInterruptedException;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.time.Durations;
import com.google.common.base.Objects;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/entity/rebind/RebindFailuresTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindFailuresTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindFailuresTest.java
index ba168cf..674d77e 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindFailuresTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindFailuresTest.java
@@ -40,6 +40,7 @@ import org.apache.brooklyn.api.policy.EnricherSpec;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -54,7 +55,6 @@ import brooklyn.entity.rebind.RebindEntityTest.MyEntity;
import brooklyn.entity.rebind.RebindEntityTest.MyEntityImpl;
import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.os.Os;
import com.google.common.base.Charsets;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/entity/rebind/RebindFeedTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindFeedTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindFeedTest.java
index c368a7a..d0d03d6 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindFeedTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindFeedTest.java
@@ -29,6 +29,8 @@ import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.core.management.internal.BrooklynGarbageCollector;
+import org.apache.brooklyn.core.util.http.BetterMockWebServer;
+import org.apache.brooklyn.core.util.task.BasicExecutionManager;
import org.apache.brooklyn.test.EntityTestUtils;
import org.apache.brooklyn.test.entity.TestEntity;
import org.apache.brooklyn.test.entity.TestEntityImpl.TestEntityWithoutEnrichers;
@@ -57,8 +59,6 @@ import org.apache.brooklyn.location.basic.SshMachineLocation;
import brooklyn.test.Asserts;
import brooklyn.util.collections.MutableList;
-import brooklyn.util.http.BetterMockWebServer;
-import brooklyn.util.task.BasicExecutionManager;
import brooklyn.util.text.Identifiers;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/entity/rebind/RebindFeedWithHaTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindFeedWithHaTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindFeedWithHaTest.java
index 868665f..c42090b 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindFeedWithHaTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindFeedWithHaTest.java
@@ -31,6 +31,8 @@ import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.util.http.BetterMockWebServer;
+import org.apache.brooklyn.core.util.task.BasicExecutionManager;
import org.apache.brooklyn.test.EntityTestUtils;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestEntity;
@@ -41,9 +43,7 @@ import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
-import brooklyn.util.http.BetterMockWebServer;
import brooklyn.util.repeat.Repeater;
-import brooklyn.util.task.BasicExecutionManager;
import brooklyn.util.time.Duration;
import com.google.common.collect.Iterables;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/entity/rebind/RebindLocationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindLocationTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindLocationTest.java
index 8c93fc7..7e54ac4 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindLocationTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindLocationTest.java
@@ -33,6 +33,7 @@ import org.apache.brooklyn.api.entity.rebind.RebindSupport;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.mementos.LocationMemento;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.test.entity.TestApplication;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
@@ -46,7 +47,6 @@ import org.apache.brooklyn.location.basic.AbstractLocation;
import brooklyn.test.Asserts;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/entity/rebind/RebindManagerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindManagerTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindManagerTest.java
index 676d040..c1312e5 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindManagerTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindManagerTest.java
@@ -25,13 +25,12 @@ import java.util.concurrent.Callable;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.task.BasicTask;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
import org.apache.brooklyn.test.entity.TestEntity;
import org.apache.brooklyn.test.entity.TestEntityImpl;
import org.testng.annotations.Test;
-import brooklyn.util.task.BasicTask;
-import brooklyn.util.task.DynamicTasks;
-
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/entity/rebind/RebindPolicyTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindPolicyTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindPolicyTest.java
index f77e3d4..d74a6fc 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindPolicyTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindPolicyTest.java
@@ -33,6 +33,7 @@ import org.apache.brooklyn.api.mementos.BrooklynMementoManifest;
import org.apache.brooklyn.api.policy.EnricherSpec;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestEntity;
import org.testng.annotations.Test;
@@ -50,7 +51,6 @@ import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.test.Asserts;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableSet;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java b/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java
index 5c39216..966ecea 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java
@@ -43,6 +43,7 @@ import org.apache.brooklyn.api.mementos.BrooklynMementoManifest;
import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.util.task.BasicExecutionManager;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityFunctions;
@@ -53,7 +54,6 @@ import brooklyn.entity.rebind.persister.PersistMode;
import brooklyn.entity.trait.Startable;
import brooklyn.util.os.Os;
import brooklyn.util.repeat.Repeater;
-import brooklyn.util.task.BasicExecutionManager;
import brooklyn.util.text.Identifiers;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/entity/rebind/transformer/impl/XsltTransformerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/transformer/impl/XsltTransformerTest.java b/core/src/test/java/brooklyn/entity/rebind/transformer/impl/XsltTransformerTest.java
index 5791dd4..cdd89a5 100644
--- a/core/src/test/java/brooklyn/entity/rebind/transformer/impl/XsltTransformerTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/transformer/impl/XsltTransformerTest.java
@@ -20,11 +20,11 @@ package brooklyn.entity.rebind.transformer.impl;
import static org.testng.Assert.assertEquals;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.text.TemplateProcessor;
import org.testng.annotations.Test;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.os.Os;
-import brooklyn.util.text.TemplateProcessor;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/entity/trait/FailingEntity.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/trait/FailingEntity.java b/core/src/test/java/brooklyn/entity/trait/FailingEntity.java
index 4d06fc4..4b8c85e 100644
--- a/core/src/test/java/brooklyn/entity/trait/FailingEntity.java
+++ b/core/src/test/java/brooklyn/entity/trait/FailingEntity.java
@@ -22,11 +22,11 @@ import java.util.List;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.test.entity.TestEntity;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.base.Function;
import com.google.common.base.Functions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/entity/trait/FailingEntityImpl.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/trait/FailingEntityImpl.java b/core/src/test/java/brooklyn/entity/trait/FailingEntityImpl.java
index 4d1d9f9..e4a5d77 100644
--- a/core/src/test/java/brooklyn/entity/trait/FailingEntityImpl.java
+++ b/core/src/test/java/brooklyn/entity/trait/FailingEntityImpl.java
@@ -22,12 +22,12 @@ import java.util.Collection;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.apache.brooklyn.test.entity.TestEntityImpl;
import org.testng.Assert;
import brooklyn.entity.basic.Entities;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.task.Tasks;
public class FailingEntityImpl extends TestEntityImpl implements FailingEntity {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/entity/trait/StartableMethodsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/trait/StartableMethodsTest.java b/core/src/test/java/brooklyn/entity/trait/StartableMethodsTest.java
index 1a3537d..f457b0d 100644
--- a/core/src/test/java/brooklyn/entity/trait/StartableMethodsTest.java
+++ b/core/src/test/java/brooklyn/entity/trait/StartableMethodsTest.java
@@ -23,6 +23,7 @@ import static org.testng.Assert.fail;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.apache.brooklyn.test.entity.TestEntity;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
@@ -30,8 +31,8 @@ import org.testng.annotations.Test;
import brooklyn.entity.BrooklynAppUnitTestSupport;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.trait.FailingEntity.RecordingEventListener;
+
import org.apache.brooklyn.location.basic.SimulatedLocation;
-import brooklyn.util.task.Tasks;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/event/feed/PollerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/event/feed/PollerTest.java b/core/src/test/java/brooklyn/event/feed/PollerTest.java
index fc799e0..1427c93 100644
--- a/core/src/test/java/brooklyn/event/feed/PollerTest.java
+++ b/core/src/test/java/brooklyn/event/feed/PollerTest.java
@@ -25,6 +25,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
import org.apache.brooklyn.test.entity.TestEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -35,7 +36,6 @@ import org.testng.annotations.Test;
import brooklyn.entity.BrooklynAppUnitTestSupport;
import brooklyn.test.Asserts;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.task.DynamicTasks;
import brooklyn.util.time.Duration;
public class PollerTest extends BrooklynAppUnitTestSupport {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/event/feed/http/HttpFeedTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/event/feed/http/HttpFeedTest.java b/core/src/test/java/brooklyn/event/feed/http/HttpFeedTest.java
index aa16b8c..e367bdf 100644
--- a/core/src/test/java/brooklyn/event/feed/http/HttpFeedTest.java
+++ b/core/src/test/java/brooklyn/event/feed/http/HttpFeedTest.java
@@ -29,6 +29,8 @@ import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.util.http.BetterMockWebServer;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
import org.apache.brooklyn.test.entity.TestEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -49,8 +51,6 @@ import brooklyn.test.Asserts;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.guava.Functionals;
-import brooklyn.util.http.BetterMockWebServer;
-import brooklyn.util.http.HttpToolResponse;
import brooklyn.util.net.Networking;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/event/feed/http/HttpValueFunctionsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/event/feed/http/HttpValueFunctionsTest.java b/core/src/test/java/brooklyn/event/feed/http/HttpValueFunctionsTest.java
index 7769427..2f83cc5 100644
--- a/core/src/test/java/brooklyn/event/feed/http/HttpValueFunctionsTest.java
+++ b/core/src/test/java/brooklyn/event/feed/http/HttpValueFunctionsTest.java
@@ -25,11 +25,10 @@ import static org.testng.Assert.assertTrue;
import java.util.NoSuchElementException;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
-import brooklyn.util.http.HttpToolResponse;
-
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gson.JsonElement;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/policy/basic/BasicPolicyTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/policy/basic/BasicPolicyTest.java b/core/src/test/java/brooklyn/policy/basic/BasicPolicyTest.java
index df779e1..5ac58c9 100644
--- a/core/src/test/java/brooklyn/policy/basic/BasicPolicyTest.java
+++ b/core/src/test/java/brooklyn/policy/basic/BasicPolicyTest.java
@@ -23,13 +23,13 @@ import static org.testng.Assert.assertEquals;
import java.util.Map;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.testng.annotations.Test;
import brooklyn.config.ConfigKey;
import brooklyn.entity.BrooklynAppUnitTestSupport;
import brooklyn.event.basic.BasicConfigKey;
import brooklyn.util.collections.MutableSet;
-import brooklyn.util.flags.SetFromFlag;
/**
* Test that policy can be created and accessed, by construction and by spec
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/qa/longevity/EntityCleanupLongevityTestFixture.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/qa/longevity/EntityCleanupLongevityTestFixture.java b/core/src/test/java/brooklyn/qa/longevity/EntityCleanupLongevityTestFixture.java
index 85eaf3d..790bfe1 100644
--- a/core/src/test/java/brooklyn/qa/longevity/EntityCleanupLongevityTestFixture.java
+++ b/core/src/test/java/brooklyn/qa/longevity/EntityCleanupLongevityTestFixture.java
@@ -29,6 +29,8 @@ import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.core.management.internal.AbstractManagementContext;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.util.task.BasicExecutionManager;
+import org.apache.brooklyn.core.util.task.TaskScheduler;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestEntity;
@@ -46,8 +48,6 @@ import brooklyn.internal.storage.impl.BrooklynStorageImpl;
import org.apache.brooklyn.location.basic.SimulatedLocation;
-import brooklyn.util.task.BasicExecutionManager;
-import brooklyn.util.task.TaskScheduler;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Time;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/qa/performance/FilePersistencePerformanceTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/qa/performance/FilePersistencePerformanceTest.java b/core/src/test/java/brooklyn/qa/performance/FilePersistencePerformanceTest.java
index 098648d..0b35670 100644
--- a/core/src/test/java/brooklyn/qa/performance/FilePersistencePerformanceTest.java
+++ b/core/src/test/java/brooklyn/qa/performance/FilePersistencePerformanceTest.java
@@ -23,6 +23,7 @@ import java.io.IOException;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.brooklyn.core.util.internal.ssh.process.ProcessTool;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
@@ -31,7 +32,6 @@ import brooklyn.entity.rebind.persister.FileBasedStoreObjectAccessor;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.internal.ssh.process.ProcessTool;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableList;
[23/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/BasicTask.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/BasicTask.java b/core/src/main/java/org/apache/brooklyn/core/util/task/BasicTask.java
new file mode 100644
index 0000000..c776e4d
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/BasicTask.java
@@ -0,0 +1,892 @@
+/*
+ * 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.util.task;
+
+import static brooklyn.util.JavaGroovyEquivalents.asString;
+import static brooklyn.util.JavaGroovyEquivalents.elvisString;
+import groovy.lang.Closure;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.management.LockInfo;
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.brooklyn.api.management.HasTaskChildren;
+import org.apache.brooklyn.api.management.Task;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.util.GroovyJavaMethods;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.guava.Maybe;
+import brooklyn.util.text.Identifiers;
+import brooklyn.util.text.Strings;
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Time;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.base.Throwables;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
+import com.google.common.util.concurrent.Callables;
+import com.google.common.util.concurrent.ExecutionList;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * The basic concrete implementation of a {@link Task} to be executed.
+ *
+ * A {@link Task} is a wrapper for an executable unit, such as a {@link Closure} or a {@link Runnable} or
+ * {@link Callable} and will run in its own {@link Thread}.
+ * <p>
+ * The task can be given an optional displayName and description in its constructor (as named
+ * arguments in the first {@link Map} parameter). It is guaranteed to have {@link Object#notify()} called
+ * once whenever the task starts running and once again when the task is about to complete. Due to
+ * the way executors work it is ugly to guarantee notification <em>after</em> completion, so instead we
+ * notify just before then expect the user to call {@link #get()} - which will throw errors if the underlying job
+ * did so - or {@link #blockUntilEnded()} which will not throw errors.
+ */
+public class BasicTask<T> implements TaskInternal<T> {
+ private static final Logger log = LoggerFactory.getLogger(BasicTask.class);
+
+ private String id = Identifiers.makeRandomId(8);
+ protected Callable<T> job;
+ public final String displayName;
+ public final String description;
+
+ protected final Set<Object> tags = Sets.newConcurrentHashSet();
+ // for debugging, to record where tasks were created
+// { tags.add(new Throwable("Creation stack trace")); }
+
+ protected Task<?> proxyTargetTask = null;
+
+ protected String blockingDetails = null;
+ protected Task<?> blockingTask = null;
+ Object extraStatusText = null;
+
+ /** listeners attached at task level; these are stored here, but run on the underlying ListenableFuture */
+ protected final ExecutionList listeners = new ExecutionList();
+
+ /**
+ * Constructor needed to prevent confusion in groovy stubs when looking for default constructor,
+ *
+ * The generics on {@link Closure} break it if that is first constructor.
+ */
+ protected BasicTask() { this(Collections.emptyMap()); }
+ protected BasicTask(Map<?,?> flags) { this(flags, (Callable<T>) null); }
+
+ public BasicTask(Callable<T> job) { this(Collections.emptyMap(), job); }
+
+ public BasicTask(Map<?,?> flags, Callable<T> job) {
+ this.job = job;
+
+ if (flags.containsKey("tag")) tags.add(flags.remove("tag"));
+ Object ftags = flags.remove("tags");
+ if (ftags!=null) {
+ if (ftags instanceof Iterable) Iterables.addAll(tags, (Iterable<?>)ftags);
+ else {
+ log.info("deprecated use of non-collection argument for 'tags' ("+ftags+") in "+this, new Throwable("trace of discouraged use of non-colleciton tags argument"));
+ tags.add(ftags);
+ }
+ }
+
+ description = elvisString(flags.remove("description"), "");
+ String d = asString(flags.remove("displayName"));
+ displayName = (d==null ? "" : d);
+ }
+
+ public BasicTask(Runnable job) { this(GroovyJavaMethods.<T>callableFromRunnable(job)); }
+ public BasicTask(Map<?,?> flags, Runnable job) { this(flags, GroovyJavaMethods.<T>callableFromRunnable(job)); }
+ public BasicTask(Closure<T> job) { this(GroovyJavaMethods.callableFromClosure(job)); }
+ public BasicTask(Map<?,?> flags, Closure<T> job) { this(flags, GroovyJavaMethods.callableFromClosure(job)); }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(id);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof Task)
+ return ((Task<?>)obj).getId().equals(getId());
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ // give display name plus id, or job and tags plus id; some jobs have been extended to include nice tostrings
+ return "Task["+
+ (Strings.isNonEmpty(displayName) ?
+ displayName :
+ (job + (tags!=null && !tags.isEmpty() ? ";"+tags : "")) ) +
+ ":"+getId()+"]";
+ }
+
+ @Override
+ public Task<T> asTask() {
+ return this;
+ }
+
+ // housekeeping --------------------
+
+ /*
+ * These flags are set by BasicExecutionManager.submit.
+ *
+ * Order is guaranteed to be as shown below, in order of #. Within each # line it is currently in the order specified by commas but this is not guaranteed.
+ * (The spaces between the # section indicate longer delays / logical separation ... it should be clear!)
+ *
+ * # submitter, submit time set, tags and other submit-time fields set
+ *
+ * # thread set, ThreadLocal getCurrentTask set
+ * # start time set, isBegun is true
+ * # task end callback run, if supplied
+ *
+ * # task runs
+ *
+ * # task end callback run, if supplied
+ * # end time set
+ * # thread cleared, ThreadLocal getCurrentTask set
+ * # Task.notifyAll()
+ * # Task.get() (result.get()) available, Task.isDone is true
+ *
+ * Few _consumers_ should care, but internally we rely on this so that, for example, status is displayed correctly.
+ * Tests should catch most things, but be careful if you change any of the above semantics.
+ */
+
+ protected long queuedTimeUtc = -1;
+ protected long submitTimeUtc = -1;
+ protected long startTimeUtc = -1;
+ protected long endTimeUtc = -1;
+ protected Maybe<Task<?>> submittedByTask;
+
+ protected volatile Thread thread = null;
+ private volatile boolean cancelled = false;
+ /** normally a {@link ListenableFuture}, except for scheduled tasks when it may be a {@link ScheduledFuture} */
+ protected volatile Future<T> internalFuture = null;
+
+ @Override
+ public synchronized void initInternalFuture(ListenableFuture<T> result) {
+ if (this.internalFuture != null)
+ throw new IllegalStateException("task "+this+" is being given a result twice");
+ this.internalFuture = result;
+ notifyAll();
+ }
+
+ // metadata accessors ------------
+
+ @Override
+ public Set<Object> getTags() { return Collections.unmodifiableSet(new LinkedHashSet<Object>(tags)); }
+
+ /** if the job is queued for submission (e.g. by another task) it can indicate that fact (and time) here;
+ * note tasks can (and often are) submitted without any queueing, in which case this value may be -1 */
+ @Override
+ public long getQueuedTimeUtc() { return queuedTimeUtc; }
+
+ @Override
+ public long getSubmitTimeUtc() { return submitTimeUtc; }
+
+ @Override
+ public long getStartTimeUtc() { return startTimeUtc; }
+
+ @Override
+ public long getEndTimeUtc() { return endTimeUtc; }
+
+ @Override
+ public Future<T> getInternalFuture() { return internalFuture; }
+
+ @Override
+ public Task<?> getSubmittedByTask() {
+ if (submittedByTask==null) return null;
+ return submittedByTask.orNull();
+ }
+
+ /** the thread where the task is running, if it is running */
+ @Override
+ public Thread getThread() { return thread; }
+
+ // basic fields --------------------
+
+ @Override
+ public boolean isQueued() {
+ return (queuedTimeUtc >= 0);
+ }
+
+ @Override
+ public boolean isQueuedOrSubmitted() {
+ return isQueued() || isSubmitted();
+ }
+
+ @Override
+ public boolean isQueuedAndNotSubmitted() {
+ return isQueued() && (!isSubmitted());
+ }
+
+ @Override
+ public boolean isSubmitted() {
+ return submitTimeUtc >= 0;
+ }
+
+ @Override
+ public boolean isBegun() {
+ return startTimeUtc >= 0;
+ }
+
+ /** marks the task as queued for execution */
+ @Override
+ public void markQueued() {
+ if (queuedTimeUtc<0)
+ queuedTimeUtc = System.currentTimeMillis();
+ }
+
+ @Override
+ public final synchronized boolean cancel() { return cancel(true); }
+
+ /** doesn't resume it, just means if something was cancelled but not submitted it could now be submitted;
+ * probably going to be removed and perhaps some mechanism for running again made available
+ * @since 0.7.0 */
+ @Beta
+ public synchronized boolean uncancel() {
+ boolean wasCancelled = cancelled;
+ cancelled = false;
+ return wasCancelled;
+ }
+
+ @Override
+ public synchronized boolean cancel(boolean mayInterruptIfRunning) {
+ if (isDone()) return false;
+ boolean cancel = true;
+ cancelled = true;
+ if (internalFuture!=null) {
+ cancel = internalFuture.cancel(mayInterruptIfRunning);
+ }
+ notifyAll();
+ return cancel;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return cancelled || (internalFuture!=null && internalFuture.isCancelled());
+ }
+
+ @Override
+ public boolean isDone() {
+ // if endTime is set, result might not be completed yet, but it will be set very soon
+ // (the two values are set close in time, result right after the endTime;
+ // but callback hooks might not see the result yet)
+ return cancelled || (internalFuture!=null && internalFuture.isDone()) || endTimeUtc>0;
+ }
+
+ /**
+ * Returns true if the task has had an error.
+ *
+ * Only true if calling {@link #get()} will throw an exception when it completes (including cancel).
+ * Implementations may set this true before completion if they have that insight, or
+ * (the default) they may compute it lazily after completion (returning false before completion).
+ */
+ @Override
+ public boolean isError() {
+ if (!isDone()) return false;
+ if (isCancelled()) return true;
+ try {
+ get();
+ return false;
+ } catch (Throwable t) {
+ return true;
+ }
+ }
+
+ // future value --------------------
+
+ @Override
+ public T get() throws InterruptedException, ExecutionException {
+ try {
+ if (!isDone())
+ Tasks.setBlockingTask(this);
+ blockUntilStarted();
+ return internalFuture.get();
+ } finally {
+ Tasks.resetBlockingTask();
+ }
+ }
+
+ @Override
+ public T getUnchecked() {
+ try {
+ return get();
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ @Override
+ public synchronized void blockUntilStarted() {
+ blockUntilStarted(null);
+ }
+
+ @Override
+ public synchronized boolean blockUntilStarted(Duration timeout) {
+ Long endTime = timeout==null ? null : System.currentTimeMillis() + timeout.toMillisecondsRoundingUp();
+ while (true) {
+ if (cancelled) throw new CancellationException();
+ if (internalFuture==null)
+ try {
+ if (timeout==null) {
+ wait();
+ } else {
+ long remaining = endTime - System.currentTimeMillis();
+ if (remaining>0)
+ wait(remaining);
+ else
+ return false;
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ Throwables.propagate(e);
+ }
+ if (internalFuture!=null) return true;
+ }
+ }
+
+ @Override
+ public void blockUntilEnded() {
+ blockUntilEnded(null);
+ }
+
+ @Override
+ public boolean blockUntilEnded(Duration timeout) {
+ Long endTime = timeout==null ? null : System.currentTimeMillis() + timeout.toMillisecondsRoundingUp();
+ try {
+ boolean started = blockUntilStarted(timeout);
+ if (!started) return false;
+ if (timeout==null) {
+ internalFuture.get();
+ } else {
+ long remaining = endTime - System.currentTimeMillis();
+ if (remaining>0)
+ internalFuture.get(remaining, TimeUnit.MILLISECONDS);
+ }
+ return isDone();
+ } catch (Throwable t) {
+ Exceptions.propagateIfFatal(t);
+ if (!(t instanceof TimeoutException) && log.isDebugEnabled())
+ log.debug("call from "+Thread.currentThread()+", blocking until '"+this+"' finishes, ended with error: "+t);
+ return isDone();
+ }
+ }
+
+ @Override
+ public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
+ return get(new Duration(timeout, unit));
+ }
+
+ @Override
+ public T get(Duration duration) throws InterruptedException, ExecutionException, TimeoutException {
+ long start = System.currentTimeMillis();
+ Long end = duration==null ? null : start + duration.toMillisecondsRoundingUp();
+ while (end==null || end > System.currentTimeMillis()) {
+ if (cancelled) throw new CancellationException();
+ if (internalFuture == null) {
+ synchronized (this) {
+ long remaining = end - System.currentTimeMillis();
+ if (internalFuture==null && remaining>0)
+ wait(remaining);
+ }
+ }
+ if (internalFuture != null) break;
+ }
+ Long remaining = end==null ? null : end - System.currentTimeMillis();
+ if (isDone()) {
+ return internalFuture.get(1, TimeUnit.MILLISECONDS);
+ } else if (remaining == null) {
+ return internalFuture.get();
+ } else if (remaining > 0) {
+ return internalFuture.get(remaining, TimeUnit.MILLISECONDS);
+ } else {
+ throw new TimeoutException();
+ }
+ }
+
+ @Override
+ public T getUnchecked(Duration duration) {
+ try {
+ return get(duration);
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ // ------------------ status ---------------------------
+
+ /**
+ * Returns a brief status string
+ *
+ * Plain-text format. Reported status if there is one, otherwise state which will be one of:
+ * <ul>
+ * <li>Not submitted
+ * <li>Submitted for execution
+ * <li>Ended by error
+ * <li>Ended by cancellation
+ * <li>Ended normally
+ * <li>Running
+ * <li>Waiting
+ * </ul>
+ */
+ @Override
+ public String getStatusSummary() {
+ return getStatusString(0);
+ }
+
+ /**
+ * Returns detailed status, suitable for a hover
+ *
+ * Plain-text format, with new-lines (and sometimes extra info) if multiline enabled.
+ */
+ @Override
+ public String getStatusDetail(boolean multiline) {
+ return getStatusString(multiline?2:1);
+ }
+
+ /**
+ * This method is useful for callers to see the status of a task.
+ *
+ * Also for developers to see best practices for examining status fields etc
+ *
+ * @param verbosity 0 = brief, 1 = one-line with some detail, 2 = lots of detail
+ */
+ protected String getStatusString(int verbosity) {
+// Thread t = getThread();
+ String rv;
+ if (submitTimeUtc <= 0) rv = "Not submitted";
+ else if (!isCancelled() && startTimeUtc <= 0) {
+ rv = "Submitted for execution";
+ if (verbosity>0) {
+ long elapsed = System.currentTimeMillis() - submitTimeUtc;
+ rv += " "+Time.makeTimeStringRoundedSince(elapsed)+" ago";
+ }
+ if (verbosity >= 2 && getExtraStatusText()!=null) {
+ rv += "\n\n"+getExtraStatusText();
+ }
+ } else if (isDone()) {
+ long elapsed = endTimeUtc - submitTimeUtc;
+ String duration = Time.makeTimeStringRounded(elapsed);
+ if (isCancelled()) {
+ rv = "Cancelled";
+ if (verbosity >= 1) rv+=" after "+duration;
+
+ if (verbosity >= 2 && getExtraStatusText()!=null) {
+ rv += "\n\n"+getExtraStatusText();
+ }
+ } else if (isError()) {
+ rv = "Failed";
+ if (verbosity >= 1) {
+ rv += " after "+duration;
+ Throwable error = Tasks.getError(this);
+
+ if (verbosity >= 2 && getExtraStatusText()!=null) {
+ rv += "\n\n"+getExtraStatusText();
+ }
+
+ //remove outer ExecException which is reported by the get(), we want the exception the task threw
+ while (error instanceof ExecutionException) error = error.getCause();
+ String errorMessage = Exceptions.collapseText(error);
+
+ if (verbosity == 1) rv += ": "+abbreviate(errorMessage);
+ if (verbosity >= 2) {
+ rv += ": "+errorMessage;
+ StringWriter sw = new StringWriter();
+ ((Throwable)error).printStackTrace(new PrintWriter(sw));
+ rv += "\n\n"+sw.getBuffer();
+ }
+ }
+ } else {
+ rv = "Completed";
+ if (verbosity>=1) {
+ if (verbosity==1) {
+ try {
+ Object v = get();
+ rv += ", " +(v==null ? "no return value (null)" : "result: "+abbreviate(v.toString()));
+ } catch (Exception e) {
+ rv += ", but error accessing result ["+e+"]"; //shouldn't happen
+ }
+ } else {
+ rv += " after "+duration;
+ try {
+ Object v = get();
+ rv += "\n\n" + (v==null ? "No return value (null)" : "Result: "+v);
+ } catch (Exception e) {
+ rv += " at first\n" +
+ "Error accessing result ["+e+"]"; //shouldn't happen
+ }
+ if (verbosity >= 2 && getExtraStatusText()!=null) {
+ rv += "\n\n"+getExtraStatusText();
+ }
+ }
+ }
+ }
+ } else {
+ rv = getActiveTaskStatusString(verbosity);
+ }
+ return rv;
+ }
+
+ private static String abbreviate(String s) {
+ s = Strings.getFirstLine(s);
+ if (s.length()>255) s = s.substring(0, 252)+ "...";
+ return s;
+ }
+
+ protected String getActiveTaskStatusString(int verbosity) {
+ String rv = "";
+ Thread t = getThread();
+
+ // Normally, it's not possible for thread==null as we were started and not ended
+
+ // However, there is a race where the task starts sand completes between the calls to getThread()
+ // at the start of the method and this call to getThread(), so both return null even though
+ // the intermediate checks returned started==true isDone()==false.
+ if (t == null) {
+ if (isDone()) {
+ return getStatusString(verbosity);
+ } else {
+ //should only happen for repeating task which is not active
+ return "Sleeping";
+ }
+ }
+
+ ThreadInfo ti = ManagementFactory.getThreadMXBean().getThreadInfo(t.getId(), (verbosity<=0 ? 0 : verbosity==1 ? 1 : Integer.MAX_VALUE));
+ if (getThread()==null)
+ //thread might have moved on to a new task; if so, recompute (it should now say "done")
+ return getStatusString(verbosity);
+
+ if (verbosity >= 1 && Strings.isNonBlank(blockingDetails)) {
+ if (verbosity==1)
+ // short status string will just show blocking details
+ return blockingDetails;
+ //otherwise show the blocking details, then a new line, then additional information
+ rv = blockingDetails + "\n\n";
+ }
+
+ if (verbosity >= 1 && blockingTask!=null) {
+ if (verbosity==1)
+ // short status string will just show blocking details
+ return "Waiting on "+blockingTask;
+ //otherwise show the blocking details, then a new line, then additional information
+ rv = "Waiting on "+blockingTask + "\n\n";
+ }
+
+ if (verbosity>=2) {
+ if (getExtraStatusText()!=null) {
+ rv += getExtraStatusText()+"\n\n";
+ }
+
+ rv += ""+toString()+"\n";
+ if (submittedByTask!=null) {
+ rv += "Submitted by "+submittedByTask+"\n";
+ }
+
+ if (this instanceof HasTaskChildren) {
+ // list children tasks for compound tasks
+ try {
+ Iterable<Task<?>> childrenTasks = ((HasTaskChildren)this).getChildren();
+ if (childrenTasks.iterator().hasNext()) {
+ rv += "Children:\n";
+ for (Task<?> child: childrenTasks) {
+ rv += " "+child+": "+child.getStatusDetail(false)+"\n";
+ }
+ }
+ } catch (ConcurrentModificationException exc) {
+ rv += " (children not available - currently being modified)\n";
+ }
+ }
+ rv += "\n";
+ }
+
+ LockInfo lock = ti.getLockInfo();
+ rv += "In progress";
+ if (verbosity>=1) {
+ if (lock==null && ti.getThreadState()==Thread.State.RUNNABLE) {
+ //not blocked
+ if (ti.isSuspended()) {
+ // when does this happen?
+ rv += ", thread suspended";
+ } else {
+ if (verbosity >= 2) rv += " ("+ti.getThreadState()+")";
+ }
+ } else {
+ rv +=", thread waiting ";
+ if (ti.getThreadState() == Thread.State.BLOCKED) {
+ rv += "(mutex) on "+lookup(lock);
+ //TODO could say who holds it
+ } else if (ti.getThreadState() == Thread.State.WAITING) {
+ rv += "(notify) on "+lookup(lock);
+ } else if (ti.getThreadState() == Thread.State.TIMED_WAITING) {
+ rv += "(timed) on "+lookup(lock);
+ } else {
+ rv = "("+ti.getThreadState()+") on "+lookup(lock);
+ }
+ }
+ }
+ if (verbosity>=2) {
+ StackTraceElement[] st = ti.getStackTrace();
+ st = brooklyn.util.javalang.StackTraceSimplifier.cleanStackTrace(st);
+ if (st!=null && st.length>0)
+ rv += "\n" +"At: "+st[0];
+ for (int ii=1; ii<st.length; ii++) {
+ rv += "\n" +" "+st[ii];
+ }
+ }
+ return rv;
+ }
+
+ protected String lookup(LockInfo info) {
+ return info!=null ? ""+info : "unknown (sleep)";
+ }
+
+ @Override
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+
+ /** allows a task user to specify why a task is blocked; for use immediately before a blocking/wait,
+ * and typically cleared immediately afterwards; referenced by management api to inspect a task
+ * which is blocking
+ */
+ @Override
+ public String setBlockingDetails(String blockingDetails) {
+ String old = this.blockingDetails;
+ this.blockingDetails = blockingDetails;
+ return old;
+ }
+
+ @Override
+ public Task<?> setBlockingTask(Task<?> blockingTask) {
+ Task<?> old = this.blockingTask;
+ this.blockingTask = blockingTask;
+ return old;
+ }
+
+ @Override
+ public void resetBlockingDetails() {
+ this.blockingDetails = null;
+ }
+
+ @Override
+ public void resetBlockingTask() {
+ this.blockingTask = null;
+ }
+
+ /** returns a textual message giving details while the task is blocked */
+ @Override
+ public String getBlockingDetails() {
+ return blockingDetails;
+ }
+
+ /** returns a task that this task is blocked on */
+ @Override
+ public Task<?> getBlockingTask() {
+ return blockingTask;
+ }
+
+ @Override
+ public void setExtraStatusText(Object extraStatus) {
+ this.extraStatusText = extraStatus;
+ }
+
+ @Override
+ public Object getExtraStatusText() {
+ return extraStatusText;
+ }
+
+ // ---- add a way to warn if task is not run
+
+ public interface TaskFinalizer {
+ public void onTaskFinalization(Task<?> t);
+ }
+
+ public static final TaskFinalizer WARN_IF_NOT_RUN = new TaskFinalizer() {
+ @Override
+ public void onTaskFinalization(Task<?> t) {
+ if (!Tasks.isAncestorCancelled(t) && !t.isSubmitted()) {
+ log.warn(t+" was never submitted; did the code create it and forget to run it? ('cancel' the task to suppress this message)");
+ log.debug("Detail of unsubmitted task "+t+":\n"+t.getStatusDetail(true));
+ return;
+ }
+ if (!t.isDone()) {
+ // shouldn't happen
+ // TODO But does happen if management context was terminated (e.g. running test suite).
+ // Should check if Execution Manager is running, and only log if it was not terminated?
+ log.warn("Task "+t+" is being finalized before completion");
+ return;
+ }
+ }
+ };
+
+ public static final TaskFinalizer NO_OP = new TaskFinalizer() {
+ @Override
+ public void onTaskFinalization(Task<?> t) {
+ }
+ };
+
+ public void ignoreIfNotRun() {
+ setFinalizer(NO_OP);
+ }
+
+ public void setFinalizer(TaskFinalizer f) {
+ TaskFinalizer finalizer = Tasks.tag(this, TaskFinalizer.class, false);
+ if (finalizer!=null && finalizer!=f)
+ throw new IllegalStateException("Cannot apply multiple finalizers");
+ if (isDone())
+ throw new IllegalStateException("Finalizer cannot be set on task "+this+" after it is finished");
+ tags.add(f);
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ TaskFinalizer finalizer = Tasks.tag(this, TaskFinalizer.class, false);
+ if (finalizer==null) finalizer = WARN_IF_NOT_RUN;
+ finalizer.onTaskFinalization(this);
+ }
+
+ public static class SubmissionErrorCatchingExecutor implements Executor {
+ final Executor target;
+ public SubmissionErrorCatchingExecutor(Executor target) {
+ this.target = target;
+ }
+ @Override
+ public void execute(Runnable command) {
+ if (isShutdown()) {
+ log.debug("Skipping execution of task callback hook "+command+" because executor is shutdown.");
+ return;
+ }
+ try {
+ target.execute(command);
+ } catch (Exception e) {
+ if (isShutdown()) {
+ log.debug("Ignoring failed execution of task callback hook "+command+" because executor is shutdown.");
+ } else {
+ log.warn("Execution of task callback hook "+command+" failed: "+e, e);
+ }
+ }
+ }
+ protected boolean isShutdown() {
+ return target instanceof ExecutorService && ((ExecutorService)target).isShutdown();
+ }
+ }
+
+ @Override
+ public void addListener(Runnable listener, Executor executor) {
+ listeners.add(listener, new SubmissionErrorCatchingExecutor(executor));
+ }
+
+ @Override
+ public void runListeners() {
+ listeners.execute();
+ }
+
+ @Override
+ public void setEndTimeUtc(long val) {
+ endTimeUtc = val;
+ }
+
+ @Override
+ public void setThread(Thread thread) {
+ this.thread = thread;
+ }
+
+ @Override
+ public Callable<T> getJob() {
+ return job;
+ }
+
+ @Override
+ public void setJob(Callable<T> job) {
+ this.job = job;
+ }
+
+ @Override
+ public ExecutionList getListeners() {
+ return listeners;
+ }
+
+ @Override
+ public void setSubmitTimeUtc(long val) {
+ submitTimeUtc = val;
+ }
+
+ private static <T> Task<T> newGoneTaskFor(Task<?> task) {
+ Task<T> t = Tasks.<T>builder().dynamic(false).name(task.getDisplayName())
+ .description("Details of the original task "+task+" have been forgotten.")
+ .body(Callables.returning((T)null)).build();
+ ((BasicTask<T>)t).ignoreIfNotRun();
+ return t;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Override
+ public void setSubmittedByTask(Task<?> task) {
+ submittedByTask = (Maybe)Maybe.softThen((Task)task, (Maybe)Maybe.of(BasicTask.newGoneTaskFor(task)));
+ }
+
+ @Override
+ public Set<Object> getMutableTags() {
+ return tags;
+ }
+
+ @Override
+ public void setStartTimeUtc(long val) {
+ startTimeUtc = val;
+ }
+
+ @Override
+ public void applyTagModifier(Function<Set<Object>,Void> modifier) {
+ modifier.apply(tags);
+ }
+
+ @Override
+ public Task<?> getProxyTarget() {
+ return proxyTargetTask;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/CanSetName.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/CanSetName.java b/core/src/main/java/org/apache/brooklyn/core/util/task/CanSetName.java
new file mode 100644
index 0000000..407a93a
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/CanSetName.java
@@ -0,0 +1,25 @@
+/*
+ * 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.util.task;
+
+public interface CanSetName {
+
+ void setName(String name);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/CompoundTask.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/CompoundTask.java b/core/src/main/java/org/apache/brooklyn/core/util/task/CompoundTask.java
new file mode 100644
index 0000000..8fdb146
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/CompoundTask.java
@@ -0,0 +1,131 @@
+/*
+ * 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.util.task;
+
+import groovy.lang.Closure;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+
+import org.apache.brooklyn.api.management.HasTaskChildren;
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.api.management.TaskAdaptable;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.entity.basic.BrooklynTaskTags;
+import brooklyn.util.collections.MutableMap;
+
+
+/**
+ * A {@link Task} that is comprised of other units of work: possibly a heterogeneous mix of {@link Task},
+ * {@link Runnable}, {@link Callable} and {@link Closure} instances.
+ *
+ * This class holds the collection of child tasks, but subclasses have the responsibility of executing them in a
+ * sensible manner by implementing the abstract {@link #runJobs} method.
+ */
+public abstract class CompoundTask<T> extends BasicTask<List<T>> implements HasTaskChildren {
+
+ @SuppressWarnings("unused")
+ private static final Logger log = LoggerFactory.getLogger(CompoundTask.class);
+
+ protected final List<Task<? extends T>> children;
+ protected final List<Object> result;
+
+ /**
+ * Constructs a new compound task containing the specified units of work.
+ *
+ * @param jobs A potentially heterogeneous mixture of {@link Runnable}, {@link Callable}, {@link Closure} and {@link Task} can be provided.
+ * @throws IllegalArgumentException if any of the passed child jobs is not one of the above types
+ */
+ public CompoundTask(Object... jobs) {
+ this( Arrays.asList(jobs) );
+ }
+
+ /**
+ * Constructs a new compound task containing the specified units of work.
+ *
+ * @param jobs A potentially heterogeneous mixture of {@link Runnable}, {@link Callable}, {@link Closure} and {@link Task} can be provided.
+ * @throws IllegalArgumentException if any of the passed child jobs is not one of the above types
+ */
+ public CompoundTask(Collection<?> jobs) {
+ this(MutableMap.of("tag", "compound"), jobs);
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public CompoundTask(Map<String,?> flags, Collection<?> jobs) {
+ super(flags);
+ super.job = new Callable<List<T>>() {
+ @Override public List<T> call() throws Exception {
+ return runJobs();
+ }
+ };
+
+ this.result = new ArrayList<Object>(jobs.size());
+ this.children = new ArrayList<Task<? extends T>>(jobs.size());
+ for (Object job : jobs) {
+ Task subtask;
+ if (job instanceof TaskAdaptable) { subtask = ((TaskAdaptable)job).asTask(); }
+ else if (job instanceof Closure) { subtask = new BasicTask<T>((Closure) job); }
+ else if (job instanceof Callable) { subtask = new BasicTask<T>((Callable) job); }
+ else if (job instanceof Runnable) { subtask = new BasicTask<T>((Runnable) job); }
+
+ else throw new IllegalArgumentException("Invalid child "+(job == null ? null : job.getClass() + " ("+job+")")+
+ " passed to compound task; must be Runnable, Callable, Closure or Task");
+
+ BrooklynTaskTags.addTagDynamically(subtask, ManagementContextInternal.SUB_TASK_TAG);
+ children.add(subtask);
+ }
+
+ for (Task<?> t: getChildren()) {
+ ((TaskInternal<?>)t).markQueued();
+ }
+ }
+
+ /** return value needs to be specified by subclass; subclass should also setBlockingDetails
+ * @throws ExecutionException
+ * @throws InterruptedException */
+ protected abstract List<T> runJobs() throws InterruptedException, ExecutionException;
+
+ protected void submitIfNecessary(TaskAdaptable<?> task) {
+ if (!task.asTask().isSubmitted()) {
+ if (BasicExecutionContext.getCurrentExecutionContext() == null) {
+ throw new IllegalStateException("Compound task ("+task+") launched from "+this+" missing required execution context");
+ } else {
+ BasicExecutionContext.getCurrentExecutionContext().submit(task);
+ }
+ }
+ }
+
+ public List<Task<? extends T>> getChildrenTyped() {
+ return children;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public List<Task<?>> getChildren() {
+ return (List) getChildrenTyped();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/DeferredSupplier.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/DeferredSupplier.java b/core/src/main/java/org/apache/brooklyn/core/util/task/DeferredSupplier.java
new file mode 100644
index 0000000..ad9416b
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/DeferredSupplier.java
@@ -0,0 +1,38 @@
+/*
+ * 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.util.task;
+
+import com.google.common.base.Supplier;
+
+/**
+ * A class that supplies objects of a single type. When used as a ConfigKey value,
+ * the evaluation is deferred until getConfig() is called. The returned value will then
+ * be coerced to the correct type.
+ *
+ * Subsequent calls to getConfig will result in further calls to deferredProvider.get(),
+ * rather than reusing the result. If you want to reuse the result, consider instead
+ * using a Future.
+ *
+ * Note that this functionality replaces the ues of Closure in brooklyn 0.4.0, which
+ * served the same purpose.
+ */
+public interface DeferredSupplier<T> extends Supplier<T> {
+ @Override
+ T get();
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/DynamicSequentialTask.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/DynamicSequentialTask.java b/core/src/main/java/org/apache/brooklyn/core/util/task/DynamicSequentialTask.java
new file mode 100644
index 0000000..e197705
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/DynamicSequentialTask.java
@@ -0,0 +1,480 @@
+/*
+ * 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.util.task;
+
+import groovy.lang.Closure;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+import org.apache.brooklyn.api.management.HasTaskChildren;
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.api.management.TaskQueueingContext;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.entity.basic.BrooklynTaskTags;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.time.CountdownTimer;
+import brooklyn.util.time.Duration;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableList;
+
+/** Represents a task whose run() method can create other tasks
+ * which are run sequentially, but that sequence runs in parallel to this task
+ * <p>
+ * There is an optional primary job run with this task, along with multiple secondary children.
+ * If any secondary task fails (assuming it isn't {@link Tasks#markInessential()} then by default
+ * subsequent tasks are not submitted and the primary task fails (but no tasks are cancelled or interrupted).
+ * You can change the behavior of this task with fields in {@link FailureHandlingConfig},
+ * or the convenience {@link TaskQueueingContext#swallowChildrenFailures()}
+ * (and {@link DynamicTasks#swallowChildrenFailures()} if you are inside the task).
+ * <p>
+ * This synchronizes on secondary tasks when submitting them, in case they may be manually submitted
+ * and the submitter wishes to ensure it is only submitted once.
+ * <p>
+ * Improvements which would be nice to have:
+ * <li> unqueued tasks not visible in api; would like that
+ * <li> uses an extra thread (submitted as background task) to monitor the secondary jobs; would be nice to remove this,
+ * and rely on {@link BasicExecutionManager} to run the jobs sequentially (combined with fix to item above)
+ * <li> would be nice to have cancel, resume, and possibly skipQueue available as operations (ideally in the REST API and GUI)
+ **/
+public class DynamicSequentialTask<T> extends BasicTask<T> implements HasTaskChildren, TaskQueueingContext {
+
+ private static final Logger log = LoggerFactory.getLogger(CompoundTask.class);
+
+ protected final Queue<Task<?>> secondaryJobsAll = new ConcurrentLinkedQueue<Task<?>>();
+ protected final Queue<Task<?>> secondaryJobsRemaining = new ConcurrentLinkedQueue<Task<?>>();
+ protected final Object jobTransitionLock = new Object();
+ protected volatile boolean primaryStarted = false;
+ protected volatile boolean primaryFinished = false;
+ protected volatile boolean secondaryQueueAborted = false;
+ protected Thread primaryThread;
+ protected DstJob dstJob;
+ protected FailureHandlingConfig failureHandlingConfig = FailureHandlingConfig.DEFAULT;
+
+ // default values for how to handle the various failures
+ @Beta
+ public static class FailureHandlingConfig {
+ /** secondary queue runs independently of primary task (submitting and blocking on each secondary task in order),
+ * but can set it up not to submit any more tasks if the primary fails */
+ public final boolean abortSecondaryQueueOnPrimaryFailure;
+ /** as {@link #abortSecondaryQueueOnPrimaryFailure} but controls cancelling of secondary queue*/
+ public final boolean cancelSecondariesOnPrimaryFailure;
+ /** secondary queue can continue submitting+blocking tasks even if a secondary task fails (unusual;
+ * typically handled by {@link TaskTags#markInessential(Task)} on the secondary tasks, in which case
+ * the secondary queue is never aborted */
+ public final boolean abortSecondaryQueueOnSecondaryFailure;
+ /** unsubmitted secondary tasks (ie those further in the queue) can be cancelled if a secondary task fails */
+ public final boolean cancelSecondariesOnSecondaryFailure;
+ /** whether to issue cancel against primary task if a secondary task fails */
+ public final boolean cancelPrimaryOnSecondaryFailure;
+ /** whether to fail this task if a secondary task fails */
+ public final boolean failParentOnSecondaryFailure;
+
+ @Beta
+ public FailureHandlingConfig(
+ boolean abortSecondaryQueueOnPrimaryFailure, boolean cancelSecondariesOnPrimaryFailure,
+ boolean abortSecondaryQueueOnSecondaryFailure, boolean cancelSecondariesOnSecondaryFailure,
+ boolean cancelPrimaryOnSecondaryFailure, boolean failParentOnSecondaryFailure) {
+ this.abortSecondaryQueueOnPrimaryFailure = abortSecondaryQueueOnPrimaryFailure;
+ this.cancelSecondariesOnPrimaryFailure = cancelSecondariesOnPrimaryFailure;
+ this.abortSecondaryQueueOnSecondaryFailure = abortSecondaryQueueOnSecondaryFailure;
+ this.cancelSecondariesOnSecondaryFailure = cancelSecondariesOnSecondaryFailure;
+ this.cancelPrimaryOnSecondaryFailure = cancelPrimaryOnSecondaryFailure;
+ this.failParentOnSecondaryFailure = failParentOnSecondaryFailure;
+ }
+
+ public static final FailureHandlingConfig DEFAULT = new FailureHandlingConfig(false, false, true, false, false, true);
+ public static final FailureHandlingConfig SWALLOWING_CHILDREN_FAILURES = new FailureHandlingConfig(false, false, false, false, false, false);
+ }
+
+ public static class QueueAbortedException extends IllegalStateException {
+ private static final long serialVersionUID = -7569362887826818524L;
+
+ public QueueAbortedException(String msg) {
+ super(msg);
+ }
+ public QueueAbortedException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+ }
+
+ /**
+ * Constructs a new compound task containing the specified units of work.
+ *
+ * @param jobs A potentially heterogeneous mixture of {@link Runnable}, {@link Callable}, {@link Closure} and {@link Task} can be provided.
+ * @throws IllegalArgumentException if any of the passed child jobs is not one of the above types
+ */
+ public DynamicSequentialTask() {
+ this(null);
+ }
+
+ public DynamicSequentialTask(Callable<T> mainJob) {
+ this(MutableMap.of("tag", "compound"), mainJob);
+ }
+
+ public DynamicSequentialTask(Map<?,?> flags, Callable<T> mainJob) {
+ super(flags);
+ this.job = dstJob = new DstJob(mainJob);
+ }
+
+ @Override
+ public void queue(Task<?> t) {
+ synchronized (jobTransitionLock) {
+ if (primaryFinished)
+ throw new IllegalStateException("Cannot add a task to "+this+" which is already finished (trying to add "+t+")");
+ if (secondaryQueueAborted)
+ throw new QueueAbortedException("Cannot add a task to "+this+" whose queue has been aborted (trying to add "+t+")");
+ secondaryJobsAll.add(t);
+ secondaryJobsRemaining.add(t);
+ BrooklynTaskTags.addTagsDynamically(t, ManagementContextInternal.SUB_TASK_TAG);
+ ((TaskInternal<?>)t).markQueued();
+ jobTransitionLock.notifyAll();
+ }
+ }
+
+ @Override
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ return cancel(mayInterruptIfRunning, mayInterruptIfRunning, true);
+ }
+ public boolean cancel(boolean mayInterruptTask, boolean interruptPrimaryThread, boolean alsoCancelChildren) {
+ if (isDone()) return false;
+ if (log.isTraceEnabled()) log.trace("cancelling {}", this);
+ boolean cancel = super.cancel(mayInterruptTask);
+ if (alsoCancelChildren) {
+ for (Task<?> t: secondaryJobsAll)
+ cancel |= t.cancel(mayInterruptTask);
+ }
+ synchronized (jobTransitionLock) {
+ if (primaryThread!=null) {
+ if (interruptPrimaryThread) {
+ if (log.isTraceEnabled()) log.trace("cancelling {} - interrupting", this);
+ primaryThread.interrupt();
+ }
+ cancel = true;
+ }
+ }
+ return cancel;
+ }
+
+ @Override
+ public synchronized boolean uncancel() {
+ secondaryQueueAborted = false;
+ return super.uncancel();
+ }
+
+ @Override
+ public Iterable<Task<?>> getChildren() {
+ return Collections.unmodifiableCollection(secondaryJobsAll);
+ }
+
+ /** submits the indicated task for execution in the current execution context, and returns immediately */
+ protected void submitBackgroundInheritingContext(Task<?> task) {
+ BasicExecutionContext ec = BasicExecutionContext.getCurrentExecutionContext();
+ if (log.isTraceEnabled()) {
+ log.trace("task {} - submitting background task {} ({})", new Object[] { Tasks.current(), task, ec });
+ }
+ if (ec==null) {
+ String message = Tasks.current()!=null ?
+ // user forgot ExecContext:
+ "Task "+this+" submitting background task requires an ExecutionContext (an ExecutionManager is not enough): submitting "+task+" in "+Tasks.current()
+ : // should not happen:
+ "Cannot submit tasks inside DST when not in a task : submitting "+task+" in "+this;
+ log.warn(message+" (rethrowing)");
+ throw new IllegalStateException(message);
+ }
+ synchronized (task) {
+ if (task.isSubmitted()) {
+ if (log.isTraceEnabled()) {
+ log.trace("DST "+this+" skipping submission of child "+task+" because it is already submitted");
+ }
+ } else {
+ try {
+ ec.submit(task);
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ // Give some context when the submit fails (happens when the target is already unmanaged)
+ throw new IllegalStateException("Failure submitting task "+task+" in "+this+": "+e.getMessage(), e);
+ }
+ }
+ }
+ }
+
+ public void setFailureHandlingConfig(FailureHandlingConfig failureHandlingConfig) {
+ this.failureHandlingConfig = failureHandlingConfig;
+ }
+ @Override
+ public void swallowChildrenFailures() {
+ setFailureHandlingConfig(FailureHandlingConfig.SWALLOWING_CHILDREN_FAILURES);
+ }
+
+ protected class DstJob implements Callable<T> {
+ protected Callable<T> primaryJob;
+ /** currently executing (or just completed) secondary task, or null if none;
+ * with jobTransitionLock notified on change and completion */
+ protected volatile Task<?> currentSecondary = null;
+ protected volatile boolean finishedSecondaries = false;
+
+ public DstJob(Callable<T> mainJob) {
+ this.primaryJob = mainJob;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public T call() throws Exception {
+
+ synchronized (jobTransitionLock) {
+ primaryStarted = true;
+ primaryThread = Thread.currentThread();
+ for (Task<?> t: secondaryJobsAll)
+ ((TaskInternal<?>)t).markQueued();
+ }
+ // TODO overkill having a thread/task for this, but it works
+ // optimisation would either use newTaskEndCallback property on task to submit
+ // or use some kind of single threaded executor for the queued tasks
+ Task<List<Object>> secondaryJobMaster = Tasks.<List<Object>>builder().dynamic(false)
+ .name("DST manager (internal)")
+ // TODO marking it transient helps it be GC'd sooner,
+ // but ideally we wouldn't have this,
+ // or else it would be a child
+ .tag(BrooklynTaskTags.TRANSIENT_TASK_TAG)
+ .body(new Callable<List<Object>>() {
+
+ @Override
+ public List<Object> call() throws Exception {
+ List<Object> result = new ArrayList<Object>();
+ try {
+ while (!secondaryQueueAborted && (!primaryFinished || !secondaryJobsRemaining.isEmpty())) {
+ synchronized (jobTransitionLock) {
+ if (!primaryFinished && secondaryJobsRemaining.isEmpty()) {
+ currentSecondary = null;
+ jobTransitionLock.wait(1000);
+ }
+ }
+ @SuppressWarnings("rawtypes")
+ Task secondaryJob = secondaryJobsRemaining.poll();
+ if (secondaryJob != null) {
+ synchronized (jobTransitionLock) {
+ currentSecondary = secondaryJob;
+ submitBackgroundInheritingContext(secondaryJob);
+ jobTransitionLock.notifyAll();
+ }
+ try {
+ result.add(secondaryJob.get());
+ } catch (Exception e) {
+ if (TaskTags.isInessential(secondaryJob)) {
+ result.add(Tasks.getError(secondaryJob));
+ if (log.isDebugEnabled())
+ log.debug("Secondary job queue for "+DynamicSequentialTask.this+" ignoring error in inessential task "+secondaryJob+": "+e);
+ } else {
+ if (failureHandlingConfig.cancelSecondariesOnSecondaryFailure) {
+ if (log.isDebugEnabled())
+ log.debug("Secondary job queue for "+DynamicSequentialTask.this+" cancelling "+secondaryJobsRemaining.size()+" remaining, due to error in task "+secondaryJob+": "+e);
+ synchronized (jobTransitionLock) {
+ for (Task<?> t: secondaryJobsRemaining)
+ t.cancel(true);
+ jobTransitionLock.notifyAll();
+ }
+ }
+
+ if (failureHandlingConfig.abortSecondaryQueueOnSecondaryFailure) {
+ if (log.isDebugEnabled())
+ log.debug("Aborting secondary job queue for "+DynamicSequentialTask.this+" due to error in child task "+secondaryJob+" ("+e+", being rethrown)");
+ secondaryQueueAborted = true;
+ throw e;
+ }
+
+ if (!primaryFinished && failureHandlingConfig.cancelPrimaryOnSecondaryFailure) {
+ cancel(true, false, false);
+ }
+
+ result.add(Tasks.getError(secondaryJob));
+ if (log.isDebugEnabled())
+ log.debug("Secondary job queue for "+DynamicSequentialTask.this+" continuing in presence of error in child task "+secondaryJob+" ("+e+", being remembered)");
+ }
+ }
+ }
+ }
+ } finally {
+ synchronized (jobTransitionLock) {
+ currentSecondary = null;
+ finishedSecondaries = true;
+ jobTransitionLock.notifyAll();
+ }
+ }
+ return result;
+ }
+ }).build();
+ ((BasicTask<?>)secondaryJobMaster).proxyTargetTask = DynamicSequentialTask.this;
+
+ submitBackgroundInheritingContext(secondaryJobMaster);
+
+ T result = null;
+ Throwable error = null;
+ Throwable uninterestingSelfError = null;
+ boolean errorIsFromChild = false;
+ try {
+ if (log.isTraceEnabled()) log.trace("calling primary job for {}", this);
+ if (primaryJob!=null) result = primaryJob.call();
+ } catch (Throwable selfException) {
+ Exceptions.propagateIfFatal(selfException);
+ if (Exceptions.getFirstThrowableOfType(selfException, QueueAbortedException.class) != null) {
+ // Error was caused by the task already having failed, and this thread calling queue() to try
+ // to queue more work. The underlying cause will be much more interesting.
+ // Without this special catch, we record error = "Cannot add a task to ... whose queue has been aborted",
+ // which gets propagated instead of the more interesting child exception.
+ uninterestingSelfError = selfException;
+ } else {
+ error = selfException;
+ errorIsFromChild = false;
+ }
+ if (failureHandlingConfig.abortSecondaryQueueOnPrimaryFailure) {
+ if (log.isDebugEnabled())
+ log.debug("Secondary job queue for "+DynamicSequentialTask.this+" aborting with "+secondaryJobsRemaining.size()+" remaining, due to error in primary task: "+selfException);
+ secondaryQueueAborted = true;
+ }
+ if (failureHandlingConfig.cancelSecondariesOnPrimaryFailure) {
+ if (log.isDebugEnabled())
+ log.debug(DynamicSequentialTask.this+" cancelling "+secondaryJobsRemaining.size()+" remaining, due to error in primary task: "+selfException);
+ synchronized (jobTransitionLock) {
+ for (Task<?> t: secondaryJobsRemaining)
+ t.cancel(true);
+ // do this early to prevent additions; and note we notify very soon below, so not notify is help off until below
+ primaryThread = null;
+ primaryFinished = true;
+ }
+ }
+ } finally {
+ try {
+ if (log.isTraceEnabled()) log.trace("cleaning up for {}", this);
+ synchronized (jobTransitionLock) {
+ // semaphore might be nicer here (aled notes as it is this is a little hard to read)
+ primaryThread = null;
+ primaryFinished = true;
+ jobTransitionLock.notifyAll();
+ }
+ if (!isCancelled() && !Thread.currentThread().isInterrupted()) {
+ if (log.isTraceEnabled()) log.trace("waiting for secondaries for {}", this);
+ // wait on tasks sequentially so that blocking information is more interesting
+ DynamicTasks.waitForLast();
+ List<Object> result2 = secondaryJobMaster.get();
+ try {
+ if (primaryJob==null) result = (T)result2;
+ } catch (ClassCastException e) { /* ignore class cast exception; leave the result as null */ }
+ }
+ } catch (Throwable childException) {
+ Exceptions.propagateIfFatal(childException);
+ if (error==null) {
+ error = childException;
+ errorIsFromChild = true;
+ } else {
+ if (log.isDebugEnabled()) log.debug("Parent task "+this+" ignoring child error ("+childException+") in presence of our own error ("+error+")");
+ }
+ }
+ }
+ if (error!=null) {
+ handleException(error, errorIsFromChild);
+ }
+ if (uninterestingSelfError != null) {
+ handleException(uninterestingSelfError, false);
+ }
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "DstJob:"+DynamicSequentialTask.this.getId();
+ }
+
+ /** waits for this job to complete, or the given time to elapse */
+ public void join(boolean includePrimary, Duration optionalTimeout) throws InterruptedException {
+ CountdownTimer timeLeft = optionalTimeout!=null ? CountdownTimer.newInstanceStarted(optionalTimeout) : null;
+ while (true) {
+ Task<?> cs;
+ Duration remaining;
+ synchronized (jobTransitionLock) {
+ cs = currentSecondary;
+ if (finishedSecondaries) return;
+ remaining = timeLeft==null ? Duration.ONE_SECOND : timeLeft.getDurationRemaining();
+ if (!remaining.isPositive()) return;
+ if (cs==null) {
+ if (!includePrimary && secondaryJobsRemaining.isEmpty()) return;
+ // parent still running, no children though
+ Tasks.setBlockingTask(DynamicSequentialTask.this);
+ jobTransitionLock.wait(remaining.toMilliseconds());
+ Tasks.resetBlockingDetails();
+ }
+ }
+ if (cs!=null) {
+ Tasks.setBlockingTask(cs);
+ cs.blockUntilEnded(remaining);
+ Tasks.resetBlockingDetails();
+ }
+ }
+ }
+ }
+
+ @Override
+ public List<Task<?>> getQueue() {
+ return ImmutableList.copyOf(secondaryJobsAll);
+ }
+
+ public void handleException(Throwable throwable, boolean fromChild) throws Exception {
+ Exceptions.propagateIfFatal(throwable);
+ if (fromChild && !failureHandlingConfig.failParentOnSecondaryFailure) {
+ log.debug("Parent task "+this+" swallowing child error: "+throwable);
+ return;
+ }
+ handleException(throwable);
+ }
+ public void handleException(Throwable throwable) throws Exception {
+ Exceptions.propagateIfFatal(throwable);
+ if (throwable instanceof Exception) {
+ // allow checked exceptions to be passed through
+ throw (Exception)throwable;
+ }
+ throw Exceptions.propagate(throwable);
+ }
+
+ @Override
+ public void drain(Duration optionalTimeout, boolean includePrimary, boolean throwFirstError) {
+ try {
+ dstJob.join(includePrimary, optionalTimeout);
+ } catch (InterruptedException e) {
+ throw Exceptions.propagate(e);
+ }
+ if (throwFirstError) {
+ if (isError())
+ getUnchecked();
+ for (Task<?> t: getQueue())
+ if (t.isError() && !TaskTags.isInessential(t))
+ t.getUnchecked();
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/DynamicTasks.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/DynamicTasks.java b/core/src/main/java/org/apache/brooklyn/core/util/task/DynamicTasks.java
new file mode 100644
index 0000000..ed46558
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/DynamicTasks.java
@@ -0,0 +1,337 @@
+/*
+ * 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.util.task;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.management.ExecutionContext;
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.api.management.TaskAdaptable;
+import org.apache.brooklyn.api.management.TaskFactory;
+import org.apache.brooklyn.api.management.TaskQueueingContext;
+import org.apache.brooklyn.api.management.TaskWrapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.time.Duration;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+
+/**
+ * Contains static methods which detect and use the current {@link TaskQueueingContext} to execute tasks.
+ *
+ * @since 0.6.0
+ */
+@Beta
+public class DynamicTasks {
+
+ private static final Logger log = LoggerFactory.getLogger(DynamicTasks.class);
+ private static final ThreadLocal<TaskQueueingContext> taskQueueingContext = new ThreadLocal<TaskQueueingContext>();
+
+ public static void setTaskQueueingContext(TaskQueueingContext newTaskQC) {
+ taskQueueingContext.set(newTaskQC);
+ }
+
+ public static TaskQueueingContext getThreadTaskQueuingContext() {
+ return taskQueueingContext.get();
+ }
+
+ public static TaskQueueingContext getTaskQueuingContext() {
+ TaskQueueingContext adder = getThreadTaskQueuingContext();
+ if (adder!=null) return adder;
+ Task<?> t = Tasks.current();
+ if (t instanceof TaskQueueingContext) return (TaskQueueingContext) t;
+ return null;
+ }
+
+
+ public static void removeTaskQueueingContext() {
+ taskQueueingContext.remove();
+ }
+
+ public static class TaskQueueingResult<T> implements TaskWrapper<T> {
+ private final Task<T> task;
+ private final boolean wasQueued;
+ private ExecutionContext execContext = null;
+
+ private TaskQueueingResult(TaskAdaptable<T> task, boolean wasQueued) {
+ this.task = task.asTask();
+ this.wasQueued = wasQueued;
+ }
+ @Override
+ public Task<T> asTask() {
+ return task;
+ }
+ @Override
+ public Task<T> getTask() {
+ return task;
+ }
+ /** returns true if the task was queued */
+ public boolean wasQueued() {
+ return wasQueued;
+ }
+ /** returns true if the task either is currently queued or has been submitted */
+ public boolean isQueuedOrSubmitted() {
+ return wasQueued || Tasks.isQueuedOrSubmitted(task);
+ }
+ /** specifies an execContext to use if the task has to be explicitly submitted;
+ * if omitted it will attempt to find one based on the current thread's context */
+ public TaskQueueingResult<T> executionContext(ExecutionContext execContext) {
+ this.execContext = execContext;
+ return this;
+ }
+ /** as {@link #executionContext(ExecutionContext)} but inferring from the entity */
+ public TaskQueueingResult<T> executionContext(Entity entity) {
+ this.execContext = ((EntityInternal)entity).getManagementSupport().getExecutionContext();
+ return this;
+ }
+ private boolean orSubmitInternal() {
+ if (!wasQueued()) {
+ if (isQueuedOrSubmitted()) {
+ log.warn("Redundant call to execute "+getTask()+"; skipping");
+ return false;
+ } else {
+ ExecutionContext ec = execContext;
+ if (ec==null)
+ ec = BasicExecutionContext.getCurrentExecutionContext();
+ if (ec==null)
+ throw new IllegalStateException("Cannot execute "+getTask()+" without an execution context; ensure caller is in an ExecutionContext");
+ ec.submit(getTask());
+ return true;
+ }
+ } else {
+ return false;
+ }
+ }
+ /** causes the task to be submitted (asynchronously) if it hasn't already been,
+ * requiring an entity execution context (will try to find a default if not set) */
+ public TaskQueueingResult<T> orSubmitAsync() {
+ orSubmitInternal();
+ return this;
+ }
+ /** convenience for setting {@link #executionContext(ExecutionContext)} then submitting async */
+ public TaskQueueingResult<T> orSubmitAsync(Entity entity) {
+ executionContext(entity);
+ return orSubmitAsync();
+ }
+ /** causes the task to be submitted *synchronously* if it hasn't already been submitted;
+ * useful in contexts such as libraries where callers may be either on a legacy call path
+ * (which assumes all commands complete immediately);
+ * requiring an entity execution context (will try to find a default if not set) */
+ public TaskQueueingResult<T> orSubmitAndBlock() {
+ if (orSubmitInternal()) task.getUnchecked();
+ return this;
+ }
+ /** convenience for setting {@link #executionContext(ExecutionContext)} then submitting blocking */
+ public TaskQueueingResult<T> orSubmitAndBlock(Entity entity) {
+ executionContext(entity);
+ return orSubmitAndBlock();
+ }
+ /** blocks for the task to be completed
+ * <p>
+ * needed in any context where subsequent commands assume the task has completed.
+ * not needed in a context where the task is simply being built up and queued.
+ * <p>
+ * throws if there are any errors
+ */
+ public T andWaitForSuccess() {
+ return task.getUnchecked();
+ }
+ public void orCancel() {
+ if (!wasQueued()) {
+ task.cancel(false);
+ }
+ }
+ }
+
+ /**
+ * Tries to add the task to the current addition context if there is one, otherwise does nothing.
+ * <p/>
+ * Call {@link TaskQueueingResult#orSubmitAsync() orSubmitAsync()} on the returned
+ * {@link TaskQueueingResult TaskQueueingResult} to handle execution of tasks in a
+ * {@link BasicExecutionContext}.
+ */
+ public static <T> TaskQueueingResult<T> queueIfPossible(TaskAdaptable<T> task) {
+ TaskQueueingContext adder = getTaskQueuingContext();
+ boolean result = false;
+ if (adder!=null)
+ result = Tasks.tryQueueing(adder, task);
+ return new TaskQueueingResult<T>(task, result);
+ }
+
+ /** @see #queueIfPossible(TaskAdaptable) */
+ public static <T> TaskQueueingResult<T> queueIfPossible(TaskFactory<? extends TaskAdaptable<T>> task) {
+ return queueIfPossible(task.newTask());
+ }
+
+ /** adds the given task to the nearest task addition context,
+ * either set as a thread-local, or in the current task, or the submitter of the task, etc
+ * <p>
+ * throws if it cannot add */
+ public static <T> Task<T> queueInTaskHierarchy(Task<T> task) {
+ Preconditions.checkNotNull(task, "Task to queue cannot be null");
+ Preconditions.checkState(!Tasks.isQueuedOrSubmitted(task), "Task to queue must not yet be submitted: {}", task);
+
+ TaskQueueingContext adder = getTaskQueuingContext();
+ if (adder!=null) {
+ if (Tasks.tryQueueing(adder, task)) {
+ log.debug("Queued task {} at context {} (no hierarchy)", task, adder);
+ return task;
+ }
+ }
+
+ Task<?> t = Tasks.current();
+ Preconditions.checkState(t!=null || adder!=null, "No task addition context available for queueing task "+task);
+
+ while (t!=null) {
+ if (t instanceof TaskQueueingContext) {
+ if (Tasks.tryQueueing((TaskQueueingContext)t, task)) {
+ log.debug("Queued task {} at hierarchical context {}", task, t);
+ return task;
+ }
+ }
+ t = t.getSubmittedByTask();
+ }
+
+ throw new IllegalStateException("No task addition context available in current task hierarchy for adding task "+task);
+ }
+
+ /**
+ * Queues the given task.
+ * <p/>
+ * This method is only valid within a dynamic task. Use {@link #queueIfPossible(TaskAdaptable)}
+ * and {@link TaskQueueingResult#orSubmitAsync()} if the calling context is a basic task.
+ *
+ * @param task The task to queue
+ * @throws IllegalStateException if no task queueing context is available
+ * @return The queued task
+ */
+ public static <V extends TaskAdaptable<?>> V queue(V task) {
+ try {
+ Preconditions.checkNotNull(task, "Task to queue cannot be null");
+ Preconditions.checkState(!Tasks.isQueued(task), "Task to queue must not yet be queued: %s", task);
+ TaskQueueingContext adder = getTaskQueuingContext();
+ if (adder==null) {
+ throw new IllegalStateException("Task "+task+" cannot be queued here; no queueing context available");
+ }
+ adder.queue(task.asTask());
+ return task;
+ } catch (Throwable e) {
+ log.warn("Error queueing "+task+" (rethrowing): "+e);
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ /** @see #queue(org.apache.brooklyn.api.management.TaskAdaptable) */
+ public static void queue(TaskAdaptable<?> task1, TaskAdaptable<?> task2, TaskAdaptable<?> ...tasks) {
+ queue(task1);
+ queue(task2);
+ for (TaskAdaptable<?> task: tasks) queue(task);
+ }
+
+ /** @see #queue(org.apache.brooklyn.api.management.TaskAdaptable) */
+ public static <T extends TaskAdaptable<?>> T queue(TaskFactory<T> taskFactory) {
+ return queue(taskFactory.newTask());
+ }
+
+ /** @see #queue(org.apache.brooklyn.api.management.TaskAdaptable) */
+ public static void queue(TaskFactory<?> task1, TaskFactory<?> task2, TaskFactory<?> ...tasks) {
+ queue(task1.newTask());
+ queue(task2.newTask());
+ for (TaskFactory<?> task: tasks) queue(task.newTask());
+ }
+
+ /** @see #queue(org.apache.brooklyn.api.management.TaskAdaptable) */
+ public static <T> Task<T> queue(String name, Callable<T> job) {
+ return DynamicTasks.queue(Tasks.<T>builder().name(name).body(job).build());
+ }
+
+ /** @see #queue(org.apache.brooklyn.api.management.TaskAdaptable) */
+ public static <T> Task<T> queue(String name, Runnable job) {
+ return DynamicTasks.queue(Tasks.<T>builder().name(name).body(job).build());
+ }
+
+ /** queues the task if needed, i.e. if it is not yet submitted (so it will run),
+ * or if it is submitted but not queued and we are in a queueing context (so it is available for informational purposes) */
+ public static <T extends TaskAdaptable<?>> T queueIfNeeded(T task) {
+ if (!Tasks.isQueued(task)) {
+ if (Tasks.isSubmitted(task) && getTaskQueuingContext()==null) {
+ // already submitted and not in a queueing context, don't try to queue
+ } else {
+ // needs submitting, put it in the queue
+ // (will throw an error if we are not a queueing context)
+ queue(task);
+ }
+ }
+ return task;
+ }
+
+ /** submits/queues the given task if needed, and gets the result (unchecked)
+ * only permitted in a queueing context (ie a DST main job) if the task is not yet submitted */
+ // things get really confusing if you try to queueInTaskHierarchy -- easy to cause deadlocks!
+ public static <T> T get(TaskAdaptable<T> t) {
+ return queueIfNeeded(t).asTask().getUnchecked();
+ }
+
+ /** As {@link #drain(Duration, boolean)} waiting forever and throwing the first error
+ * (excluding errors in inessential tasks),
+ * then returning the last task in the queue (which is guaranteed to have finished without error,
+ * if this method returns without throwing) */
+ public static Task<?> waitForLast() {
+ drain(null, true);
+ // this call to last is safe, as the above guarantees everything will have run
+ // (on errors the above will throw so we won't come here)
+ List<Task<?>> q = DynamicTasks.getTaskQueuingContext().getQueue();
+ return q.isEmpty() ? null : Iterables.getLast(q);
+ }
+
+ /** Calls {@link TaskQueueingContext#drain(Duration, boolean, boolean)} on the current task context */
+ public static TaskQueueingContext drain(Duration optionalTimeout, boolean throwFirstError) {
+ TaskQueueingContext qc = DynamicTasks.getTaskQueuingContext();
+ Preconditions.checkNotNull(qc, "Cannot drain when there is no queueing context");
+ qc.drain(optionalTimeout, false, throwFirstError);
+ return qc;
+ }
+
+ /** as {@link Tasks#swallowChildrenFailures()} but requiring a {@link TaskQueueingContext}. */
+ @Beta
+ public static void swallowChildrenFailures() {
+ Preconditions.checkNotNull(DynamicTasks.getTaskQueuingContext(), "Task queueing context required here");
+ Tasks.swallowChildrenFailures();
+ }
+
+ /** same as {@link Tasks#markInessential()}
+ * (but included here for convenience as it is often used in conjunction with {@link DynamicTasks}) */
+ public static void markInessential() {
+ Tasks.markInessential();
+ }
+
+ /** queues the task if possible, otherwise submits it asynchronously; returns the task for callers to
+ * {@link Task#getUnchecked()} or {@link Task#blockUntilEnded()} */
+ public static <T> Task<T> submit(TaskAdaptable<T> task, Entity entity) {
+ return queueIfPossible(task).orSubmitAsync(entity).asTask();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/ExecutionListener.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/ExecutionListener.java b/core/src/main/java/org/apache/brooklyn/core/util/task/ExecutionListener.java
new file mode 100644
index 0000000..5341b21
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/ExecutionListener.java
@@ -0,0 +1,31 @@
+/*
+ * 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.util.task;
+
+import org.apache.brooklyn.api.management.Task;
+
+public interface ExecutionListener {
+
+ /** invoked when a task completes:
+ * {@link Task#getEndTimeUtc()} and {@link Task#isDone()} are guaranteed to be set,
+ * and {@link Task#get()} should return immediately for most Task implementations
+ * (care has been taken to avoid potential deadlocks here, waiting for a result!) */
+ public void onTaskDone(Task<?> task);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/ExecutionUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/ExecutionUtils.java b/core/src/main/java/org/apache/brooklyn/core/util/task/ExecutionUtils.java
new file mode 100644
index 0000000..be677e3
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/ExecutionUtils.java
@@ -0,0 +1,49 @@
+/*
+ * 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.util.task;
+
+import groovy.lang.Closure;
+
+import java.util.concurrent.Callable;
+
+import com.google.common.base.Function;
+import com.google.common.base.Throwables;
+
+public class ExecutionUtils {
+ /**
+ * Attempts to run/call the given object, with the given arguments if possible, preserving the return value if there is one (null otherwise);
+ * throws exception if the callable is a non-null object which cannot be invoked (not a callable or runnable)
+ * @deprecated since 0.7.0 ; this super-loose typing should be avoided; if it is needed, let's move it to one of the Groovy compatibility classes
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public static Object invoke(Object callable, Object ...args) {
+ if (callable instanceof Closure) return ((Closure<?>)callable).call(args);
+ if (callable instanceof Callable) {
+ try {
+ return ((Callable<?>)callable).call();
+ } catch (Throwable t) {
+ throw Throwables.propagate(t);
+ }
+ }
+ if (callable instanceof Runnable) { ((Runnable)callable).run(); return null; }
+ if (callable instanceof Function && args.length == 1) { return ((Function)callable).apply(args[0]); }
+ if (callable==null) return null;
+ throw new IllegalArgumentException("Cannot invoke unexpected object "+callable+" of type "+callable.getClass()+", with "+args.length+" args");
+ }
+}
[35/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/osgi/Osgis.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/osgi/Osgis.java b/core/src/main/java/brooklyn/util/osgi/Osgis.java
deleted file mode 100644
index 3bf972e..0000000
--- a/core/src/main/java/brooklyn/util/osgi/Osgis.java
+++ /dev/null
@@ -1,719 +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 brooklyn.util.osgi;
-
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.jar.Attributes;
-import java.util.jar.JarInputStream;
-import java.util.jar.JarOutputStream;
-import java.util.jar.Manifest;
-
-import javax.annotation.Nullable;
-
-import org.apache.felix.framework.FrameworkFactory;
-import org.apache.felix.framework.util.StringMap;
-import org.apache.felix.framework.util.manifestparser.ManifestParser;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.Constants;
-import org.osgi.framework.Version;
-import org.osgi.framework.launch.Framework;
-import org.osgi.framework.namespace.PackageNamespace;
-import org.osgi.framework.wiring.BundleCapability;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
-
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.collections.MutableSet;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.exceptions.ReferenceWithError;
-import brooklyn.util.guava.Maybe;
-import brooklyn.util.net.Urls;
-import brooklyn.util.os.Os;
-import brooklyn.util.stream.Streams;
-import brooklyn.util.text.Strings;
-import brooklyn.util.time.Duration;
-import brooklyn.util.time.Time;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Joiner;
-import com.google.common.base.Objects;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.base.Stopwatch;
-
-/**
- * utilities for working with osgi.
- * osgi support is in early days (June 2014) so this class is beta, subject to change,
- * particularly in how framework is started and bundles installed.
- *
- * @since 0.7.0 */
-@Beta
-public class Osgis {
- private static final Logger LOG = LoggerFactory.getLogger(Osgis.class);
-
- private static final String EXTENSION_PROTOCOL = "system";
- private static final String MANIFEST_PATH = "META-INF/MANIFEST.MF";
- private static final Set<String> SYSTEM_BUNDLES = MutableSet.of();
-
- public static class VersionedName {
- private final String symbolicName;
- private final Version version;
- public VersionedName(Bundle b) {
- this.symbolicName = b.getSymbolicName();
- this.version = b.getVersion();
- }
- public VersionedName(String symbolicName, Version version) {
- this.symbolicName = symbolicName;
- this.version = version;
- }
- @Override public String toString() {
- return symbolicName + ":" + Strings.toString(version);
- }
- public boolean equals(String sn, String v) {
- return symbolicName.equals(sn) && (version == null && v == null || version != null && version.toString().equals(v));
- }
- public boolean equals(String sn, Version v) {
- return symbolicName.equals(sn) && (version == null && v == null || version != null && version.equals(v));
- }
- public String getSymbolicName() {
- return symbolicName;
- }
- public Version getVersion() {
- return version;
- }
- @Override
- public int hashCode() {
- return Objects.hashCode(symbolicName, version);
- }
- @Override
- public boolean equals(Object other) {
- if (!(other instanceof VersionedName)) return false;
- VersionedName o = (VersionedName) other;
- return Objects.equal(symbolicName, o.symbolicName) && Objects.equal(version, o.version);
- }
- }
-
- public static class BundleFinder {
- protected final Framework framework;
- protected String symbolicName;
- protected String version;
- protected String url;
- protected boolean urlMandatory = false;
- protected final List<Predicate<? super Bundle>> predicates = MutableList.of();
-
- protected BundleFinder(Framework framework) {
- this.framework = framework;
- }
-
- public BundleFinder symbolicName(String symbolicName) {
- this.symbolicName = symbolicName;
- return this;
- }
-
- public BundleFinder version(String version) {
- this.version = version;
- return this;
- }
-
- public BundleFinder id(String symbolicNameOptionallyWithVersion) {
- if (Strings.isBlank(symbolicNameOptionallyWithVersion))
- return this;
-
- Maybe<VersionedName> nv = parseOsgiIdentifier(symbolicNameOptionallyWithVersion);
- if (nv.isAbsent())
- throw new IllegalArgumentException("Cannot parse symbolic-name:version string '"+symbolicNameOptionallyWithVersion+"'");
-
- return id(nv.get());
- }
-
- private BundleFinder id(VersionedName nv) {
- symbolicName(nv.getSymbolicName());
- if (nv.getVersion() != null) {
- version(nv.getVersion().toString());
- }
- return this;
- }
-
- public BundleFinder bundle(CatalogBundle bundle) {
- if (bundle.isNamed()) {
- symbolicName(bundle.getSymbolicName());
- version(bundle.getVersion());
- }
- if (bundle.getUrl() != null) {
- requiringFromUrl(bundle.getUrl());
- }
- return this;
- }
-
- /** Looks for a bundle matching the given URL;
- * unlike {@link #requiringFromUrl(String)} however, if the URL does not match any bundles
- * it will return other matching bundles <i>if</if> a {@link #symbolicName(String)} is specified.
- */
- public BundleFinder preferringFromUrl(String url) {
- this.url = url;
- urlMandatory = false;
- return this;
- }
-
- /** Requires the bundle to have the given URL set as its location. */
- public BundleFinder requiringFromUrl(String url) {
- this.url = url;
- urlMandatory = true;
- return this;
- }
-
- /** Finds the best matching bundle. */
- public Maybe<Bundle> find() {
- return findOne(false);
- }
-
- /** Finds the matching bundle, requiring it to be unique. */
- public Maybe<Bundle> findUnique() {
- return findOne(true);
- }
-
- protected Maybe<Bundle> findOne(boolean requireExactlyOne) {
- if (symbolicName==null && url==null)
- throw new IllegalStateException(this+" must be given either a symbolic name or a URL");
-
- List<Bundle> result = findAll();
- if (result.isEmpty())
- return Maybe.absent("No bundle matching "+getConstraintsDescription());
- if (requireExactlyOne && result.size()>1)
- return Maybe.absent("Multiple bundles ("+result.size()+") matching "+getConstraintsDescription());
-
- return Maybe.of(result.get(0));
- }
-
- /** Finds all matching bundles, in decreasing version order. */
- public List<Bundle> findAll() {
- boolean urlMatched = false;
- List<Bundle> result = MutableList.of();
- for (Bundle b: framework.getBundleContext().getBundles()) {
- if (symbolicName!=null && !symbolicName.equals(b.getSymbolicName())) continue;
- if (version!=null && !Version.parseVersion(version).equals(b.getVersion())) continue;
- for (Predicate<? super Bundle> predicate: predicates) {
- if (!predicate.apply(b)) continue;
- }
-
- // check url last, because if it isn't mandatory we should only clear if we find a url
- // for which the other items also match
- if (url!=null) {
- boolean matches = url.equals(b.getLocation());
- if (urlMandatory) {
- if (!matches) continue;
- else urlMatched = true;
- } else {
- if (matches) {
- if (!urlMatched) {
- result.clear();
- urlMatched = true;
- }
- } else {
- if (urlMatched) {
- // can't use this bundle as we have previously found a preferred bundle, with a matching url
- continue;
- }
- }
- }
- }
-
- result.add(b);
- }
-
- if (symbolicName==null && url!=null && !urlMatched) {
- // if we only "preferred" the url, and we did not match it, and we did not have a symbolic name,
- // then clear the results list!
- result.clear();
- }
-
- Collections.sort(result, new Comparator<Bundle>() {
- @Override
- public int compare(Bundle o1, Bundle o2) {
- return o2.getVersion().compareTo(o1.getVersion());
- }
- });
-
- return result;
- }
-
- public String getConstraintsDescription() {
- List<String> parts = MutableList.of();
- if (symbolicName!=null) parts.add("symbolicName="+symbolicName);
- if (version!=null) parts.add("version="+version);
- if (url!=null)
- parts.add("url["+(urlMandatory ? "required" : "preferred")+"]="+url);
- if (!predicates.isEmpty())
- parts.add("predicates="+predicates);
- return Joiner.on(";").join(parts);
- }
-
- public String toString() {
- return getClass().getCanonicalName()+"["+getConstraintsDescription()+"]";
- }
-
- public BundleFinder version(final Predicate<Version> versionPredicate) {
- return satisfying(new Predicate<Bundle>() {
- @Override
- public boolean apply(Bundle input) {
- return versionPredicate.apply(input.getVersion());
- }
- });
- }
-
- public BundleFinder satisfying(Predicate<? super Bundle> predicate) {
- predicates.add(predicate);
- return this;
- }
- }
-
- public static BundleFinder bundleFinder(Framework framework) {
- return new BundleFinder(framework);
- }
-
- /** @deprecated since 0.7.0 use {@link #bundleFinder(Framework)} */ @Deprecated
- public static List<Bundle> getBundlesByName(Framework framework, String symbolicName, Predicate<Version> versionMatcher) {
- return bundleFinder(framework).symbolicName(symbolicName).version(versionMatcher).findAll();
- }
-
- /** @deprecated since 0.7.0 use {@link #bundleFinder(Framework)} */ @Deprecated
- public static List<Bundle> getBundlesByName(Framework framework, String symbolicName) {
- return bundleFinder(framework).symbolicName(symbolicName).findAll();
- }
-
- /**
- * Tries to find a bundle in the given framework with name matching either `name' or `name:version'.
- * @deprecated since 0.7.0 use {@link #bundleFinder(Framework)} */ @Deprecated
- public static Maybe<Bundle> getBundle(Framework framework, String symbolicNameOptionallyWithVersion) {
- return bundleFinder(framework).id(symbolicNameOptionallyWithVersion).find();
- }
-
- /** @deprecated since 0.7.0 use {@link #bundleFinder(Framework)} */ @Deprecated
- public static Maybe<Bundle> getBundle(Framework framework, String symbolicName, String version) {
- return bundleFinder(framework).symbolicName(symbolicName).version(version).find();
- }
-
- /** @deprecated since 0.7.0 use {@link #bundleFinder(Framework)} */ @Deprecated
- public static Maybe<Bundle> getBundle(Framework framework, String symbolicName, Version version) {
- return bundleFinder(framework).symbolicName(symbolicName).version(Predicates.equalTo(version)).findUnique();
- }
-
- // -------- creating
-
- /*
- * loading framework factory and starting framework based on:
- * http://felix.apache.org/documentation/subprojects/apache-felix-framework/apache-felix-framework-launching-and-embedding.html
- */
-
- public static FrameworkFactory newFrameworkFactory() {
- URL url = Osgis.class.getClassLoader().getResource(
- "META-INF/services/org.osgi.framework.launch.FrameworkFactory");
- if (url != null) {
- try {
- BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
- try {
- for (String s = br.readLine(); s != null; s = br.readLine()) {
- s = s.trim();
- // load the first non-empty, non-commented line
- if ((s.length() > 0) && (s.charAt(0) != '#')) {
- return (FrameworkFactory) Class.forName(s).newInstance();
- }
- }
- } finally {
- if (br != null) br.close();
- }
- } catch (Exception e) {
- // class creation exceptions are not interesting to caller...
- throw Exceptions.propagate(e);
- }
- }
- throw new IllegalStateException("Could not find framework factory.");
- }
-
- public static Framework newFrameworkStarted(String felixCacheDir, boolean clean, Map<?,?> extraStartupConfig) {
- Map<Object,Object> cfg = MutableMap.copyOf(extraStartupConfig);
- if (clean) cfg.put(Constants.FRAMEWORK_STORAGE_CLEAN, "onFirstInit");
- if (felixCacheDir!=null) cfg.put(Constants.FRAMEWORK_STORAGE, felixCacheDir);
- cfg.put(Constants.FRAMEWORK_BSNVERSION, Constants.FRAMEWORK_BSNVERSION_MULTIPLE);
- FrameworkFactory factory = newFrameworkFactory();
-
- Stopwatch timer = Stopwatch.createStarted();
- Framework framework = factory.newFramework(cfg);
- try {
- framework.init();
- installBootBundles(framework);
- framework.start();
- } catch (Exception e) {
- // framework bundle start exceptions are not interesting to caller...
- throw Exceptions.propagate(e);
- }
- LOG.debug("System bundles are: "+SYSTEM_BUNDLES);
- LOG.debug("OSGi framework started in " + Duration.of(timer));
- return framework;
- }
-
- private static void installBootBundles(Framework framework) {
- Stopwatch timer = Stopwatch.createStarted();
- LOG.debug("Installing OSGi boot bundles from "+Osgis.class.getClassLoader()+"...");
- Enumeration<URL> resources;
- try {
- resources = Osgis.class.getClassLoader().getResources(MANIFEST_PATH);
- } catch (IOException e) {
- throw Exceptions.propagate(e);
- }
- BundleContext bundleContext = framework.getBundleContext();
- Map<String, Bundle> installedBundles = getInstalledBundlesById(bundleContext);
- while(resources.hasMoreElements()) {
- URL url = resources.nextElement();
- ReferenceWithError<?> installResult = installExtensionBundle(bundleContext, url, installedBundles, getVersionedId(framework));
- if (installResult.hasError() && !installResult.masksErrorIfPresent()) {
- // it's reported as a critical error, so warn here
- LOG.warn("Unable to install manifest from "+url+": "+installResult.getError(), installResult.getError());
- } else {
- Object result = installResult.getWithoutError();
- if (result instanceof Bundle) {
- String v = getVersionedId( (Bundle)result );
- SYSTEM_BUNDLES.add(v);
- if (installResult.hasError()) {
- LOG.debug(installResult.getError().getMessage()+(result!=null ? " ("+result+"/"+v+")" : ""));
- } else {
- LOG.debug("Installed "+v+" from "+url);
- }
- } else if (installResult.hasError()) {
- LOG.debug(installResult.getError().getMessage());
- }
- }
- }
- LOG.debug("Installed OSGi boot bundles in "+Time.makeTimeStringRounded(timer)+": "+Arrays.asList(framework.getBundleContext().getBundles()));
- }
-
- private static Map<String, Bundle> getInstalledBundlesById(BundleContext bundleContext) {
- Map<String, Bundle> installedBundles = new HashMap<String, Bundle>();
- Bundle[] bundles = bundleContext.getBundles();
- for (Bundle b : bundles) {
- installedBundles.put(getVersionedId(b), b);
- }
- return installedBundles;
- }
-
- /** Wraps the bundle if successful or already installed, wraps TRUE if it's the system entry,
- * wraps null if the bundle is already installed from somewhere else;
- * in all these cases <i>masking</i> an explanatory error if already installed or it's the system entry.
- * <p>
- * Returns an instance wrapping null and <i>throwing</i> an error if the bundle could not be installed.
- */
- private static ReferenceWithError<?> installExtensionBundle(BundleContext bundleContext, URL manifestUrl, Map<String, Bundle> installedBundles, String frameworkVersionedId) {
- //ignore http://felix.extensions:9/ system entry
- if("felix.extensions".equals(manifestUrl.getHost()))
- return ReferenceWithError.newInstanceMaskingError(null, new IllegalArgumentException("Skipping install of internal extension bundle from "+manifestUrl));
-
- try {
- Manifest manifest = readManifest(manifestUrl);
- if (!isValidBundle(manifest))
- return ReferenceWithError.newInstanceMaskingError(null, new IllegalArgumentException("Resource at "+manifestUrl+" is not an OSGi bundle: no valid manifest"));
-
- String versionedId = getVersionedId(manifest);
- URL bundleUrl = ResourceUtils.getContainerUrl(manifestUrl, MANIFEST_PATH);
-
- Bundle existingBundle = installedBundles.get(versionedId);
- if (existingBundle != null) {
- if (!bundleUrl.equals(existingBundle.getLocation()) &&
- //the framework bundle is always pre-installed, don't display duplicate info
- !versionedId.equals(frameworkVersionedId)) {
- return ReferenceWithError.newInstanceMaskingError(null, new IllegalArgumentException("Bundle "+versionedId+" (from manifest " + manifestUrl + ") is already installed, from " + existingBundle.getLocation()));
- }
- return ReferenceWithError.newInstanceMaskingError(existingBundle, new IllegalArgumentException("Bundle "+versionedId+" from manifest " + manifestUrl + " is already installed"));
- }
-
- byte[] jar = buildExtensionBundle(manifest);
- LOG.debug("Installing boot bundle " + bundleUrl);
- //mark the bundle as extension so we can detect it later using the "system:" protocol
- //(since we cannot access BundleImpl.isExtension)
- Bundle newBundle = bundleContext.installBundle(EXTENSION_PROTOCOL + ":" + bundleUrl.toString(), new ByteArrayInputStream(jar));
- installedBundles.put(versionedId, newBundle);
- return ReferenceWithError.newInstanceWithoutError(newBundle);
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- return ReferenceWithError.newInstanceThrowingError(null,
- new IllegalStateException("Problem installing extension bundle " + manifestUrl + ": "+e, e));
- }
- }
-
- private static Manifest readManifest(URL manifestUrl) throws IOException {
- Manifest manifest;
- InputStream in = null;
- try {
- in = manifestUrl.openStream();
- manifest = new Manifest(in);
- } finally {
- if (in != null) {
- try {in.close();}
- catch (Exception e) {};
- }
- }
- return manifest;
- }
-
- private static byte[] buildExtensionBundle(Manifest manifest) throws IOException {
- Attributes atts = manifest.getMainAttributes();
-
- //the following properties are invalid in extension bundles
- atts.remove(new Attributes.Name(Constants.IMPORT_PACKAGE));
- atts.remove(new Attributes.Name(Constants.REQUIRE_BUNDLE));
- atts.remove(new Attributes.Name(Constants.BUNDLE_NATIVECODE));
- atts.remove(new Attributes.Name(Constants.DYNAMICIMPORT_PACKAGE));
- atts.remove(new Attributes.Name(Constants.BUNDLE_ACTIVATOR));
-
- //mark as extension bundle
- atts.putValue(Constants.FRAGMENT_HOST, "system.bundle; extension:=framework");
-
- //create the jar containing the manifest
- ByteArrayOutputStream jar = new ByteArrayOutputStream();
- JarOutputStream out = new JarOutputStream(jar, manifest);
- out.close();
- return jar.toByteArray();
- }
-
- private static boolean isValidBundle(Manifest manifest) {
- Attributes atts = manifest.getMainAttributes();
- return atts.containsKey(new Attributes.Name(Constants.BUNDLE_MANIFESTVERSION));
- }
-
- private static String getVersionedId(Bundle b) {
- return b.getSymbolicName() + ":" + b.getVersion();
- }
-
- private static String getVersionedId(Manifest manifest) {
- Attributes atts = manifest.getMainAttributes();
- return atts.getValue(Constants.BUNDLE_SYMBOLICNAME) + ":" +
- atts.getValue(Constants.BUNDLE_VERSION);
- }
-
- /**
- * Installs a bundle from the given URL, doing a check if already installed, and
- * using the {@link ResourceUtils} loader for this project (brooklyn core)
- */
- public static Bundle install(Framework framework, String url) throws BundleException {
- boolean isLocal = isLocalUrl(url);
- String localUrl = url;
- if (!isLocal) {
- localUrl = cacheFile(url);
- }
-
- try {
- Bundle bundle = getInstalledBundle(framework, localUrl);
- if (bundle != null) {
- return bundle;
- }
-
- // use our URL resolution so we get classpath items
- LOG.debug("Installing bundle into {} from url: {}", framework, url);
- InputStream stream = getUrlStream(localUrl);
- Bundle installedBundle = framework.getBundleContext().installBundle(url, stream);
-
- return installedBundle;
- } finally {
- if (!isLocal) {
- try {
- new File(new URI(localUrl)).delete();
- } catch (URISyntaxException e) {
- throw Exceptions.propagate(e);
- }
- }
- }
- }
-
- private static String cacheFile(String url) {
- InputStream in = getUrlStream(url);
- File cache = Os.writeToTempFile(in, "bundle-cache", "jar");
- return cache.toURI().toString();
- }
-
- private static boolean isLocalUrl(String url) {
- String protocol = Urls.getProtocol(url);
- return "file".equals(protocol) ||
- "classpath".equals(protocol) ||
- "jar".equals(protocol);
- }
-
- private static Bundle getInstalledBundle(Framework framework, String url) {
- Bundle bundle = framework.getBundleContext().getBundle(url);
- if (bundle != null) {
- return bundle;
- }
-
- // We now support same version installed multiple times (avail since OSGi 4.3+).
- // However we do not support overriding *system* bundles, ie anything already on the classpath.
- // If we wanted to disable multiple versions, see comments below, and reference to FRAMEWORK_BSNVERSION_MULTIPLE above.
-
- // Felix already assumes the stream is pointing to a JAR
- JarInputStream stream;
- try {
- stream = new JarInputStream(getUrlStream(url));
- } catch (IOException e) {
- throw Exceptions.propagate(e);
- }
- Manifest manifest = stream.getManifest();
- Streams.closeQuietly(stream);
- if (manifest == null) {
- throw new IllegalStateException("Missing manifest file in bundle or not a jar file.");
- }
- String versionedId = getVersionedId(manifest);
- for (Bundle installedBundle : framework.getBundleContext().getBundles()) {
- if (versionedId.equals(getVersionedId(installedBundle))) {
- if (SYSTEM_BUNDLES.contains(versionedId)) {
- LOG.debug("Already have system bundle "+versionedId+" from "+installedBundle+"/"+installedBundle.getLocation()+" when requested "+url+"; not installing");
- // "System bundles" (ie things on the classpath) cannot be overridden
- return installedBundle;
- } else {
- LOG.debug("Already have bundle "+versionedId+" from "+installedBundle+"/"+installedBundle.getLocation()+" when requested "+url+"; but it is not a system bundle so proceeding");
- // Other bundles can be installed multiple times. To ignore multiples and continue to use the old one,
- // just return the installedBundle as done just above for system bundles.
- }
- }
- }
- return null;
- }
-
- private static InputStream getUrlStream(String url) {
- return ResourceUtils.create(Osgis.class).getResourceFromUrl(url);
- }
-
- public static boolean isExtensionBundle(Bundle bundle) {
- String location = bundle.getLocation();
- return location != null &&
- EXTENSION_PROTOCOL.equals(Urls.getProtocol(location));
- }
-
- /** Takes a string which might be of the form "symbolic-name" or "symbolic-name:version" (or something else entirely)
- * and returns a VersionedName. The versionedName.getVersion() will be null if if there was no version in the input
- * (or returning {@link Maybe#absent()} if not valid, with a suitable error message). */
- public static Maybe<VersionedName> parseOsgiIdentifier(String symbolicNameOptionalWithVersion) {
- if (Strings.isBlank(symbolicNameOptionalWithVersion))
- return Maybe.absent("OSGi identifier is blank");
-
- String[] parts = symbolicNameOptionalWithVersion.split(":");
- if (parts.length>2)
- return Maybe.absent("OSGi identifier has too many parts; max one ':' symbol");
-
- Version v = null;
- if (parts.length == 2) {
- try {
- v = Version.parseVersion(parts[1]);
- } catch (IllegalArgumentException e) {
- return Maybe.absent("OSGi identifier has invalid version string ("+e.getMessage()+")");
- }
- }
-
- return Maybe.of(new VersionedName(parts[0], v));
- }
-
- /**
- * The class is not used, staying for future reference.
- * Remove after OSGi transition is completed.
- */
- public static class ManifestHelper {
-
- private static ManifestParser parse;
- private Manifest manifest;
- private String source;
-
- private static final String WIRING_PACKAGE = PackageNamespace.PACKAGE_NAMESPACE;
-
- public static ManifestHelper forManifestContents(String contents) throws IOException, BundleException {
- ManifestHelper result = forManifest(Streams.newInputStreamWithContents(contents));
- result.source = contents;
- return result;
- }
-
- public static ManifestHelper forManifest(URL url) throws IOException, BundleException {
- InputStream in = null;
- try {
- in = url.openStream();
- return forManifest(in);
- } finally {
- if (in != null) in.close();
- }
- }
-
- public static ManifestHelper forManifest(InputStream in) throws IOException, BundleException {
- return forManifest(new Manifest(in));
- }
-
- public static ManifestHelper forManifest(Manifest manifest) throws BundleException {
- ManifestHelper result = new ManifestHelper();
- result.manifest = manifest;
- parse = new ManifestParser(null, null, null, new StringMap(manifest.getMainAttributes()));
- return result;
- }
-
- public String getSymbolicName() {
- return parse.getSymbolicName();
- }
-
- public Version getVersion() {
- return parse.getBundleVersion();
- }
-
- public String getSymbolicNameVersion() {
- return getSymbolicName()+":"+getVersion();
- }
-
- public List<String> getExportedPackages() {
- MutableList<String> result = MutableList.of();
- for (BundleCapability c: parse.getCapabilities()) {
- if (WIRING_PACKAGE.equals(c.getNamespace())) {
- result.add((String)c.getAttributes().get(WIRING_PACKAGE));
- }
- }
- return result;
- }
-
- @Nullable public String getSource() {
- return source;
- }
-
- public Manifest getManifest() {
- return manifest;
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/AbstractExecutionContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/AbstractExecutionContext.java b/core/src/main/java/brooklyn/util/task/AbstractExecutionContext.java
deleted file mode 100644
index f3511d7..0000000
--- a/core/src/main/java/brooklyn/util/task/AbstractExecutionContext.java
+++ /dev/null
@@ -1,75 +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 brooklyn.util.task;
-
-import java.util.Map;
-import java.util.concurrent.Callable;
-
-import org.apache.brooklyn.api.management.ExecutionContext;
-import org.apache.brooklyn.api.management.ExecutionManager;
-import org.apache.brooklyn.api.management.Task;
-import org.apache.brooklyn.api.management.TaskAdaptable;
-
-import com.google.common.collect.Maps;
-
-public abstract class AbstractExecutionContext implements ExecutionContext {
-
- /**
- * Submits the given runnable/callable/task for execution (in a separate thread);
- * supported keys in the map include: tags (add'l tags to put on the resulting task),
- * description (string), and others as described in the reference below
- *
- * @see ExecutionManager#submit(Map, Task)
- */
- @Override
- public Task<?> submit(Map<?,?> properties, Runnable runnable) { return submitInternal(properties, runnable); }
-
- /** @see #submit(Map, Runnable) */
- @Override
- public Task<?> submit(Runnable runnable) { return submitInternal(Maps.newLinkedHashMap(), runnable); }
-
- /** @see #submit(Map, Runnable) */
- @Override
- public <T> Task<T> submit(Callable<T> callable) { return submitInternal(Maps.newLinkedHashMap(), callable); }
-
- /** @see #submit(Map, Runnable) */
- @Override
- public <T> Task<T> submit(Map<?,?> properties, Callable<T> callable) { return submitInternal(properties, callable); }
-
- /** @see #submit(Map, Runnable) */
- @Override
- public <T> Task<T> submit(TaskAdaptable<T> task) { return submitInternal(Maps.newLinkedHashMap(), task.asTask()); }
-
- /** @see #submit(Map, Runnable) */
- @Override
- public <T> Task<T> submit(Map<?,?> properties, TaskAdaptable<T> task) { return submitInternal(properties, task.asTask()); }
-
- /**
- * Provided for compatibility
- *
- * Submit is preferred if a handle on the resulting Task is desired (although a task can be passed in so this is not always necessary)
- *
- * @see #submit(Map, Runnable)
- */
- public void execute(Runnable r) { submit(r); }
-
- /** does the work internally of submitting the task; note that the return value may be a wrapper task even if a task is passed in,
- * if the execution context where the target should run is different (e.g. submitting an effector task cross-context) */
- protected abstract <T> Task<T> submitInternal(Map<?,?> properties, Object task);
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/BasicExecutionContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/BasicExecutionContext.java b/core/src/main/java/brooklyn/util/task/BasicExecutionContext.java
deleted file mode 100644
index 8942a18..0000000
--- a/core/src/main/java/brooklyn/util/task/BasicExecutionContext.java
+++ /dev/null
@@ -1,221 +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 brooklyn.util.task;
-
-import java.lang.reflect.Proxy;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Callable;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ExecutorService;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.management.ExecutionContext;
-import org.apache.brooklyn.api.management.ExecutionManager;
-import org.apache.brooklyn.api.management.HasTaskChildren;
-import org.apache.brooklyn.api.management.Task;
-import org.apache.brooklyn.api.management.TaskAdaptable;
-import org.apache.brooklyn.api.management.entitlement.EntitlementContext;
-import org.apache.brooklyn.core.management.entitlement.Entitlements;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.entity.basic.BrooklynTaskTags;
-import brooklyn.entity.basic.BrooklynTaskTags.WrappedEntity;
-import brooklyn.entity.basic.EntityInternal;
-
-import com.google.common.base.Function;
-import com.google.common.collect.Iterables;
-
-/**
- * A means of executing tasks against an ExecutionManager with a given bucket/set of tags pre-defined
- * (so that it can look like an {@link Executor} and also supply {@link ExecutorService#submit(Callable)}
- */
-public class BasicExecutionContext extends AbstractExecutionContext {
-
- private static final Logger log = LoggerFactory.getLogger(BasicExecutionContext.class);
-
- static final ThreadLocal<BasicExecutionContext> perThreadExecutionContext = new ThreadLocal<BasicExecutionContext>();
-
- public static BasicExecutionContext getCurrentExecutionContext() { return perThreadExecutionContext.get(); }
-
- final ExecutionManager executionManager;
- final Set<Object> tags = new LinkedHashSet<Object>();
-
- public BasicExecutionContext(ExecutionManager executionManager) {
- this(Collections.emptyMap(), executionManager);
- }
-
- /**
- * Supported flags are {@code tag} and {@code tags}
- *
- * @see ExecutionManager#submit(Map, Task)
- */
- public BasicExecutionContext(Map<?, ?> flags, ExecutionManager executionManager) {
- this.executionManager = executionManager;
-
- if (flags.get("tag") != null) tags.add(flags.remove("tag"));
- if (flags.containsKey("tags")) tags.addAll((Collection<?>)flags.remove("tags"));
-
- // FIXME brooklyn-specific check, just for sanity
- // the context tag should always be a non-proxy entity, because that is what is passed to effector tasks
- // which may require access to internal methods
- for (Object tag: tags) {
- if (tag instanceof BrooklynTaskTags.WrappedEntity) {
- if (Proxy.isProxyClass(((WrappedEntity)tag).entity.getClass())) {
- log.warn(""+this+" has entity proxy in "+tag);
- }
- }
- }
- }
-
- public ExecutionManager getExecutionManager() {
- return executionManager;
- }
-
- /** returns tasks started by this context (or tasks which have all the tags on this object) */
- public Set<Task<?>> getTasks() { return executionManager.getTasksWithAllTags((Set<?>)tags); }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- @Override
- protected <T> Task<T> submitInternal(Map<?,?> propertiesQ, final Object task) {
- if (task instanceof TaskAdaptable<?> && !(task instanceof Task<?>))
- return submitInternal(propertiesQ, ((TaskAdaptable<?>)task).asTask());
-
- Map properties = propertiesQ;
- if (properties.get("tags")==null) properties.put("tags", new ArrayList());
- Collection taskTags = (Collection)properties.get("tags");
-
- // FIXME some of this is brooklyn-specific logic, should be moved to a BrooklynExecContext subclass;
- // the issue is that we want to ensure that cross-entity calls switch execution contexts;
- // previously it was all very messy how that was handled (and it didn't really handle it in many cases)
- if (task instanceof Task<?>) taskTags.addAll( ((Task<?>)task).getTags() );
- Entity target = BrooklynTaskTags.getWrappedEntityOfType(taskTags, BrooklynTaskTags.TARGET_ENTITY);
-
- if (target!=null && !tags.contains(BrooklynTaskTags.tagForContextEntity(target))) {
- // task is switching execution context boundaries
- /*
- * longer notes:
- * you fall in to this block if the caller requests a target entity different to the current context
- * (e.g. where entity X is invoking an effector on Y, it will start in X's context,
- * but the effector should run in Y's context).
- *
- * if X is invoking an effector on himself in his own context, or a sensor or other task, it will not come in to this block.
- */
- final ExecutionContext tc = ((EntityInternal)target).getExecutionContext();
- if (log.isDebugEnabled())
- log.debug("Switching task context on execution of "+task+": from "+this+" to "+target+" (in "+Tasks.current()+")");
-
- if (task instanceof Task<?>) {
- final Task<T> t = (Task<T>)task;
- if (!Tasks.isQueuedOrSubmitted(t) && (!(Tasks.current() instanceof HasTaskChildren) ||
- !Iterables.contains( ((HasTaskChildren)Tasks.current()).getChildren(), t ))) {
- // this task is switching execution context boundaries _and_ it is not a child and not yet queued,
- // so wrap it in a task running in this context to keep a reference to the child
- // (this matters when we are navigating in the GUI; without it we lose the reference to the child
- // when browsing in the context of the parent)
- return submit(Tasks.<T>builder().name("Cross-context execution: "+t.getDescription()).dynamic(true).body(new Callable<T>() {
- public T call() {
- return DynamicTasks.get(t);
- }
- }).build());
- } else {
- // if we are already tracked by parent, just submit it
- return tc.submit(t);
- }
- } else {
- // as above, but here we are definitely not a child (what we are submitting isn't even a task)
- // (will only come here if properties defines tags including a target entity, which probably never happens)
- submit(Tasks.<T>builder().name("Cross-context execution").dynamic(true).body(new Callable<T>() {
- public T call() {
- if (task instanceof Callable) {
- return DynamicTasks.queue( Tasks.<T>builder().dynamic(false).body((Callable<T>)task).build() ).getUnchecked();
- } else if (task instanceof Runnable) {
- return DynamicTasks.queue( Tasks.<T>builder().dynamic(false).body((Runnable)task).build() ).getUnchecked();
- } else {
- throw new IllegalArgumentException("Unhandled task type: "+task+"; type="+(task!=null ? task.getClass() : "null"));
- }
- }
- }).build());
- }
- }
-
- EntitlementContext entitlementContext = BrooklynTaskTags.getEntitlement(taskTags);
- if (entitlementContext==null)
- entitlementContext = Entitlements.getEntitlementContext();
- if (entitlementContext!=null) {
- taskTags.add(BrooklynTaskTags.tagForEntitlement(entitlementContext));
- }
-
- taskTags.addAll(tags);
-
- if (Tasks.current()!=null && BrooklynTaskTags.isTransient(Tasks.current())
- && !taskTags.contains(BrooklynTaskTags.NON_TRANSIENT_TASK_TAG) && !taskTags.contains(BrooklynTaskTags.TRANSIENT_TASK_TAG)) {
- // tag as transient if submitter is transient, unless explicitly tagged as non-transient
- taskTags.add(BrooklynTaskTags.TRANSIENT_TASK_TAG);
- }
-
- final Object startCallback = properties.get("newTaskStartCallback");
- properties.put("newTaskStartCallback", new Function<Object,Void>() {
- public Void apply(Object it) {
- registerPerThreadExecutionContext();
- if (startCallback!=null) ExecutionUtils.invoke(startCallback, it);
- return null;
- }});
-
- final Object endCallback = properties.get("newTaskEndCallback");
- properties.put("newTaskEndCallback", new Function<Object,Void>() {
- public Void apply(Object it) {
- try {
- if (endCallback!=null) ExecutionUtils.invoke(endCallback, it);
- } finally {
- clearPerThreadExecutionContext();
- }
- return null;
- }});
-
- if (task instanceof Task) {
- return executionManager.submit(properties, (Task)task);
- } else if (task instanceof Callable) {
- return executionManager.submit(properties, (Callable)task);
- } else if (task instanceof Runnable) {
- return (Task<T>) executionManager.submit(properties, (Runnable)task);
- } else {
- throw new IllegalArgumentException("Unhandled task type: task="+task+"; type="+(task!=null ? task.getClass() : "null"));
- }
- }
-
- private void registerPerThreadExecutionContext() { perThreadExecutionContext.set(this); }
-
- private void clearPerThreadExecutionContext() { perThreadExecutionContext.remove(); }
-
- @Override
- public boolean isShutdown() {
- return getExecutionManager().isShutdown();
- }
-
- @Override
- public String toString() {
- return super.toString()+"("+tags+")";
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/BasicExecutionManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/BasicExecutionManager.java b/core/src/main/java/brooklyn/util/task/BasicExecutionManager.java
deleted file mode 100644
index 13d035b..0000000
--- a/core/src/main/java/brooklyn/util/task/BasicExecutionManager.java
+++ /dev/null
@@ -1,755 +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 brooklyn.util.task;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.SynchronousQueue;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-
-import org.apache.brooklyn.api.management.ExecutionManager;
-import org.apache.brooklyn.api.management.HasTaskChildren;
-import org.apache.brooklyn.api.management.Task;
-import org.apache.brooklyn.api.management.TaskAdaptable;
-import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.text.Identifiers;
-
-import com.google.common.annotations.Beta;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.CaseFormat;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Sets;
-import com.google.common.util.concurrent.ExecutionList;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ThreadFactoryBuilder;
-
-/**
- * Manages the execution of atomic tasks and scheduled (recurring) tasks,
- * including setting tags and invoking callbacks.
- */
-public class BasicExecutionManager implements ExecutionManager {
- private static final Logger log = LoggerFactory.getLogger(BasicExecutionManager.class);
-
- private static final boolean RENAME_THREADS = BrooklynFeatureEnablement.isEnabled(BrooklynFeatureEnablement.FEATURE_RENAME_THREADS);
-
- private static class PerThreadCurrentTaskHolder {
- public static final ThreadLocal<Task<?>> perThreadCurrentTask = new ThreadLocal<Task<?>>();
- }
-
- public static ThreadLocal<Task<?>> getPerThreadCurrentTask() {
- return PerThreadCurrentTaskHolder.perThreadCurrentTask;
- }
-
- private final ThreadFactory threadFactory;
-
- private final ThreadFactory daemonThreadFactory;
-
- private final ExecutorService runner;
-
- private final ScheduledExecutorService delayedRunner;
-
- // TODO Could have a set of all knownTasks; but instead we're having a separate set per tag,
- // so the same task could be listed multiple times if it has multiple tags...
-
- //access to this field AND to members in this field is synchronized,
- //to allow us to preserve order while guaranteeing thread-safe
- //(but more testing is needed before we are completely sure it is thread-safe!)
- //synch blocks are as finely grained as possible for efficiency;
- //NB CopyOnWriteArraySet is a perf bottleneck, and the simple map makes it easier to remove when a tag is empty
- private Map<Object,Set<Task<?>>> tasksByTag = new HashMap<Object,Set<Task<?>>>();
-
- private ConcurrentMap<String,Task<?>> tasksById = new ConcurrentHashMap<String,Task<?>>();
-
- private ConcurrentMap<Object, TaskScheduler> schedulerByTag = new ConcurrentHashMap<Object, TaskScheduler>();
-
- /** count of all tasks submitted, including finished */
- private final AtomicLong totalTaskCount = new AtomicLong();
-
- /** tasks submitted but not yet done (or in cases of interruption/cancelled not yet GC'd) */
- private Map<String,String> incompleteTaskIds = new ConcurrentHashMap<String,String>();
-
- /** tasks started but not yet finished */
- private final AtomicInteger activeTaskCount = new AtomicInteger();
-
- private final List<ExecutionListener> listeners = new CopyOnWriteArrayList<ExecutionListener>();
-
- private final static ThreadLocal<String> threadOriginalName = new ThreadLocal<String>() {
- protected String initialValue() {
- // should not happen, as only access is in _afterEnd with a check that _beforeStart was invoked
- log.warn("No original name recorded for thread "+Thread.currentThread().getName()+"; task "+Tasks.current());
- return "brooklyn-thread-pool-"+Identifiers.makeRandomId(8);
- }
- };
-
- public BasicExecutionManager(String contextid) {
- threadFactory = newThreadFactory(contextid);
- daemonThreadFactory = new ThreadFactoryBuilder()
- .setThreadFactory(threadFactory)
- .setDaemon(true)
- .build();
-
- // use Executors.newCachedThreadPool(daemonThreadFactory), but timeout of 1s rather than 60s for better shutdown!
- runner = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 10L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(),
- daemonThreadFactory);
-
- delayedRunner = new ScheduledThreadPoolExecutor(1, daemonThreadFactory);
- }
-
- private final static class UncaughtExceptionHandlerImplementation implements Thread.UncaughtExceptionHandler {
- @Override
- public void uncaughtException(Thread t, Throwable e) {
- log.error("Uncaught exception in thread "+t.getName(), e);
- }
- }
-
- /**
- * For use by overriders to use custom thread factory.
- * But be extremely careful: called by constructor, so before sub-class' constructor will
- * have been invoked!
- */
- protected ThreadFactory newThreadFactory(String contextid) {
- return new ThreadFactoryBuilder()
- .setNameFormat("brooklyn-execmanager-"+contextid+"-%d")
- .setUncaughtExceptionHandler(new UncaughtExceptionHandlerImplementation())
- .build();
- }
-
- public void shutdownNow() {
- runner.shutdownNow();
- delayedRunner.shutdownNow();
- }
-
- public void addListener(ExecutionListener listener) {
- listeners.add(listener);
- }
-
- public void removeListener(ExecutionListener listener) {
- listeners.remove(listener);
- }
-
- /**
- * Deletes the given tag, including all tasks using this tag.
- *
- * Useful, for example, if an entity is being expunged so that we don't keep holding
- * a reference to it as a tag.
- */
- public void deleteTag(Object tag) {
- Set<Task<?>> tasks;
- synchronized (tasksByTag) {
- tasks = tasksByTag.remove(tag);
- }
- if (tasks != null) {
- for (Task<?> task : tasks) {
- deleteTask(task);
- }
- }
- }
-
- public void deleteTask(Task<?> task) {
- boolean removed = deleteTaskNonRecursive(task);
- if (!removed) return;
-
- if (task instanceof HasTaskChildren) {
- List<Task<?>> children = ImmutableList.copyOf(((HasTaskChildren)task).getChildren());
- for (Task<?> child : children) {
- deleteTask(child);
- }
- }
- }
-
- protected boolean deleteTaskNonRecursive(Task<?> task) {
- Set<?> tags = checkNotNull(task, "task").getTags();
- for (Object tag : tags) {
- synchronized (tasksByTag) {
- Set<Task<?>> tasks = tasksWithTagLiveOrNull(tag);
- if (tasks != null) {
- tasks.remove(task);
- if (tasks.isEmpty()) {
- tasksByTag.remove(tag);
- }
- }
- }
- }
- Task<?> removed = tasksById.remove(task.getId());
- incompleteTaskIds.remove(task.getId());
- if (removed!=null && removed.isSubmitted() && !removed.isDone()) {
- log.warn("Deleting submitted task before completion: "+removed+"; this task will continue to run in the background outwith "+this+", but perhaps it should have been cancelled?");
- }
- return removed != null;
- }
-
- public boolean isShutdown() {
- return runner.isShutdown();
- }
-
- /** count of all tasks submitted */
- public long getTotalTasksSubmitted() {
- return totalTaskCount.get();
- }
-
- /** count of tasks submitted but not ended */
- public long getNumIncompleteTasks() {
- return incompleteTaskIds.size();
- }
-
- /** count of tasks started but not ended */
- public long getNumActiveTasks() {
- return activeTaskCount.get();
- }
-
- /** count of tasks kept in memory, often including ended tasks */
- public long getNumInMemoryTasks() {
- return tasksById.size();
- }
-
- private Set<Task<?>> tasksWithTagCreating(Object tag) {
- Preconditions.checkNotNull(tag);
- synchronized (tasksByTag) {
- Set<Task<?>> result = tasksWithTagLiveOrNull(tag);
- if (result==null) {
- result = Collections.synchronizedSet(new LinkedHashSet<Task<?>>());
- tasksByTag.put(tag, result);
- }
- return result;
- }
- }
-
- /** exposes live view, for internal use only */
- @Beta
- public Set<Task<?>> tasksWithTagLiveOrNull(Object tag) {
- synchronized (tasksByTag) {
- return tasksByTag.get(tag);
- }
- }
-
- @Override
- public Task<?> getTask(String id) {
- return tasksById.get(id);
- }
-
- /** not on interface because potentially expensive */
- public List<Task<?>> getAllTasks() {
- // not sure if synching makes any difference; have not observed CME's yet
- // (and so far this is only called when a CME was caught on a previous operation)
- synchronized (tasksById) {
- return MutableList.copyOf(tasksById.values());
- }
- }
-
- @Override
- public Set<Task<?>> getTasksWithTag(Object tag) {
- Set<Task<?>> result = tasksWithTagLiveOrNull(tag);
- if (result==null) return Collections.emptySet();
- synchronized (result) {
- return (Set<Task<?>>)Collections.unmodifiableSet(new LinkedHashSet<Task<?>>(result));
- }
- }
-
- @Override
- public Set<Task<?>> getTasksWithAnyTag(Iterable<?> tags) {
- Set<Task<?>> result = new LinkedHashSet<Task<?>>();
- Iterator<?> ti = tags.iterator();
- while (ti.hasNext()) {
- Set<Task<?>> tasksForTag = tasksWithTagLiveOrNull(ti.next());
- if (tasksForTag!=null) {
- synchronized (tasksForTag) {
- result.addAll(tasksForTag);
- }
- }
- }
- return Collections.unmodifiableSet(result);
- }
-
- /** only works with at least one tag; returns empty if no tags */
- @Override
- public Set<Task<?>> getTasksWithAllTags(Iterable<?> tags) {
- //NB: for this method retrieval for multiple tags could be made (much) more efficient (if/when it is used with multiple tags!)
- //by first looking for the least-used tag, getting those tasks, and then for each of those tasks
- //checking whether it contains the other tags (looking for second-least used, then third-least used, etc)
- Set<Task<?>> result = new LinkedHashSet<Task<?>>();
- boolean first = true;
- Iterator<?> ti = tags.iterator();
- while (ti.hasNext()) {
- Object tag = ti.next();
- if (first) {
- first = false;
- result.addAll(getTasksWithTag(tag));
- } else {
- result.retainAll(getTasksWithTag(tag));
- }
- }
- return Collections.unmodifiableSet(result);
- }
-
- /** live view of all tasks, for internal use only */
- @Beta
- public Collection<Task<?>> allTasksLive() { return tasksById.values(); }
-
- public Set<Object> getTaskTags() {
- synchronized (tasksByTag) {
- return Collections.unmodifiableSet(Sets.newLinkedHashSet(tasksByTag.keySet()));
- }
- }
-
- public Task<?> submit(Runnable r) { return submit(new LinkedHashMap<Object,Object>(1), r); }
- public Task<?> submit(Map<?,?> flags, Runnable r) { return submit(flags, new BasicTask<Void>(flags, r)); }
-
- public <T> Task<T> submit(Callable<T> c) { return submit(new LinkedHashMap<Object,Object>(1), c); }
- public <T> Task<T> submit(Map<?,?> flags, Callable<T> c) { return submit(flags, new BasicTask<T>(flags, c)); }
-
- public <T> Task<T> submit(TaskAdaptable<T> t) { return submit(new LinkedHashMap<Object,Object>(1), t); }
- public <T> Task<T> submit(Map<?,?> flags, TaskAdaptable<T> task) {
- if (!(task instanceof Task))
- task = task.asTask();
- synchronized (task) {
- if (((TaskInternal<?>)task).getInternalFuture()!=null) return (Task<T>)task;
- return submitNewTask(flags, (Task<T>) task);
- }
- }
-
- public <T> Task<T> scheduleWith(Task<T> task) { return scheduleWith(Collections.emptyMap(), task); }
- public <T> Task<T> scheduleWith(Map<?,?> flags, Task<T> task) {
- synchronized (task) {
- if (((TaskInternal<?>)task).getInternalFuture()!=null) return task;
- return submitNewTask(flags, task);
- }
- }
-
- protected Task<?> submitNewScheduledTask(final Map<?,?> flags, final ScheduledTask task) {
- tasksById.put(task.getId(), task);
- totalTaskCount.incrementAndGet();
-
- beforeSubmitScheduledTaskAllIterations(flags, task);
-
- return submitSubsequentScheduledTask(flags, task);
- }
-
- @SuppressWarnings("unchecked")
- protected Task<?> submitSubsequentScheduledTask(final Map<?,?> flags, final ScheduledTask task) {
- if (!task.isDone()) {
- task.internalFuture = delayedRunner.schedule(new ScheduledTaskCallable(task, flags),
- task.delay.toNanoseconds(), TimeUnit.NANOSECONDS);
- } else {
- afterEndScheduledTaskAllIterations(flags, task);
- }
- return task;
- }
-
- protected class ScheduledTaskCallable implements Callable<Object> {
- public ScheduledTask task;
- public Map<?,?> flags;
-
- public ScheduledTaskCallable(ScheduledTask task, Map<?, ?> flags) {
- this.task = task;
- this.flags = flags;
- }
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- public Object call() {
- if (task.startTimeUtc==-1) task.startTimeUtc = System.currentTimeMillis();
- TaskInternal<?> taskScheduled = null;
- try {
- beforeStartScheduledTaskSubmissionIteration(flags, task);
- taskScheduled = (TaskInternal<?>) task.newTask();
- taskScheduled.setSubmittedByTask(task);
- final Callable<?> oldJob = taskScheduled.getJob();
- final TaskInternal<?> taskScheduledF = taskScheduled;
- taskScheduled.setJob(new Callable() { public Object call() {
- boolean resubmitted = false;
- task.recentRun = taskScheduledF;
- try {
- synchronized (task) {
- task.notifyAll();
- }
- Object result;
- try {
- result = oldJob.call();
- } catch (Exception e) {
- if (!Tasks.isInterrupted()) {
- log.warn("Error executing "+oldJob+" (scheduled job of "+task+" - "+task.getDescription()+"); cancelling scheduled execution", e);
- } else {
- log.debug("Interrupted executing "+oldJob+" (scheduled job of "+task+" - "+task.getDescription()+"); cancelling scheduled execution: "+e);
- }
- throw Exceptions.propagate(e);
- }
- task.runCount++;
- if (task.period!=null && !task.isCancelled()) {
- task.delay = task.period;
- submitSubsequentScheduledTask(flags, task);
- resubmitted = true;
- }
- return result;
- } finally {
- // do in finally block in case we were interrupted
- if (!resubmitted)
- afterEndScheduledTaskAllIterations(flags, task);
- }
- }});
- task.nextRun = taskScheduled;
- BasicExecutionContext ec = BasicExecutionContext.getCurrentExecutionContext();
- if (ec!=null) return ec.submit(taskScheduled);
- else return submit(taskScheduled);
- } finally {
- afterEndScheduledTaskSubmissionIteration(flags, task, taskScheduled);
- }
- }
-
- @Override
- public String toString() {
- return "ScheduledTaskCallable["+task+","+flags+"]";
- }
- }
-
- private final class SubmissionCallable<T> implements Callable<T> {
- private final Map<?, ?> flags;
- private final Task<T> task;
-
- private SubmissionCallable(Map<?, ?> flags, Task<T> task) {
- this.flags = flags;
- this.task = task;
- }
-
- public T call() {
- try {
- T result = null;
- Throwable error = null;
- String oldThreadName = Thread.currentThread().getName();
- try {
- if (RENAME_THREADS) {
- String newThreadName = oldThreadName+"-"+task.getDisplayName()+
- "["+task.getId().substring(0, 8)+"]";
- Thread.currentThread().setName(newThreadName);
- }
- beforeStartAtomicTask(flags, task);
- if (!task.isCancelled()) {
- result = ((TaskInternal<T>)task).getJob().call();
- } else throw new CancellationException();
- } catch(Throwable e) {
- error = e;
- } finally {
- if (RENAME_THREADS) {
- Thread.currentThread().setName(oldThreadName);
- }
- afterEndAtomicTask(flags, task);
- }
- if (error!=null) {
- /* we throw, after logging debug.
- * the throw means the error is available for task submitters to monitor.
- * however it is possible no one is monitoring it, in which case we will have debug logging only for errors.
- * (the alternative, of warn-level logging in lots of places where we don't want it, seems worse!)
- */
- if (log.isDebugEnabled()) {
- // debug only here, because most submitters will handle failures
- log.debug("Exception running task "+task+" (rethrowing): "+error.getMessage(), error);
- if (log.isTraceEnabled())
- log.trace("Trace for exception running task "+task+" (rethrowing): "+error.getMessage(), error);
- }
- throw Exceptions.propagate(error);
- }
- return result;
- } finally {
- ((TaskInternal<?>)task).runListeners();
- }
- }
-
- @Override
- public String toString() {
- return "BEM.call("+task+","+flags+")";
- }
- }
-
- private final static class ListenableForwardingFutureForTask<T> extends ListenableForwardingFuture<T> {
- private final Task<T> task;
-
- private ListenableForwardingFutureForTask(Future<T> delegate, ExecutionList list, Task<T> task) {
- super(delegate, list);
- this.task = task;
- }
-
- @Override
- public boolean cancel(boolean mayInterruptIfRunning) {
- boolean result = false;
- if (!task.isCancelled()) result |= task.cancel(mayInterruptIfRunning);
- result |= super.cancel(mayInterruptIfRunning);
- ((TaskInternal<?>)task).runListeners();
- return result;
- }
- }
-
- private final class SubmissionListenerToCallOtherListeners<T> implements Runnable {
- private final Task<T> task;
-
- private SubmissionListenerToCallOtherListeners(Task<T> task) {
- this.task = task;
- }
-
- @Override
- public void run() {
- try {
- ((TaskInternal<?>)task).runListeners();
- } catch (Exception e) {
- log.warn("Error running task listeners for task "+task+" done", e);
- }
-
- for (ExecutionListener listener : listeners) {
- try {
- listener.onTaskDone(task);
- } catch (Exception e) {
- log.warn("Error running execution listener "+listener+" of task "+task+" done", e);
- }
- }
- }
- }
-
- @SuppressWarnings("unchecked")
- protected <T> Task<T> submitNewTask(final Map<?,?> flags, final Task<T> task) {
- if (task instanceof ScheduledTask)
- return (Task<T>) submitNewScheduledTask(flags, (ScheduledTask)task);
-
- tasksById.put(task.getId(), task);
- totalTaskCount.incrementAndGet();
-
- beforeSubmitAtomicTask(flags, task);
-
- if (((TaskInternal<T>)task).getJob() == null)
- throw new NullPointerException("Task "+task+" submitted with with null job: job must be supplied.");
-
- Callable<T> job = new SubmissionCallable<T>(flags, task);
-
- // If there's a scheduler then use that; otherwise execute it directly
- Set<TaskScheduler> schedulers = null;
- for (Object tago: task.getTags()) {
- TaskScheduler scheduler = getTaskSchedulerForTag(tago);
- if (scheduler!=null) {
- if (schedulers==null) schedulers = new LinkedHashSet<TaskScheduler>(2);
- schedulers.add(scheduler);
- }
- }
- Future<T> future;
- if (schedulers!=null && !schedulers.isEmpty()) {
- if (schedulers.size()>1) log.warn("multiple schedulers detected, using only the first, for "+task+": "+schedulers);
- future = schedulers.iterator().next().submit(job);
- } else {
- future = runner.submit(job);
- }
- // on completion, listeners get triggered above; here, below we ensure they get triggered on cancel
- // (and we make sure the same ExecutionList is used in the future as in the task)
- ListenableFuture<T> listenableFuture = new ListenableForwardingFutureForTask<T>(future, ((TaskInternal<T>)task).getListeners(), task);
- // doesn't matter whether the listener is added to the listenableFuture or the task,
- // except that for the task we can more easily wrap it so that it only logs debug if the executor is shutdown
- // (avoid a bunch of ugly warnings in tests which start and stop things a lot!)
- // [probably even nicer to run this in the same thread, it doesn't do much; but that is messier to implement]
- ((TaskInternal<T>)task).addListener(new SubmissionListenerToCallOtherListeners<T>(task), runner);
-
- ((TaskInternal<T>)task).initInternalFuture(listenableFuture);
-
- return task;
- }
-
- protected void beforeSubmitScheduledTaskAllIterations(Map<?,?> flags, Task<?> task) {
- internalBeforeSubmit(flags, task);
- }
- protected void beforeSubmitAtomicTask(Map<?,?> flags, Task<?> task) {
- internalBeforeSubmit(flags, task);
- }
- /** invoked when a task is submitted */
- protected void internalBeforeSubmit(Map<?,?> flags, Task<?> task) {
- incompleteTaskIds.put(task.getId(), task.getId());
-
- Task<?> currentTask = Tasks.current();
- if (currentTask!=null) ((TaskInternal<?>)task).setSubmittedByTask(currentTask);
- ((TaskInternal<?>)task).setSubmitTimeUtc(System.currentTimeMillis());
-
- if (flags.get("tag")!=null) ((TaskInternal<?>)task).getMutableTags().add(flags.remove("tag"));
- if (flags.get("tags")!=null) ((TaskInternal<?>)task).getMutableTags().addAll((Collection<?>)flags.remove("tags"));
-
- for (Object tag: ((TaskInternal<?>)task).getTags()) {
- tasksWithTagCreating(tag).add(task);
- }
- }
-
- protected void beforeStartScheduledTaskSubmissionIteration(Map<?,?> flags, Task<?> task) {
- internalBeforeStart(flags, task);
- }
- protected void beforeStartAtomicTask(Map<?,?> flags, Task<?> task) {
- internalBeforeStart(flags, task);
- }
-
- /** invoked in a task's thread when a task is starting to run (may be some time after submitted),
- * but before doing any of the task's work, so that we can update bookkeeping and notify callbacks */
- protected void internalBeforeStart(Map<?,?> flags, Task<?> task) {
- activeTaskCount.incrementAndGet();
-
- //set thread _before_ start time, so we won't get a null thread when there is a start-time
- if (log.isTraceEnabled()) log.trace(""+this+" beforeStart, task: "+task);
- if (!task.isCancelled()) {
- Thread thread = Thread.currentThread();
- ((TaskInternal<?>)task).setThread(thread);
- if (RENAME_THREADS) {
- threadOriginalName.set(thread.getName());
- String newThreadName = "brooklyn-" + CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, task.getDisplayName().replace(" ", "")) + "-" + task.getId().substring(0, 8);
- thread.setName(newThreadName);
- }
- PerThreadCurrentTaskHolder.perThreadCurrentTask.set(task);
- ((TaskInternal<?>)task).setStartTimeUtc(System.currentTimeMillis());
- }
- ExecutionUtils.invoke(flags.get("newTaskStartCallback"), task);
- }
-
- /** normally (if not interrupted) called once for each call to {@link #beforeSubmitScheduledTaskAllIterations(Map, Task)} */
- protected void afterEndScheduledTaskAllIterations(Map<?,?> flags, Task<?> task) {
- internalAfterEnd(flags, task, false, true);
- }
- /** called once for each call to {@link #beforeStartScheduledTaskSubmissionIteration(Map, Task)},
- * with a per-iteration task generated by the surrounding scheduled task */
- protected void afterEndScheduledTaskSubmissionIteration(Map<?,?> flags, Task<?> scheduledTask, Task<?> taskIteration) {
- internalAfterEnd(flags, scheduledTask, true, false);
- }
- /** called once for each task on which {@link #beforeStartAtomicTask(Map, Task)} is invoked,
- * and normally (if not interrupted prior to start)
- * called once for each task on which {@link #beforeSubmitAtomicTask(Map, Task)} */
- protected void afterEndAtomicTask(Map<?,?> flags, Task<?> task) {
- internalAfterEnd(flags, task, true, true);
- }
- /** normally (if not interrupted) called once for each call to {@link #internalBeforeSubmit(Map, Task)},
- * and, for atomic tasks and scheduled-task submission iterations where
- * always called once if {@link #internalBeforeStart(Map, Task)} is invoked and in the same thread as that method */
- protected void internalAfterEnd(Map<?,?> flags, Task<?> task, boolean startedInThisThread, boolean isEndingAllIterations) {
- if (log.isTraceEnabled()) log.trace(this+" afterEnd, task: "+task);
- if (startedInThisThread) {
- activeTaskCount.decrementAndGet();
- }
- if (isEndingAllIterations) {
- incompleteTaskIds.remove(task.getId());
- ExecutionUtils.invoke(flags.get("newTaskEndCallback"), task);
- ((TaskInternal<?>)task).setEndTimeUtc(System.currentTimeMillis());
- }
-
- if (startedInThisThread) {
- PerThreadCurrentTaskHolder.perThreadCurrentTask.remove();
- //clear thread _after_ endTime set, so we won't get a null thread when there is no end-time
- if (RENAME_THREADS && startedInThisThread) {
- Thread thread = task.getThread();
- if (thread==null) {
- log.warn("BasicTask.afterEnd invoked without corresponding beforeStart");
- } else {
- thread.setName(threadOriginalName.get());
- threadOriginalName.remove();
- }
- }
- ((TaskInternal<?>)task).setThread(null);
- }
- synchronized (task) { task.notifyAll(); }
- }
-
- public TaskScheduler getTaskSchedulerForTag(Object tag) {
- return schedulerByTag.get(tag);
- }
-
- public void setTaskSchedulerForTag(Object tag, Class<? extends TaskScheduler> scheduler) {
- synchronized (schedulerByTag) {
- TaskScheduler old = getTaskSchedulerForTag(tag);
- if (old!=null) {
- if (scheduler.isAssignableFrom(old.getClass())) {
- /* already have such an instance */
- return;
- }
- //might support multiple in future...
- throw new IllegalStateException("Not allowed to set multiple TaskSchedulers on ExecutionManager tag (tag "+tag+", has "+old+", setting new "+scheduler+")");
- }
- try {
- TaskScheduler schedulerI = scheduler.newInstance();
- // allow scheduler to have a nice name, for logging etc
- if (schedulerI instanceof CanSetName) ((CanSetName)schedulerI).setName(""+tag);
- setTaskSchedulerForTag(tag, schedulerI);
- } catch (InstantiationException e) {
- throw Exceptions.propagate(e);
- } catch (IllegalAccessException e) {
- throw Exceptions.propagate(e);
- }
- }
- }
-
- /**
- * Defines a {@link TaskScheduler} to run on all subsequently submitted jobs with the given tag.
- *
- * Maximum of one allowed currently. Resubmissions of the same scheduler (or scheduler class)
- * allowed. If changing, you must call {@link #clearTaskSchedulerForTag(Object)} between the two.
- *
- * @see #setTaskSchedulerForTag(Object, Class)
- */
- public void setTaskSchedulerForTag(Object tag, TaskScheduler scheduler) {
- synchronized (schedulerByTag) {
- scheduler.injectExecutor(runner);
-
- Object old = schedulerByTag.put(tag, scheduler);
- if (old!=null && old!=scheduler) {
- //might support multiple in future...
- throw new IllegalStateException("Not allowed to set multiple TaskSchedulers on ExecutionManager tag (tag "+tag+")");
- }
- }
- }
-
- /**
- * Forgets that any scheduler was associated with a tag.
- *
- * @see #setTaskSchedulerForTag(Object, TaskScheduler)
- * @see #setTaskSchedulerForTag(Object, Class)
- */
- public boolean clearTaskSchedulerForTag(Object tag) {
- synchronized (schedulerByTag) {
- Object old = schedulerByTag.remove(tag);
- return (old!=null);
- }
- }
-
- @VisibleForTesting
- public ConcurrentMap<Object, TaskScheduler> getSchedulerByTag() {
- return schedulerByTag;
- }
-
-}
[25/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/sshj/SshjTool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/sshj/SshjTool.java b/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/sshj/SshjTool.java
new file mode 100644
index 0000000..8262729
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/sshj/SshjTool.java
@@ -0,0 +1,1091 @@
+/*
+ * 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.util.internal.ssh.sshj;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Throwables.getCausalChain;
+import static com.google.common.collect.Iterables.any;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicReference;
+
+import net.schmizz.sshj.connection.ConnectionException;
+import net.schmizz.sshj.connection.channel.direct.PTYMode;
+import net.schmizz.sshj.connection.channel.direct.Session;
+import net.schmizz.sshj.connection.channel.direct.Session.Command;
+import net.schmizz.sshj.connection.channel.direct.Session.Shell;
+import net.schmizz.sshj.connection.channel.direct.SessionChannel;
+import net.schmizz.sshj.sftp.FileAttributes;
+import net.schmizz.sshj.sftp.SFTPClient;
+import net.schmizz.sshj.transport.TransportException;
+import net.schmizz.sshj.xfer.InMemorySourceFile;
+
+import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
+import org.apache.brooklyn.core.util.internal.ssh.BackoffLimitedRetryHandler;
+import org.apache.brooklyn.core.util.internal.ssh.ShellTool;
+import org.apache.brooklyn.core.util.internal.ssh.SshAbstractTool;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
+import org.apache.commons.io.input.ProxyInputStream;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.exceptions.RuntimeTimeoutException;
+import brooklyn.util.io.FileUtil;
+import brooklyn.util.repeat.Repeater;
+import brooklyn.util.stream.KnownSizeInputStream;
+import brooklyn.util.stream.StreamGobbler;
+import brooklyn.util.stream.Streams;
+import brooklyn.util.text.Strings;
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Time;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Joiner;
+import com.google.common.base.Predicate;
+import com.google.common.base.Stopwatch;
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.io.CountingOutputStream;
+import com.google.common.net.HostAndPort;
+import com.google.common.primitives.Ints;
+
+/**
+ * For ssh and scp-style commands, using the sshj library.
+ */
+public class SshjTool extends SshAbstractTool implements SshTool {
+
+ /*
+ * TODO synchronization of connect/disconnect needs revisited!
+ * Saw SshjToolIntegrationTest.testExecBigConcurrentCommand fail with:
+ * Caused by: java.lang.AssertionError
+ * at net.schmizz.sshj.SSHClient.auth(SSHClient.java:204)
+ * i.e. another thread had called disconnect just before the failing thread
+ * did SSHClient.auth.
+ * Having multiple threads call connect/disconnect is going to be brittle. With
+ * our retries we can get away with it usually, but it's not good!
+ *
+ * TODO need to upgrade sshj version from 0.8.1 to 0.9, but jclouds 1.7.2 still
+ * relies on 0.8.1. In 0.9, it fixes the https://github.com/shikhar/sshj/issues/89
+ * so does not throw AssertionError.
+ */
+
+ private static final Logger LOG = LoggerFactory.getLogger(SshjTool.class);
+
+ protected final int sshTries;
+ protected final long sshTriesTimeout;
+ protected final BackoffLimitedRetryHandler backoffLimitedRetryHandler;
+
+ /** Terminal type name for {@code allocatePTY} option. */
+ final static String TERM = "vt100"; // "dumb"
+
+ private class CloseFtpChannelOnCloseInputStream extends ProxyInputStream {
+ private final SFTPClient sftp;
+
+ private CloseFtpChannelOnCloseInputStream(InputStream proxy, SFTPClient sftp) {
+ super(proxy);
+ this.sftp = sftp;
+ }
+
+ @Override
+ public void close() throws IOException {
+ super.close();
+ closeWhispering(sftp, this);
+ }
+ }
+
+ private final SshjClientConnection sshClientConnection;
+
+ public static SshjToolBuilder builder() {
+ return new SshjToolBuilder();
+ }
+
+ public static class SshjToolBuilder extends Builder<SshjTool, SshjToolBuilder> {
+ }
+
+ public static class Builder<T extends SshjTool, B extends Builder<T,B>> extends AbstractSshToolBuilder<T,B> {
+ protected long connectTimeout;
+ protected long sessionTimeout;
+ protected int sshTries = 4; //allow 4 tries by default, much safer
+ protected long sshTriesTimeout = 2*60*1000; //allow 2 minutes by default (so if too slow trying sshTries times, abort anyway)
+ protected long sshRetryDelay = 50L;
+
+ @Override
+ public B from(Map<String,?> props) {
+ super.from(props);
+ sshTries = getOptionalVal(props, PROP_SSH_TRIES);
+ sshTriesTimeout = getOptionalVal(props, PROP_SSH_TRIES_TIMEOUT);
+ sshRetryDelay = getOptionalVal(props, PROP_SSH_RETRY_DELAY);
+ connectTimeout = getOptionalVal(props, PROP_CONNECT_TIMEOUT);
+ sessionTimeout = getOptionalVal(props, PROP_SESSION_TIMEOUT);
+ return self();
+ }
+ public B connectTimeout(int val) {
+ this.connectTimeout = val; return self();
+ }
+ public B sessionTimeout(int val) {
+ this.sessionTimeout = val; return self();
+ }
+ public B sshRetries(int val) {
+ this.sshTries = val; return self();
+ }
+ public B sshRetriesTimeout(int val) {
+ this.sshTriesTimeout = val; return self();
+ }
+ public B sshRetryDelay(long val) {
+ this.sshRetryDelay = val; return self();
+ }
+ @Override
+ @SuppressWarnings("unchecked")
+ public T build() {
+ return (T) new SshjTool(this);
+ }
+ }
+
+ public SshjTool(Map<String,?> map) {
+ this(builder().from(map));
+ }
+
+ protected SshjTool(Builder<?,?> builder) {
+ super(builder);
+
+ sshTries = builder.sshTries;
+ sshTriesTimeout = builder.sshTriesTimeout;
+ backoffLimitedRetryHandler = new BackoffLimitedRetryHandler(sshTries, builder.sshRetryDelay);
+
+ sshClientConnection = SshjClientConnection.builder()
+ .hostAndPort(HostAndPort.fromParts(host, port))
+ .username(user)
+ .password(password)
+ .privateKeyPassphrase(privateKeyPassphrase)
+ .privateKeyData(privateKeyData)
+ .privateKeyFile(privateKeyFile)
+ .strictHostKeyChecking(strictHostKeyChecking)
+ .connectTimeout(builder.connectTimeout)
+ .sessionTimeout(builder.sessionTimeout)
+ .build();
+
+ if (LOG.isTraceEnabled()) LOG.trace("Created SshTool {} ({})", this, System.identityHashCode(this));
+ }
+
+ @Override
+ public void connect() {
+ try {
+ if (LOG.isTraceEnabled()) LOG.trace("Connecting SshjTool {} ({})", this, System.identityHashCode(this));
+ acquire(sshClientConnection);
+ } catch (Exception e) {
+ if (LOG.isDebugEnabled()) LOG.debug(toString()+" failed to connect (rethrowing)", e);
+ throw propagate(e, "failed to connect");
+ }
+ }
+
+ @Override
+ @Deprecated // see super
+ public void connect(int maxAttempts) {
+ connect(); // FIXME Should callers instead configure sshTries? But that would apply to all ssh attempts
+ }
+
+ @Override
+ public void disconnect() {
+ if (LOG.isTraceEnabled()) LOG.trace("Disconnecting SshjTool {} ({})", this, System.identityHashCode(this));
+ try {
+ Stopwatch perfStopwatch = Stopwatch.createStarted();
+ sshClientConnection.clear();
+ if (LOG.isTraceEnabled()) LOG.trace("SSH Performance: {} disconnect took {}", sshClientConnection.getHostAndPort(), Time.makeTimeStringRounded(perfStopwatch));
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ @Override
+ public boolean isConnected() {
+ return sshClientConnection.isConnected() && sshClientConnection.isAuthenticated();
+ }
+
+ @Override
+ public int copyToServer(java.util.Map<String,?> props, byte[] contents, String pathAndFileOnRemoteServer) {
+ return copyToServer(props, newInputStreamSupplier(contents), contents.length, pathAndFileOnRemoteServer);
+ }
+
+ @Override
+ public int copyToServer(Map<String,?> props, InputStream contents, String pathAndFileOnRemoteServer) {
+ /* sshj needs to:
+ * 1) to know the length of the InputStream to copy the file to perform copy; and
+ * 2) re-read the input stream on retry if the first attempt fails.
+ * For now, write it to a file, unless caller supplies a KnownSizeInputStream
+ *
+ * (We could have a switch where we hold it in memory if less than some max size,
+ * but most the routines should supply a string or byte array or similar,
+ * so we probably don't come here too often.)
+ */
+ if (contents instanceof KnownSizeInputStream) {
+ return copyToServer(props, Suppliers.ofInstance(contents), ((KnownSizeInputStream)contents).length(), pathAndFileOnRemoteServer);
+ } else {
+ File tempFile = writeTempFile(contents);
+ try {
+ return copyToServer(props, tempFile, pathAndFileOnRemoteServer);
+ } finally {
+ tempFile.delete();
+ }
+ }
+ }
+
+ @Override
+ public int copyToServer(Map<String,?> props, File localFile, String pathAndFileOnRemoteServer) {
+ return copyToServer(props, newInputStreamSupplier(localFile), (int)localFile.length(), pathAndFileOnRemoteServer);
+ }
+
+ private int copyToServer(Map<String,?> props, Supplier<InputStream> contentsSupplier, long length, String pathAndFileOnRemoteServer) {
+ acquire(new PutFileAction(props, pathAndFileOnRemoteServer, contentsSupplier, length));
+ return 0; // TODO Can we assume put will have thrown exception if failed? Rather than exit code != 0?
+ }
+
+
+ @Override
+ public int copyFromServer(Map<String,?> props, String pathAndFileOnRemoteServer, File localFile) {
+ InputStream contents = acquire(new GetFileAction(pathAndFileOnRemoteServer));
+ try {
+ FileUtil.copyTo(contents, localFile);
+ return 0; // TODO Can we assume put will have thrown exception if failed? Rather than exit code != 0?
+ } finally {
+ Streams.closeQuietly(contents);
+ }
+ }
+
+ /**
+ * This creates a script containing the user's commands, copies it to the remote server, and
+ * executes the script. The script is then deleted.
+ * <p>
+ * Executing commands directly is fraught with dangers! Here are other options, and their problems:
+ * <ul>
+ * <li>Use execCommands, rather than shell.
+ * The user's environment will not be setup normally (e.g. ~/.bash_profile will not have been sourced)
+ * so things like wget may not be on the PATH.
+ * <li>Send the stream of commands to the shell.
+ * But characters being sent can be lost.
+ * Try the following (e.g. in an OS X terminal):
+ * - sleep 5
+ * - <paste a command that is 1000s of characters long>
+ * Only the first 1024 characters appear. The rest are lost.
+ * If sending a stream of commands, you need to be careful not send the next (big) command while the
+ * previous one is still executing.
+ * <li>Send a stream to the shell, but spot when the previous command has completed.
+ * e.g. by looking for the prompt (but what if the commands being executed change the prompt?)
+ * e.g. by putting every second command as "echo <uid>", and waiting for the stdout.
+ * This gets fiddly...
+ * </ul>
+ *
+ * So on balance, the script-based approach seems most reliable, even if there is an overhead
+ * of separate message(s) for copying the file!
+ *
+ * Another consideration is long-running scripts. On some clouds when executing a script that takes
+ * several minutes, we have seen it fail with -1 (e.g. 1 in 20 times). This suggests the ssh connection
+ * is being dropped. To avoid this problem, we can execute the script asynchronously, writing to files
+ * the stdout/stderr/pid/exitStatus. We then periodically poll to retrieve the contents of these files.
+ * Use {@link #PROP_EXEC_ASYNC} to force this mode of execution.
+ */
+ @Override
+ public int execScript(final Map<String,?> props, final List<String> commands, final Map<String,?> env) {
+ Boolean execAsync = getOptionalVal(props, PROP_EXEC_ASYNC);
+ if (Boolean.TRUE.equals(execAsync) && BrooklynFeatureEnablement.isEnabled(BrooklynFeatureEnablement.FEATURE_SSH_ASYNC_EXEC)) {
+ return execScriptAsyncAndPoll(props, commands, env);
+ } else {
+ if (Boolean.TRUE.equals(execAsync)) {
+ if (LOG.isDebugEnabled()) LOG.debug("Ignoring ssh exec-async configuration, because feature is disabled");
+ }
+ return new ToolAbstractExecScript(props) {
+ public int run() {
+ String scriptContents = toScript(props, commands, env);
+ if (LOG.isTraceEnabled()) LOG.trace("Running shell command at {} as script: {}", host, scriptContents);
+ copyToServer(ImmutableMap.of("permissions", "0700"), scriptContents.getBytes(), scriptPath);
+ return asInt(acquire(new ShellAction(buildRunScriptCommand(), out, err, execTimeout)), -1);
+ }
+ }.run();
+ }
+ }
+
+ /**
+ * Executes the script in the background (`nohup ... &`), and then executes other ssh commands to poll for the
+ * stdout, stderr and exit code of that original process (which will each have been written to separate files).
+ *
+ * The polling is a "long poll". That is, it executes a long-running ssh command to retrieve the stdout, etc.
+ * If that long-poll command fails, then we just execute another one to pick up from where it left off.
+ * This means we do not need to execute many ssh commands (which are expensive), but can still return promptly
+ * when the command completes.
+ *
+ * Much of this was motivated by https://issues.apache.org/jira/browse/BROOKLYN-106, which is no longer
+ * an issue. The retries (e.g. in the upload-script) are arguably overkill given that {@link #acquire(SshAction)}
+ * will already retry. However, leaving this in place as it could prove useful when working with flakey
+ * networks in the future.
+ *
+ * TODO There are (probably) issues with this method when using {@link ShellTool#PROP_RUN_AS_ROOT}.
+ * I (Aled) saw the .pid file having an owner of root:root, and a failure message in stderr of:
+ * -bash: line 3: /tmp/brooklyn-20150113-161203056-XMEo-move_install_dir_from_user_to_.pid: Permission denied
+ */
+ protected int execScriptAsyncAndPoll(final Map<String,?> props, final List<String> commands, final Map<String,?> env) {
+ return new ToolAbstractAsyncExecScript(props) {
+ private int maxConsecutiveSshFailures = 3;
+ private Duration maxDelayBetweenPolls = Duration.seconds(20);
+ private Duration pollTimeout = getOptionalVal(props, PROP_EXEC_ASYNC_POLLING_TIMEOUT, Duration.FIVE_MINUTES);
+ private int iteration = 0;
+ private int consecutiveSshFailures = 0;
+ private int stdoutCount = 0;
+ private int stderrCount = 0;
+ private Stopwatch timer;
+
+ public int run() {
+ timer = Stopwatch.createStarted();
+ final String scriptContents = toScript(props, commands, env);
+ if (LOG.isTraceEnabled()) LOG.trace("Running shell command at {} as async script: {}", host, scriptContents);
+
+ // Upload script; try repeatedly because have seen timeout intermittently on vcloud-director (BROOKLYN-106 related).
+ boolean uploadSuccess = Repeater.create("async script upload on "+SshjTool.this.toString()+" (for "+getSummary()+")")
+ .backoffTo(maxDelayBetweenPolls)
+ .limitIterationsTo(3)
+ .rethrowException()
+ .until(new Callable<Boolean>() {
+ @Override
+ public Boolean call() throws Exception {
+ iteration++;
+ if (LOG.isDebugEnabled()) {
+ String msg = "Uploading (iteration="+iteration+") for async script on "+SshjTool.this.toString()+" (for "+getSummary()+")";
+ if (iteration == 1) {
+ LOG.trace(msg);
+ } else {
+ LOG.debug(msg);
+ }
+ }
+ copyToServer(ImmutableMap.of("permissions", "0700"), scriptContents.getBytes(), scriptPath);
+ return true;
+ }})
+ .run();
+
+ if (!uploadSuccess) {
+ // Unexpected! Should have either returned true or have rethrown the exception; should never get false.
+ String msg = "Unexpected state: repeated failure for async script upload on "+SshjTool.this.toString()+" ("+getSummary()+")";
+ LOG.warn(msg+"; rethrowing");
+ throw new IllegalStateException(msg);
+ }
+
+ // Execute script asynchronously
+ int execResult = asInt(acquire(new ShellAction(buildRunScriptCommand(), out, err, execTimeout)), -1);
+ if (execResult != 0) return execResult;
+
+ // Long polling to get the status
+ try {
+ final AtomicReference<Integer> result = new AtomicReference<Integer>();
+ boolean success = Repeater.create("async script long-poll on "+SshjTool.this.toString()+" (for "+getSummary()+")")
+ .backoffTo(maxDelayBetweenPolls)
+ .limitTimeTo(execTimeout)
+ .until(new Callable<Boolean>() {
+ @Override
+ public Boolean call() throws Exception {
+ iteration++;
+ if (LOG.isDebugEnabled()) LOG.debug("Doing long-poll (iteration="+iteration+") for async script to complete on "+SshjTool.this.toString()+" (for "+getSummary()+")");
+ Integer exitstatus = longPoll();
+ result.set(exitstatus);
+ return exitstatus != null;
+ }})
+ .run();
+
+ if (!success) {
+ // Timed out
+ String msg = "Timeout for async script to complete on "+SshjTool.this.toString()+" ("+getSummary()+")";
+ LOG.warn(msg+"; rethrowing");
+ throw new TimeoutException(msg);
+ }
+
+ return result.get();
+
+ } catch (Exception e) {
+ LOG.debug("Problem polling for async script on "+SshjTool.this.toString()+" (for "+getSummary()+"); rethrowing after deleting temporary files", e);
+ throw Exceptions.propagate(e);
+ } finally {
+ // Delete the temporary files created (and the `tail -c` commands that might have been left behind by long-polls).
+ // Using pollTimeout so doesn't wait forever, but waits for a reasonable (configurable) length of time.
+ // TODO also execute this if the `buildRunScriptCommand` fails, as that might have left files behind?
+ try {
+ int execDeleteResult = asInt(acquire(new ShellAction(deleteTemporaryFilesCommand(), out, err, pollTimeout)), -1);
+ if (execDeleteResult != 0) {
+ LOG.debug("Problem deleting temporary files of async script on "+SshjTool.this.toString()+" (for "+getSummary()+"): exit status "+execDeleteResult);
+ }
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ LOG.debug("Problem deleting temporary files of async script on "+SshjTool.this.toString()+" (for "+getSummary()+"); continuing", e);
+ }
+ }
+ }
+
+ Integer longPoll() throws IOException {
+ // Long-polling to get stdout, stderr + exit status of async task.
+ // If our long-poll disconnects, we will just re-execute.
+ // We wrap the stdout/stderr so that we can get the size count.
+ // If we disconnect, we will pick up from that char of the stream.
+ // TODO Additional stdout/stderr written by buildLongPollCommand() could interfere,
+ // causing us to miss some characters.
+ Duration nextPollTimeout = Duration.min(pollTimeout, Duration.millis(execTimeout.toMilliseconds()-timer.elapsed(TimeUnit.MILLISECONDS)));
+ CountingOutputStream countingOut = (out == null) ? null : new CountingOutputStream(out);
+ CountingOutputStream countingErr = (err == null) ? null : new CountingOutputStream(err);
+ List<String> pollCommand = buildLongPollCommand(stdoutCount, stderrCount, nextPollTimeout);
+ Duration sshJoinTimeout = nextPollTimeout.add(Duration.TEN_SECONDS);
+ ShellAction action = new ShellAction(pollCommand, countingOut, countingErr, sshJoinTimeout);
+
+ int longPollResult;
+ try {
+ longPollResult = asInt(acquire(action, 3, nextPollTimeout), -1);
+ } catch (RuntimeTimeoutException e) {
+ if (LOG.isDebugEnabled()) LOG.debug("Long-poll timed out on "+SshjTool.this.toString()+" (for "+getSummary()+"): "+e);
+ return null;
+ }
+ stdoutCount += (countingOut == null) ? 0 : countingOut.getCount();
+ stderrCount += (countingErr == null) ? 0 : countingErr.getCount();
+
+ if (longPollResult == 0) {
+ if (LOG.isDebugEnabled()) LOG.debug("Long-poll succeeded (exit status 0) on "+SshjTool.this.toString()+" (for "+getSummary()+")");
+ return longPollResult; // success
+
+ } else if (longPollResult == -1) {
+ // probably a connection failure; try again
+ if (LOG.isDebugEnabled()) LOG.debug("Long-poll received exit status -1; will retry on "+SshjTool.this.toString()+" (for "+getSummary()+")");
+ return null;
+
+ } else if (longPollResult == 125) {
+ // 125 is the special code for timeout in long-poll (see buildLongPollCommand).
+ // However, there is a tiny chance that the underlying command might have returned that exact exit code!
+ // Don't treat a timeout as a "consecutiveSshFailure".
+ if (LOG.isDebugEnabled()) LOG.debug("Long-poll received exit status "+longPollResult+"; most likely timeout; retrieving actual status on "+SshjTool.this.toString()+" (for "+getSummary()+")");
+ return retrieveStatusCommand();
+
+ } else {
+ // want to double-check whether this is the exit-code from the async process, or
+ // some unexpected failure in our long-poll command.
+ if (LOG.isDebugEnabled()) LOG.debug("Long-poll received exit status "+longPollResult+"; retrieving actual status on "+SshjTool.this.toString()+" (for "+getSummary()+")");
+ Integer result = retrieveStatusCommand();
+ if (result != null) {
+ return result;
+ }
+ }
+
+ consecutiveSshFailures++;
+ if (consecutiveSshFailures > maxConsecutiveSshFailures) {
+ LOG.warn("Aborting on "+consecutiveSshFailures+" consecutive ssh connection errors (return -1) when polling for async script to complete on "+SshjTool.this.toString()+" ("+getSummary()+")");
+ return -1;
+ } else {
+ LOG.info("Retrying after ssh connection error when polling for async script to complete on "+SshjTool.this.toString()+" ("+getSummary()+")");
+ return null;
+ }
+ }
+
+ Integer retrieveStatusCommand() throws IOException {
+ // want to double-check whether this is the exit-code from the async process, or
+ // some unexpected failure in our long-poll command.
+ ByteArrayOutputStream statusOut = new ByteArrayOutputStream();
+ ByteArrayOutputStream statusErr = new ByteArrayOutputStream();
+ int statusResult = asInt(acquire(new ShellAction(buildRetrieveStatusCommand(), statusOut, statusErr, execTimeout)), -1);
+
+ if (statusResult == 0) {
+ // The status we retrieved really is valid; return it.
+ // TODO How to ensure no additional output in stdout/stderr when parsing below?
+ String statusOutStr = new String(statusOut.toByteArray()).trim();
+ if (Strings.isEmpty(statusOutStr)) {
+ // suggests not yet completed; will retry with long-poll
+ if (LOG.isDebugEnabled()) LOG.debug("Long-poll retrieved status directly; command successful but no result available on "+SshjTool.this.toString()+" (for "+getSummary()+")");
+ return null;
+ } else {
+ if (LOG.isDebugEnabled()) LOG.debug("Long-poll retrieved status directly; returning '"+statusOutStr+"' on "+SshjTool.this.toString()+" (for "+getSummary()+")");
+ int result = Integer.parseInt(statusOutStr);
+ return result;
+ }
+
+ } else if (statusResult == -1) {
+ // probably a connection failure; try again with long-poll
+ if (LOG.isDebugEnabled()) LOG.debug("Long-poll retrieving status directly received exit status -1; will retry on "+SshjTool.this.toString()+" (for "+getSummary()+")");
+ return null;
+
+ } else {
+ if (out != null) {
+ out.write(toUTF8ByteArray("retrieving status failed with exit code "+statusResult+" (stdout follow)"));
+ out.write(statusOut.toByteArray());
+ }
+ if (err != null) {
+ err.write(toUTF8ByteArray("retrieving status failed with exit code "+statusResult+" (stderr follow)"));
+ err.write(statusErr.toByteArray());
+ }
+
+ if (LOG.isDebugEnabled()) LOG.debug("Long-poll retrieving status failed; returning "+statusResult+" on "+SshjTool.this.toString()+" (for "+getSummary()+")");
+ return statusResult;
+ }
+ }
+ }.run();
+ }
+
+ public int execShellDirect(Map<String,?> props, List<String> commands, Map<String,?> env) {
+ OutputStream out = getOptionalVal(props, PROP_OUT_STREAM);
+ OutputStream err = getOptionalVal(props, PROP_ERR_STREAM);
+ Duration execTimeout = getOptionalVal(props, PROP_EXEC_TIMEOUT);
+
+ List<String> cmdSequence = toCommandSequence(commands, env);
+ List<String> allcmds = ImmutableList.<String>builder()
+ .add(getOptionalVal(props, PROP_DIRECT_HEADER))
+ .addAll(cmdSequence)
+ .add("exit $?")
+ .build();
+
+ if (LOG.isTraceEnabled()) LOG.trace("Running shell command at {}: {}", host, allcmds);
+
+ Integer result = acquire(new ShellAction(allcmds, out, err, execTimeout));
+ if (LOG.isTraceEnabled()) LOG.trace("Running shell command at {} completed: return status {}", host, result);
+ return asInt(result, -1);
+ }
+
+ @Override
+ public int execCommands(Map<String,?> props, List<String> commands, Map<String,?> env) {
+ if (Boolean.FALSE.equals(props.get("blocks"))) {
+ throw new IllegalArgumentException("Cannot exec non-blocking: command="+commands);
+ }
+
+ // If async is set, then do it as execScript
+ Boolean execAsync = getOptionalVal(props, PROP_EXEC_ASYNC);
+ if (Boolean.TRUE.equals(execAsync) && BrooklynFeatureEnablement.isEnabled(BrooklynFeatureEnablement.FEATURE_SSH_ASYNC_EXEC)) {
+ return execScriptAsyncAndPoll(props, commands, env);
+ }
+
+ OutputStream out = getOptionalVal(props, PROP_OUT_STREAM);
+ OutputStream err = getOptionalVal(props, PROP_ERR_STREAM);
+ String separator = getOptionalVal(props, PROP_SEPARATOR);
+ Duration execTimeout = getOptionalVal(props, PROP_EXEC_TIMEOUT);
+
+ List<String> allcmds = toCommandSequence(commands, env);
+ String singlecmd = Joiner.on(separator).join(allcmds);
+
+ if (Boolean.TRUE.equals(getOptionalVal(props, PROP_RUN_AS_ROOT))) {
+ LOG.warn("Cannot run as root when executing as command; run as a script instead (will run as normal user): "+singlecmd);
+ }
+
+ if (LOG.isTraceEnabled()) LOG.trace("Running command at {}: {}", host, singlecmd);
+
+ Command result = acquire(new ExecAction(singlecmd, out, err, execTimeout));
+ if (LOG.isTraceEnabled()) LOG.trace("Running command at {} completed: exit code {}", host, result.getExitStatus());
+ // can be null if no exit status is received (observed on kill `ps aux | grep thing-to-grep-for | awk {print $2}`
+ if (result.getExitStatus()==null) LOG.warn("Null exit status running at {}: {}", host, singlecmd);
+
+ return asInt(result.getExitStatus(), -1);
+ }
+
+ protected void checkConnected() {
+ if (!isConnected()) {
+ throw new IllegalStateException(String.format("(%s) ssh not connected!", toString()));
+ }
+ }
+
+ protected void backoffForAttempt(int retryAttempt, String message) {
+ backoffLimitedRetryHandler.imposeBackoffExponentialDelay(retryAttempt, message);
+ }
+
+ protected <T, C extends SshAction<T>> T acquire(C action) {
+ return acquire(action, sshTries, sshTriesTimeout == 0 ? Duration.PRACTICALLY_FOREVER : Duration.millis(sshTriesTimeout));
+ }
+
+ protected <T, C extends SshAction<T>> T acquire(C action, int sshTries, Duration sshTriesTimeout) {
+ Stopwatch stopwatch = Stopwatch.createStarted();
+
+ for (int i = 0; i < sshTries; i++) {
+ try {
+ action.clear();
+ if (LOG.isTraceEnabled()) LOG.trace(">> ({}) acquiring {}", toString(), action);
+ Stopwatch perfStopwatch = Stopwatch.createStarted();
+
+ T returnVal;
+ try {
+ returnVal = action.create();
+ } catch (AssertionError e) {
+ /*
+ * TODO In net.schmizz.sshj.SSHClient.auth(SSHClient.java:204) throws AssertionError
+ * if not connected. This can happen if another thread has called disconnect
+ * concurrently. This is changed in sshj v0.9.0 to instead throw an IllegalStateException.
+ *
+ * For now, we'll retry. See "TODO" at top of class about synchronization.
+ */
+ throw new IllegalStateException("Problem in "+toString()+" for "+action, e);
+ }
+
+ if (LOG.isTraceEnabled()) LOG.trace("<< ({}) acquired {}", toString(), returnVal);
+ if (LOG.isTraceEnabled()) LOG.trace("SSH Performance: {} {} took {}", new Object[] {
+ sshClientConnection.getHostAndPort(),
+ action.getClass().getSimpleName() != null ? action.getClass().getSimpleName() : action,
+ Time.makeTimeStringRounded(perfStopwatch)});
+ return returnVal;
+ } catch (Exception e) {
+ // uninformative net.schmizz.sshj.connection.ConnectionException:
+ // Request failed (reason=UNKNOWN) may mean remote Subsytem is disabled (e.g. for FTP)
+ // if key is missing, get a UserAuth error
+ String errorMessage = String.format("(%s) error acquiring %s", toString(), action);
+ String fullMessage = String.format("%s (attempt %s/%s, in time %s/%s)",
+ errorMessage, (i+1), sshTries, Time.makeTimeStringRounded(stopwatch.elapsed(TimeUnit.MILLISECONDS)),
+ (sshTriesTimeout.equals(Duration.PRACTICALLY_FOREVER) ? "unlimited" : Time.makeTimeStringRounded(sshTriesTimeout)));
+ try {
+ disconnect();
+ } catch (Exception e2) {
+ LOG.debug("<< ("+toString()+") error closing connection: "+e+" / "+e2, e);
+ }
+ if (i + 1 == sshTries) {
+ LOG.debug("<< {} (rethrowing, out of retries): {}", fullMessage, e.getMessage());
+ throw propagate(e, fullMessage + "; out of retries");
+ } else if (sshTriesTimeout.isShorterThan(stopwatch)) {
+ LOG.debug("<< {} (rethrowing, out of time - max {}): {}", new Object[] { fullMessage, Time.makeTimeStringRounded(sshTriesTimeout), e.getMessage() });
+ throw new RuntimeTimeoutException(fullMessage + "; out of time", e);
+ } else {
+ if (LOG.isDebugEnabled()) LOG.debug("<< {}: {}", fullMessage, e.getMessage());
+ backoffForAttempt(i + 1, errorMessage + ": " + e.getMessage());
+ if (action != sshClientConnection)
+ connect();
+ continue;
+ }
+ }
+ }
+ assert false : "should not reach here";
+ return null;
+ }
+
+ private final SshAction<SFTPClient> sftpConnection = new SshAction<SFTPClient>() {
+
+ private SFTPClient sftp;
+
+ @Override
+ public void clear() {
+ closeWhispering(sftp, this);
+ sftp = null;
+ }
+
+ @Override
+ public SFTPClient create() throws IOException {
+ checkConnected();
+ sftp = sshClientConnection.ssh.newSFTPClient();
+ return sftp;
+ }
+
+ @Override
+ public String toString() {
+ return "SFTPClient()";
+ }
+ };
+
+ private class GetFileAction implements SshAction<InputStream> {
+ private final String path;
+ private SFTPClient sftp;
+
+ GetFileAction(String path) {
+ this.path = checkNotNull(path, "path");
+ }
+
+ @Override
+ public void clear() throws IOException {
+ closeWhispering(sftp, this);
+ sftp = null;
+ }
+
+ @Override
+ public InputStream create() throws Exception {
+ sftp = acquire(sftpConnection);
+ return new CloseFtpChannelOnCloseInputStream(
+ sftp.getSFTPEngine().open(path).getInputStream(), sftp);
+ }
+
+ @Override
+ public String toString() {
+ return "Payload(path=[" + path + "])";
+ }
+ }
+
+ private class PutFileAction implements SshAction<Void> {
+ // TODO support backup as a property?
+
+ private SFTPClient sftp;
+ private final String path;
+ private final int permissionsMask;
+ private final long lastModificationDate;
+ private final long lastAccessDate;
+ private final int uid;
+ private final Supplier<InputStream> contentsSupplier;
+ private final Integer length;
+
+ PutFileAction(Map<String,?> props, String path, Supplier<InputStream> contentsSupplier, long length) {
+ String permissions = getOptionalVal(props, PROP_PERMISSIONS);
+ long lastModificationDateVal = getOptionalVal(props, PROP_LAST_MODIFICATION_DATE);
+ long lastAccessDateVal = getOptionalVal(props, PROP_LAST_ACCESS_DATE);
+ if (lastAccessDateVal <= 0 ^ lastModificationDateVal <= 0) {
+ lastAccessDateVal = Math.max(lastAccessDateVal, lastModificationDateVal);
+ lastModificationDateVal = Math.max(lastAccessDateVal, lastModificationDateVal);
+ }
+ this.permissionsMask = Integer.parseInt(permissions, 8);
+ this.lastAccessDate = lastAccessDateVal;
+ this.lastModificationDate = lastModificationDateVal;
+ this.uid = getOptionalVal(props, PROP_OWNER_UID);
+ this.path = checkNotNull(path, "path");
+ this.contentsSupplier = checkNotNull(contentsSupplier, "contents");
+ this.length = Ints.checkedCast(checkNotNull((long)length, "size"));
+ }
+
+ @Override
+ public void clear() {
+ closeWhispering(sftp, this);
+ sftp = null;
+ }
+
+ @Override
+ public Void create() throws Exception {
+ final AtomicReference<InputStream> inputStreamRef = new AtomicReference<InputStream>();
+ sftp = acquire(sftpConnection);
+ try {
+ sftp.put(new InMemorySourceFile() {
+ @Override public String getName() {
+ return path;
+ }
+ @Override public long getLength() {
+ return length;
+ }
+ @Override public InputStream getInputStream() throws IOException {
+ InputStream contents = contentsSupplier.get();
+ inputStreamRef.set(contents);
+ return contents;
+ }
+ }, path);
+ sftp.chmod(path, permissionsMask);
+ if (uid != -1) {
+ sftp.chown(path, uid);
+ }
+ if (lastAccessDate > 0) {
+ sftp.setattr(path, new FileAttributes.Builder()
+ .withAtimeMtime(lastAccessDate, lastModificationDate)
+ .build());
+ }
+ } finally {
+ closeWhispering(inputStreamRef.get(), this);
+ }
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return "Put(path=[" + path + " "+length+"])";
+ }
+ }
+
+ // TODO simpler not to use predicates
+ @VisibleForTesting
+ Predicate<String> causalChainHasMessageContaining(final Exception from) {
+ return new Predicate<String>() {
+ @Override
+ public boolean apply(final String input) {
+ return any(getCausalChain(from), new Predicate<Throwable>() {
+ @Override
+ public boolean apply(Throwable throwable) {
+ return (throwable.toString().contains(input))
+ || (throwable.getMessage() != null && throwable.getMessage().contains(input));
+ }
+ });
+ }
+ };
+ }
+
+ protected SshAction<Session> newSessionAction() {
+
+ return new SshAction<Session>() {
+
+ private Session session = null;
+
+ @Override
+ public void clear() throws TransportException, ConnectionException {
+ closeWhispering(session, this);
+ session = null;
+ }
+
+ @Override
+ public Session create() throws Exception {
+ checkConnected();
+ session = sshClientConnection.ssh.startSession();
+ if (allocatePTY) {
+ session.allocatePTY(TERM, 80, 24, 0, 0, Collections.<PTYMode, Integer> emptyMap());
+ }
+ return session;
+ }
+
+ @Override
+ public String toString() {
+ return "Session()";
+ }
+ };
+
+ }
+
+ class ExecAction implements SshAction<Command> {
+ private final String command;
+ private final OutputStream out;
+ private final OutputStream err;
+ private final Duration timeout;
+
+ private Session session;
+ private Shell shell;
+ private StreamGobbler outgobbler;
+ private StreamGobbler errgobbler;
+
+ ExecAction(String command, OutputStream out, OutputStream err, Duration timeout) {
+ this.command = checkNotNull(command, "command");
+ this.out = out;
+ this.err = err;
+ Duration sessionTimeout = (sshClientConnection.getSessionTimeout() == 0)
+ ? Duration.PRACTICALLY_FOREVER
+ : Duration.millis(sshClientConnection.getSessionTimeout());
+ this.timeout = (timeout == null) ? sessionTimeout : Duration.min(timeout, sessionTimeout);
+ }
+
+ @Override
+ public void clear() throws TransportException, ConnectionException {
+ closeWhispering(session, this);
+ closeWhispering(shell, this);
+ closeWhispering(outgobbler, this);
+ closeWhispering(errgobbler, this);
+ session = null;
+ shell = null;
+ }
+
+ @Override
+ public Command create() throws Exception {
+ try {
+ session = acquire(newSessionAction());
+
+ Command output = session.exec(checkNotNull(command, "command"));
+
+ if (out != null) {
+ outgobbler = new StreamGobbler(output.getInputStream(), out, (Logger)null);
+ outgobbler.start();
+ }
+ if (err != null) {
+ errgobbler = new StreamGobbler(output.getErrorStream(), err, (Logger)null);
+ errgobbler.start();
+ }
+ try {
+ output.join((int)Math.min(timeout.toMilliseconds(), Integer.MAX_VALUE), TimeUnit.MILLISECONDS);
+ return output;
+
+ } finally {
+ // wait for all stdout/stderr to have been re-directed
+ try {
+ // Don't use forever (i.e. 0) because BROOKLYN-106: ssh hangs
+ long joinTimeout = 10*1000;
+ if (outgobbler != null) outgobbler.join(joinTimeout);
+ if (errgobbler != null) errgobbler.join(joinTimeout);
+ } catch (InterruptedException e) {
+ LOG.warn("Interrupted gobbling streams from ssh: "+command, e);
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ } finally {
+ clear();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Exec(command=[" + command + "])";
+ }
+ }
+
+ class ShellAction implements SshAction<Integer> {
+ @VisibleForTesting
+ final List<String> commands;
+ @VisibleForTesting
+ final OutputStream out;
+ @VisibleForTesting
+ final OutputStream err;
+
+ private Session session;
+ private Shell shell;
+ private StreamGobbler outgobbler;
+ private StreamGobbler errgobbler;
+ private Duration timeout;
+
+ ShellAction(List<String> commands, OutputStream out, OutputStream err, Duration timeout) {
+ this.commands = checkNotNull(commands, "commands");
+ this.out = out;
+ this.err = err;
+ Duration sessionTimeout = (sshClientConnection.getSessionTimeout() == 0)
+ ? Duration.PRACTICALLY_FOREVER
+ : Duration.millis(sshClientConnection.getSessionTimeout());
+ this.timeout = (timeout == null) ? sessionTimeout : Duration.min(timeout, sessionTimeout);
+ }
+
+ @Override
+ public void clear() throws TransportException, ConnectionException {
+ closeWhispering(session, this);
+ closeWhispering(shell, this);
+ closeWhispering(outgobbler, this);
+ closeWhispering(errgobbler, this);
+ session = null;
+ shell = null;
+ }
+
+ @Override
+ public Integer create() throws Exception {
+ try {
+ session = acquire(newSessionAction());
+
+ shell = session.startShell();
+
+ if (out != null) {
+ InputStream outstream = shell.getInputStream();
+ outgobbler = new StreamGobbler(outstream, out, (Logger)null);
+ outgobbler.start();
+ }
+ if (err != null) {
+ InputStream errstream = shell.getErrorStream();
+ errgobbler = new StreamGobbler(errstream, err, (Logger)null);
+ errgobbler.start();
+ }
+
+ OutputStream output = shell.getOutputStream();
+
+ for (CharSequence cmd : commands) {
+ try {
+ output.write(toUTF8ByteArray(cmd+"\n"));
+ output.flush();
+ } catch (ConnectionException e) {
+ if (!shell.isOpen()) {
+ // shell is closed; presumably the user command did `exit`
+ if (LOG.isDebugEnabled()) LOG.debug("Shell closed to {} when executing {}", SshjTool.this.toString(), commands);
+ break;
+ } else {
+ throw e;
+ }
+ }
+ }
+ // workaround attempt for SSHJ deadlock - https://github.com/shikhar/sshj/issues/105
+ synchronized (shell.getOutputStream()) {
+ shell.sendEOF();
+ }
+ closeWhispering(output, this);
+
+ boolean timedOut = false;
+ try {
+ long timeoutMillis = Math.min(timeout.toMilliseconds(), Integer.MAX_VALUE);
+ long timeoutEnd = System.currentTimeMillis() + timeoutMillis;
+ Exception last = null;
+ do {
+ if (!shell.isOpen() && ((SessionChannel)session).getExitStatus()!=null)
+ // shell closed, and exit status returned
+ break;
+ boolean endBecauseReturned =
+ // if either condition is satisfied, then wait 1s in hopes the other does, then return
+ (!shell.isOpen() || ((SessionChannel)session).getExitStatus()!=null);
+ try {
+ shell.join(1000, TimeUnit.MILLISECONDS);
+ } catch (ConnectionException e) {
+ last = e;
+ }
+ if (endBecauseReturned) {
+ // shell is still open, ie some process is running
+ // but we have a result code, so main shell is finished
+ // we waited one second extra to allow any background process
+ // which is nohupped to really be in the background (#162)
+ // now let's bail out
+ break;
+ }
+ } while (System.currentTimeMillis() < timeoutEnd);
+ if (shell.isOpen() && ((SessionChannel)session).getExitStatus()==null) {
+ LOG.debug("Timeout ({}) in SSH shell to {}", timeout, this);
+ // we timed out, or other problem -- reproduce the error.
+ // The shell.join should always have thrown ConnectionExceptoin (looking at code of
+ // AbstractChannel), but javadoc of Channel doesn't explicity say that so play it safe.
+ timedOut = true;
+ throw (last != null) ? last : new TimeoutException("Timeout after "+timeout+" executing "+this);
+ }
+ return ((SessionChannel)session).getExitStatus();
+ } finally {
+ // wait for all stdout/stderr to have been re-directed
+ closeWhispering(shell, this);
+ shell = null;
+ try {
+ // Don't use forever (i.e. 0) because BROOKLYN-106: ssh hangs
+ long joinTimeout = (timedOut) ? 1000 : 10*1000;
+ if (outgobbler != null) {
+ outgobbler.join(joinTimeout);
+ outgobbler.close();
+ }
+ if (errgobbler != null) {
+ errgobbler.join(joinTimeout);
+ errgobbler.close();
+ }
+ } catch (InterruptedException e) {
+ LOG.warn("Interrupted gobbling streams from ssh: "+commands, e);
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ } finally {
+ clear();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Shell(command=[" + commands + "])";
+ }
+ }
+
+ private byte[] toUTF8ByteArray(String string) {
+ return org.bouncycastle.util.Strings.toUTF8ByteArray(string);
+ }
+
+ private Supplier<InputStream> newInputStreamSupplier(final byte[] contents) {
+ return new Supplier<InputStream>() {
+ @Override public InputStream get() {
+ return new ByteArrayInputStream(contents);
+ }
+ };
+ }
+
+ private Supplier<InputStream> newInputStreamSupplier(final File file) {
+ return new Supplier<InputStream>() {
+ @Override public InputStream get() {
+ try {
+ return new FileInputStream(file);
+ } catch (FileNotFoundException e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+ };
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/javalang/ReflectionScanner.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/javalang/ReflectionScanner.java b/core/src/main/java/org/apache/brooklyn/core/util/javalang/ReflectionScanner.java
new file mode 100644
index 0000000..e0b824a
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/javalang/ReflectionScanner.java
@@ -0,0 +1,135 @@
+/*
+ * 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.util.javalang;
+
+import java.lang.annotation.Annotation;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+import org.reflections.ReflectionUtils;
+import org.reflections.Reflections;
+import org.reflections.Store;
+import org.reflections.scanners.Scanner;
+import org.reflections.scanners.SubTypesScanner;
+import org.reflections.scanners.TypeAnnotationsScanner;
+import org.reflections.util.ClasspathHelper;
+import org.reflections.util.ConfigurationBuilder;
+import org.reflections.util.FilterBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.util.text.Strings;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+
+/** Facade on {@link Reflections} which logs warnings for unloadable classes but does not fail */
+public class ReflectionScanner {
+
+ private static final Logger log = LoggerFactory.getLogger(ReflectionScanner.class);
+
+ protected final ClassLoader[] classLoaders;
+ protected final Reflections reflections;
+
+ /** scanner which will look in the given urls
+ * (or if those are null attempt to infer from the first entry in the classloaders,
+ * although currently that seems to only pick up directories, not JAR's),
+ * optionally filtering for the given prefix;
+ * any or all arguments can be null to accept all (and use default classpath for classloading).
+ **/
+ public ReflectionScanner(
+ final Iterable<URL> urlsToScan,
+ final String optionalPrefix,
+ final ClassLoader ...classLoaders) {
+ reflections = new Reflections(new ConfigurationBuilder() {
+ {
+ final Predicate<String> filter =
+ Strings.isNonEmpty(optionalPrefix) ? new FilterBuilder.Include(FilterBuilder.prefix(optionalPrefix)) : null;
+
+ if (urlsToScan!=null)
+ setUrls(ImmutableSet.copyOf(urlsToScan));
+ else if (classLoaders.length>0 && classLoaders[0]!=null)
+ setUrls(
+ ClasspathHelper.forPackage(Strings.isNonEmpty(optionalPrefix) ? optionalPrefix : "",
+ asClassLoaderVarArgs(classLoaders[0])));
+
+ if (filter!=null) filterInputsBy(filter);
+
+ Scanner typeScanner = new TypeAnnotationsScanner();
+ if (filter!=null) typeScanner = typeScanner.filterResultsBy(filter);
+ Scanner subTypeScanner = new SubTypesScanner();
+ if (filter!=null) subTypeScanner = subTypeScanner.filterResultsBy(filter);
+ setScanners(typeScanner, subTypeScanner);
+
+ for (ClassLoader cl: classLoaders)
+ if (cl!=null) addClassLoader(cl);
+ }
+ });
+ this.classLoaders = Iterables.toArray(Iterables.filter(Arrays.asList(classLoaders), Predicates.notNull()), ClassLoader.class);
+ }
+
+ private static ClassLoader[] asClassLoaderVarArgs(final ClassLoader classLoaderToSearch) {
+ return classLoaderToSearch==null ? new ClassLoader[0] : new ClassLoader[] { classLoaderToSearch };
+ }
+
+ public Store getStore() {
+ return reflections.getStore();
+ }
+
+ /** overrides delegate so as to log rather than throw exception if a class cannot be loaded */
+ public <T> Set<Class<? extends T>> getSubTypesOf(final Class<T> type) {
+ Set<String> subTypes = getStore().getSubTypesOf(type.getName());
+ return ImmutableSet.copyOf(this.<T>forNames(subTypes, "sub-type of "+type));
+ }
+
+ /** overrides delegate so as to log rather than throw exception if a class cannot be loaded */
+ public Set<Class<?>> getTypesAnnotatedWith(Class<? extends Annotation> annotation) {
+ Set<String> annotatedWith = getStore().getTypesAnnotatedWith(annotation.getName());
+ return ImmutableSet.copyOf(this.forNames(annotatedWith, "annotated "+annotation.getName()));
+ }
+
+ @SuppressWarnings("unchecked")
+ protected <T> List<Class<? extends T>> forNames(Set<String> classNames, final String context) {
+ List<Class<? extends T>> result = new ArrayList<Class<? extends T>>();
+ for (String className : classNames) {
+ //noinspection unchecked
+ try {
+ Class<? extends T> clazz = (Class<? extends T>) loadClass(className);
+ if (clazz != null) {
+ result.add(clazz);
+ } else {
+ log.warn("Unable to instantiate '"+className+"' ("+context+")");
+ }
+ } catch (Throwable e) {
+ log.warn("Unable to instantiate '"+className+"' ("+context+"): "+e);
+ }
+ }
+ return result;
+ }
+
+ protected Class<?> loadClass(String className) {
+ return ReflectionUtils.forName(className, classLoaders);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/javalang/UrlClassLoader.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/javalang/UrlClassLoader.java b/core/src/main/java/org/apache/brooklyn/core/util/javalang/UrlClassLoader.java
new file mode 100644
index 0000000..afd0c8e
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/javalang/UrlClassLoader.java
@@ -0,0 +1,70 @@
+/*
+ * 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.util.javalang;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Arrays;
+
+import org.apache.brooklyn.core.util.ResourceUtils;
+
+import brooklyn.util.exceptions.Exceptions;
+
+/** like URLClassLoader (and delegates to it) but:
+ * * has a nice toString
+ * * supports var args constructor
+ * * supports file://~/xxx semantics (remaps it to user.home);
+ * ideally we'd also support mvn, classpath, osgi, etc
+ */
+public class UrlClassLoader extends URLClassLoader {
+
+ private URL[] urls;
+
+ public UrlClassLoader(URL ...urls) {
+ super(tidy(urls));
+ this.urls = urls;
+ }
+
+ public UrlClassLoader(String ...urls) {
+ this(asUrls(urls));
+ }
+
+ private static URL[] asUrls(String[] urls) {
+ URL[] urlo = new URL[urls.length];
+ try {
+ for (int i=0; i<urls.length; i++)
+ urlo[i] = new URL(urls[i]);
+ } catch (MalformedURLException e) {
+ throw Exceptions.propagate(e);
+ }
+ return urlo;
+ }
+
+ private static URL[] tidy(URL[] urls) {
+ for (int i=0; i<urls.length; i++)
+ urls[i] = ResourceUtils.tidy(urls[i]);
+ return urls;
+ }
+
+ @Override
+ public String toString() {
+ return "UrlClassLoader"+Arrays.asList(urls);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/mutex/MutexSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/mutex/MutexSupport.java b/core/src/main/java/org/apache/brooklyn/core/util/mutex/MutexSupport.java
new file mode 100644
index 0000000..2a90f95
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/mutex/MutexSupport.java
@@ -0,0 +1,119 @@
+/*
+ * 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.util.mutex;
+
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableMap;
+
+public class MutexSupport implements WithMutexes {
+
+ private static final Logger log = LoggerFactory.getLogger(MutexSupport.class);
+ private final Map<String,SemaphoreWithOwners> semaphores = new LinkedHashMap<String,SemaphoreWithOwners>();
+
+ protected synchronized SemaphoreWithOwners getSemaphore(String mutexId) {
+ return getSemaphore(mutexId, false);
+ }
+ // NB: the map could be "lock-striped" (hashed on mutexId) to avoid the central lock
+ protected synchronized SemaphoreWithOwners getSemaphore(String mutexId, boolean requestBeforeReturning) {
+ SemaphoreWithOwners s = semaphores.get(mutexId);
+ if (s==null) {
+ s = new SemaphoreWithOwners(mutexId);
+ semaphores.put(mutexId, s);
+ }
+ if (requestBeforeReturning) s.indicateCallingThreadWillRequest();
+ return s;
+ }
+ /** forces deletion of the given mutex if it is unused;
+ * normally not required as is done automatically on close
+ * (but possibly needed where there are cancelations and risk of memory leaks) */
+ public synchronized void cleanupMutex(String mutexId) {
+ SemaphoreWithOwners s = semaphores.get(mutexId);
+ if (!s.isInUse()) semaphores.remove(mutexId);
+ }
+ public synchronized void cleanup() {
+ Iterator<SemaphoreWithOwners> si = semaphores.values().iterator();
+ while (si.hasNext()) {
+ SemaphoreWithOwners s = si.next();
+ if (!s.isInUse()) si.remove();
+ }
+ }
+
+ @Override
+ public synchronized boolean hasMutex(String mutexId) {
+ SemaphoreWithOwners s = semaphores.get(mutexId);
+ if (s!=null) return s.isCallingThreadAnOwner();
+ return false;
+ }
+
+ @Override
+ public void acquireMutex(String mutexId, String description) throws InterruptedException {
+ SemaphoreWithOwners s = getSemaphore(mutexId, true);
+ if (description!=null) Tasks.setBlockingDetails(description+" - waiting for "+mutexId);
+ if (log.isDebugEnabled())
+ log.debug("Acquiring mutex: "+mutexId+"@"+this+" - "+description);
+ s.acquire();
+ if (description!=null) Tasks.setBlockingDetails(null);
+ s.setDescription(description);
+ if (log.isDebugEnabled())
+ log.debug("Acquired mutex: "+mutexId+"@"+this+" - "+description);
+ }
+
+ @Override
+ public boolean tryAcquireMutex(String mutexId, String description) {
+ SemaphoreWithOwners s = getSemaphore(mutexId, true);
+ if (s.tryAcquire()) {
+ if (log.isDebugEnabled())
+ log.debug("Acquired mutex (opportunistic): "+mutexId+"@"+this+" - "+description);
+ s.setDescription(description);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public synchronized void releaseMutex(String mutexId) {
+ SemaphoreWithOwners s;
+ if (log.isDebugEnabled())
+ log.debug("Releasing mutex: "+mutexId+"@"+this);
+ synchronized (this) { s = semaphores.get(mutexId); }
+ if (s==null) throw new IllegalStateException("No mutex known for '"+mutexId+"'");
+ s.release();
+ cleanupMutex(mutexId);
+ }
+
+ @Override
+ public synchronized String toString() {
+ return super.toString()+"["+semaphores.size()+" semaphores: "+semaphores.values()+"]";
+ }
+
+ /** Returns the semaphores in use at the time the method is called, for inspection purposes (and testing).
+ * The semaphores used by this class may change over time so callers are strongly discouraged
+ * from manipulating the semaphore objects themselves.
+ */
+ public synchronized Map<String,SemaphoreWithOwners> getAllSemaphores() {
+ return ImmutableMap.<String,SemaphoreWithOwners>copyOf(semaphores);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/mutex/SemaphoreForTasks.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/mutex/SemaphoreForTasks.java b/core/src/main/java/org/apache/brooklyn/core/util/mutex/SemaphoreForTasks.java
new file mode 100644
index 0000000..7e805b0
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/mutex/SemaphoreForTasks.java
@@ -0,0 +1,112 @@
+/*
+ * 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.util.mutex;
+
+import java.util.List;
+import java.util.Set;
+
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.task.Tasks;
+
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.collections.MutableSet;
+import brooklyn.util.time.Time;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+
+
+/** A subclass of {@link SemaphoreWithOwners}
+ * which additionally sets Task blocking information.
+ * <p>
+ * TODO As tasks are distributed this should support distribution across the management context. */
+public class SemaphoreForTasks extends SemaphoreWithOwners {
+
+ private static final long serialVersionUID = 7898283056223005952L;
+
+ /** unused at present, but wanted on the API for when this may be federated */
+ @SuppressWarnings("unused")
+ private final ManagementContext mgmt;
+
+ final private MutableList<Task<?>> owningTasks = new MutableList<Task<?>>();
+ final private MutableSet<Task<?>> requestingTasks = new MutableSet<Task<?>>();
+
+ public SemaphoreForTasks(String name, ManagementContext mgmt) {
+ super(name);
+ this.mgmt = Preconditions.checkNotNull(mgmt);
+ }
+
+ public SemaphoreForTasks(String name, int permits, boolean fair, ManagementContext mgmt) {
+ super(name, permits, fair);
+ this.mgmt = Preconditions.checkNotNull(mgmt);
+ }
+
+ public synchronized Set<Task<?>> getRequestingTasks() {
+ return ImmutableSet.copyOf(requestingTasks);
+ }
+
+ public synchronized List<Task<?>> getOwningTasks() {
+ return ImmutableList.copyOf(owningTasks);
+ }
+
+ @Override
+ protected synchronized void onRequesting() {
+ if (!owningTasks.isEmpty() || !requestingTasks.isEmpty()) {
+ Tasks.setBlockingTask( !requestingTasks.isEmpty() ? Iterables.getLast(requestingTasks) : Iterables.getFirst(owningTasks, null) );
+ Tasks.setBlockingDetails("Waiting on semaphore "+getName()+" ("+getDescription()+"); "
+ + "queued at "+Time.makeDateString()+" when "+getRequestingThreads().size()+" ahead in queue");
+ }
+ requestingTasks.addIfNotNull(Tasks.current());
+ super.onRequesting();
+ }
+
+ @Override
+ protected synchronized void onRequestFinished() {
+ super.onRequestFinished();
+ requestingTasks.removeIfNotNull(Tasks.current());
+
+ Tasks.resetBlockingDetails();
+ Tasks.resetBlockingTask();
+ }
+
+ @Override
+ protected synchronized void onAcquired(int permits) {
+ super.onAcquired(permits);
+ for (int i=0; i<permits; i++)
+ owningTasks.appendIfNotNull(Tasks.current());
+ }
+
+ @Override
+ protected synchronized void onReleased(int permits) {
+ super.onReleased(permits);
+ for (int i=0; i<permits; i++)
+ owningTasks.removeIfNotNull(Tasks.current());
+ }
+
+ @Override
+ public synchronized String toString() {
+ return super.toString()+"["
+ + "owningTasks="+owningTasks
+ + "; requestingTasks="+requestingTasks+"]";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/mutex/SemaphoreWithOwners.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/mutex/SemaphoreWithOwners.java b/core/src/main/java/org/apache/brooklyn/core/util/mutex/SemaphoreWithOwners.java
new file mode 100644
index 0000000..0144d4d
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/mutex/SemaphoreWithOwners.java
@@ -0,0 +1,231 @@
+/*
+ * 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.util.mutex;
+
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+import brooklyn.util.exceptions.Exceptions;
+
+import com.google.common.collect.ImmutableList;
+
+/** a subclass of {@link Semaphore}
+ * which tracks who created and released the semaphores,
+ * and which requires the same thread to release as created it. */
+public class SemaphoreWithOwners extends Semaphore {
+ public SemaphoreWithOwners(String name) {
+ this(name, 1, true);
+ }
+ public SemaphoreWithOwners(String name, int permits, boolean fair) {
+ super(permits, fair);
+ this.name = name;
+ }
+ private static final long serialVersionUID = -5303474637353009454L;
+ final private List<Thread> owningThreads = new ArrayList<Thread>();
+ final private Set<Thread> requestingThreads = new LinkedHashSet<Thread>();
+
+ @Override
+ public void acquire() throws InterruptedException {
+ try {
+ onRequesting();
+ super.acquire();
+ onAcquired(1);
+ } finally {
+ onRequestFinished();
+ }
+ }
+ @Override
+ public void acquire(int permits) throws InterruptedException {
+ try {
+ onRequesting();
+ super.acquire(permits);
+ onAcquired(permits);
+ } finally {
+ onRequestFinished();
+ }
+ }
+ @Override
+ public void acquireUninterruptibly() {
+ try {
+ onRequesting();
+ super.acquireUninterruptibly();
+ onAcquired(1);
+ } finally {
+ onRequestFinished();
+ }
+ }
+ @Override
+ public void acquireUninterruptibly(int permits) {
+ try {
+ onRequesting();
+ super.acquireUninterruptibly(permits);
+ onAcquired(permits);
+ } finally {
+ onRequestFinished();
+ }
+ }
+
+ public void acquireUnchecked() {
+ try {
+ acquire();
+ } catch (InterruptedException e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+ public void acquireUnchecked(int numPermits) {
+ try {
+ acquire(numPermits);
+ } catch (InterruptedException e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ @Override
+ public boolean tryAcquire() {
+ try {
+ onRequesting();
+ if (super.tryAcquire()) {
+ onAcquired(1);
+ return true;
+ }
+ return false;
+ } finally {
+ onRequestFinished();
+ }
+ }
+ @Override
+ public boolean tryAcquire(int permits) {
+ try {
+ onRequesting();
+ if (super.tryAcquire(permits)) {
+ onAcquired(permits);
+ return true;
+ }
+ return false;
+ } finally {
+ onRequestFinished();
+ }
+ }
+ @Override
+ public boolean tryAcquire(int permits, long timeout, TimeUnit unit) throws InterruptedException {
+ try {
+ onRequesting();
+ if (super.tryAcquire(permits, timeout, unit)) {
+ onAcquired(permits);
+ return true;
+ }
+ return false;
+ } finally {
+ onRequestFinished();
+ }
+ }
+ @Override
+ public boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException {
+ try {
+ onRequesting();
+ if (super.tryAcquire(timeout, unit)) {
+ onAcquired(1);
+ return true;
+ }
+ return false;
+ } finally {
+ onRequestFinished();
+ }
+ }
+
+ /** invoked when a caller successfully acquires a mutex, before {@link #onRequestFinished()} */
+ protected synchronized void onAcquired(int permits) {
+ for (int i=0; i<permits; i++) owningThreads.add(Thread.currentThread());
+ }
+ /** invoked when a caller is about to request a semaphore (before it might block);
+ * guaranteed to call {@link #onRequestFinished()} after the blocking,
+ * with a call to {@link #onAcquired(int)} beforehand if the acquisition was successful */
+ protected synchronized void onRequesting() {
+ requestingThreads.add(Thread.currentThread());
+ }
+ /** invoked when a caller has completed requesting a mutex, whether successful, aborted, or interrupted */
+ protected synchronized void onRequestFinished() {
+ requestingThreads.remove(Thread.currentThread());
+ }
+
+ @Override
+ public void release() {
+ super.release();
+ onReleased(1);
+ }
+ @Override
+ public void release(int permits) {
+ super.release(permits);
+ onReleased(permits);
+ }
+
+ /** invoked when a caller has released permits */
+ protected synchronized void onReleased(int permits) {
+ boolean result = true;
+ for (int i=0; i<permits; i++) result = owningThreads.remove(Thread.currentThread()) & result;
+ if (!result) throw new IllegalStateException("Thread "+Thread.currentThread()+" which released "+this+" did not own it.");
+ }
+
+ /** true iff there are any owners or any requesters (callers blocked trying to acquire) */
+ public synchronized boolean isInUse() {
+ return !owningThreads.isEmpty() || !requestingThreads.isEmpty();
+ }
+
+ /** true iff the calling thread is one of the owners */
+ public synchronized boolean isCallingThreadAnOwner() {
+ return owningThreads.contains(Thread.currentThread());
+ }
+
+ private final String name;
+ /** constructor-time supplied name */
+ public String getName() { return name; }
+
+ private String description;
+ public void setDescription(String description) { this.description = description; }
+ /** caller supplied description */
+ public String getDescription() { return description; }
+
+ /** unmodifiable view of threads owning the permits; threads with multiple permits listed multiply */
+ public synchronized List<Thread> getOwningThreads() {
+ return ImmutableList.<Thread>copyOf(owningThreads);
+ }
+ /** unmodifiable view of threads requesting access (blocked or briefly trying to acquire);
+ * this is guaranteed to be cleared _after_ getOwners
+ * (synchronizing on this class while reading both fields will give canonical access) */
+ public synchronized List<Thread> getRequestingThreads() {
+ return ImmutableList.<Thread>copyOf(requestingThreads);
+ }
+
+ @Override
+ public synchronized String toString() {
+ return super.toString()+"["+name+"; description="+description+"; owning="+owningThreads+"; requesting="+requestingThreads+"]";
+ }
+
+ /** Indicate that the calling thread is going to acquire or tryAcquire,
+ * in order to set up the semaphore's isInUse() value appropriately for certain checks.
+ * It *must* do so after invoking this method. */
+ public void indicateCallingThreadWillRequest() {
+ requestingThreads.add(Thread.currentThread());
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/mutex/WithMutexes.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/mutex/WithMutexes.java b/core/src/main/java/org/apache/brooklyn/core/util/mutex/WithMutexes.java
new file mode 100644
index 0000000..82eab02
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/mutex/WithMutexes.java
@@ -0,0 +1,45 @@
+/*
+ * 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.util.mutex;
+
+/** interface which allows multiple callers to co-operate using named mutexes, inspectably,
+ * and containing implementation as inner class
+ * <p>
+ * MutexSupport is a common implementation of this.
+ * mixin code frequently delegates to this,
+ * as shown in the test case's WithMutexesTest.SampleWithMutexesDelegatingMixin class
+ **/
+public interface WithMutexes {
+
+ /** returns true if the calling thread has the mutex with the given ID */
+ public boolean hasMutex(String mutexId);
+
+ /** acquires a mutex, if available, otherwise blocks on its becoming available;
+ * caller must release after use */
+ public void acquireMutex(String mutexId, String description) throws InterruptedException;
+
+ /** acquires a mutex and returns true, if available; otherwise immediately returns false;
+ * caller must release after use if this returns true */
+ public boolean tryAcquireMutex(String mutexId, String description);
+
+ /** releases a mutex, triggering another thread to use it or cleaning it up if no one else is waiting;
+ * this should only be called by the mutex owner (thread) */
+ public void releaseMutex(String mutexId);
+
+}
[18/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/qa/performance/TaskPerformanceTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/qa/performance/TaskPerformanceTest.java b/core/src/test/java/brooklyn/qa/performance/TaskPerformanceTest.java
index 6e4a0d0..c940a36 100644
--- a/core/src/test/java/brooklyn/qa/performance/TaskPerformanceTest.java
+++ b/core/src/test/java/brooklyn/qa/performance/TaskPerformanceTest.java
@@ -26,6 +26,8 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.brooklyn.core.util.task.BasicExecutionManager;
+import org.apache.brooklyn.core.util.task.SingleThreadedScheduler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.BeforeMethod;
@@ -33,8 +35,6 @@ import org.testng.annotations.Test;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.task.BasicExecutionManager;
-import brooklyn.util.task.SingleThreadedScheduler;
import brooklyn.util.time.Time;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/test/HttpService.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/test/HttpService.java b/core/src/test/java/brooklyn/test/HttpService.java
index 2710211..80f63f0 100644
--- a/core/src/test/java/brooklyn/test/HttpService.java
+++ b/core/src/test/java/brooklyn/test/HttpService.java
@@ -40,10 +40,10 @@ import org.eclipse.jetty.webapp.WebAppContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.brooklyn.api.location.PortRange;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.crypto.SecureKeys;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.crypto.SecureKeys;
import brooklyn.util.javalang.Threads;
import brooklyn.util.os.Os;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/test/policy/TestEnricher.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/test/policy/TestEnricher.java b/core/src/test/java/brooklyn/test/policy/TestEnricher.java
index c204c8b..88cc362 100644
--- a/core/src/test/java/brooklyn/test/policy/TestEnricher.java
+++ b/core/src/test/java/brooklyn/test/policy/TestEnricher.java
@@ -23,6 +23,7 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import com.google.common.reflect.TypeToken;
@@ -30,7 +31,6 @@ import brooklyn.config.ConfigKey;
import brooklyn.enricher.basic.AbstractEnricher;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.util.flags.SetFromFlag;
public class TestEnricher extends AbstractEnricher {
@SetFromFlag("confName")
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/test/policy/TestPolicy.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/test/policy/TestPolicy.java b/core/src/test/java/brooklyn/test/policy/TestPolicy.java
index b93450c..184eb4e 100644
--- a/core/src/test/java/brooklyn/test/policy/TestPolicy.java
+++ b/core/src/test/java/brooklyn/test/policy/TestPolicy.java
@@ -22,12 +22,12 @@ import java.util.Collections;
import java.util.Map;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.event.basic.BasicConfigKey;
import brooklyn.policy.basic.AbstractPolicy;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.reflect.TypeToken;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/BrooklynMavenArtifactsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/BrooklynMavenArtifactsTest.java b/core/src/test/java/brooklyn/util/BrooklynMavenArtifactsTest.java
deleted file mode 100644
index 0fcfdf7..0000000
--- a/core/src/test/java/brooklyn/util/BrooklynMavenArtifactsTest.java
+++ /dev/null
@@ -1,96 +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 brooklyn.util;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-import brooklyn.test.Asserts;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.maven.MavenArtifact;
-import brooklyn.util.maven.MavenRetriever;
-import brooklyn.util.stream.Streams;
-import brooklyn.util.text.Strings;
-import brooklyn.util.time.Duration;
-import brooklyn.util.time.Time;
-
-@Test
-public class BrooklynMavenArtifactsTest {
-
- private static final Logger log = LoggerFactory.getLogger(BrooklynMavenArtifactsTest.class);
-
- @Test(groups="Integration")
- public void testUtilsCommon() {
- ResourceUtils.create(this).checkUrlExists(BrooklynMavenArtifacts.localUrlForJar("brooklyn-utils-common"));
- }
-
- @Test(groups="Integration")
- public void testExampleWar() {
- String url = BrooklynMavenArtifacts.localUrl("example", "brooklyn-example-hello-world-sql-webapp", "war");
- ResourceUtils.create(this).checkUrlExists(url);
- log.info("found example war at: "+url);
- }
-
- @Test(groups="Integration")
- // runs without internet but doesn't assert what it should, and can take a long time, so integration
- public void testBadExampleWar() {
- String url = BrooklynMavenArtifacts.localUrl("example", "brooklyn-example-GOODBYE-world-sql-webapp", "war");
- Assert.assertFalse(ResourceUtils.create(this).doesUrlExist(url), "should not exist: "+url);
- }
-
- public void testHostedIsHttp() {
- String common = BrooklynMavenArtifacts.hostedUrlForJar("brooklyn-utils-common");
- log.info("online should be at: "+common);
- Assert.assertTrue(common.startsWith("http"));
- }
-
- @Test(groups="Integration")
- public void testHistoricHosted() {
- // NB: this should be a version known to be up at sonatype or maven central, NOT necessarily the current version!
- String snapshot = MavenRetriever.hostedUrl(MavenArtifact.fromCoordinate("org.apache.brooklyn:brooklyn-utils-common:jar:0.7.0-SNAPSHOT"));
- log.info("Sample snapshot URL is: "+snapshot);
- checkValidArchive(snapshot);
- ResourceUtils.create(this).checkUrlExists(snapshot);
-
- // NB: this should be a version known to be up at sonatype or maven central, NOT necessarily the current version!
- String release = MavenRetriever.hostedUrl(MavenArtifact.fromCoordinate("io.brooklyn:brooklyn-utils-common:jar:0.6.0"));
- log.info("Sample release URL is: "+release);
- checkValidArchive(release);
- }
-
- private void checkValidArchive(final String url) {
- // Note have seen response code 500 from repository.apache.org, for
- // https://repository.apache.org/service/local/artifact/maven/redirect?r=snapshots&v=0.7.0-SNAPSHOT&g=org.apache.brooklyn&a=brooklyn-utils-common&e=jar
- // Therefore willing to retry, rather than failing immediately.
- Asserts.succeedsEventually(new Runnable() {
- @Override public void run() {
- try {
- byte[] bytes = Streams.readFully(ResourceUtils.create(this).getResourceFromUrl(url));
- // confirm this follow redirects!
- Assert.assertTrue(bytes.length > 100*1000, "download of "+url+" is suspect ("+Strings.makeSizeString(bytes.length)+")");
- // (could also check it is a zip etc)
- } catch (Exception e) {
- throw Exceptions.propagate(e);
- }
- }});
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/ResourceUtilsHttpTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/ResourceUtilsHttpTest.java b/core/src/test/java/brooklyn/util/ResourceUtilsHttpTest.java
deleted file mode 100644
index daac00a..0000000
--- a/core/src/test/java/brooklyn/util/ResourceUtilsHttpTest.java
+++ /dev/null
@@ -1,196 +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 brooklyn.util;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.apache.http.HttpException;
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpResponse;
-import org.apache.http.HttpStatus;
-import org.apache.http.entity.StringEntity;
-import org.apache.http.localserver.RequestBasicAuth;
-import org.apache.http.localserver.ResponseBasicUnauthorized;
-import org.apache.http.protocol.HttpContext;
-import org.apache.http.protocol.HttpRequestHandler;
-import org.apache.http.protocol.ResponseServer;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-import brooklyn.test.TestHttpRequestHandler;
-import brooklyn.test.TestHttpServer;
-import brooklyn.util.stream.Streams;
-import brooklyn.util.text.Strings;
-
-public class ResourceUtilsHttpTest {
- private ResourceUtils utils;
- private TestHttpServer server;
- private String baseUrl;
-
- @BeforeClass(alwaysRun=true)
- public void setUp() throws Exception {
- utils = ResourceUtils.create(this, "mycontext");
- server = new TestHttpServer()
- .interceptor(new ResponseServer())
- .interceptor(new ResponseBasicUnauthorized())
- .interceptor(new RequestBasicAuth())
- .handler("/simple", new TestHttpRequestHandler().response("OK"))
- .handler("/empty", new TestHttpRequestHandler().code(HttpStatus.SC_NO_CONTENT))
- .handler("/missing", new TestHttpRequestHandler().code(HttpStatus.SC_NOT_FOUND).response("Missing"))
- .handler("/redirect", new TestHttpRequestHandler().code(HttpStatus.SC_MOVED_TEMPORARILY).response("Redirect").header("Location", "/simple"))
- .handler("/cycle", new TestHttpRequestHandler().code(HttpStatus.SC_MOVED_TEMPORARILY).response("Redirect").header("Location", "/cycle"))
- .handler("/secure", new TestHttpRequestHandler().code(HttpStatus.SC_MOVED_TEMPORARILY).response("Redirect").header("Location", "https://0.0.0.0/"))
- .handler("/auth", new AuthHandler("test", "test", "OK"))
- .handler("/auth_escape", new AuthHandler("test@me:/", "test", "OK"))
- .handler("/auth_escape2", new AuthHandler("test@me:test", "", "OK"))
- .handler("/no_credentials", new CheckNoCredentials())
- .start();
- baseUrl = server.getUrl();
- }
-
- @AfterClass(alwaysRun=true)
- public void tearDown() throws Exception {
- server.stop();
- }
-
- @Test
- public void testGet() throws Exception {
- InputStream stream = utils.getResourceFromUrl(baseUrl + "/simple");
- assertEquals(Streams.readFullyString(stream), "OK");
- }
-
- @Test
- public void testGetEmpty() throws Exception {
- InputStream stream = utils.getResourceFromUrl(baseUrl + "/empty");
- assertEquals(Streams.readFullyString(stream), "");
- }
-
- @Test
- public void testGetProtected() throws Exception {
- String url = baseUrl.replace("http://", "http://test:test@") + "/auth";
- InputStream stream = utils.getResourceFromUrl(url);
- assertEquals(Streams.readFullyString(stream), "OK");
- }
-
- @Test
- public void testGetProtectedEscape() throws Exception {
- String url = baseUrl.replace("http://", "http://test%40me%3A%2F:test@") + "/auth_escape";
- InputStream stream = utils.getResourceFromUrl(url);
- assertEquals(Streams.readFullyString(stream), "OK");
- }
-
- @Test
- public void testGetProtectedEscape2() throws Exception {
- String url = baseUrl.replace("http://", "http://test%40me%3Atest@") + "/auth_escape2";
- InputStream stream = utils.getResourceFromUrl(url);
- assertEquals(Streams.readFullyString(stream), "OK");
- }
-
- @Test(expectedExceptions = RuntimeException.class)
- public void testProtectedFailsWithoutCredentials() throws Exception {
- utils.getResourceFromUrl(baseUrl + "/auth");
- }
-
- @Test
- public void testInvalidCredentialsNotPassed() throws Exception {
- String url = baseUrl + "/no_credentials?no:auth@needed";
- InputStream stream = utils.getResourceFromUrl(url);
- assertEquals(Streams.readFullyString(stream), "OK");
- }
-
- @Test
- public void testRedirect() throws Exception {
- InputStream stream = utils.getResourceFromUrl(baseUrl + "/redirect");
- assertEquals(Streams.readFullyString(stream), "OK");
- }
-
- @Test(expectedExceptions = RuntimeException.class)
- public void testCycleRedirect() throws Exception {
- InputStream stream = utils.getResourceFromUrl(baseUrl + "/cycle");
- assertEquals(Streams.readFullyString(stream), "OK");
- }
-
- @Test(expectedExceptions = RuntimeException.class)
- public void testGetMissing() throws Exception {
- utils.getResourceFromUrl(baseUrl + "/missing");
- }
-
- @Test(expectedExceptions = RuntimeException.class)
- public void testFollowsProtoChange() throws Exception {
- utils.getResourceFromUrl(baseUrl + "/secure");
- }
-
- // See https://github.com/brooklyncentral/brooklyn/issues/1338
- @Test(groups={"Integration"})
- public void testResourceFromUrlFollowsRedirect() throws Exception {
- String contents = new ResourceUtils(this).getResourceAsString("http://bit.ly/brooklyn-visitors-creation-script");
- assertFalse(contents.contains("bit.ly"), "contents="+contents);
- }
-
- private static class AuthHandler implements HttpRequestHandler {
- private String username;
- private String password;
- private String responseBody;
-
- public AuthHandler(String username, String password, String response) {
- this.username = username;
- this.password = password;
- this.responseBody = response;
- }
-
- @Override
- public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException {
- String creds = (String) context.getAttribute("creds");
- if (creds == null || !creds.equals(getExpectedCredentials())) {
- response.setStatusCode(HttpStatus.SC_UNAUTHORIZED);
- } else {
- response.setEntity(new StringEntity(responseBody));
- }
- }
-
- private String getExpectedCredentials() {
- if (Strings.isEmpty(password)) {
- return username;
- } else {
- return username + ":" + password;
- }
- }
-
- }
-
- private static class CheckNoCredentials implements HttpRequestHandler {
-
- @Override
- public void handle(HttpRequest request, HttpResponse response,
- HttpContext context) throws HttpException, IOException {
- String creds = (String) context.getAttribute("creds");
- if (creds == null) {
- response.setEntity(new StringEntity("OK"));
- } else {
- response.setStatusCode(HttpStatus.SC_BAD_REQUEST);
- }
- }
-
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/ResourceUtilsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/ResourceUtilsTest.java b/core/src/test/java/brooklyn/util/ResourceUtilsTest.java
deleted file mode 100644
index de54ebb..0000000
--- a/core/src/test/java/brooklyn/util/ResourceUtilsTest.java
+++ /dev/null
@@ -1,189 +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 brooklyn.util;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.List;
-import java.util.NoSuchElementException;
-import java.util.Properties;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-import brooklyn.util.net.Urls;
-import brooklyn.util.os.Os;
-import brooklyn.util.stream.Streams;
-import brooklyn.util.text.Identifiers;
-
-import com.google.common.base.Charsets;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import com.google.common.io.Files;
-
-public class ResourceUtilsTest {
-
- private static final Logger log = LoggerFactory.getLogger(ResourceUtilsTest.class);
-
- private String tempFileContents = "abc";
- private ResourceUtils utils;
- private File tempFile;
-
- @BeforeClass(alwaysRun=true)
- public void setUp() throws Exception {
- utils = ResourceUtils.create(this, "mycontext");
- tempFile = Os.writeToTempFile(new ByteArrayInputStream(tempFileContents.getBytes()), "resourceutils-test", ".txt");
- }
-
- @AfterClass(alwaysRun=true)
- public void tearDown() throws Exception {
- if (tempFile != null) tempFile.delete();
- }
-
- @Test
- public void testWriteStreamToTempFile() throws Exception {
- File tempFileLocal = Os.writeToTempFile(new ByteArrayInputStream("mycontents".getBytes()), "resourceutils-test", ".txt");
- try {
- List<String> lines = Files.readLines(tempFileLocal, Charsets.UTF_8);
- assertEquals(lines, ImmutableList.of("mycontents"));
- } finally {
- tempFileLocal.delete();
- }
- }
-
- @Test
- public void testPropertiesStreamToTempFile() throws Exception {
- Properties props = new Properties();
- props.setProperty("mykey", "myval");
- File tempFileLocal = Os.writePropertiesToTempFile(props, "resourceutils-test", ".txt");
- FileInputStream fis = null;
- try {
- fis = new FileInputStream(tempFileLocal);
- Properties props2 = new Properties();
- props2.load(fis);
- assertEquals(props2.getProperty("mykey"), "myval");
- } finally {
- Streams.closeQuietly(fis);
- tempFileLocal.delete();
- }
- }
-
- @Test
- public void testGetResourceViaClasspathWithPrefix() throws Exception {
- InputStream stream = utils.getResourceFromUrl("classpath://brooklyn/config/sample.properties");
- assertNotNull(stream);
- }
-
- @Test
- public void testGetResourceViaClasspathWithoutPrefix() throws Exception {
- InputStream stream = utils.getResourceFromUrl("/brooklyn/config/sample.properties");
- assertNotNull(stream);
- }
-
- @Test
- public void testGetResourceViaFileWithPrefix() throws Exception {
- // The correct format for file URLs is file:///<absolute path>.
- // On UNIX file:///tmp.
- // On Windows both file:/C:/temp and file:///C:/temp are supported by Java,
- // while Windows itself supports the latter only.
- // Note that file://C:/temp is *wrong*, because C: is interpreted as the host
- InputStream stream = utils.getResourceFromUrl(tempFile.toURI().toURL().toString());
- assertEquals(Streams.readFullyString(stream), tempFileContents);
- }
-
- @Test
- public void testGetResourceViaFileWithoutPrefix() throws Exception {
- InputStream stream = utils.getResourceFromUrl(tempFile.getAbsolutePath());
- assertEquals(Streams.readFullyString(stream), tempFileContents);
- }
-
- @Test
- public void testClassLoaderDir() throws Exception {
- String d = utils.getClassLoaderDir();
- log.info("Found resource "+this+" in: "+d);
- assertTrue(new File(d, "brooklyn/util/").exists());
- }
-
- @Test
- public void testClassLoaderDirFromJar() throws Exception {
- String d = utils.getClassLoaderDir("java/lang/Object.class");
- log.info("Found Object in: "+d);
- assertTrue(d.toLowerCase().endsWith(".jar"));
- }
-
- @Test
- public void testClassLoaderDirFromJarWithSlash() throws Exception {
- String d = utils.getClassLoaderDir("/java/lang/Object.class");
- log.info("Found Object in: "+d);
- assertTrue(d.toLowerCase().endsWith(".jar"));
- }
-
- @Test(expectedExceptions={NoSuchElementException.class})
- public void testClassLoaderDirNotFound() throws Exception {
- String d = utils.getClassLoaderDir("/somewhere/not/found/XXX.xxx");
- // above should fail
- log.warn("Uh oh found imaginary resource in: "+d);
- }
-
- @Test(groups="Integration")
- public void testGetResourceViaSftp() throws Exception {
- InputStream stream = utils.getResourceFromUrl("sftp://localhost:"+tempFile.getAbsolutePath());
- assertEquals(Streams.readFullyString(stream), tempFileContents);
- }
-
- @Test(groups="Integration")
- public void testGetResourceViaSftpWithUsername() throws Exception {
- String user = System.getProperty("user.name");
- InputStream stream = utils.getResourceFromUrl("sftp://"+user+"@localhost:"+tempFile.getAbsolutePath());
- assertEquals(Streams.readFullyString(stream), tempFileContents);
- }
-
- @Test
- public void testDataUrl() throws Exception {
- assertEquals(utils.getResourceAsString("data:,hello"), "hello");
- assertEquals(utils.getResourceAsString("data:,hello%20world"), "hello world");
- // above is correct. below are not valid ... but we accept them anyway
- assertEquals(utils.getResourceAsString("data:hello"), "hello");
- assertEquals(utils.getResourceAsString("data://hello"), "hello");
- assertEquals(utils.getResourceAsString("data:hello world"), "hello world");
- assertEquals(utils.getResourceAsString(Urls.asDataUrlBase64("hello world")), "hello world");
-
- String longString = Identifiers.makeRandomId(256);
- for (int a=32; a<128; a++) longString += (char)a;
- assertEquals(utils.getResourceAsString(Urls.asDataUrlBase64(longString)), longString);
- }
-
- @Test
- public void testGetResources() {
- Iterable<URL> manifests = ResourceUtils.create().getResources("META-INF/MANIFEST.MF");
- assertFalse(Iterables.isEmpty(manifests));
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/config/ConfigBagTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/config/ConfigBagTest.java b/core/src/test/java/brooklyn/util/config/ConfigBagTest.java
deleted file mode 100644
index 93cf6ed..0000000
--- a/core/src/test/java/brooklyn/util/config/ConfigBagTest.java
+++ /dev/null
@@ -1,191 +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 brooklyn.util.config;
-
-import static org.testng.Assert.assertEquals;
-
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.time.Duration;
-
-public class ConfigBagTest {
-
- @SuppressWarnings("unused")
- private static final Logger log = LoggerFactory.getLogger(ConfigBagTest.class);
-
- private static final ConfigKey<String> K1 = ConfigKeys.newStringConfigKey("k1");
- private static final ConfigKey<String> K2 = ConfigKeys.newStringConfigKey("k2");
- private static final ConfigKey<String> K3 = ConfigKeys.newStringConfigKey("k3");
-
- @Test
- public void testPutAndGet() {
- ConfigBag bag = ConfigBag.newInstance();
- bag.put(K1, "v1");
- assertEquals(bag.get(K1), "v1");
- }
-
- @Test
- public void testPutStringAndGet() {
- ConfigBag bag = ConfigBag.newInstance();
- bag.putAsStringKey(K1.getName(), "v1");
- assertEquals(bag.get(K1), "v1");
- }
-
- @Test
- public void testUnused() {
- ConfigBag bag = ConfigBag.newInstance();
- bag.put(K1, "v1");
- bag.put(K2, "v2a");
- assertEquals(bag.get(K1), "v1");
- assertEquals(bag.getUnusedConfig().size(), 1);
- assertEquals(bag.peek(K2), "v2a");
- assertEquals(bag.getUnusedConfig().size(), 1);
- assertEquals(bag.get(K2), "v2a");
- Assert.assertTrue(bag.getUnusedConfig().isEmpty());
- }
-
- @Test
- public void testOrder() {
- ConfigBag bag = ConfigBag.newInstance();
- bag.put(K1, "v1");
- bag.put(K2, "v2");
- bag.put(K3, "v3");
- Assert.assertEquals(MutableList.copyOf(bag.getAllConfig().keySet()), MutableList.of(K1.getName(), K2.getName(), K3.getName()));
- Assert.assertEquals(MutableList.copyOf(bag.getAllConfig().values()), MutableList.of("v1", "v2", "v3"));
- }
-
- @Test
- public void testCopyOverwriteAndGet() {
- ConfigBag bag1 = ConfigBag.newInstance();
- bag1.put(K1, "v1");
- bag1.put(K2, "v2a");
- bag1.put(K3, "v3");
- assertEquals(bag1.get(K1), "v1");
-
- ConfigBag bag2 = ConfigBag.newInstanceCopying(bag1).putAll(MutableMap.of(K2, "v2b"));
- assertEquals(bag1.getUnusedConfig().size(), 2);
- assertEquals(bag2.getUnusedConfig().size(), 2);
-
- assertEquals(bag2.get(K1), "v1");
- assertEquals(bag1.get(K2), "v2a");
- assertEquals(bag1.getUnusedConfig().size(), 1);
- assertEquals(bag2.getUnusedConfig().size(), 2);
-
- assertEquals(bag2.get(K2), "v2b");
- assertEquals(bag2.getUnusedConfig().size(), 1);
-
- assertEquals(bag2.get(K3), "v3");
- assertEquals(bag2.getUnusedConfig().size(), 0);
- assertEquals(bag1.getUnusedConfig().size(), 1);
- }
-
- @Test
- public void testCopyExtendingAndGet() {
- ConfigBag bag1 = ConfigBag.newInstance();
- bag1.put(K1, "v1");
- bag1.put(K2, "v2a");
- bag1.put(K3, "v3");
- assertEquals(bag1.get(K1), "v1");
-
- ConfigBag bag2 = ConfigBag.newInstanceExtending(bag1, null).putAll(MutableMap.of(K2, "v2b"));
- assertEquals(bag1.getUnusedConfig().size(), 2);
- assertEquals(bag2.getUnusedConfig().size(), 2, "unused are: "+bag2.getUnusedConfig());
-
- assertEquals(bag2.get(K1), "v1");
- assertEquals(bag1.get(K2), "v2a");
- assertEquals(bag1.getUnusedConfig().size(), 1);
- assertEquals(bag2.getUnusedConfig().size(), 2);
-
- assertEquals(bag2.get(K2), "v2b");
- assertEquals(bag2.getUnusedConfig().size(), 1);
-
- assertEquals(bag2.get(K3), "v3");
- assertEquals(bag2.getUnusedConfig().size(), 0);
- // when extended, the difference is that parent is also marked
- assertEquals(bag1.getUnusedConfig().size(), 0);
- }
-
- @Test
- public void testConcurrent() throws InterruptedException {
- ConfigBag bag = ConfigBag.newInstance();
- bag.put(K1, "v1");
- bag.put(K2, "v2");
- bag.put(K3, "v3");
- runConcurrentTest(bag, 10, Duration.millis(50));
- }
-
- @Test(groups="Integration")
- public void testConcurrentBig() throws InterruptedException {
- ConfigBag bag = ConfigBag.newInstance();
- bag.put(K1, "v1");
- bag.put(K2, "v2");
- bag.put(K3, "v3");
- runConcurrentTest(bag, 20, Duration.seconds(5));
- }
-
- private void runConcurrentTest(final ConfigBag bag, int numThreads, Duration time) throws InterruptedException {
- List<Thread> threads = MutableList.of();
- final Map<Thread,Exception> exceptions = new ConcurrentHashMap<Thread,Exception>();
- final AtomicInteger successes = new AtomicInteger();
- for (int i=0; i<numThreads; i++) {
- Thread t = new Thread() {
- @Override
- public void run() {
- try {
- while (!interrupted()) {
- if (Math.random()<0.9)
- bag.put(ConfigKeys.newStringConfigKey("k"+((int)(10*Math.random()))), "v"+((int)(10*Math.random())));
- if (Math.random()<0.8)
- bag.get(ConfigKeys.newStringConfigKey("k"+((int)(10*Math.random()))));
- if (Math.random()<0.2)
- bag.copy(bag);
- if (Math.random()<0.6)
- bag.remove(ConfigKeys.newStringConfigKey("k"+((int)(10*Math.random()))));
- successes.incrementAndGet();
- }
- } catch (Exception e) {
- exceptions.put(Thread.currentThread(), e);
- Exceptions.propagateIfFatal(e);
- }
- }
- };
- t.setName("ConfigBagTest-concurrent-thread-"+i);
- threads.add(t);
- }
- for (Thread t: threads) t.start();
- time.countdownTimer().waitForExpiry();
- for (Thread t: threads) t.interrupt();
- for (Thread t: threads) t.join();
- Assert.assertTrue(exceptions.isEmpty(), "Got "+exceptions.size()+"/"+numThreads+" exceptions ("+successes.get()+" successful): "+exceptions);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/crypto/SecureKeysAndSignerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/crypto/SecureKeysAndSignerTest.java b/core/src/test/java/brooklyn/util/crypto/SecureKeysAndSignerTest.java
deleted file mode 100644
index 1bdb0a3..0000000
--- a/core/src/test/java/brooklyn/util/crypto/SecureKeysAndSignerTest.java
+++ /dev/null
@@ -1,166 +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 brooklyn.util.crypto;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.nio.charset.Charset;
-import java.security.KeyPair;
-import java.security.PublicKey;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.crypto.SecureKeys.PassphraseProblem;
-import brooklyn.util.os.Os;
-
-import com.google.common.io.Files;
-
-public class SecureKeysAndSignerTest {
-
- // a bit slow, so marked as integration (but possibly due to leftover rebind-cleanup, benign failures writing to /tmp/xx)
- @Test(groups="Integration")
- public void testGenerateSignedKeys() throws Exception {
- FluentKeySigner signer = new FluentKeySigner("the-root").
- validForYears(2).
- selfsign();
- X509Certificate signerCert = signer.getAuthorityCertificate();
-
- KeyPair aKey = SecureKeys.newKeyPair();
- X509Certificate aCert = signer.newCertificateFor("A", aKey);
-
- KeyPair bKey = SecureKeys.newKeyPair();
- X509Certificate bCert = signer.newCertificateFor("B", bKey);
-
- FluentKeySigner selfSigner1 = new FluentKeySigner("self1").selfsign();
- X509Certificate selfCert1 = selfSigner1.getAuthorityCertificate();
-
- SecureKeys.getTrustManager(aCert).checkClientTrusted(new X509Certificate[] { aCert }, "RSA");
- SecureKeys.getTrustManager(signerCert).checkClientTrusted(new X509Certificate[] { signerCert }, "RSA");
-
- try {
- SecureKeys.getTrustManager(aCert).checkClientTrusted(new X509Certificate[] { bCert }, "RSA");
- Assert.fail("Trust manager for A should not accept B");
- } catch (CertificateException e) { /* expected */ }
-
-// SecureKeys.getTrustManager(signerCert).checkClientTrusted(new X509Certificate[] { aCert }, "RSA");
- // NB, the above failes; we have to convert to a canonical implementation, handled by the following
-
- Assert.assertTrue(SecureKeys.isCertificateAuthorizedBy(signerCert, signerCert));
- Assert.assertTrue(SecureKeys.isCertificateAuthorizedBy(aCert, signerCert));
- Assert.assertTrue(SecureKeys.isCertificateAuthorizedBy(bCert, signerCert));
- Assert.assertFalse(SecureKeys.isCertificateAuthorizedBy(signerCert, aCert));
- Assert.assertFalse(SecureKeys.isCertificateAuthorizedBy(bCert, aCert));
-
- Assert.assertTrue(SecureKeys.isCertificateAuthorizedBy(selfCert1, selfCert1));
- Assert.assertFalse(SecureKeys.isCertificateAuthorizedBy(selfCert1, signerCert));
- }
-
- @Test
- public void testInjectCertificateAuthority() throws Exception {
- KeyPair caKey = SecureKeys.newKeyPair();
- X509Certificate caCert = new FluentKeySigner("the-root", caKey).selfsign().getAuthorityCertificate();
-
- FluentKeySigner signer = new FluentKeySigner(caCert, caKey);
- Assert.assertEquals("the-root", signer.getCommonName());
-
- KeyPair aKey = SecureKeys.newKeyPair();
- X509Certificate aCert = signer.newCertificateFor("A", aKey);
-
- Assert.assertTrue(SecureKeys.isCertificateAuthorizedBy(aCert, caCert));
- }
-
- @Test
- public void testReadRsaKey() throws Exception {
- KeyPair key = SecureKeys.readPem(ResourceUtils.create(this).getResourceFromUrl("classpath://brooklyn/util/crypto/sample_rsa.pem"), null);
- checkNonTrivial(key);
- }
-
- @Test(expectedExceptions=IllegalStateException.class)
- public void testReadRsaPublicKeyAsPemFails() throws Exception {
- // should fail; see next test
- SecureKeys.readPem(ResourceUtils.create(this).getResourceFromUrl("classpath://brooklyn/util/crypto/sample_rsa.pem.pub"), null);
- }
-
- @Test
- public void testReadRsaPublicKeyAsAuthKeysWorks() throws Exception {
- PublicKey key = AuthorizedKeysParser.decodePublicKey(
- ResourceUtils.create(this).getResourceAsString("classpath://brooklyn/util/crypto/sample_rsa.pem.pub"));
- KeyPair fromPem = SecureKeys.readPem(ResourceUtils.create(this).getResourceFromUrl("classpath://brooklyn/util/crypto/sample_rsa.pem"), null);
- Assert.assertEquals(key, fromPem.getPublic());
- }
-
- @Test
- public void testEncodeDecodeRsaPublicKey() throws Exception {
- String data = ResourceUtils.create(this).getResourceAsString("classpath://brooklyn/util/crypto/sample_rsa.pem.pub");
- PublicKey key = AuthorizedKeysParser.decodePublicKey(data);
- String data2 = AuthorizedKeysParser.encodePublicKey(key);
- Assert.assertTrue(data.contains(data2), "Expected to find '"+data2+"' in '"+data+"'");
- PublicKey key2 = AuthorizedKeysParser.decodePublicKey(data2);
- Assert.assertEquals(key2, key);
- }
-
- @Test
- public void testEncodeDecodeDsaPublicKey() throws Exception {
- String data = ResourceUtils.create(this).getResourceAsString("classpath://brooklyn/util/crypto/sample_dsa.pem.pub");
- PublicKey key = AuthorizedKeysParser.decodePublicKey(data);
- String data2 = AuthorizedKeysParser.encodePublicKey(key);
- Assert.assertTrue(data.contains(data2), "Expected to find '"+data2+"' in '"+data+"'");
- PublicKey key2 = AuthorizedKeysParser.decodePublicKey(data2);
- Assert.assertEquals(key2, key);
- }
-
- @Test
- public void testReadDsaKey() throws Exception {
- KeyPair key = SecureKeys.readPem(ResourceUtils.create(this).getResourceFromUrl("classpath://brooklyn/util/crypto/sample_dsa.pem"), null);
- checkNonTrivial(key);
- }
-
- @Test(expectedExceptions=Exception.class)
- public void testCantReadRsaPassphraseKeyWithoutPassphrase() throws Exception {
- KeyPair key = SecureKeys.readPem(ResourceUtils.create(this).getResourceFromUrl("classpath://brooklyn/util/crypto/sample_rsa_passphrase.pem"), null);
- checkNonTrivial(key);
- }
-
- @Test(expectedExceptions=PassphraseProblem.class)
- public void testReadRsaPassphraseWithoutKeyFails() throws Exception {
- SecureKeys.readPem(ResourceUtils.create(this).getResourceFromUrl("classpath://brooklyn/util/crypto/sample_rsa_passphrase.pem"), null);
- }
-
- @Test
- public void testReadRsaPassphraseKeyAndWriteWithoutPassphrase() throws Exception {
- KeyPair key = SecureKeys.readPem(ResourceUtils.create(this).getResourceFromUrl("classpath://brooklyn/util/crypto/sample_rsa_passphrase.pem"), "passphrase");
- checkNonTrivial(key);
- File f = Os.newTempFile(getClass(), "brooklyn-sample_rsa_passphrase_without_passphrase.pem");
- Files.write(SecureKeys.stringPem(key), f, Charset.defaultCharset());
- KeyPair key2 = SecureKeys.readPem(new FileInputStream(f), null);
- checkNonTrivial(key2);
- Assert.assertEquals(key2.getPrivate().getEncoded(), key.getPrivate().getEncoded());
- Assert.assertEquals(key2.getPublic().getEncoded(), key.getPublic().getEncoded());
- }
-
- private void checkNonTrivial(KeyPair key) {
- Assert.assertNotEquals(key.getPrivate().getEncoded().length, 0);
- Assert.assertNotEquals(key.getPublic().getEncoded().length, 0);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/file/ArchiveBuilderTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/file/ArchiveBuilderTest.java b/core/src/test/java/brooklyn/util/file/ArchiveBuilderTest.java
deleted file mode 100644
index 6469f5a..0000000
--- a/core/src/test/java/brooklyn/util/file/ArchiveBuilderTest.java
+++ /dev/null
@@ -1,193 +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 brooklyn.util.file;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Set;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-
-import javax.annotation.Nullable;
-
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-import brooklyn.util.collections.MutableSet;
-import brooklyn.util.os.Os;
-import brooklyn.util.text.Identifiers;
-
-import com.google.common.base.Charsets;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.io.Files;
-
-/**
- * Test the operation of the {@link ArchiveBuilder} class.
- */
-@Test
-public class ArchiveBuilderTest {
-
- private File parentDir, tmpDir, tmpDir2;
- private Predicate<ZipEntry> isDirectory = new Predicate<ZipEntry>() {
- @Override
- public boolean apply(@Nullable ZipEntry input) {
- return input.isDirectory();
- }
- };
-
- @BeforeClass
- public void createTmpDirAndFiles() throws IOException {
- parentDir = Os.newTempDir(getClass().getSimpleName());
- Os.deleteOnExitRecursively(parentDir);
- tmpDir = new File(parentDir, Identifiers.makeRandomId(4));
- Os.mkdirs(tmpDir);
- Files.write("abcdef", new File(tmpDir, "data01.txt"), Charsets.US_ASCII);
- Files.write("123456", new File(tmpDir, "data02.txt"), Charsets.US_ASCII);
- Files.write("qqqqqq", new File(tmpDir, "data03.txt"), Charsets.US_ASCII);
-
- tmpDir2 = new File(parentDir, Identifiers.makeRandomId(4));
- Os.mkdirs(tmpDir2);
- Files.write("zzzzzz", new File(tmpDir2, "data04.txt"), Charsets.US_ASCII);
- }
-
- @Test
- public void testCreateZipFromDir() throws Exception {
- File archive = ArchiveBuilder.zip().addDirContentsAt(tmpDir, ".").create();
- archive.deleteOnExit();
-
- List<ZipEntry> entries = Lists.newArrayList();
- ZipInputStream input = new ZipInputStream(new FileInputStream(archive));
- ZipEntry entry = input.getNextEntry();
- while (entry != null) {
- entries.add(entry);
- entry = input.getNextEntry();
- }
- assertEquals(entries.size(), 4);
- Iterable<ZipEntry> directories = Iterables.filter(entries, isDirectory);
- Iterable<ZipEntry> files = Iterables.filter(entries, Predicates.not(isDirectory));
- assertEquals(Iterables.size(directories), 1);
- assertEquals(Iterables.size(files), 3);
- String dirName = Iterables.getOnlyElement(directories).getName();
- assertEquals(dirName, "./");
-
- Set<String> names = MutableSet.of();
- for (ZipEntry file : files) {
- assertTrue(file.getName().startsWith(dirName));
- names.add(file.getName());
- }
- assertTrue(names.contains("./data01.txt"));
- assertFalse(names.contains("./data04.txt"));
- input.close();
- }
-
- @Test
- public void testCreateZipFromTwoDirs() throws Exception {
- File archive = ArchiveBuilder.zip().addDirContentsAt(tmpDir, ".").addDirContentsAt(tmpDir2, ".").create();
- archive.deleteOnExit();
-
- List<ZipEntry> entries = Lists.newArrayList();
- ZipInputStream input = new ZipInputStream(new FileInputStream(archive));
- ZipEntry entry = input.getNextEntry();
- while (entry != null) {
- entries.add(entry);
- entry = input.getNextEntry();
- }
- assertEquals(entries.size(), 5);
- Iterable<ZipEntry> directories = Iterables.filter(entries, isDirectory);
- Iterable<ZipEntry> files = Iterables.filter(entries, Predicates.not(isDirectory));
- assertEquals(Iterables.size(directories), 1);
- assertEquals(Iterables.size(files), 4);
- String dirName = Iterables.getOnlyElement(directories).getName();
- assertEquals(dirName, "./");
-
- Set<String> names = MutableSet.of();
- for (ZipEntry file : files) {
- assertTrue(file.getName().startsWith(dirName));
- names.add(file.getName());
- }
- assertTrue(names.contains("./data01.txt"));
- assertTrue(names.contains("./data04.txt"));
- input.close();
- }
- @Test
- public void testCreateZipFromFiles() throws Exception {
- ArchiveBuilder builder = ArchiveBuilder.zip();
- for (String fileName : Arrays.asList("data01.txt", "data02.txt", "data03.txt")) {
- builder.addAt(new File(tmpDir, fileName), ".");
- }
- File archive = builder.create();
- archive.deleteOnExit();
-
- List<ZipEntry> entries = Lists.newArrayList();
- ZipInputStream input = new ZipInputStream(new FileInputStream(archive));
- ZipEntry entry = input.getNextEntry();
- while (entry != null) {
- entries.add(entry);
- entry = input.getNextEntry();
- }
- assertEquals(entries.size(), 3);
- Iterable<ZipEntry> directories = Iterables.filter(entries, isDirectory);
- Iterable<ZipEntry> files = Iterables.filter(entries, Predicates.not(isDirectory));
- assertTrue(Iterables.isEmpty(directories));
- assertEquals(Iterables.size(files), 3);
- for (ZipEntry file : files) {
- assertTrue(file.getName().startsWith(Os.mergePathsUnix(".", "data")));
- }
- input.close();
- }
-
- @Test
- public void testCreateZipFromFilesWithBaseDir() throws Exception {
- ArchiveBuilder builder = ArchiveBuilder.zip();
- String baseDir = tmpDir.getName();
- for (String fileName : Arrays.asList("data01.txt", "data02.txt", "data03.txt")) {
- builder.addFromLocalBaseDir(parentDir, Os.mergePaths(baseDir, fileName));
- }
- File archive = builder.create();
- archive.deleteOnExit();
-
- List<ZipEntry> entries = Lists.newArrayList();
- ZipInputStream input = new ZipInputStream(new FileInputStream(archive));
- ZipEntry entry = input.getNextEntry();
- while (entry != null) {
- entries.add(entry);
- entry = input.getNextEntry();
- }
- assertEquals(entries.size(), 3);
- Iterable<ZipEntry> directories = Iterables.filter(entries, isDirectory);
- Iterable<ZipEntry> files = Iterables.filter(entries, Predicates.not(isDirectory));
- assertTrue(Iterables.isEmpty(directories));
- assertEquals(Iterables.size(files), 3);
- for (ZipEntry file : files) {
- assertTrue(file.getName().startsWith(Os.mergePathsUnix(".", baseDir)));
- }
- input.close();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/file/ArchiveUtilsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/file/ArchiveUtilsTest.java b/core/src/test/java/brooklyn/util/file/ArchiveUtilsTest.java
deleted file mode 100644
index 6715444..0000000
--- a/core/src/test/java/brooklyn/util/file/ArchiveUtilsTest.java
+++ /dev/null
@@ -1,135 +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 brooklyn.util.file;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
-
-import java.io.File;
-import java.util.Map;
-
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.entity.BrooklynAppUnitTestSupport;
-import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.os.Os;
-
-import com.google.api.client.repackaged.com.google.common.base.Joiner;
-import com.google.common.base.Charsets;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.io.Files;
-
-// Test are integration, because relies on ssh/scp via SshMachineLocation
-public class ArchiveUtilsTest extends BrooklynAppUnitTestSupport {
-
- private SshMachineLocation machine;
- private ResourceUtils resourceUtils;
-
- private Map<String, String> archiveContents = ImmutableMap.of("a.txt", "mya");
- private File destDir;
- private File origZip;
- private File origJar;
-
- @BeforeClass(alwaysRun=true)
- public void setUpClass() throws Exception {
- origZip = newZip(archiveContents);
- origJar = Os.newTempFile(ArchiveUtilsTest.class, ".jar");
- Files.copy(origZip, origJar);
- }
-
- @AfterClass(alwaysRun=true)
- public void tearDownClass() throws Exception {
- if (origZip != null) origZip.delete();
- if (origJar != null) origJar.delete();
- }
-
- @BeforeMethod(alwaysRun=true)
- @Override
- public void setUp() throws Exception {
- super.setUp();
- machine = app.newLocalhostProvisioningLocation().obtain();
- resourceUtils = ResourceUtils.create(ArchiveUtilsTest.class);
- destDir = Os.newTempDir(getClass().getSimpleName());
- }
-
- @AfterMethod(alwaysRun=true)
- @Override
- public void tearDown() throws Exception {
- super.tearDown();
- if (destDir != null) Os.deleteRecursively(destDir);
- }
-
- @Test(groups="Integration")
- public void testDeployZipWithNoOptionalArgsSupplied() throws Exception {
- boolean result = ArchiveUtils.deploy(resourceUtils, ImmutableMap.<String, Object>of(), origZip.getAbsolutePath(), machine, destDir.getAbsolutePath(), true, null, null);
- assertTrue(result);
- assertFilesEqual(new File(destDir, origZip.getName()), origZip);
- assertSubFilesEqual(destDir, archiveContents);
- }
-
- @Test(groups="Integration")
- public void testDeployZipDeletingArchiveAfterUnpack() throws Exception {
- boolean result = ArchiveUtils.deploy(resourceUtils, ImmutableMap.<String, Object>of(), origZip.getAbsolutePath(), machine, destDir.getAbsolutePath(), false, null, null);
- assertTrue(result);
- assertFalse(new File(destDir, origZip.getName()).exists());
- assertSubFilesEqual(destDir, archiveContents);
- }
-
- @Test(groups="Integration")
- public void testDeployJarNotUnpacked() throws Exception {
- ArchiveUtils.deploy(origJar.getAbsolutePath(), machine, destDir.getAbsolutePath());
- assertFilesEqual(new File(destDir, origJar.getName()), origJar);
- }
-
- @Test(groups="Integration")
- public void testDeployExplicitDestFile() throws Exception {
- String destFile = "custom-destFile.jar";
- ArchiveUtils.deploy(origJar.getAbsolutePath(), machine, destDir.getAbsolutePath(), destFile);
- assertFilesEqual(new File(destDir, destFile), origJar);
- }
-
- private File newZip(Map<String, String> files) throws Exception {
- File parentDir = Os.newTempDir(getClass().getSimpleName()+"-archive");
- for (Map.Entry<String, String> entry : files.entrySet()) {
- File subFile = new File(Os.mergePaths(parentDir.getAbsolutePath(), entry.getKey()));
- subFile.getParentFile().mkdirs();
- Files.write(entry.getValue(), subFile, Charsets.UTF_8);
- }
- return ArchiveBuilder.zip().addDirContentsAt(parentDir, ".").create();
- }
-
- private void assertFilesEqual(File f1, File f2) throws Exception {
- byte[] bytes1 = Files.asByteSource(f1).read();
- byte[] bytes2 = Files.asByteSource(f1).read();
- assertEquals(bytes1, bytes2, "f1="+f1+"; f2="+f2);
- }
-
- private void assertSubFilesEqual(File parentDir, Map<String, String> files) throws Exception {
- for (Map.Entry<String, String> entry : archiveContents.entrySet()) {
- File subFile = new File(Os.mergePaths(parentDir.getAbsolutePath(), entry.getKey()));
- assertEquals(Joiner.on("\n").join(Files.readLines(subFile, Charsets.UTF_8)), entry.getValue());
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/flags/MethodCoercionsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/flags/MethodCoercionsTest.java b/core/src/test/java/brooklyn/util/flags/MethodCoercionsTest.java
deleted file mode 100644
index 4d06ca4..0000000
--- a/core/src/test/java/brooklyn/util/flags/MethodCoercionsTest.java
+++ /dev/null
@@ -1,146 +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 brooklyn.util.flags;
-
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.guava.Maybe;
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableList;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-import java.lang.reflect.Method;
-import java.util.List;
-
-import static org.testng.Assert.*;
-
-public class MethodCoercionsTest {
-
- private Method singleParameterMethod;
- private Method multiParameterMethod;
- private Method singleCollectionParameterMethod;
-
- @BeforeClass
- public void testFixtureSetUp() {
- try {
- singleParameterMethod = TestClass.class.getMethod("singleParameterMethod", int.class);
- multiParameterMethod = TestClass.class.getMethod("multiParameterMethod", boolean.class, int.class);
- singleCollectionParameterMethod = TestClass.class.getMethod("singleCollectionParameterMethod", List.class);
- } catch (NoSuchMethodException e) {
- throw Exceptions.propagate(e);
- }
- }
-
- @Test
- public void testMatchSingleParameterMethod() throws Exception {
- Predicate<Method> predicate = MethodCoercions.matchSingleParameterMethod("singleParameterMethod", "42");
- assertTrue(predicate.apply(singleParameterMethod));
- assertFalse(predicate.apply(multiParameterMethod));
- assertFalse(predicate.apply(singleCollectionParameterMethod));
- }
-
- @Test
- public void testTryFindAndInvokeSingleParameterMethod() throws Exception {
- TestClass instance = new TestClass();
- Maybe<?> maybe = MethodCoercions.tryFindAndInvokeSingleParameterMethod(instance, "singleParameterMethod", "42");
- assertTrue(maybe.isPresent());
- assertTrue(instance.wasSingleParameterMethodCalled());
- }
-
- @Test
- public void testMatchMultiParameterMethod() throws Exception {
- Predicate<Method> predicate = MethodCoercions.matchMultiParameterMethod("multiParameterMethod", ImmutableList.of("true", "42"));
- assertFalse(predicate.apply(singleParameterMethod));
- assertTrue(predicate.apply(multiParameterMethod));
- assertFalse(predicate.apply(singleCollectionParameterMethod));
- }
-
- @Test
- public void testTryFindAndInvokeMultiParameterMethod() throws Exception {
- TestClass instance = new TestClass();
- Maybe<?> maybe = MethodCoercions.tryFindAndInvokeMultiParameterMethod(instance, "multiParameterMethod", ImmutableList.of("true", "42"));
- assertTrue(maybe.isPresent());
- assertTrue(instance.wasMultiParameterMethodCalled());
- }
-
- @Test
- public void testTryFindAndInvokeBestMatchingMethod() throws Exception {
- TestClass instance = new TestClass();
- Maybe<?> maybe = MethodCoercions.tryFindAndInvokeBestMatchingMethod(instance, "singleParameterMethod", "42");
- assertTrue(maybe.isPresent());
- assertTrue(instance.wasSingleParameterMethodCalled());
-
- instance = new TestClass();
- maybe = MethodCoercions.tryFindAndInvokeBestMatchingMethod(instance, "multiParameterMethod", ImmutableList.of("true", "42"));
- assertTrue(maybe.isPresent());
- assertTrue(instance.wasMultiParameterMethodCalled());
-
- instance = new TestClass();
- maybe = MethodCoercions.tryFindAndInvokeBestMatchingMethod(instance, "singleCollectionParameterMethod", ImmutableList.of("fred", "joe"));
- assertTrue(maybe.isPresent());
- assertTrue(instance.wasSingleCollectionParameterMethodCalled());
- }
-/*
- @Test
- public void testMatchSingleCollectionParameterMethod() throws Exception {
- Predicate<Method> predicate = MethodCoercions.matchSingleCollectionParameterMethod("singleCollectionParameterMethod", ImmutableList.of("42"));
- assertFalse(predicate.apply(singleParameterMethod));
- assertFalse(predicate.apply(multiParameterMethod));
- assertTrue(predicate.apply(singleCollectionParameterMethod));
- }
-
- @Test
- public void testTryFindAndInvokeSingleCollectionParameterMethod() throws Exception {
- TestClass instance = new TestClass();
- Maybe<?> maybe = MethodCoercions.tryFindAndInvokeSingleCollectionParameterMethod(instance, "singleCollectionParameterMethod", ImmutableList.of("42"));
- assertTrue(maybe.isPresent());
- assertTrue(instance.wasSingleCollectionParameterMethodCalled());
- }
-*/
- public static class TestClass {
-
- private boolean singleParameterMethodCalled;
- private boolean multiParameterMethodCalled;
- private boolean singleCollectionParameterMethodCalled;
-
- public void singleParameterMethod(int parameter) {
- singleParameterMethodCalled = true;
- }
-
- public void multiParameterMethod(boolean parameter1, int parameter2) {
- multiParameterMethodCalled = true;
- }
-
- public void singleCollectionParameterMethod(List<String> parameter) {
- singleCollectionParameterMethodCalled = true;
- }
-
- public boolean wasSingleParameterMethodCalled() {
- return singleParameterMethodCalled;
- }
-
- public boolean wasMultiParameterMethodCalled() {
- return multiParameterMethodCalled;
- }
-
- public boolean wasSingleCollectionParameterMethodCalled() {
- return singleCollectionParameterMethodCalled;
- }
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/http/BetterMockWebServer.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/http/BetterMockWebServer.java b/core/src/test/java/brooklyn/util/http/BetterMockWebServer.java
deleted file mode 100644
index fb76903..0000000
--- a/core/src/test/java/brooklyn/util/http/BetterMockWebServer.java
+++ /dev/null
@@ -1,138 +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 brooklyn.util.http;
-
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.Proxy;
-import java.net.URL;
-
-import javax.net.ssl.SSLSocketFactory;
-
-import com.google.common.base.Throwables;
-import com.google.mockwebserver.Dispatcher;
-import com.google.mockwebserver.MockResponse;
-import com.google.mockwebserver.MockWebServer;
-import com.google.mockwebserver.RecordedRequest;
-
-/** like MockWebServer (and delegating) but:
- * <li> allows subclassing
- * <li> easy way to create instance which returns localhost for {@link #getHostName()}
- * (since otherwise you can get failures on networks which misconfigure hostname)
- * */
-public class BetterMockWebServer {
-
- final MockWebServer delegate = new MockWebServer();
- String hostname = null;
- boolean isHttps = false;
-
- public static BetterMockWebServer newInstanceLocalhost() {
- return new BetterMockWebServer().setHostName("localhost");
- }
-
- /** use {@link #newInstanceLocalhost()} or subclass */
- protected BetterMockWebServer() {}
-
- public BetterMockWebServer setHostName(String hostname) {
- this.hostname = hostname;
- return this;
- }
-
-
- // --- delegate methods (unchanged)
-
- public void enqueue(MockResponse response) {
- delegate.enqueue(response);
- }
-
- public boolean equals(Object obj) {
- return delegate.equals(obj);
- }
-
- public String getCookieDomain() {
- return delegate.getCookieDomain();
- }
-
- public String getHostName() {
- if (hostname!=null) return hostname;
- return delegate.getHostName();
- }
-
- public int getPort() {
- return delegate.getPort();
- }
-
- public int getRequestCount() {
- return delegate.getRequestCount();
- }
-
- public URL getUrl(String path) {
- try {
- return isHttps
- ? new URL("https://" + getHostName() + ":" + getPort() + path)
- : new URL("http://" + getHostName() + ":" + getPort() + path);
- } catch (MalformedURLException e) {
- throw Throwables.propagate(e);
- }
- }
-
- public int hashCode() {
- return delegate.hashCode();
- }
-
- public void play() throws IOException {
- delegate.play();
- }
-
- public void play(int port) throws IOException {
- delegate.play(port);
- }
-
- public void setBodyLimit(int maxBodyLength) {
- delegate.setBodyLimit(maxBodyLength);
- }
-
- public void setDispatcher(Dispatcher dispatcher) {
- delegate.setDispatcher(dispatcher);
- }
-
- public void shutdown() throws IOException {
- delegate.shutdown();
- }
-
- public RecordedRequest takeRequest() throws InterruptedException {
- return delegate.takeRequest();
- }
-
- public Proxy toProxyAddress() {
- return delegate.toProxyAddress();
- }
-
- public String toString() {
- return delegate.toString();
- }
-
- public void useHttps(SSLSocketFactory sslSocketFactory, boolean tunnelProxy) {
- isHttps = true;
- delegate.useHttps(sslSocketFactory, tunnelProxy);
- }
-
-
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/http/HttpToolIntegrationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/http/HttpToolIntegrationTest.java b/core/src/test/java/brooklyn/util/http/HttpToolIntegrationTest.java
deleted file mode 100644
index dc9fc31..0000000
--- a/core/src/test/java/brooklyn/util/http/HttpToolIntegrationTest.java
+++ /dev/null
@@ -1,98 +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 brooklyn.util.http;
-
-import static org.testng.Assert.assertTrue;
-
-import java.net.URI;
-
-import org.apache.http.client.HttpClient;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import org.apache.brooklyn.location.basic.PortRanges;
-import brooklyn.test.HttpService;
-
-import com.google.common.collect.ImmutableMap;
-
-public class HttpToolIntegrationTest {
-
- // TODO Expand test coverage for credentials etc
-
- private HttpService httpService;
- private HttpService httpsService;
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() throws Exception {
- httpService = new HttpService(PortRanges.fromString("9000+"), false).start();
- httpsService = new HttpService(PortRanges.fromString("9000+"), true).start();
- }
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws Exception {
- if (httpService != null) httpService.shutdown();
- if (httpsService != null) httpsService.shutdown();
- }
-
- @Test(groups = {"Integration"})
- public void testHttpGet() throws Exception {
- URI baseUri = new URI(httpService.getUrl());
-
- HttpClient client = HttpTool.httpClientBuilder().build();
- HttpToolResponse result = HttpTool.httpGet(client, baseUri, ImmutableMap.<String,String>of());
- assertTrue(new String(result.getContent()).contains("Hello, World"), "val="+new String(result.getContent()));
- }
-
- @Test(groups = {"Integration"})
- public void testHttpRedirect() throws Exception {
- URI baseUri = new URI(httpService.getUrl() + "hello/redirectAbsolute");
-
- HttpClient client = HttpTool.httpClientBuilder().laxRedirect(true).build();
- HttpToolResponse result = HttpTool.httpGet(client, baseUri, ImmutableMap.<String,String>of());
- assertTrue(new String(result.getContent()).contains("Hello, World"), "val="+new String(result.getContent()));
- }
-
- @Test(groups = {"Integration"})
- public void testHttpPost() throws Exception {
- URI baseUri = new URI(httpService.getUrl());
-
- HttpClient client = HttpTool.httpClientBuilder().build();
- HttpToolResponse result = HttpTool.httpPost(client, baseUri, ImmutableMap.<String,String>of(), new byte[0]);
- assertTrue(new String(result.getContent()).contains("Hello, World"), "val="+new String(result.getContent()));
- }
-
- @Test(groups = {"Integration"})
- public void testHttpsGetWithTrustAll() throws Exception {
- URI baseUri = new URI(httpsService.getUrl());
-
- HttpClient client = HttpTool.httpClientBuilder().https(true).trustAll().build();
- HttpToolResponse result = HttpTool.httpGet(client, baseUri, ImmutableMap.<String,String>of());
- assertTrue(new String(result.getContent()).contains("Hello, World"), "val="+new String(result.getContent()));
- }
-
- @Test(groups = {"Integration"})
- public void testHttpsPostWithTrustSelfSigned() throws Exception {
- URI baseUri = new URI(httpsService.getUrl());
-
- HttpClient client = HttpTool.httpClientBuilder().https(true).trustSelfSigned().build();
- HttpToolResponse result = HttpTool.httpPost(client, baseUri, ImmutableMap.<String,String>of(), new byte[0]);
- assertTrue(new String(result.getContent()).contains("Hello, World"), "val="+new String(result.getContent()));
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/internal/FlagUtilsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/internal/FlagUtilsTest.java b/core/src/test/java/brooklyn/util/internal/FlagUtilsTest.java
deleted file mode 100644
index ed98dba..0000000
--- a/core/src/test/java/brooklyn/util/internal/FlagUtilsTest.java
+++ /dev/null
@@ -1,314 +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 brooklyn.util.internal;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
-
-import java.lang.reflect.Field;
-import java.net.InetAddress;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.brooklyn.api.entity.trait.Configurable;
-import org.apache.brooklyn.api.management.Task;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.Test;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.config.ConfigKey.HasConfigKey;
-import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.flags.FlagUtils;
-import brooklyn.util.flags.SetFromFlag;
-
-import com.google.common.base.Function;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-
-public class FlagUtilsTest {
-
- public static final Logger log = LoggerFactory.getLogger(FlagUtilsTest.class);
-
- @Test
- public void testGetAllFields() {
- log.info("types {}", FlagUtils.getAllAssignableTypes(Baz.class));
- assertEquals(FlagUtils.getAllAssignableTypes(Baz.class), ImmutableList.of(Baz.class, Foo.class, Bar.class));
- List<Field> fs = FlagUtils.getAllFields(Baz.class);
- for (Field f : fs) {
- log.info("field {} {}", f.getName(), f);
- }
- List<String> fsn = ImmutableList.copyOf(Iterables.transform(fs, new Function<Field, String>() {
- @Override public String apply(Field f) {
- return f.getName();
- }}));
- assertTrue(fsn.indexOf("A") >= 0);
- assertTrue(fsn.indexOf("w") > fsn.indexOf("A"));
- assertTrue(fsn.indexOf("x") > fsn.indexOf("A") );
- assertTrue(fsn.indexOf("yNotY") > fsn.indexOf("A"));
- assertTrue(fsn.indexOf("Z") > fsn.indexOf("yNotY") );
- }
-
- @Test
- public void testSetFieldsFromFlags() {
- Foo f = new Foo();
- Map<?,?> m = MutableMap.of("w", 3, "x", 1, "y", 7, "z", 9);
- Map<?, ?> unused = FlagUtils.setFieldsFromFlags(m, f);
- assertEquals(f.w, 3);
- assertEquals(f.x, 1);
- assertEquals(f.yNotY, 7);
- assertEquals(unused, ImmutableMap.of("z", 9));
- Map<?,?> m2 = FlagUtils.getFieldsWithValues(f);
- m.remove("z");
- assertEquals(m2, m);
- }
-
- @Test
- public void testCollectionCoercionOnSetFromFlags() {
- WithSpecialFieldTypes s = new WithSpecialFieldTypes();
- Map<?,?> m = ImmutableMap.of("set", ImmutableSet.of(1));
- FlagUtils.setFieldsFromFlags(m, s);
- assertEquals(s.set, ImmutableSet.of(1));
- }
-
- @Test
- public void testInetAddressCoercionOnSetFromFlags() {
- WithSpecialFieldTypes s = new WithSpecialFieldTypes();
- Map<?,?> m = ImmutableMap.of("inet", "127.0.0.1");
- FlagUtils.setFieldsFromFlags(m, s);
- assertEquals(s.inet.getHostAddress(), "127.0.0.1");
- }
-
- @Test
- public void testNonImmutableField() {
- Foo f = new Foo();
- FlagUtils.setFieldsFromFlags(ImmutableMap.of("w", 8), f);
- assertEquals(f.w, 8);
- FlagUtils.setFieldsFromFlags(ImmutableMap.of("w", 9), f);
- assertEquals(f.w, 9);
- }
-
- @Test
- public void testImmutableIntField() {
- Foo f = new Foo();
- FlagUtils.setFieldsFromFlags(ImmutableMap.of("x", 8), f);
- assertEquals(f.x, 8);
- boolean succeededWhenShouldntHave = false;
- try {
- FlagUtils.setFieldsFromFlags(ImmutableMap.of("x", 9), f);
- succeededWhenShouldntHave = true;
- } catch (IllegalStateException e) {
- //expected
- }
- assertFalse(succeededWhenShouldntHave);
- assertEquals(f.x, 8);
- }
-
- @Test
- public void testImmutableObjectField() {
- WithImmutableNonNullableObject o = new WithImmutableNonNullableObject();
- FlagUtils.setFieldsFromFlags(ImmutableMap.of("a", "a", "b", "b"), o);
- assertEquals(o.a, "a");
- assertEquals(o.b, "b");
-
- FlagUtils.setFieldsFromFlags(ImmutableMap.of("a", "a2"), o);
- assertEquals(o.a, "a2");
-
- boolean succeededWhenShouldntHave = false;
- try {
- FlagUtils.setFieldsFromFlags(ImmutableMap.of("b", "b2"), o);
- succeededWhenShouldntHave = true;
- } catch (IllegalStateException e) {
- //expected
- }
- assertFalse(succeededWhenShouldntHave);
- assertEquals(o.b, "b");
- }
-
- @Test
- public void testNonNullable() {
- WithImmutableNonNullableObject o = new WithImmutableNonNullableObject();
- //allowed
- FlagUtils.setFieldsFromFlags(MutableMap.of("a", null), o);
- assertEquals(o.a, null);
- assertEquals(o.b, null);
- //not allowed
- boolean succeededWhenShouldntHave = false;
- try {
- FlagUtils.setFieldsFromFlags(MutableMap.of("b", null), o);
- succeededWhenShouldntHave = true;
- } catch (IllegalArgumentException e) {
- //expected
- }
- assertFalse(succeededWhenShouldntHave);
- assertEquals(o.b, null);
- }
-
- @Test
- public void testGetAnnotatedFields() throws Exception {
- Map<Field, SetFromFlag> fm = FlagUtils.getAnnotatedFields(WithImmutableNonNullableObject.class);
- assertEquals(fm.keySet().size(), 2);
- assertTrue(fm.get(WithImmutableNonNullableObject.class.getDeclaredField("b")).immutable());
- }
-
- @Test
- public void testCheckRequired() {
- WithImmutableNonNullableObject f = new WithImmutableNonNullableObject();
- FlagUtils.setFieldsFromFlags(ImmutableMap.of("a", "a is a"), f);
- assertEquals(f.a, "a is a");
- assertEquals(f.b, null);
- int exceptions = 0;
- try {
- FlagUtils.checkRequiredFields(f);
- } catch (IllegalStateException e) {
- exceptions++;
- }
- assertEquals(exceptions, 1);
- }
-
- @Test
- public void testSetConfigKeys() {
- FooCK f = new FooCK();
- Map<?,?> unused = FlagUtils.setFieldsFromFlags(ImmutableMap.of("f1", 9, "ck1", "do-set", "ck2", "dont-set", "c3", "do-set"), f);
- assertEquals(f.bag.get(FooCK.CK1), "do-set");
- assertEquals(f.bag.get(FooCK.CK3), "do-set");
- assertEquals(f.f1, 9);
- assertEquals(f.bag.containsKey(FooCK.CK2), false);
- assertEquals(unused, ImmutableMap.of("ck2", "dont-set"));
- }
-
- @Test
- public void testSetAllConfigKeys() {
- FooCK f = new FooCK();
- Map<?,?> unused = FlagUtils.setAllConfigKeys(ImmutableMap.of("f1", 9, "ck1", "do-set", "ck2", "do-set-2", "c3", "do-set"), f, true);
- assertEquals(f.bag.get(FooCK.CK1), "do-set");
- assertEquals(f.bag.get(FooCK.CK3), "do-set");
- assertEquals(f.bag.containsKey(FooCK.CK2), true);
- assertEquals(f.bag.get(FooCK.CK2), "do-set-2");
- assertEquals(unused, ImmutableMap.of("f1", 9));
- }
-
- @Test
- public void testSetFromConfigKeys() {
- FooCK f = new FooCK();
- Map<?, ?> unused = FlagUtils.setFieldsFromFlags(ImmutableMap.of(new BasicConfigKey<Integer>(Integer.class, "f1"), 9, "ck1", "do-set", "ck2", "dont-set"), f);
- assertEquals(f.bag.get(FooCK.CK1), "do-set");
- assertEquals(f.f1, 9);
- assertEquals(f.bag.containsKey(FooCK.CK2), false);
- assertEquals(unused, ImmutableMap.of("ck2", "dont-set"));
- }
-
- public static class Foo {
- @SetFromFlag
- int w;
-
- @SetFromFlag(immutable=true)
- private int x;
-
- @SetFromFlag("y")
- public int yNotY;
- }
-
- public static interface Bar {
- static final String Z = "myzval";
- }
-
- public static class Baz extends Foo implements Bar {
- @SuppressWarnings("unused") //inspected by reflection
- private static int A;
- }
-
- public static class WithImmutableNonNullableObject {
- @SetFromFlag
- Object a;
- @SetFromFlag(immutable=true, nullable=false)
- public Object b;
- }
-
- public static class WithSpecialFieldTypes {
- @SetFromFlag Set<?> set;
- @SetFromFlag InetAddress inet;
- }
-
- public static class FooCK implements Configurable {
- @SetFromFlag
- public static ConfigKey<String> CK1 = ConfigKeys.newStringConfigKey("ck1");
-
- public static ConfigKey<String> CK2 = ConfigKeys.newStringConfigKey("ck2");
-
- @SetFromFlag("c3")
- public static ConfigKey<String> CK3 = ConfigKeys.newStringConfigKey("ck3");
-
- @SetFromFlag
- int f1;
-
- ConfigBag bag = new ConfigBag();
- BasicConfigurationSupport configSupport = new BasicConfigurationSupport();
-
- @Override
- public ConfigurationSupport config() {
- return configSupport;
- }
-
- public <T> T setConfig(ConfigKey<T> key, T val) {
- return config().set(key, val);
- }
-
- private class BasicConfigurationSupport implements ConfigurationSupport {
- @Override
- public <T> T get(ConfigKey<T> key) {
- return bag.get(key);
- }
-
- @Override
- public <T> T get(HasConfigKey<T> key) {
- return get(key.getConfigKey());
- }
-
- @Override
- public <T> T set(ConfigKey<T> key, T val) {
- T old = bag.get(key);
- bag.configure(key, val);
- return old;
- }
-
- @Override
- public <T> T set(HasConfigKey<T> key, T val) {
- return set(key.getConfigKey(), val);
- }
-
- @Override
- public <T> T set(ConfigKey<T> key, Task<T> val) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public <T> T set(HasConfigKey<T> key, Task<T> val) {
- return set(key.getConfigKey(), val);
- }
- }
- }
-}
\ No newline at end of file
[31/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/system/internal/ExecWithLoggingHelpers.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/system/internal/ExecWithLoggingHelpers.java b/core/src/main/java/brooklyn/util/task/system/internal/ExecWithLoggingHelpers.java
deleted file mode 100644
index c2b8907..0000000
--- a/core/src/main/java/brooklyn/util/task/system/internal/ExecWithLoggingHelpers.java
+++ /dev/null
@@ -1,200 +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 brooklyn.util.task.system.internal;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.PipedInputStream;
-import java.io.PipedOutputStream;
-import java.util.List;
-import java.util.Map;
-
-import org.slf4j.Logger;
-
-import brooklyn.config.ConfigKey;
-import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.flags.TypeCoercions;
-import brooklyn.util.internal.ssh.ShellAbstractTool;
-import brooklyn.util.internal.ssh.ShellTool;
-import brooklyn.util.stream.StreamGobbler;
-import brooklyn.util.stream.Streams;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.text.Strings;
-
-import com.google.common.base.Function;
-import com.google.common.base.Throwables;
-
-public abstract class ExecWithLoggingHelpers {
-
- public static final ConfigKey<OutputStream> STDOUT = SshMachineLocation.STDOUT;
- public static final ConfigKey<OutputStream> STDERR = SshMachineLocation.STDERR;
- public static final ConfigKey<Boolean> NO_STDOUT_LOGGING = SshMachineLocation.NO_STDOUT_LOGGING;
- public static final ConfigKey<Boolean> NO_STDERR_LOGGING = SshMachineLocation.NO_STDERR_LOGGING;
- public static final ConfigKey<String> LOG_PREFIX = SshMachineLocation.LOG_PREFIX;
-
- protected final String shortName;
- protected Logger commandLogger = null;
-
- public interface ExecRunner {
- public int exec(ShellTool ssh, Map<String,?> flags, List<String> cmds, Map<String,?> env);
- }
-
- protected abstract <T> T execWithTool(MutableMap<String, Object> toolCreationAndConnectionProperties, Function<ShellTool, T> runMethodOnTool);
- protected abstract void preExecChecks();
- protected abstract String getTargetName();
- protected abstract String constructDefaultLoggingPrefix(ConfigBag execFlags);
-
- /** takes a very short name for use in blocking details, e.g. SSH or Process */
- public ExecWithLoggingHelpers(String shortName) {
- this.shortName = shortName;
- }
-
- public ExecWithLoggingHelpers logger(Logger commandLogger) {
- this.commandLogger = commandLogger;
- return this;
- }
-
- public int execScript(Map<String,?> props, String summaryForLogging, List<String> commands, Map<String,?> env) {
- // TODO scriptHeader are the extra commands we expect the SshTool/ShellTool to add.
- // Would be better if could get this from the ssh-tool, rather than assuming it will behave as
- // we expect.
- String scriptHeader = ShellAbstractTool.getOptionalVal(props, ShellTool.PROP_SCRIPT_HEADER);
-
- return execWithLogging(props, summaryForLogging, commands, env, scriptHeader, new ExecRunner() {
- @Override public int exec(ShellTool ssh, Map<String, ?> flags, List<String> cmds, Map<String, ?> env) {
- return ssh.execScript(flags, cmds, env);
- }});
- }
-
- protected static <T> T getOptionalVal(Map<String,?> map, ConfigKey<T> keyC) {
- if (keyC==null) return null;
- String key = keyC.getName();
- if (map!=null && map.containsKey(key)) {
- return TypeCoercions.coerce(map.get(key), keyC.getTypeToken());
- } else {
- return keyC.getDefaultValue();
- }
- }
-
- public int execCommands(Map<String,?> props, String summaryForLogging, List<String> commands, Map<String,?> env) {
- return execWithLogging(props, summaryForLogging, commands, env, new ExecRunner() {
- @Override public int exec(ShellTool tool, Map<String,?> flags, List<String> cmds, Map<String,?> env) {
- return tool.execCommands(flags, cmds, env);
- }});
- }
-
- public int execWithLogging(Map<String,?> props, final String summaryForLogging, final List<String> commands,
- final Map<String,?> env, final ExecRunner execCommand) {
- return execWithLogging(props, summaryForLogging, commands, env, null, execCommand);
- }
-
- @SuppressWarnings("resource")
- public int execWithLogging(Map<String,?> props, final String summaryForLogging, final List<String> commands,
- final Map<String,?> env, String expectedCommandHeaders, final ExecRunner execCommand) {
- if (commandLogger!=null && commandLogger.isDebugEnabled()) {
- String allcmds = (Strings.isBlank(expectedCommandHeaders) ? "" : expectedCommandHeaders + " ; ") + Strings.join(commands, " ; ");
- commandLogger.debug("{}, initiating "+shortName.toLowerCase()+" on machine {}{}: {}",
- new Object[] {summaryForLogging, getTargetName(),
- env!=null && !env.isEmpty() ? " (env "+env+")": "", allcmds});
- }
-
- if (commands.isEmpty()) {
- if (commandLogger!=null && commandLogger.isDebugEnabled())
- commandLogger.debug("{}, on machine {}, ending: no commands to run", summaryForLogging, getTargetName());
- return 0;
- }
-
- final ConfigBag execFlags = new ConfigBag().putAll(props);
- // some props get overridden in execFlags, so remove them from the tool flags
- final ConfigBag toolFlags = new ConfigBag().putAll(props).removeAll(
- LOG_PREFIX, STDOUT, STDERR, ShellTool.PROP_NO_EXTRA_OUTPUT);
-
- execFlags.configure(ShellTool.PROP_SUMMARY, summaryForLogging);
-
- PipedOutputStream outO = null;
- PipedOutputStream outE = null;
- StreamGobbler gO=null, gE=null;
- try {
- preExecChecks();
-
- String logPrefix = execFlags.get(LOG_PREFIX);
- if (logPrefix==null) logPrefix = constructDefaultLoggingPrefix(execFlags);
-
- if (!execFlags.get(NO_STDOUT_LOGGING)) {
- PipedInputStream insO = new PipedInputStream();
- outO = new PipedOutputStream(insO);
-
- String stdoutLogPrefix = "["+(logPrefix != null ? logPrefix+":stdout" : "stdout")+"] ";
- gO = new StreamGobbler(insO, execFlags.get(STDOUT), commandLogger).setLogPrefix(stdoutLogPrefix);
- gO.start();
-
- execFlags.put(STDOUT, outO);
- }
-
- if (!execFlags.get(NO_STDERR_LOGGING)) {
- PipedInputStream insE = new PipedInputStream();
- outE = new PipedOutputStream(insE);
-
- String stderrLogPrefix = "["+(logPrefix != null ? logPrefix+":stderr" : "stderr")+"] ";
- gE = new StreamGobbler(insE, execFlags.get(STDERR), commandLogger).setLogPrefix(stderrLogPrefix);
- gE.start();
-
- execFlags.put(STDERR, outE);
- }
-
- Tasks.setBlockingDetails(shortName+" executing, "+summaryForLogging);
- try {
- return execWithTool(MutableMap.copyOf(toolFlags.getAllConfig()), new Function<ShellTool, Integer>() {
- public Integer apply(ShellTool tool) {
- int result = execCommand.exec(tool, MutableMap.copyOf(execFlags.getAllConfig()), commands, env);
- if (commandLogger!=null && commandLogger.isDebugEnabled())
- commandLogger.debug("{}, on machine {}, completed: return status {}",
- new Object[] {summaryForLogging, getTargetName(), result});
- return result;
- }});
-
- } finally {
- Tasks.setBlockingDetails(null);
- }
-
- } catch (IOException e) {
- if (commandLogger!=null && commandLogger.isDebugEnabled())
- commandLogger.debug("{}, on machine {}, failed: {}", new Object[] {summaryForLogging, getTargetName(), e});
- throw Throwables.propagate(e);
- } finally {
- // Must close the pipedOutStreams, otherwise input will never read -1 so StreamGobbler thread would never die
- if (outO!=null) try { outO.flush(); } catch (IOException e) {}
- if (outE!=null) try { outE.flush(); } catch (IOException e) {}
- Streams.closeQuietly(outO);
- Streams.closeQuietly(outE);
-
- try {
- if (gE!=null) { gE.join(); }
- if (gO!=null) { gO.join(); }
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- Throwables.propagate(e);
- }
- }
-
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/system/internal/SystemProcessTaskFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/system/internal/SystemProcessTaskFactory.java b/core/src/main/java/brooklyn/util/task/system/internal/SystemProcessTaskFactory.java
deleted file mode 100644
index e6eb831..0000000
--- a/core/src/main/java/brooklyn/util/task/system/internal/SystemProcessTaskFactory.java
+++ /dev/null
@@ -1,131 +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 brooklyn.util.task.system.internal;
-
-import java.io.File;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.internal.ssh.ShellTool;
-import brooklyn.util.internal.ssh.process.ProcessTool;
-import brooklyn.util.task.system.ProcessTaskWrapper;
-
-import com.google.common.base.Function;
-
-public class SystemProcessTaskFactory<T extends SystemProcessTaskFactory<T,RET>,RET> extends AbstractProcessTaskFactory<T, RET> {
-
- private static final Logger log = LoggerFactory.getLogger(SystemProcessTaskFactory.class);
-
- // FIXME Plum this through?!
- private File directory;
- private Boolean loginShell;
-
- public SystemProcessTaskFactory(String ...commands) {
- super(commands);
- }
-
- public T directory(File directory) {
- markDirty();
- this.directory = directory;
- return self();
- }
-
- public T loginShell(boolean loginShell) {
- markDirty();
- this.loginShell = loginShell;
- return self();
- }
-
- @Override
- public T machine(SshMachineLocation machine) {
- log.warn("Not permitted to set machines on "+this+" (ignoring - "+machine+")");
- if (log.isDebugEnabled())
- log.debug("Source of attempt to set machines on "+this+" ("+machine+")",
- new Throwable("Source of attempt to set machines on "+this+" ("+machine+")"));
- return self();
- }
-
- @Override
- public ProcessTaskWrapper<RET> newTask() {
- return new SystemProcessTaskWrapper();
- }
-
- protected class SystemProcessTaskWrapper extends ProcessTaskWrapper<RET> {
- protected final String taskTypeShortName;
-
- public SystemProcessTaskWrapper() {
- this("Process");
- }
- public SystemProcessTaskWrapper(String taskTypeShortName) {
- super(SystemProcessTaskFactory.this);
- this.taskTypeShortName = taskTypeShortName;
- }
- @Override
- protected ConfigBag getConfigForRunning() {
- ConfigBag result = super.getConfigForRunning();
- if (directory != null) config.put(ProcessTool.PROP_DIRECTORY, directory.getAbsolutePath());
- if (loginShell != null) config.put(ProcessTool.PROP_LOGIN_SHELL, loginShell);
- return result;
- }
- @Override
- protected void run(ConfigBag config) {
- if (Boolean.FALSE.equals(this.runAsScript)) {
- this.exitCode = newExecWithLoggingHelpers().execCommands(config.getAllConfig(), getSummary(), getCommands(), getShellEnvironment());
- } else { // runScript = null or TRUE
- this.exitCode = newExecWithLoggingHelpers().execScript(config.getAllConfig(), getSummary(), getCommands(), getShellEnvironment());
- }
- }
- @Override
- protected String taskTypeShortName() { return taskTypeShortName; }
- }
-
- protected ExecWithLoggingHelpers newExecWithLoggingHelpers() {
- return new ExecWithLoggingHelpers("Process") {
- @Override
- protected <U> U execWithTool(MutableMap<String, Object> props, Function<ShellTool, U> task) {
- // properties typically passed to both
- if (log.isDebugEnabled() && props!=null && !props.isEmpty())
- log.debug("Ignoring flags "+props+" when running "+this);
- return task.apply(new ProcessTool());
- }
- @Override
- protected void preExecChecks() {}
- @Override
- protected String constructDefaultLoggingPrefix(ConfigBag execFlags) {
- return "system.exec";
- }
- @Override
- protected String getTargetName() {
- return "local host";
- }
- }.logger(log);
- }
-
- /** concrete instance (for generics) */
- public static class ConcreteSystemProcessTaskFactory<RET> extends SystemProcessTaskFactory<ConcreteSystemProcessTaskFactory<RET>, RET> {
- public ConcreteSystemProcessTaskFactory(String ...commands) {
- super(commands);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/text/DataUriSchemeParser.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/text/DataUriSchemeParser.java b/core/src/main/java/brooklyn/util/text/DataUriSchemeParser.java
deleted file mode 100644
index 393ab20..0000000
--- a/core/src/main/java/brooklyn/util/text/DataUriSchemeParser.java
+++ /dev/null
@@ -1,267 +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 brooklyn.util.text;
-
-import java.io.ByteArrayInputStream;
-import java.io.UnsupportedEncodingException;
-import java.net.MalformedURLException;
-import java.net.URLDecoder;
-import java.nio.charset.Charset;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-import brooklyn.util.exceptions.Exceptions;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.io.BaseEncoding;
-//import com.sun.jersey.core.util.Base64;
-
-/** implementation (currently hokey) of RFC-2397 data: URI scheme.
- * see: http://stackoverflow.com/questions/12353552/any-rfc-2397-data-uri-parser-for-java */
-public class DataUriSchemeParser {
-
- public static final String PROTOCOL_PREFIX = "data:";
- public static final String DEFAULT_MIME_TYPE = "text/plain";
- public static final String DEFAULT_CHARSET = "US-ASCII";
-
- private final String url;
- private int parseIndex = 0;
- private boolean isParsed = false;
- private boolean allowMissingComma = false;
- private boolean allowSlashesAfterColon = false;
- private boolean allowOtherLaxities = false;
-
- private String mimeType;
- private byte[] data;
- private Map<String,String> parameters = new LinkedHashMap<String,String>();
-
- public DataUriSchemeParser(String url) {
- this.url = Preconditions.checkNotNull(url, "url");
- }
-
- // ---- static conveniences -----
-
- public static String toString(String url) {
- return new DataUriSchemeParser(url).lax().parse().getDataAsString();
- }
-
- public static byte[] toBytes(String url) {
- return new DataUriSchemeParser(url).lax().parse().getData();
- }
-
- // ---- accessors (once it is parsed) -----------
-
- public String getCharset() {
- String charset = parameters.get("charset");
- if (charset!=null) return charset;
- return DEFAULT_CHARSET;
- }
-
- public String getMimeType() {
- assertParsed();
- if (mimeType!=null) return mimeType;
- return DEFAULT_MIME_TYPE;
- }
-
- public Map<String, String> getParameters() {
- return ImmutableMap.<String, String>copyOf(parameters);
- }
-
- public byte[] getData() {
- assertParsed();
- return data;
- }
-
- public ByteArrayInputStream getDataAsInputStream() {
- return new ByteArrayInputStream(getData());
- }
-
- public String getDataAsString() {
- return new String(getData(), Charset.forName(getCharset()));
- }
-
- // ---- config ------------------
-
- public synchronized DataUriSchemeParser lax() {
- return allowMissingComma(true).allowSlashesAfterColon(true).allowOtherLaxities(true);
- }
-
- public synchronized DataUriSchemeParser allowMissingComma(boolean allowMissingComma) {
- assertNotParsed();
- this.allowMissingComma = allowMissingComma;
- return this;
- }
-
- public synchronized DataUriSchemeParser allowSlashesAfterColon(boolean allowSlashesAfterColon) {
- assertNotParsed();
- this.allowSlashesAfterColon = allowSlashesAfterColon;
- return this;
- }
-
- private synchronized DataUriSchemeParser allowOtherLaxities(boolean allowOtherLaxities) {
- assertNotParsed();
- this.allowOtherLaxities = allowOtherLaxities;
- return this;
- }
-
- private void assertNotParsed() {
- if (isParsed) throw new IllegalStateException("Operation not permitted after parsing");
- }
-
- private void assertParsed() {
- if (!isParsed) throw new IllegalStateException("Operation not permitted before parsing");
- }
-
- public synchronized DataUriSchemeParser parse() {
- try {
- return parseChecked();
- } catch (Exception e) {
- throw Exceptions.propagate(e);
- }
- }
-
- public synchronized DataUriSchemeParser parseChecked() throws UnsupportedEncodingException, MalformedURLException {
- if (isParsed) return this;
-
- skipOptional(PROTOCOL_PREFIX);
- if (allowSlashesAfterColon)
- while (skipOptional("/")) ;
-
- if (allowMissingComma && remainder().indexOf(',')==-1) {
- mimeType = DEFAULT_MIME_TYPE;
- parameters.put("charset", DEFAULT_CHARSET);
- } else {
- parseMediaType();
- parseParameterOrParameterValues();
- skipRequired(",");
- }
-
- parseData();
-
- isParsed = true;
- return this;
- }
-
- private void parseMediaType() throws MalformedURLException {
- if (remainder().startsWith(";") || remainder().startsWith(","))
- return;
- int slash = remainder().indexOf("/");
- if (slash==-1) throw new MalformedURLException("Missing required '/' in MIME type of data: URL");
- String type = read(slash);
- skipRequired("/");
- int next = nextSemiOrComma();
- String subtype = read(next);
- mimeType = type+"/"+subtype;
- }
-
- private String read(int next) {
- String result = remainder().substring(0, next);
- parseIndex += next;
- return result;
- }
-
- private int nextSemiOrComma() throws MalformedURLException {
- int semi = remainder().indexOf(';');
- int comma = remainder().indexOf(',');
- if (semi<0 && comma<0) throw new MalformedURLException("Missing required ',' in data: URL");
- if (semi<0) return comma;
- if (comma<0) return semi;
- return Math.min(semi, comma);
- }
-
- private void parseParameterOrParameterValues() throws MalformedURLException {
- while (true) {
- if (!remainder().startsWith(";")) return;
- parseIndex++;
- int eq = remainder().indexOf('=');
- String word, value;
- int nextSemiOrComma = nextSemiOrComma();
- if (eq==-1 || eq>nextSemiOrComma) {
- word = read(nextSemiOrComma);
- value = null;
- } else {
- word = read(eq);
- if (remainder().startsWith("\"")) {
- // is quoted
- parseIndex++;
- int nextUnescapedQuote = nextUnescapedQuote();
- value = "\"" + read(nextUnescapedQuote);
- } else {
- value = read(nextSemiOrComma());
- }
- }
- parameters.put(word, value);
- }
- }
-
- private int nextUnescapedQuote() throws MalformedURLException {
- int i=0;
- String r = remainder();
- boolean escaped = false;
- while (i<r.length()) {
- if (escaped) {
- escaped = false;
- } else {
- if (r.charAt(i)=='"') return i;
- if (r.charAt(i)=='\\') escaped = true;
- }
- i++;
- }
- throw new MalformedURLException("Unclosed double-quote in data: URL");
- }
-
- private void parseData() throws UnsupportedEncodingException, MalformedURLException {
- if (parameters.containsKey("base64")) {
- checkNoParamValue("base64");
- data = BaseEncoding.base64().decode(remainder());
- } else if (parameters.containsKey("base64url")) {
- checkNoParamValue("base64url");
- data = BaseEncoding.base64Url().decode(remainder());
- } else {
- data = URLDecoder.decode(remainder(), getCharset()).getBytes(Charset.forName(getCharset()));
- }
- }
-
- private void checkNoParamValue(String param) throws MalformedURLException {
- if (allowOtherLaxities) return;
- String value = parameters.get(param);
- if (value!=null)
- throw new MalformedURLException(param+" parameter must not take a value ("+value+") in data: URL");
- }
-
- private String remainder() {
- return url.substring(parseIndex);
- }
-
- private boolean skipOptional(String word) {
- if (remainder().startsWith(word)) {
- parseIndex += word.length();
- return true;
- }
- return false;
- }
-
- private void skipRequired(String word) throws MalformedURLException {
- if (!remainder().startsWith(word))
- throw new MalformedURLException("Missing required '"+word+"' at position "+parseIndex+" of data: URL");
- parseIndex += word.length();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/text/TemplateProcessor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/text/TemplateProcessor.java b/core/src/main/java/brooklyn/util/text/TemplateProcessor.java
deleted file mode 100644
index eb0c2ad..0000000
--- a/core/src/main/java/brooklyn/util/text/TemplateProcessor.java
+++ /dev/null
@@ -1,397 +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 brooklyn.util.text;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.util.Map;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.drivers.EntityDriver;
-import org.apache.brooklyn.api.event.AttributeSensor;
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.entity.basic.Entities;
-import brooklyn.entity.basic.EntityInternal;
-import brooklyn.event.basic.DependentConfiguration;
-import brooklyn.event.basic.Sensors;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.exceptions.Exceptions;
-
-import com.google.common.base.Charsets;
-import com.google.common.collect.Iterables;
-import com.google.common.io.Files;
-
-import freemarker.cache.StringTemplateLoader;
-import freemarker.template.Configuration;
-import freemarker.template.ObjectWrapper;
-import freemarker.template.Template;
-import freemarker.template.TemplateHashModel;
-import freemarker.template.TemplateModel;
-import freemarker.template.TemplateModelException;
-
-/** A variety of methods to assist in Freemarker template processing,
- * including passing in maps with keys flattened (dot-separated namespace),
- * and accessing {@link ManagementContext} brooklyn.properties
- * and {@link Entity}, {@link EntityDriver}, and {@link Location} methods and config.
- * <p>
- * See {@link #processTemplateContents(String, ManagementContextInternal, Map)} for
- * a description of how management access is done.
- */
-public class TemplateProcessor {
-
- private static final Logger log = LoggerFactory.getLogger(TemplateProcessor.class);
-
- protected static TemplateModel wrapAsTemplateModel(Object o) throws TemplateModelException {
- if (o instanceof Map) return new DotSplittingTemplateModel((Map<?,?>)o);
- return ObjectWrapper.DEFAULT_WRAPPER.wrap(o);
- }
-
- /** @deprecated since 0.7.0 use {@link #processTemplateFile(String, Map)} */ @Deprecated
- public static String processTemplate(String templateFileName, Map<String, ? extends Object> substitutions) {
- return processTemplateFile(templateFileName, substitutions);
- }
-
- /** As per {@link #processTemplateContents(String, Map)}, but taking a file. */
- public static String processTemplateFile(String templateFileName, Map<String, ? extends Object> substitutions) {
- String templateContents;
- try {
- templateContents = Files.toString(new File(templateFileName), Charsets.UTF_8);
- } catch (IOException e) {
- log.warn("Error loading file " + templateFileName, e);
- throw Exceptions.propagate(e);
- }
- return processTemplateContents(templateContents, substitutions);
- }
-
- /** @deprecated since 0.7.0 use {@link #processTemplateFile(String, EntityDriver, Map)} */ @Deprecated
- public static String processTemplate(String templateFileName, EntityDriver driver, Map<String, ? extends Object> extraSubstitutions) {
- return processTemplateFile(templateFileName, driver, extraSubstitutions);
- }
-
- /** Processes template contents according to {@link EntityAndMapTemplateModel}. */
- public static String processTemplateFile(String templateFileName, EntityDriver driver, Map<String, ? extends Object> extraSubstitutions) {
- String templateContents;
- try {
- templateContents = Files.toString(new File(templateFileName), Charsets.UTF_8);
- } catch (IOException e) {
- log.warn("Error loading file " + templateFileName, e);
- throw Exceptions.propagate(e);
- }
- return processTemplateContents(templateContents, driver, extraSubstitutions);
- }
-
- /** Processes template contents according to {@link EntityAndMapTemplateModel}. */
- public static String processTemplateContents(String templateContents, EntityDriver driver, Map<String,? extends Object> extraSubstitutions) {
- return processTemplateContents(templateContents, new EntityAndMapTemplateModel(driver, extraSubstitutions));
- }
-
- /** Processes template contents according to {@link EntityAndMapTemplateModel}. */
- public static String processTemplateContents(String templateContents, ManagementContext managementContext, Map<String,? extends Object> extraSubstitutions) {
- return processTemplateContents(templateContents, new EntityAndMapTemplateModel(managementContext, extraSubstitutions));
- }
-
- /**
- * A Freemarker {@link TemplateHashModel} which will correctly handle entries of the form "a.b" in this map,
- * matching against template requests for "${a.b}".
- * <p>
- * Freemarker requests "a" in a map when given such a request, and expects that to point to a map
- * with a key "b". This model provides such maps even for "a.b" in a map.
- * <p>
- * However if "a" <b>and</b> "a.b" are in the map, this will <b>not</b> currently do the deep mapping.
- * (It does not have enough contextual information from Freemarker to handle this case.) */
- public static final class DotSplittingTemplateModel implements TemplateHashModel {
- protected final Map<?,?> map;
-
- protected DotSplittingTemplateModel(Map<?,?> map) {
- this.map = map;
- }
-
- @Override
- public boolean isEmpty() { return map!=null && map.isEmpty(); }
-
- public boolean contains(String key) {
- if (map==null) return false;
- if (map.containsKey(key)) return true;
- for (Map.Entry<?,?> entry: map.entrySet()) {
- String k = Strings.toString(entry.getKey());
- if (k.startsWith(key+".")) {
- // contains this prefix
- return true;
- }
- }
- return false;
- }
-
- @Override
- public TemplateModel get(String key) throws TemplateModelException {
- if (map==null) return null;
- try {
- if (map.containsKey(key))
- return wrapAsTemplateModel( map.get(key) );
-
- Map<String,Object> result = MutableMap.of();
- for (Map.Entry<?,?> entry: map.entrySet()) {
- String k = Strings.toString(entry.getKey());
- if (k.startsWith(key+".")) {
- String k2 = Strings.removeFromStart(k, key+".");
- result.put(k2, entry.getValue());
- }
- }
- if (!result.isEmpty())
- return wrapAsTemplateModel( result );
-
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- throw new IllegalStateException("Error accessing config '"+key+"'"+": "+e, e);
- }
-
- return null;
- }
-
- @Override
- public String toString() {
- return getClass().getName()+"["+map+"]";
- }
- }
-
- /** FreeMarker {@link TemplateHashModel} which resolves keys inside the given entity or management context.
- * Callers are required to include dots for dot-separated keys.
- * Freemarker will only due this when in inside bracket notation in an outer map, as in <code>${outer['a.b.']}</code>;
- * as a result this is intended only for use by {@link EntityAndMapTemplateModel} where
- * a caller has used bracked notation, as in <code>${mgmt['key.subkey']}</code>. */
- protected static final class EntityConfigTemplateModel implements TemplateHashModel {
- protected final EntityInternal entity;
- protected final ManagementContext mgmt;
-
- protected EntityConfigTemplateModel(EntityInternal entity) {
- this.entity = entity;
- this.mgmt = entity.getManagementContext();
- }
-
- protected EntityConfigTemplateModel(ManagementContext mgmt) {
- this.entity = null;
- this.mgmt = mgmt;
- }
-
- @Override
- public boolean isEmpty() { return false; }
-
- @Override
- public TemplateModel get(String key) throws TemplateModelException {
- try {
- Object result = null;
-
- if (entity!=null)
- result = entity.getConfig(ConfigKeys.builder(Object.class).name(key).build());
- if (result==null && mgmt!=null)
- result = mgmt.getConfig().getConfig(ConfigKeys.builder(Object.class).name(key).build());
-
- if (result!=null)
- return wrapAsTemplateModel( result );
-
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- throw new IllegalStateException("Error accessing config '"+key+"'"
- + (entity!=null ? " on "+entity : "")+": "+e, e);
- }
-
- return null;
- }
-
- @Override
- public String toString() {
- return getClass().getName()+"["+entity+"]";
- }
- }
-
- protected final static class EntityAttributeTemplateModel implements TemplateHashModel {
- protected final EntityInternal entity;
-
- protected EntityAttributeTemplateModel(EntityInternal entity) {
- this.entity = entity;
- }
-
- @Override
- public boolean isEmpty() throws TemplateModelException {
- return false;
- }
-
- @Override
- public TemplateModel get(String key) throws TemplateModelException {
- Object result;
- try {
- result = Entities.submit(entity, DependentConfiguration.attributeWhenReady(entity,
- Sensors.builder(Object.class, key).persistence(AttributeSensor.SensorPersistenceMode.NONE).build())).get();
- } catch (Exception e) {
- throw Exceptions.propagate(e);
- }
- if (result == null) {
- return null;
- } else {
- return wrapAsTemplateModel(result);
- }
- }
-
- @Override
- public String toString() {
- return getClass().getName()+"["+entity+"]";
- }
- }
-
- /**
- * Provides access to config on an entity or management context, using
- * <code>${config['entity.config.key']}</code> or <code>${mgmt['brooklyn.properties.key']}</code> notation,
- * and also allowing access to <code>getX()</code> methods on entity (interface) or driver
- * using <code>${entity.x}</code> or <code><${driver.x}</code>.
- * Optional extra properties can be supplied, treated as per {@link DotSplittingTemplateModel}.
- */
- protected static final class EntityAndMapTemplateModel implements TemplateHashModel {
- protected final EntityInternal entity;
- protected final EntityDriver driver;
- protected final ManagementContext mgmt;
- protected final DotSplittingTemplateModel extraSubstitutionsModel;
-
- protected EntityAndMapTemplateModel(ManagementContext mgmt, Map<String,? extends Object> extraSubstitutions) {
- this.entity = null;
- this.driver = null;
- this.mgmt = mgmt;
- this.extraSubstitutionsModel = new DotSplittingTemplateModel(extraSubstitutions);
- }
-
- protected EntityAndMapTemplateModel(EntityDriver driver, Map<String,? extends Object> extraSubstitutions) {
- this.driver = driver;
- this.entity = (EntityInternal) driver.getEntity();
- this.mgmt = entity.getManagementContext();
- this.extraSubstitutionsModel = new DotSplittingTemplateModel(extraSubstitutions);
- }
-
- protected EntityAndMapTemplateModel(EntityInternal entity, Map<String,? extends Object> extraSubstitutions) {
- this.entity = entity;
- this.driver = null;
- this.mgmt = entity.getManagementContext();
- this.extraSubstitutionsModel = new DotSplittingTemplateModel(extraSubstitutions);
- }
-
- @Override
- public boolean isEmpty() { return false; }
-
- @Override
- public TemplateModel get(String key) throws TemplateModelException {
- if (extraSubstitutionsModel.contains(key))
- return wrapAsTemplateModel( extraSubstitutionsModel.get(key) );
-
- if ("entity".equals(key) && entity!=null)
- return wrapAsTemplateModel( entity );
- if ("config".equals(key)) {
- if (entity!=null)
- return new EntityConfigTemplateModel(entity);
- else
- return new EntityConfigTemplateModel(mgmt);
- }
- if ("mgmt".equals(key)) {
- return new EntityConfigTemplateModel(mgmt);
- }
-
- if ("driver".equals(key) && driver!=null)
- return wrapAsTemplateModel( driver );
- if ("location".equals(key)) {
- if (driver!=null && driver.getLocation()!=null)
- return wrapAsTemplateModel( driver.getLocation() );
- if (entity!=null)
- return wrapAsTemplateModel( Iterables.getOnlyElement( entity.getLocations() ) );
- }
- if ("attribute".equals(key)) {
- return new EntityAttributeTemplateModel(entity);
- }
-
- if (mgmt!=null) {
- // TODO deprecated in 0.7.0, remove after next version
- // ie not supported to access global props without qualification
- Object result = mgmt.getConfig().getConfig(ConfigKeys.builder(Object.class).name(key).build());
- if (result!=null) {
- log.warn("Deprecated access of global brooklyn.properties value for "+key+"; should be qualified with 'mgmt.'");
- return wrapAsTemplateModel( result );
- }
- }
-
- if ("javaSysProps".equals(key))
- return wrapAsTemplateModel( System.getProperties() );
-
- return null;
- }
-
- @Override
- public String toString() {
- return getClass().getName()+"["+(entity!=null ? entity : mgmt)+"]";
- }
- }
-
- /** Processes template contents with the given items in scope as per {@link EntityAndMapTemplateModel}. */
- public static String processTemplateContents(String templateContents, final EntityInternal entity, Map<String,? extends Object> extraSubstitutions) {
- return processTemplateContents(templateContents, new EntityAndMapTemplateModel(entity, extraSubstitutions));
- }
-
- /** Processes template contents using the given map, passed to freemarker,
- * with dot handling as per {@link DotSplittingTemplateModel}. */
- public static String processTemplateContents(String templateContents, final Map<String, ? extends Object> substitutions) {
- TemplateHashModel root;
- try {
- root = substitutions != null
- ? (TemplateHashModel)wrapAsTemplateModel(substitutions)
- : null;
- } catch (TemplateModelException e) {
- throw new IllegalStateException("Unable to set up TemplateHashModel to parse template, given "+substitutions+": "+e, e);
- }
-
- return processTemplateContents(templateContents, root);
- }
-
- /** Processes template contents against the given {@link TemplateHashModel}. */
- public static String processTemplateContents(String templateContents, final TemplateHashModel substitutions) {
- try {
- Configuration cfg = new Configuration();
- StringTemplateLoader templateLoader = new StringTemplateLoader();
- templateLoader.putTemplate("config", templateContents);
- cfg.setTemplateLoader(templateLoader);
- Template template = cfg.getTemplate("config");
-
- // TODO could expose CAMP '$brooklyn:' style dsl, based on template.createProcessingEnvironment
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- Writer out = new OutputStreamWriter(baos);
- template.process(substitutions, out);
- out.flush();
-
- return new String(baos.toByteArray());
- } catch (Exception e) {
- log.warn("Error processing template (propagating): "+e, e);
- log.debug("Template which could not be parsed (causing "+e+") is:"
- + (Strings.isMultiLine(templateContents) ? "\n"+templateContents : templateContents));
- throw Exceptions.propagate(e);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/xstream/CompilerIndependentOuterClassFieldMapper.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/xstream/CompilerIndependentOuterClassFieldMapper.java b/core/src/main/java/brooklyn/util/xstream/CompilerIndependentOuterClassFieldMapper.java
deleted file mode 100644
index f9a1f00..0000000
--- a/core/src/main/java/brooklyn/util/xstream/CompilerIndependentOuterClassFieldMapper.java
+++ /dev/null
@@ -1,166 +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 brooklyn.util.xstream;
-
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.thoughtworks.xstream.core.Caching;
-import com.thoughtworks.xstream.mapper.Mapper;
-import com.thoughtworks.xstream.mapper.MapperWrapper;
-
-/**
- * <p>Compiler independent outer class field mapper.</p>
- * <p>Different compilers generate different indexes for the names of outer class reference
- * field (this$N) leading to deserialization errors.</p>
- * <ul>
- * <li> eclipse-[groovy-]compiler counts all outer static classes
- * <li> OpenJDK/Oracle/IBM compiler starts at 0, regardless of the nesting level
- * </ul>
- * <p>The mapper will be able to update field names for instances with a single this$N
- * field only (including those from parent classes).</p>
- * <p>For difference between generated field names compare
- * {@code src/test/java/brooklyn/util/xstream/compiler_compatibility_eclipse.xml} and
- * {@code src/test/java/brooklyn/util/xstream/compiler_compatibility_oracle.xml},
- * generated from {@code brooklyn.util.xstream.CompilerCompatibilityTest}</p>
- * <p>JLS 1.1 relevant section, copied verbatim for a lack of reliable URL:</p>
- * <blockquote>
- * <p>Java 1.1 compilers are strongly encouraged, though not required, to use the
- * following naming conventions when implementing inner classes. Compilers may
- * not use synthetic names of the forms defined here for any other purposes.</p>
- * <p>A synthetic field pointing to the outermost enclosing instance is named this$0.
- * The next-outermost enclosing instance is this$1, and so forth. (At most one such
- * field is necessary in any given inner class.) A synthetic field containing a copy
- * of a constant v is named val$v. These fields are final.</p>
- * </blockquote>
- * <p>Currently available at
- * http://web.archive.org/web/20000830111107/http://java.sun.com/products/jdk/1.1/docs/guide/innerclasses/spec/innerclasses.doc10.html</p>
- */
-public class CompilerIndependentOuterClassFieldMapper extends MapperWrapper implements Caching {
- public static final Logger LOG = LoggerFactory.getLogger(CompilerIndependentOuterClassFieldMapper.class);
-
- private static final String OUTER_CLASS_FIELD_PREFIX = "this$";
-
- private final Map<String, Collection<String>> classOuterFields = new ConcurrentHashMap<String, Collection<String>>();
-
- public CompilerIndependentOuterClassFieldMapper(Mapper wrapped) {
- super(wrapped);
- classOuterFields.put(Object.class.getName(), Collections.<String>emptyList());
- }
-
- @Override
- public String realMember(@SuppressWarnings("rawtypes") Class type, String serialized) {
- // Let com.thoughtworks.xstream.mapper.OuterClassMapper also run on the input.
- String serializedFieldName = super.realMember(type, serialized);
-
- if (serializedFieldName.startsWith(OUTER_CLASS_FIELD_PREFIX)) {
- Collection<String> compiledFieldNames = findOuterClassFieldNames(type);
- if (compiledFieldNames.size() == 0) {
- throw new IllegalStateException("Unable to find any outer class fields in " + type + ", searching specifically for " + serializedFieldName);
- }
-
- Set<String> uniqueFieldNames = new HashSet<String>(compiledFieldNames);
- String deserializeFieldName;
- if (!compiledFieldNames.contains(serializedFieldName)) {
- String msg =
- "Unable to find outer class field " + serializedFieldName + " in class " + type + ". " +
- "This could be caused by " +
- "1) changing the class (or one of its parents) to a static or " +
- "2) moving the class to a different lexical level (enclosing classes) or " +
- "3) using a different compiler (i.e eclipse vs oracle) at the time the object was serialized. ";
- if (uniqueFieldNames.size() == 1) {
- // Try to fix the field naming only for the case with a single field or
- // multiple fields with the same name, in which case XStream puts defined-in
- // for the field declared in super.
- //
- // We don't have access to the XML elements from here to check for same name
- // so we check the target class instead. This should work most of the time, but
- // if code is recompiled in such a way that the new instance has fields with
- // different names, where only the field of the extending class is renamed and
- // the super field is not, then the instance will be deserialized incorrectly -
- // the super field will be assigned both times. If the field type is incompatible
- // then a casting exception will be thrown, if it's the same then only the warning
- // below will indicate of a possible problem down the line - most probably NPE on
- // the this$N field.
- deserializeFieldName = compiledFieldNames.iterator().next();
- LOG.warn(msg + "Will use the field " + deserializeFieldName + " instead.");
- } else {
- // Multiple fields with differing names case - don't try to fix it.
- // Better fail with an explicit error, and have someone fix it manually,
- // than try to fix it here non-reliably and have it fail down the line
- // with some unrelated error.
- // XStream will fail later with a field not found exception.
- LOG.error(msg + "Will fail with a field not found exception. " +
- "Edit the persistence state manually and update the field names. "+
- "Existing field names are " + uniqueFieldNames);
- deserializeFieldName = serializedFieldName;
- }
- } else {
- if (uniqueFieldNames.size() > 1) {
- // Log at debug level as the actual problem would occur in very specific cases. Only
- // useful when the compiler is changed, otherwise leads to false positives.
- LOG.debug("Deserializing the non-static class " + type + " with multiple outer class fields " + uniqueFieldNames + ". " +
- "When changing compilers it's possible that the instance won't be able to be deserialized due to changed outer class field names. " +
- "In those cases deserialization could fail with field not found exception or class cast exception following this log line.");
- }
- deserializeFieldName = serializedFieldName;
- }
-
- return deserializeFieldName;
- } else {
- return serializedFieldName;
- }
- }
-
- private Collection<String> findOuterClassFieldNames(Class<?> type) {
- Collection<String> fields = classOuterFields.get(type.getName());
- if (fields == null) {
- fields = new ArrayList<String>();
- addOuterClassFields(type, fields);
- classOuterFields.put(type.getName(), fields);
- }
- return fields;
- }
-
- private void addOuterClassFields(Class<?> type, Collection<String> fields) {
- for (Field field : type.getDeclaredFields()) {
- if (field.isSynthetic()) {
- fields.add(field.getName());
- }
- }
- if (type.getSuperclass() != null) {
- addOuterClassFields(type.getSuperclass(), fields);
- }
- }
-
- @Override
- public void flushCache() {
- classOuterFields.keySet().retainAll(Collections.singletonList(Object.class.getName()));
- }
-
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/xstream/EnumCaseForgivingConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/xstream/EnumCaseForgivingConverter.java b/core/src/main/java/brooklyn/util/xstream/EnumCaseForgivingConverter.java
deleted file mode 100644
index 96bafe6..0000000
--- a/core/src/main/java/brooklyn/util/xstream/EnumCaseForgivingConverter.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 brooklyn.util.xstream;
-
-import brooklyn.util.exceptions.Exceptions;
-
-import com.thoughtworks.xstream.converters.UnmarshallingContext;
-import com.thoughtworks.xstream.converters.enums.EnumConverter;
-import com.thoughtworks.xstream.io.HierarchicalStreamReader;
-
-/** ... except this doesn't seem to get applied when we think it should
- * (normal xstream.resgisterConverter doesn't apply to enums) */
-public class EnumCaseForgivingConverter extends EnumConverter {
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
- Class type = context.getRequiredType();
- if (type.getSuperclass() != Enum.class) {
- type = type.getSuperclass(); // polymorphic enums
- }
- String token = reader.getValue();
- // this is the new bit (overriding superclass to accept case-insensitive)
- return resolve(type, token);
- }
-
- public static <T extends Enum<T>> T resolve(Class<T> type, String token) {
- try {
- return Enum.valueOf(type, token.toUpperCase());
- } catch (Exception e) {
-
- // new stuff here: try reading case insensitive
-
- Exceptions.propagateIfFatal(e);
- try {
- for (T v: type.getEnumConstants())
- if (v.name().equalsIgnoreCase(token)) return v;
- throw e;
- } catch (Exception e2) {
- throw Exceptions.propagate(e2);
- }
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/xstream/EnumCaseForgivingSingleValueConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/xstream/EnumCaseForgivingSingleValueConverter.java b/core/src/main/java/brooklyn/util/xstream/EnumCaseForgivingSingleValueConverter.java
deleted file mode 100644
index a7aba8c..0000000
--- a/core/src/main/java/brooklyn/util/xstream/EnumCaseForgivingSingleValueConverter.java
+++ /dev/null
@@ -1,35 +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 brooklyn.util.xstream;
-
-import com.thoughtworks.xstream.converters.enums.EnumSingleValueConverter;
-
-public class EnumCaseForgivingSingleValueConverter extends EnumSingleValueConverter {
-
- private final Class enumType;
-
- public EnumCaseForgivingSingleValueConverter(Class type) {
- super(type);
- enumType = type;
- }
-
- public Object fromString(String str) {
- return EnumCaseForgivingConverter.resolve(enumType, str);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/xstream/ImmutableListConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/xstream/ImmutableListConverter.java b/core/src/main/java/brooklyn/util/xstream/ImmutableListConverter.java
deleted file mode 100644
index df33142..0000000
--- a/core/src/main/java/brooklyn/util/xstream/ImmutableListConverter.java
+++ /dev/null
@@ -1,54 +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 brooklyn.util.xstream;
-
-import java.util.Collection;
-
-import com.google.common.base.Predicates;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.thoughtworks.xstream.converters.UnmarshallingContext;
-import com.thoughtworks.xstream.converters.collections.CollectionConverter;
-import com.thoughtworks.xstream.io.HierarchicalStreamReader;
-import com.thoughtworks.xstream.mapper.Mapper;
-
-public class ImmutableListConverter extends CollectionConverter {
-
- public ImmutableListConverter(Mapper mapper) {
- super(mapper);
- }
-
- @Override
- public boolean canConvert(@SuppressWarnings("rawtypes") Class type) {
- return ImmutableList.class.isAssignableFrom(type);
- }
-
- // marshalling is the same
- // so is unmarshalling the entries
-
- // only differences are creating the overarching collection, which we do after the fact
- // (optimizing format on disk as opposed to in-memory), and we discard null values
- // to avoid failing entirely.
- public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
- Collection<?> collection = Lists.newArrayList();
- populateCollection(reader, context, collection);
- return ImmutableList.copyOf(Iterables.filter(collection, Predicates.notNull()));
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/xstream/ImmutableMapConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/xstream/ImmutableMapConverter.java b/core/src/main/java/brooklyn/util/xstream/ImmutableMapConverter.java
deleted file mode 100644
index aa8ca4c..0000000
--- a/core/src/main/java/brooklyn/util/xstream/ImmutableMapConverter.java
+++ /dev/null
@@ -1,56 +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 brooklyn.util.xstream;
-
-import java.util.Map;
-import java.util.Map.Entry;
-
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-import com.thoughtworks.xstream.converters.UnmarshallingContext;
-import com.thoughtworks.xstream.io.HierarchicalStreamReader;
-import com.thoughtworks.xstream.mapper.Mapper;
-
-public class ImmutableMapConverter extends MapConverter {
-
- public ImmutableMapConverter(Mapper mapper) {
- super(mapper);
- }
-
- @Override
- public boolean canConvert(@SuppressWarnings("rawtypes") Class type) {
- return ImmutableMap.class.isAssignableFrom(type);
- }
-
- // marshalling is the same
- // so is unmarshalling the entries
-
- // only differences are creating the overarching collection, which we do after the fact
- // (optimizing format on disk as opposed to in-memory), and we discard null key/values
- // to avoid failing entirely.
- public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
- Map<?, ?> map = Maps.newLinkedHashMap();
- populateMap(reader, context, map);
- return ImmutableMap.copyOf(Maps.filterEntries(map, new Predicate<Map.Entry<?,?>>() {
- @Override public boolean apply(Entry<?, ?> input) {
- return input != null && input.getKey() != null && input.getValue() != null;
- }}));
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/xstream/ImmutableSetConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/xstream/ImmutableSetConverter.java b/core/src/main/java/brooklyn/util/xstream/ImmutableSetConverter.java
deleted file mode 100644
index 11ee3ce..0000000
--- a/core/src/main/java/brooklyn/util/xstream/ImmutableSetConverter.java
+++ /dev/null
@@ -1,54 +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 brooklyn.util.xstream;
-
-import java.util.Collection;
-
-import com.google.common.base.Predicates;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.thoughtworks.xstream.converters.UnmarshallingContext;
-import com.thoughtworks.xstream.converters.collections.CollectionConverter;
-import com.thoughtworks.xstream.io.HierarchicalStreamReader;
-import com.thoughtworks.xstream.mapper.Mapper;
-
-public class ImmutableSetConverter extends CollectionConverter {
-
- public ImmutableSetConverter(Mapper mapper) {
- super(mapper);
- }
-
- @Override
- public boolean canConvert(@SuppressWarnings("rawtypes") Class type) {
- return ImmutableSet.class.isAssignableFrom(type);
- }
-
- // marshalling is the same
- // so is unmarshalling the entries
-
- // only differences are creating the overarching collection, which we do after the fact
- // (optimizing format on disk as opposed to in-memory), and we discard null values
- // to avoid failing entirely.
- public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
- Collection<?> collection = Lists.newArrayList();
- populateCollection(reader, context, collection);
- return ImmutableSet.copyOf(Iterables.filter(collection, Predicates.notNull()));
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/xstream/Inet4AddressConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/xstream/Inet4AddressConverter.java b/core/src/main/java/brooklyn/util/xstream/Inet4AddressConverter.java
deleted file mode 100644
index dbd704b..0000000
--- a/core/src/main/java/brooklyn/util/xstream/Inet4AddressConverter.java
+++ /dev/null
@@ -1,65 +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 brooklyn.util.xstream;
-
-import java.net.Inet4Address;
-import java.net.UnknownHostException;
-
-import brooklyn.util.exceptions.Exceptions;
-
-import com.thoughtworks.xstream.converters.Converter;
-import com.thoughtworks.xstream.converters.MarshallingContext;
-import com.thoughtworks.xstream.converters.UnmarshallingContext;
-import com.thoughtworks.xstream.io.HierarchicalStreamReader;
-import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
-
-public class Inet4AddressConverter implements Converter {
-
- @Override
- public boolean canConvert(@SuppressWarnings("rawtypes") Class type) {
- return type.equals(Inet4Address.class);
- }
-
- @Override
- public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
- Inet4Address addr = (Inet4Address) source;
- writer.setValue(addr.getHostName()+"/"+addr.getHostAddress());
- }
-
- @Override
- public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
- String hostSlashAddress = reader.getValue();
- int i = hostSlashAddress.indexOf('/');
- try {
- if (i==-1) {
- return Inet4Address.getByName(hostSlashAddress);
- } else {
- String host = hostSlashAddress.substring(0, i);
- String addrS = hostSlashAddress.substring(i+1);
- byte[] addr = new byte[4];
- String[] addrSI = addrS.split("\\.");
- for (int k=0; k<4; k++) addr[k] = (byte)(int)Integer.valueOf(addrSI[k]);
- return Inet4Address.getByAddress(host, addr);
- }
- } catch (UnknownHostException e) {
- throw Exceptions.propagate(e);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/xstream/MapConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/xstream/MapConverter.java b/core/src/main/java/brooklyn/util/xstream/MapConverter.java
deleted file mode 100644
index 5ee2a6a..0000000
--- a/core/src/main/java/brooklyn/util/xstream/MapConverter.java
+++ /dev/null
@@ -1,104 +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 brooklyn.util.xstream;
-
-import java.util.ConcurrentModificationException;
-import java.util.Iterator;
-import java.util.Map;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.thoughtworks.xstream.converters.MarshallingContext;
-import com.thoughtworks.xstream.converters.UnmarshallingContext;
-import com.thoughtworks.xstream.core.ReferencingMarshallingContext;
-import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
-import com.thoughtworks.xstream.io.HierarchicalStreamReader;
-import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
-import com.thoughtworks.xstream.mapper.Mapper;
-
-/** equivalent to super, but cleaner methods, overridable, logging, and some retries */
-public class MapConverter extends com.thoughtworks.xstream.converters.collections.MapConverter {
-
- private static final Logger log = LoggerFactory.getLogger(MapConverter.class);
-
- public MapConverter(Mapper mapper) {
- super(mapper);
- }
-
- @SuppressWarnings({ "rawtypes" })
- public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
- Map map = (Map) source;
- try {
- for (Iterator iterator = map.entrySet().iterator(); iterator.hasNext();) {
- Map.Entry entry = (Map.Entry) iterator.next();
- marshalEntry(writer, context, entry);
- }
- } catch (ConcurrentModificationException e) {
- log.debug("Map "
- // seems there is no non-deprecated way to get the path...
- + (context instanceof ReferencingMarshallingContext ? "at "+((ReferencingMarshallingContext)context).currentPath() : "")
- + "["+source+"] modified while serializing; will fail, and retry may be attempted");
- throw e;
- // would be nice to attempt to re-serialize being slightly more defensive, as code below;
- // but the code above may have written partial data so that is dangerous, we could have corrupted output.
- // if we could mark and restore in the output stream then we could do this below (but we don't have that in our stream),
- // or we could try this copying code in the first instance (but that's slow);
- // error is rare most of the time (e.g. attribute being updated) so we bail on this whole attempt
- // and simply try serializing the map-owner (e.g. an entity) again.
-// ImmutableList entries = ImmutableList.copyOf(map.entrySet());
-// for (Iterator iterator = entries.iterator(); iterator.hasNext();) {
-// Map.Entry entry = (Map.Entry) iterator.next();
-// marshalEntry(writer, context, entry);
-// }
- }
- }
-
- protected String getEntryNodeName() { return mapper().serializedClass(Map.Entry.class); }
-
- protected void marshalEntry(HierarchicalStreamWriter writer, MarshallingContext context, Map.Entry entry) {
- ExtendedHierarchicalStreamWriterHelper.startNode(writer, getEntryNodeName(), Map.Entry.class);
-
- writeItem(entry.getKey(), context, writer);
- writeItem(entry.getValue(), context, writer);
-
- writer.endNode();
- }
-
- protected void populateMap(HierarchicalStreamReader reader, UnmarshallingContext context, Map map) {
- while (reader.hasMoreChildren()) {
- reader.moveDown();
- unmarshalEntry(reader, context, map);
- reader.moveUp();
- }
- }
-
- protected void unmarshalEntry(HierarchicalStreamReader reader, UnmarshallingContext context, Map map) {
- reader.moveDown();
- Object key = readItem(reader, context, map);
- reader.moveUp();
-
- reader.moveDown();
- Object value = readItem(reader, context, map);
- reader.moveUp();
-
- map.put(key, value);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/xstream/MutableSetConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/xstream/MutableSetConverter.java b/core/src/main/java/brooklyn/util/xstream/MutableSetConverter.java
deleted file mode 100644
index 3432751..0000000
--- a/core/src/main/java/brooklyn/util/xstream/MutableSetConverter.java
+++ /dev/null
@@ -1,44 +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 brooklyn.util.xstream;
-
-import brooklyn.util.collections.MutableSet;
-
-import com.thoughtworks.xstream.converters.collections.CollectionConverter;
-import com.thoughtworks.xstream.mapper.Mapper;
-
-public class MutableSetConverter extends CollectionConverter {
-
- // Although this class seems pointless (!), without registering an explicit converter for MutableSet then the
- // declaration for Set interferes, causing MutableSet.map field to be null on deserialization.
-
- public MutableSetConverter(Mapper mapper) {
- super(mapper);
- }
-
- @Override
- public boolean canConvert(@SuppressWarnings("rawtypes") Class type) {
- return MutableSet.class.isAssignableFrom(type);
- }
-
- @Override
- protected Object createCollection(Class type) {
- return new MutableSet<Object>();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/xstream/StringKeyMapConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/xstream/StringKeyMapConverter.java b/core/src/main/java/brooklyn/util/xstream/StringKeyMapConverter.java
deleted file mode 100644
index 26aba7a..0000000
--- a/core/src/main/java/brooklyn/util/xstream/StringKeyMapConverter.java
+++ /dev/null
@@ -1,134 +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 brooklyn.util.xstream;
-
-import java.util.Map;
-import java.util.Map.Entry;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.TypeCoercions;
-import brooklyn.util.text.Identifiers;
-
-import com.thoughtworks.xstream.converters.MarshallingContext;
-import com.thoughtworks.xstream.converters.UnmarshallingContext;
-import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
-import com.thoughtworks.xstream.io.HierarchicalStreamReader;
-import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
-import com.thoughtworks.xstream.mapper.Mapper;
-
-/** converter which simplifies representation of a map for string-based keys,
- * to <key>value</key>, or <entry key="key" type="string">value</entry>
- * @author alex
- *
- */
-public class StringKeyMapConverter extends MapConverter {
-
- private static final Logger log = LoggerFactory.getLogger(StringKeyMapConverter.class);
-
- // full stop is technically allowed ... goes against "best practice" ...
- // but simplifies property maps, and is used elsewhere in xstream's repn
- final static String VALID_XML_NODE_NAME_CHARS = Identifiers.JAVA_GOOD_NONSTART_CHARS + ".";
-
- final static String VALID_XML_NODE_NAME_START_CHARS = Identifiers.JAVA_GOOD_START_CHARS + ".";
-
- public StringKeyMapConverter(Mapper mapper) {
- super(mapper);
- }
-
- protected boolean isKeyValidForNodeName(String key) {
- // return false to always write as <entry key="key" ...; otherwise only use that when key is not valid xml
- return Identifiers.isValidToken(key, VALID_XML_NODE_NAME_START_CHARS, VALID_XML_NODE_NAME_CHARS);
- }
-
- public boolean canConvert(Class type) {
- return super.canConvert(type) || type.getName().equals(MutableMap.class.getName());
- }
-
- @Override
- protected void marshalEntry(HierarchicalStreamWriter writer, MarshallingContext context, Entry entry) {
- if (entry.getKey() instanceof String) {
- marshalStringKey(writer, context, entry);
- } else {
- super.marshalEntry(writer, context, entry);
- }
- }
-
- protected void marshalStringKey(HierarchicalStreamWriter writer, MarshallingContext context, Entry entry) {
- String key = (String)entry.getKey();
- String entryNodeName = getEntryNodeName();
- boolean useKeyAsNodeName = (!key.equals(entryNodeName) && isKeyValidForNodeName(key));
- if (useKeyAsNodeName) entryNodeName = key;
- ExtendedHierarchicalStreamWriterHelper.startNode(writer, entryNodeName, Map.Entry.class);
- if (!useKeyAsNodeName)
- writer.addAttribute("key", key);
-
- Object value = entry.getValue();
- if (entry.getValue()!=null && isInlineableType(value.getClass())) {
- if (!(value instanceof String))
- writer.addAttribute("type", mapper().serializedClass(entry.getValue().getClass()));
- if (entry.getValue().getClass().isEnum())
- writer.setValue(((Enum)entry.getValue()).name());
- else
- writer.setValue(""+entry.getValue());
- } else {
- writeItem(entry.getValue(), context, writer);
- }
-
- writer.endNode();
- }
-
- protected boolean isInlineableType(Class<?> type) {
- return TypeCoercions.isPrimitiveOrBoxer(type) || String.class.equals(type) || type.isEnum();
- }
-
- @Override
- protected void unmarshalEntry(HierarchicalStreamReader reader, UnmarshallingContext context, Map map) {
- String key = reader.getNodeName();
- if (key.equals(getEntryNodeName())) key = reader.getAttribute("key");
- if (key==null) {
- super.unmarshalEntry(reader, context, map);
- } else {
- unmarshalStringKey(reader, context, map, key);
- }
- }
-
- protected void unmarshalStringKey(HierarchicalStreamReader reader, UnmarshallingContext context, Map map, String key) {
- String type = reader.getAttribute("type");
- Object value;
- if (type==null && reader.hasMoreChildren()) {
- reader.moveDown();
- value = readItem(reader, context, map);
- reader.moveUp();
- } else {
- Class typeC = type!=null ? mapper().realClass(type) : String.class;
- try {
- value = TypeCoercions.coerce(reader.getValue(), typeC);
- } catch (Exception e) {
- log.warn("FAILED to coerce "+reader.getValue()+" to "+typeC+": "+e);
- throw Exceptions.propagate(e);
- }
- }
- map.put(key, value);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/xstream/XmlSerializer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/xstream/XmlSerializer.java b/core/src/main/java/brooklyn/util/xstream/XmlSerializer.java
deleted file mode 100644
index 7220254..0000000
--- a/core/src/main/java/brooklyn/util/xstream/XmlSerializer.java
+++ /dev/null
@@ -1,97 +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 brooklyn.util.xstream;
-
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.Map;
-import java.util.Set;
-
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.collections.MutableSet;
-
-import com.google.common.collect.ImmutableList;
-import com.thoughtworks.xstream.XStream;
-import com.thoughtworks.xstream.mapper.MapperWrapper;
-
-public class XmlSerializer<T> {
-
- protected final XStream xstream;
-
- public XmlSerializer() {
- xstream = new XStream() {
- @Override
- protected MapperWrapper wrapMapper(MapperWrapper next) {
- MapperWrapper result = super.wrapMapper(next);
- return XmlSerializer.this.wrapMapper(result);
- }
- };
-
- // list as array list is default
- xstream.alias("map", Map.class, LinkedHashMap.class);
- xstream.alias("set", Set.class, LinkedHashSet.class);
-
- xstream.registerConverter(new StringKeyMapConverter(xstream.getMapper()), /* priority */ 10);
- xstream.alias("MutableMap", MutableMap.class);
- xstream.alias("MutableSet", MutableSet.class);
- xstream.alias("MutableList", MutableList.class);
-
- // Needs an explicit MutableSet converter!
- // Without it, the alias for "set" seems to interfere with the MutableSet.map field, so it gets
- // a null field on deserialization.
- xstream.registerConverter(new MutableSetConverter(xstream.getMapper()));
-
- xstream.aliasType("ImmutableList", ImmutableList.class);
- xstream.registerConverter(new ImmutableListConverter(xstream.getMapper()));
- xstream.registerConverter(new ImmutableSetConverter(xstream.getMapper()));
- xstream.registerConverter(new ImmutableMapConverter(xstream.getMapper()));
-
- xstream.registerConverter(new EnumCaseForgivingConverter());
- xstream.registerConverter(new Inet4AddressConverter());
- }
-
- protected MapperWrapper wrapMapper(MapperWrapper next) {
- return new CompilerIndependentOuterClassFieldMapper(next);
- }
-
- public void serialize(Object object, Writer writer) {
- xstream.toXML(object, writer);
- }
-
- @SuppressWarnings("unchecked")
- public T deserialize(Reader xml) {
- return (T) xstream.fromXML(xml);
- }
-
- public String toString(T memento) {
- Writer writer = new StringWriter();
- serialize(memento, writer);
- return writer.toString();
- }
-
- public T fromString(String xml) {
- return deserialize(new StringReader(xml));
- }
-
-}
[33/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/ForwardingTask.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/ForwardingTask.java b/core/src/main/java/brooklyn/util/task/ForwardingTask.java
deleted file mode 100644
index 3bc3427..0000000
--- a/core/src/main/java/brooklyn/util/task/ForwardingTask.java
+++ /dev/null
@@ -1,325 +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 brooklyn.util.task;
-
-import java.util.Set;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-import org.apache.brooklyn.api.management.Task;
-
-import brooklyn.util.time.Duration;
-
-import com.google.common.base.Function;
-import com.google.common.collect.ForwardingObject;
-import com.google.common.util.concurrent.ExecutionList;
-import com.google.common.util.concurrent.ListenableFuture;
-
-public abstract class ForwardingTask<T> extends ForwardingObject implements TaskInternal<T> {
-
- /** Constructor for use by subclasses. */
- protected ForwardingTask() {}
-
- @Override
- protected abstract TaskInternal<T> delegate();
-
- @Override
- public void addListener(Runnable listener, Executor executor) {
- delegate().addListener(listener, executor);
- }
-
- @Override
- public boolean cancel(boolean arg0) {
- return delegate().cancel(arg0);
- }
-
- @Override
- public T get() throws InterruptedException, ExecutionException {
- return delegate().get();
- }
-
- @Override
- public T get(long arg0, TimeUnit arg1) throws InterruptedException, ExecutionException, TimeoutException {
- return delegate().get(arg0, arg1);
- }
-
- @Override
- public boolean isCancelled() {
- return delegate().isCancelled();
- }
-
- @Override
- public boolean isDone() {
- return delegate().isDone();
- }
-
- @Override
- public Task<T> asTask() {
- return delegate().asTask();
- }
-
- @Override
- public String getId() {
- return delegate().getId();
- }
-
- @Override
- public Set<Object> getTags() {
- return delegate().getTags();
- }
-
- @Override
- public long getSubmitTimeUtc() {
- return delegate().getSubmitTimeUtc();
- }
-
- @Override
- public long getStartTimeUtc() {
- return delegate().getStartTimeUtc();
- }
-
- @Override
- public long getEndTimeUtc() {
- return delegate().getEndTimeUtc();
- }
-
- @Override
- public String getDisplayName() {
- return delegate().getDisplayName();
- }
-
- @Override
- public String getDescription() {
- return delegate().getDescription();
- }
-
- @Override
- public Task<?> getSubmittedByTask() {
- return delegate().getSubmittedByTask();
- }
-
- @Override
- public Thread getThread() {
- return delegate().getThread();
- }
-
- @Override
- public boolean isSubmitted() {
- return delegate().isSubmitted();
- }
-
- @Override
- public boolean isBegun() {
- return delegate().isBegun();
- }
-
- @Override
- public boolean isError() {
- return delegate().isError();
- }
-
- @Override
- public void blockUntilStarted() {
- delegate().blockUntilStarted();
- }
-
- @Override
- public void blockUntilEnded() {
- delegate().blockUntilEnded();
- }
-
- @Override
- public boolean blockUntilEnded(Duration timeout) {
- return delegate().blockUntilEnded(timeout);
- }
-
- @Override
- public String getStatusSummary() {
- return delegate().getStatusSummary();
- }
-
- @Override
- public String getStatusDetail(boolean multiline) {
- return delegate().getStatusDetail(multiline);
- }
-
- @Override
- public T get(Duration duration) throws InterruptedException, ExecutionException, TimeoutException {
- return delegate().get(duration);
- }
-
- @Override
- public T getUnchecked() {
- return delegate().getUnchecked();
- }
-
- @Override
- public T getUnchecked(Duration duration) {
- return delegate().getUnchecked(duration);
- }
-
- @Override
- public void initInternalFuture(ListenableFuture<T> result) {
- delegate().initInternalFuture(result);
- }
-
- @Override
- public long getQueuedTimeUtc() {
- return delegate().getQueuedTimeUtc();
- }
-
- @Override
- public Future<T> getInternalFuture() {
- return delegate().getInternalFuture();
- }
-
- @Override
- public boolean isQueued() {
- return delegate().isQueued();
- }
-
- @Override
- public boolean isQueuedOrSubmitted() {
- return delegate().isQueuedOrSubmitted();
- }
-
- @Override
- public boolean isQueuedAndNotSubmitted() {
- return delegate().isQueuedAndNotSubmitted();
- }
-
- @Override
- public void markQueued() {
- delegate().markQueued();
- }
-
- @Override
- public boolean cancel() {
- return delegate().cancel();
- }
-
- @Override
- public boolean blockUntilStarted(Duration timeout) {
- return delegate().blockUntilStarted(timeout);
- }
-
- @Override
- public String setBlockingDetails(String blockingDetails) {
- return delegate().setBlockingDetails(blockingDetails);
- }
-
- @Override
- public Task<?> setBlockingTask(Task<?> blockingTask) {
- return delegate().setBlockingTask(blockingTask);
- }
-
- @Override
- public void resetBlockingDetails() {
- delegate().resetBlockingDetails();
- }
-
- @Override
- public void resetBlockingTask() {
- delegate().resetBlockingTask();
- }
-
- @Override
- public String getBlockingDetails() {
- return delegate().getBlockingDetails();
- }
-
- @Override
- public Task<?> getBlockingTask() {
- return delegate().getBlockingTask();
- }
-
- @Override
- public void setExtraStatusText(Object extraStatus) {
- delegate().setExtraStatusText(extraStatus);
- }
-
- @Override
- public Object getExtraStatusText() {
- return delegate().getExtraStatusText();
- }
-
- @Override
- public void runListeners() {
- delegate().runListeners();
- }
-
- @Override
- public void setEndTimeUtc(long val) {
- delegate().setEndTimeUtc(val);
- }
-
- @Override
- public void setThread(Thread thread) {
- delegate().setThread(thread);
- }
-
- @Override
- public Callable<T> getJob() {
- return delegate().getJob();
- }
-
- @Override
- public void setJob(Callable<T> job) {
- delegate().setJob(job);
- }
-
- @Override
- public ExecutionList getListeners() {
- return delegate().getListeners();
- }
-
- @Override
- public void setSubmitTimeUtc(long currentTimeMillis) {
- delegate().setSubmitTimeUtc(currentTimeMillis);
- }
-
- @Override
- public void setSubmittedByTask(Task<?> task) {
- delegate().setSubmittedByTask(task);
- }
-
- @Override
- public Set<Object> getMutableTags() {
- return delegate().getMutableTags();
- }
-
- @Override
- public void setStartTimeUtc(long currentTimeMillis) {
- delegate().setStartTimeUtc(currentTimeMillis);
- }
-
- @Override
- public void applyTagModifier(Function<Set<Object>, Void> modifier) {
- delegate().applyTagModifier(modifier);
- }
-
- @Override
- public Task<?> getProxyTarget() {
- return delegate().getProxyTarget();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/ListenableForwardingFuture.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/ListenableForwardingFuture.java b/core/src/main/java/brooklyn/util/task/ListenableForwardingFuture.java
deleted file mode 100644
index 8111332..0000000
--- a/core/src/main/java/brooklyn/util/task/ListenableForwardingFuture.java
+++ /dev/null
@@ -1,50 +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 brooklyn.util.task;
-
-import java.util.concurrent.Executor;
-import java.util.concurrent.Future;
-
-import com.google.common.util.concurrent.ExecutionList;
-import com.google.common.util.concurrent.ForwardingFuture.SimpleForwardingFuture;
-import com.google.common.util.concurrent.ListenableFuture;
-
-/** Wraps a Future, making it a ListenableForwardingFuture, but with the caller having the resposibility to:
- * <li> invoke the listeners on job completion (success or error)
- * <li> invoke the listeners on cancel */
-public abstract class ListenableForwardingFuture<T> extends SimpleForwardingFuture<T> implements ListenableFuture<T> {
-
- final ExecutionList listeners;
-
- protected ListenableForwardingFuture(Future<T> delegate) {
- super(delegate);
- this.listeners = new ExecutionList();
- }
-
- protected ListenableForwardingFuture(Future<T> delegate, ExecutionList list) {
- super(delegate);
- this.listeners = list;
- }
-
- @Override
- public void addListener(Runnable listener, Executor executor) {
- listeners.add(listener, executor);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/ParallelTask.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/ParallelTask.java b/core/src/main/java/brooklyn/util/task/ParallelTask.java
deleted file mode 100644
index d6e65ab..0000000
--- a/core/src/main/java/brooklyn/util/task/ParallelTask.java
+++ /dev/null
@@ -1,85 +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 brooklyn.util.task;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ExecutionException;
-
-import org.apache.brooklyn.api.management.Task;
-
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.text.Strings;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-
-/**
- * Runs {@link Task}s in parallel.
- *
- * No guarantees of order of starting the tasks, but the return value is a
- * {@link List} of the return values of supplied tasks in the same
- * order they were passed as arguments.
- */
-public class ParallelTask<T> extends CompoundTask<T> {
- public ParallelTask(Object... tasks) { super(tasks); }
-
- public ParallelTask(Map<String,?> flags, Collection<? extends Object> tasks) { super(flags, tasks); }
- public ParallelTask(Collection<? extends Object> tasks) { super(tasks); }
-
- public ParallelTask(Map<String,?> flags, Iterable<? extends Object> tasks) { super(flags, ImmutableList.copyOf(tasks)); }
- public ParallelTask(Iterable<? extends Object> tasks) { super(ImmutableList.copyOf(tasks)); }
-
- @Override
- protected List<T> runJobs() throws InterruptedException, ExecutionException {
- setBlockingDetails("Executing "+
- (children.size()==1 ? "1 child task" :
- children.size()+" children tasks in parallel") );
- for (Task<? extends T> task : children) {
- submitIfNecessary(task);
- }
-
- List<T> result = Lists.newArrayList();
- List<Exception> exceptions = Lists.newArrayList();
- for (Task<? extends T> task : children) {
- T x;
- try {
- x = task.get();
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- if (TaskTags.isInessential(task)) {
- // ignore exception as it's inessential
- } else {
- exceptions.add(e);
- }
- x = null;
- }
- result.add(x);
- }
-
- if (exceptions.isEmpty()) {
- return result;
- } else {
- if (result.size()==1 && exceptions.size()==1)
- throw Exceptions.propagate( exceptions.get(0) );
- throw Exceptions.propagate(exceptions.size()+" of "+result.size()+" parallel child task"+Strings.s(result.size())+" failed", exceptions);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/ScheduledTask.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/ScheduledTask.java b/core/src/main/java/brooklyn/util/task/ScheduledTask.java
deleted file mode 100644
index eabff49..0000000
--- a/core/src/main/java/brooklyn/util/task/ScheduledTask.java
+++ /dev/null
@@ -1,185 +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 brooklyn.util.task;
-
-import static brooklyn.util.GroovyJavaMethods.elvis;
-import static brooklyn.util.GroovyJavaMethods.truth;
-
-import java.util.Map;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.brooklyn.api.management.Task;
-
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.time.Duration;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Throwables;
-
-/**
- * A task which runs with a fixed period.
- * <p>
- * Note that some termination logic, including {@link #addListener(Runnable, java.util.concurrent.Executor)},
- * is not precisely defined.
- */
-// TODO ScheduledTask is a very pragmatic implementation; would be nice to tighten,
-// reduce external assumptions about internal structure, and clarify "done" semantics
-public class ScheduledTask extends BasicTask {
-
- final Callable<Task<?>> taskFactory;
- /** initial delay before running, set as flag in constructor; defaults to 0 */
- protected Duration delay;
- /** time to wait between executions, or null if not to repeat (default), set as flag to constructor;
- * this may be modified for subsequent submissions by a running task generated by the factory
- * using getSubmittedByTask().setPeriod(Duration) */
- protected Duration period = null;
- /** optional, set as flag in constructor; defaults to null meaning no limit */
- protected Integer maxIterations = null;
-
- protected int runCount=0;
- protected Task<?> recentRun, nextRun;
-
- public int getRunCount() { return runCount; }
- public ScheduledFuture<?> getNextScheduled() { return (ScheduledFuture<?>)internalFuture; }
-
- public ScheduledTask(Callable<Task<?>> taskFactory) {
- this(MutableMap.of(), taskFactory);
- }
-
- public ScheduledTask(final Task<?> task) {
- this(MutableMap.of(), task);
- }
-
- public ScheduledTask(Map flags, final Task<?> task){
- this(flags, new Callable<Task<?>>(){
- @Override
- public Task<?> call() throws Exception {
- return task;
- }});
- }
-
- public ScheduledTask(Map flags, Callable<Task<?>> taskFactory) {
- super(flags);
- this.taskFactory = taskFactory;
-
- delay = Duration.of(elvis(flags.remove("delay"), 0));
- period = Duration.of(elvis(flags.remove("period"), null));
- maxIterations = elvis(flags.remove("maxIterations"), null);
- }
-
- public ScheduledTask delay(Duration d) {
- this.delay = d;
- return this;
- }
- public ScheduledTask delay(long val) {
- return delay(Duration.millis(val));
- }
-
- public ScheduledTask period(Duration d) {
- this.period = d;
- return this;
- }
- public ScheduledTask period(long val) {
- return period(Duration.millis(val));
- }
-
- public ScheduledTask maxIterations(int val) {
- this.maxIterations = val;
- return this;
- }
-
- public Callable<Task<?>> getTaskFactory() {
- return taskFactory;
- }
-
- public Task<?> newTask() {
- try {
- return taskFactory.call();
- } catch (Exception e) {
- throw Throwables.propagate(e);
- }
- }
-
- protected String getActiveTaskStatusString(int verbosity) {
- StringBuilder rv = new StringBuilder("Scheduler");
- if (runCount>0) rv.append(", iteration "+(runCount+1));
- if (recentRun!=null) rv.append(", last run "+
- Duration.sinceUtc(recentRun.getStartTimeUtc())+" ms ago");
- if (truth(getNextScheduled())) {
- Duration untilNext = Duration.millis(getNextScheduled().getDelay(TimeUnit.MILLISECONDS));
- if (untilNext.isPositive())
- rv.append(", next in "+untilNext);
- else
- rv.append(", next imminent");
- }
- return rv.toString();
- }
-
- @Override
- public boolean isDone() {
- return isCancelled() || (maxIterations!=null && maxIterations <= runCount) || (period==null && nextRun!=null && nextRun.isDone());
- }
-
- public synchronized void blockUntilFirstScheduleStarted() {
- // TODO Assumes that maxIterations is not negative!
- while (true) {
- if (isCancelled()) throw new CancellationException();
- if (recentRun==null)
- try {
- wait();
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- Throwables.propagate(e);
- }
- if (recentRun!=null) return;
- }
- }
-
- public void blockUntilEnded() {
- while (!isDone()) super.blockUntilEnded();
- }
-
- /** gets the value of the most recently run task */
- public Object get() throws InterruptedException, ExecutionException {
- blockUntilStarted();
- blockUntilFirstScheduleStarted();
- return (truth(recentRun)) ? recentRun.get() : internalFuture.get();
- }
-
- @Override
- public synchronized boolean cancel(boolean mayInterrupt) {
- boolean result = super.cancel(mayInterrupt);
- if (nextRun!=null) {
- nextRun.cancel(mayInterrupt);
- notifyAll();
- }
- return result;
- }
-
- /** internal method used to allow callers to wait for underlying tasks to finished in the case of cancellation
- * @param duration */
- @Beta
- public boolean blockUntilNextRunFinished(Duration timeout) {
- return Tasks.blockUntilInternalTasksEnded(nextRun, timeout);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/SequentialTask.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/SequentialTask.java b/core/src/main/java/brooklyn/util/task/SequentialTask.java
deleted file mode 100644
index e739eb0..0000000
--- a/core/src/main/java/brooklyn/util/task/SequentialTask.java
+++ /dev/null
@@ -1,58 +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 brooklyn.util.task;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ExecutionException;
-
-import org.apache.brooklyn.api.management.Task;
-
-import com.google.common.collect.ImmutableList;
-
-
-/** runs tasks in order, waiting for one to finish before starting the next; return value here is TBD;
- * (currently is all the return values of individual tasks, but we
- * might want some pipeline support and eventually only to return final value...) */
-public class SequentialTask<T> extends CompoundTask<T> {
-
- public SequentialTask(Object... tasks) { super(tasks); }
-
- public SequentialTask(Map<String,?> flags, Collection<? extends Object> tasks) { super(flags, tasks); }
- public SequentialTask(Collection<? extends Object> tasks) { super(tasks); }
-
- public SequentialTask(Map<String,?> flags, Iterable<? extends Object> tasks) { super(flags, ImmutableList.copyOf(tasks)); }
- public SequentialTask(Iterable<? extends Object> tasks) { super(ImmutableList.copyOf(tasks)); }
-
- protected List<T> runJobs() throws InterruptedException, ExecutionException {
- setBlockingDetails("Executing "+
- (children.size()==1 ? "1 child task" :
- children.size()+" children tasks sequentially") );
-
- List<T> result = new ArrayList<T>();
- for (Task<? extends T> task : children) {
- submitIfNecessary(task);
- // throw exception (and cancel subsequent tasks) on error
- result.add(task.get());
- }
- return result;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/SingleThreadedScheduler.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/SingleThreadedScheduler.java b/core/src/main/java/brooklyn/util/task/SingleThreadedScheduler.java
deleted file mode 100644
index a48bac8..0000000
--- a/core/src/main/java/brooklyn/util/task/SingleThreadedScheduler.java
+++ /dev/null
@@ -1,216 +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 brooklyn.util.task;
-
-import java.util.Queue;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.apache.brooklyn.api.management.Task;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Instances of this class ensures that {@link Task}s execute with in-order
- * single-threaded semantics.
- *
- * Tasks can be presented through {@link #submit(Callable)}. The order of execution is the
- * sumbission order.
- * <p>
- * This implementation does so by blocking on a {@link ConcurrentLinkedQueue}, <em>after</em>
- * the task is started in a thread (and {@link Task#isBegun()} returns true), but (of course)
- * <em>before</em> the {@link TaskInternal#getJob()} actually gets invoked.
- */
-public class SingleThreadedScheduler implements TaskScheduler, CanSetName {
- private static final Logger LOG = LoggerFactory.getLogger(SingleThreadedScheduler.class);
-
- private final Queue<QueuedSubmission<?>> order = new ConcurrentLinkedQueue<QueuedSubmission<?>>();
- private int queueSize = 0;
- private final AtomicBoolean running = new AtomicBoolean(false);
-
- private ExecutorService executor;
-
- private String name;
-
- @Override
- public void setName(String name) {
- this.name = name;
- }
-
- @Override
- public String toString() {
- return name!=null ? "SingleThreadedScheduler["+name+"]" : super.toString();
- }
-
- @Override
- public void injectExecutor(ExecutorService executor) {
- this.executor = executor;
- }
-
- @Override
- public synchronized <T> Future<T> submit(Callable<T> c) {
- if (running.compareAndSet(false, true)) {
- return executeNow(c);
- } else {
- WrappingFuture<T> f = new WrappingFuture<T>();
- order.add(new QueuedSubmission<T>(c, f));
- queueSize++;
- if (queueSize>0 && (queueSize == 50 || (queueSize<=500 && (queueSize%100)==0) || (queueSize%1000)==0) && queueSize!=lastSizeWarn) {
- LOG.warn("{} is backing up, {} tasks queued", this, queueSize);
- if (LOG.isDebugEnabled()) {
- LOG.debug("Task queue backing up detail, queue "+this+"; task context is "+Tasks.current()+"; latest task is "+c+"; first task is "+order.peek());
- }
- lastSizeWarn = queueSize;
- }
- return f;
- }
- }
- int lastSizeWarn = 0;
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- private synchronized void onEnd() {
- boolean done = false;
- while (!done) {
- if (order.isEmpty()) {
- running.set(false);
- done = true;
- } else {
- QueuedSubmission<?> qs = order.remove();
- queueSize--;
- if (!qs.f.isCancelled()) {
- Future future = executeNow(qs.c);
- qs.f.setDelegate(future);
- done = true;
- }
- }
- }
- }
-
- private synchronized <T> Future<T> executeNow(final Callable<T> c) {
- return executor.submit(new Callable<T>() {
- @Override public T call() throws Exception {
- try {
- return c.call();
- } finally {
- onEnd();
- }
- }});
- }
-
-
- private static class QueuedSubmission<T> {
- final Callable<T> c;
- final WrappingFuture<T> f;
-
- QueuedSubmission(Callable<T> c, WrappingFuture<T> f) {
- this.c = c;
- this.f = f;
- }
-
- @Override
- public String toString() {
- return "QueuedSubmission["+c+"]@"+Integer.toHexString(System.identityHashCode(this));
- }
- }
-
- /**
- * A future, where the task may not yet have been submitted to the real executor.
- * It delegates to the real future if present, and otherwise waits for that to appear
- */
- private static class WrappingFuture<T> implements Future<T> {
- private volatile Future<T> delegate;
- private boolean cancelled;
-
- void setDelegate(Future<T> delegate) {
- synchronized (this) {
- this.delegate = delegate;
- notifyAll();
- }
- }
-
- @Override public boolean cancel(boolean mayInterruptIfRunning) {
- if (delegate != null) {
- return delegate.cancel(mayInterruptIfRunning);
- } else {
- cancelled = true;
- synchronized (this) {
- notifyAll();
- }
- return true;
- }
- }
-
- @Override public boolean isCancelled() {
- if (delegate != null) {
- return delegate.isCancelled();
- } else {
- return cancelled;
- }
- }
-
- @Override public boolean isDone() {
- return (delegate != null) ? delegate.isDone() : cancelled;
- }
-
- @Override public T get() throws CancellationException, ExecutionException, InterruptedException {
- if (cancelled) {
- throw new CancellationException();
- } else if (delegate != null) {
- return delegate.get();
- } else {
- synchronized (this) {
- while (delegate == null && !cancelled) {
- wait();
- }
- }
- return get();
- }
- }
-
- @Override public T get(long timeout, TimeUnit unit) throws CancellationException, ExecutionException, InterruptedException, TimeoutException {
- long endtime = System.currentTimeMillis()+unit.toMillis(timeout);
-
- if (cancelled) {
- throw new CancellationException();
- } else if (delegate != null) {
- return delegate.get(timeout, unit);
- } else if (System.currentTimeMillis() >= endtime) {
- throw new TimeoutException();
- } else {
- synchronized (this) {
- while (delegate == null && !cancelled && System.currentTimeMillis() < endtime) {
- long remaining = endtime - System.currentTimeMillis();
- if (remaining > 0) {
- wait(remaining);
- }
- }
- }
- long remaining = endtime - System.currentTimeMillis();
- return get(remaining, TimeUnit.MILLISECONDS);
- }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/TaskBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/TaskBuilder.java b/core/src/main/java/brooklyn/util/task/TaskBuilder.java
deleted file mode 100644
index ecd4d4f..0000000
--- a/core/src/main/java/brooklyn/util/task/TaskBuilder.java
+++ /dev/null
@@ -1,184 +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 brooklyn.util.task;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Callable;
-
-import org.apache.brooklyn.api.management.Task;
-import org.apache.brooklyn.api.management.TaskAdaptable;
-import org.apache.brooklyn.api.management.TaskFactory;
-import org.apache.brooklyn.api.management.TaskQueueingContext;
-
-import brooklyn.util.JavaGroovyEquivalents;
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.collections.MutableSet;
-
-import com.google.common.collect.Iterables;
-
-/** Convenience for creating tasks; note that DynamicSequentialTask is the default */
-public class TaskBuilder<T> {
-
- String name = null;
- String description = null;
- Callable<T> body = null;
- Boolean swallowChildrenFailures = null;
- List<TaskAdaptable<?>> children = MutableList.of();
- Set<Object> tags = MutableSet.of();
- Map<String,Object> flags = MutableMap.of();
- Boolean dynamic = null;
- boolean parallel = false;
-
- public static <T> TaskBuilder<T> builder() {
- return new TaskBuilder<T>();
- }
-
- public TaskBuilder<T> name(String name) {
- this.name = name;
- return this;
- }
-
- public TaskBuilder<T> description(String description) {
- this.description = description;
- return this;
- }
-
- /** whether task that is built has been explicitly specified to be a dynamic task
- * (ie a Task which is also a {@link TaskQueueingContext}
- * whereby new tasks can be added after creation */
- public TaskBuilder<T> dynamic(boolean dynamic) {
- this.dynamic = dynamic;
- return this;
- }
-
- /** whether task that is built should be parallel; cannot (currently) also be dynamic */
- public TaskBuilder<T> parallel(boolean parallel) {
- this.parallel = parallel;
- return this;
- }
-
- public TaskBuilder<T> body(Callable<T> body) {
- this.body = body;
- return this;
- }
-
- /** sets up a dynamic task not to fail even if children fail */
- public TaskBuilder<T> swallowChildrenFailures(boolean swallowChildrenFailures) {
- this.swallowChildrenFailures = swallowChildrenFailures;
- return this;
- }
-
- public TaskBuilder<T> body(Runnable body) {
- this.body = JavaGroovyEquivalents.<T>toCallable(body);
- return this;
- }
-
- /** adds a child to the given task; the semantics of how the child is executed is set using
- * {@link #dynamic(boolean)} and {@link #parallel(boolean)} */
- public TaskBuilder<T> add(TaskAdaptable<?> child) {
- children.add(child);
- return this;
- }
-
- public TaskBuilder<T> addAll(Iterable<? extends TaskAdaptable<?>> additionalChildren) {
- Iterables.addAll(children, additionalChildren);
- return this;
- }
-
- public TaskBuilder<T> add(TaskAdaptable<?>... additionalChildren) {
- children.addAll(Arrays.asList(additionalChildren));
- return this;
- }
-
- /** adds a tag to the given task */
- public TaskBuilder<T> tag(Object tag) {
- tags.add(tag);
- return this;
- }
-
- /** adds a flag to the given task */
- public TaskBuilder<T> flag(String flag, Object value) {
- flags.put(flag, value);
- return this;
- }
-
- /** adds the given flags to the given task */
- public TaskBuilder<T> flags(Map<String,Object> flags) {
- this.flags.putAll(flags);
- return this;
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public Task<T> build() {
- MutableMap<String, Object> taskFlags = MutableMap.copyOf(flags);
- if (name!=null) taskFlags.put("displayName", name);
- if (description!=null) taskFlags.put("description", description);
- if (!tags.isEmpty()) taskFlags.put("tags", tags);
-
- if (Boolean.FALSE.equals(dynamic) && children.isEmpty()) {
- if (swallowChildrenFailures!=null)
- throw new IllegalArgumentException("Cannot set swallowChildrenFailures for non-dynamic task: "+this);
- return new BasicTask<T>(taskFlags, body);
- }
-
- // prefer dynamic set unless (a) user has said not dynamic, or (b) it's parallel (since there is no dynamic parallel yet)
- // dynamic has better cancel (will interrupt the thread) and callers can submit tasks flexibly;
- // however dynamic uses an extra thread and task and is noisy for contexts which don't need it
- if (Boolean.TRUE.equals(dynamic) || (dynamic==null && !parallel)) {
- if (parallel)
- throw new UnsupportedOperationException("No implementation of parallel dynamic aggregate task available");
- DynamicSequentialTask<T> result = new DynamicSequentialTask<T>(taskFlags, body);
- if (swallowChildrenFailures!=null && swallowChildrenFailures.booleanValue()) result.swallowChildrenFailures();
- for (TaskAdaptable t: children)
- result.queue(t.asTask());
- return result;
- }
-
- // T must be of type List<V> for these to be valid
- if (body != null) {
- throw new UnsupportedOperationException("No implementation of non-dynamic task with both body and children");
- }
- if (swallowChildrenFailures!=null) {
- throw new IllegalArgumentException("Cannot set swallowChildrenFailures for non-dynamic task: "+this);
- }
-
- if (parallel)
- return new ParallelTask(taskFlags, children);
- else
- return new SequentialTask(taskFlags, children);
- }
-
- /** returns a a factory based on this builder */
- public TaskFactory<Task<T>> buildFactory() {
- return new TaskFactory<Task<T>>() {
- public Task<T> newTask() {
- return build();
- }
- };
- }
-
- @Override
- public String toString() {
- return super.toString()+"["+name+"]";
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/TaskInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/TaskInternal.java b/core/src/main/java/brooklyn/util/task/TaskInternal.java
deleted file mode 100644
index 51dbddb..0000000
--- a/core/src/main/java/brooklyn/util/task/TaskInternal.java
+++ /dev/null
@@ -1,125 +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 brooklyn.util.task;
-
-import java.util.Set;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
-
-import org.apache.brooklyn.api.management.ExecutionManager;
-import org.apache.brooklyn.api.management.Task;
-
-import brooklyn.util.time.Duration;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Function;
-import com.google.common.util.concurrent.ExecutionList;
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * All tasks being passed to the {@link ExecutionManager} should implement this.
- * Users are strongly encouraged to use (or extend) {@link BasicTask}, rather than
- * implementing a task from scratch.
- *
- * The methods on this interface will change in subsequent releases. Because this is
- * marked as beta, the normal deprecation policy for these methods does not apply.
- *
- * @author aled
- */
-@Beta
-public interface TaskInternal<T> extends Task<T> {
-
- /** sets the internal future object used to record the association to a job submitted to an {@link ExecutorService} */
- void initInternalFuture(ListenableFuture<T> result);
-
- /** returns the underlying future where this task's results will come in; see {@link #initInternalFuture(ListenableFuture)} */
- Future<T> getInternalFuture();
-
- /** if the job is queued for submission (e.g. by another task) it can indicate that fact (and time) here;
- * note tasks can (and often are) submitted without any queueing, in which case this value may be -1 */
- long getQueuedTimeUtc();
-
- boolean isQueuedOrSubmitted();
- boolean isQueuedAndNotSubmitted();
- boolean isQueued();
-
- /** marks the task as queued for execution */
- void markQueued();
-
- boolean cancel();
-
- boolean blockUntilStarted(Duration timeout);
-
- /** allows a task user to specify why a task is blocked; for use immediately before a blocking/wait,
- * and typically cleared immediately afterwards; referenced by management api to inspect a task
- * which is blocking
- * <p>
- * returns previous details, in case caller wishes to recall and restore it (e.g. if it is doing a sub-blocking)
- */
- String setBlockingDetails(String blockingDetails);
-
- /** as {@link #setBlockingDetails(String)} but records a task which is blocking,
- * for use e.g. in a gui to navigate to the current active subtask
- * <p>
- * returns previous blocking task, in case caller wishes to recall and restore it
- */
- Task<?> setBlockingTask(Task<?> blockingTask);
-
- void resetBlockingDetails();
-
- void resetBlockingTask();
-
- /** returns a textual message giving details while the task is blocked */
- String getBlockingDetails();
-
- /** returns a task that this task is blocked on */
- Task<?> getBlockingTask();
-
- void setExtraStatusText(Object extraStatus);
-
- Object getExtraStatusText();
-
- void runListeners();
-
- void setEndTimeUtc(long val);
-
- void setThread(Thread thread);
-
- Callable<T> getJob();
-
- void setJob(Callable<T> job);
-
- ExecutionList getListeners();
-
- void setSubmitTimeUtc(long currentTimeMillis);
-
- void setSubmittedByTask(Task<?> task);
-
- Set<Object> getMutableTags();
-
- void setStartTimeUtc(long currentTimeMillis);
-
- void applyTagModifier(Function<Set<Object>,Void> modifier);
-
- /** if a task is a proxy for another one (used mainly for internal tasks),
- * this returns the "real" task represented by this one */
- Task<?> getProxyTarget();
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/TaskScheduler.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/TaskScheduler.java b/core/src/main/java/brooklyn/util/task/TaskScheduler.java
deleted file mode 100644
index a10e63a..0000000
--- a/core/src/main/java/brooklyn/util/task/TaskScheduler.java
+++ /dev/null
@@ -1,41 +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 brooklyn.util.task;
-
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
-
-import org.apache.brooklyn.api.management.Task;
-
-/**
- * The scheduler is an internal mechanism to decorate {@link Task}s.
- *
- * It can control how the tasks are scheduled for execution (e.g. single-threaded execution,
- * prioritised, etc).
- */
-public interface TaskScheduler {
-
- public void injectExecutor(ExecutorService executor);
-
- /**
- * Called by {@link BasicExecutionManager} to schedule tasks.
- */
- public <T> Future<T> submit(Callable<T> c);
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/TaskTags.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/TaskTags.java b/core/src/main/java/brooklyn/util/task/TaskTags.java
deleted file mode 100644
index a9da252..0000000
--- a/core/src/main/java/brooklyn/util/task/TaskTags.java
+++ /dev/null
@@ -1,71 +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 brooklyn.util.task;
-
-import java.util.Set;
-
-import javax.annotation.Nullable;
-
-import org.apache.brooklyn.api.management.Task;
-import org.apache.brooklyn.api.management.TaskAdaptable;
-
-import com.google.common.base.Function;
-
-public class TaskTags {
-
- /** marks a task which is allowed to fail without failing his parent */
- public static final String INESSENTIAL_TASK = "inessential";
-
- /** marks a task which is a subtask of another */
- public static final String SUB_TASK_TAG = "SUB-TASK";
-
- public static void addTagDynamically(TaskAdaptable<?> task, final Object tag) {
- ((BasicTask<?>)task.asTask()).applyTagModifier(new Function<Set<Object>, Void>() {
- public Void apply(@Nullable Set<Object> input) {
- input.add(tag);
- return null;
- }
- });
- }
-
- public static void addTagsDynamically(TaskAdaptable<?> task, final Object tag1, final Object ...tags) {
- ((BasicTask<?>)task.asTask()).applyTagModifier(new Function<Set<Object>, Void>() {
- public Void apply(@Nullable Set<Object> input) {
- input.add(tag1);
- for (Object tag: tags) input.add(tag);
- return null;
- }
- });
- }
-
-
- public static boolean isInessential(Task<?> task) {
- return hasTag(task, INESSENTIAL_TASK);
- }
-
- public static boolean hasTag(Task<?> task, Object tag) {
- return task.getTags().contains(tag);
- }
-
- public static <U,V extends TaskAdaptable<U>> V markInessential(V task) {
- addTagDynamically(task, INESSENTIAL_TASK);
- return task;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/Tasks.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/Tasks.java b/core/src/main/java/brooklyn/util/task/Tasks.java
deleted file mode 100644
index c25dd19..0000000
--- a/core/src/main/java/brooklyn/util/task/Tasks.java
+++ /dev/null
@@ -1,488 +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 brooklyn.util.task;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.FutureTask;
-
-import javax.annotation.Nullable;
-
-import org.apache.brooklyn.api.management.ExecutionContext;
-import org.apache.brooklyn.api.management.HasTaskChildren;
-import org.apache.brooklyn.api.management.Task;
-import org.apache.brooklyn.api.management.TaskAdaptable;
-import org.apache.brooklyn.api.management.TaskFactory;
-import org.apache.brooklyn.api.management.TaskQueueingContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.exceptions.ReferenceWithError;
-import brooklyn.util.repeat.Repeater;
-import brooklyn.util.time.CountdownTimer;
-import brooklyn.util.time.Duration;
-import brooklyn.util.time.Time;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.base.Supplier;
-import com.google.common.collect.Iterables;
-
-public class Tasks {
-
- private static final Logger log = LoggerFactory.getLogger(Tasks.class);
-
- /** convenience for setting "blocking details" on any task where the current thread is running;
- * typically invoked prior to a wait, for transparency to a user;
- * then invoked with 'null' just after the wait */
- public static String setBlockingDetails(String description) {
- Task<?> current = current();
- if (current instanceof TaskInternal)
- return ((TaskInternal<?>)current).setBlockingDetails(description);
- return null;
- }
- public static void resetBlockingDetails() {
- Task<?> current = current();
- if (current instanceof TaskInternal)
- ((TaskInternal<?>)current).resetBlockingDetails();
- }
- public static Task<?> setBlockingTask(Task<?> blocker) {
- Task<?> current = current();
- if (current instanceof TaskInternal)
- return ((TaskInternal<?>)current).setBlockingTask(blocker);
- return null;
- }
- public static void resetBlockingTask() {
- Task<?> current = current();
- if (current instanceof TaskInternal)
- ((TaskInternal<?>)current).resetBlockingTask();
- }
-
- /** convenience for setting "blocking details" on any task where the current thread is running,
- * while the passed code is executed; often used from groovy as
- * <pre>{@code withBlockingDetails("sleeping 5s") { Thread.sleep(5000); } }</pre>
- * If code block is null, the description is set until further notice (not cleareed). */
- @SuppressWarnings("rawtypes")
- public static <T> T withBlockingDetails(String description, Callable<T> code) throws Exception {
- Task current = current();
- if (code==null) {
- log.warn("legacy invocation of withBlockingDetails with null code block, ignoring");
- return null;
- }
- String prevBlockingDetails = null;
- if (current instanceof TaskInternal) {
- prevBlockingDetails = ((TaskInternal)current).setBlockingDetails(description);
- }
- try {
- return code.call();
- } finally {
- if (current instanceof TaskInternal)
- ((TaskInternal)current).setBlockingDetails(prevBlockingDetails);
- }
- }
-
- /** the {@link Task} where the current thread is executing, if executing in a Task, otherwise null;
- * if the current task is a proxy, this returns the target of that proxy */
- @SuppressWarnings("rawtypes")
- public static Task current() {
- return getFinalProxyTarget(BasicExecutionManager.getPerThreadCurrentTask().get());
- }
-
- public static Task<?> getFinalProxyTarget(Task<?> task) {
- if (task==null) return null;
- Task<?> proxy = ((TaskInternal<?>)task).getProxyTarget();
- if (proxy==null || proxy.equals(task)) return task;
- return getFinalProxyTarget(proxy);
- }
-
- /** creates a {@link ValueResolver} instance which allows significantly more customization than
- * the various {@link #resolveValue(Object, Class, ExecutionContext)} methods here */
- public static <T> ValueResolver<T> resolving(Object v, Class<T> type) {
- return new ValueResolver<T>(v, type);
- }
-
- public static ValueResolver.ResolverBuilderPretype resolving(Object v) {
- return new ValueResolver.ResolverBuilderPretype(v);
- }
-
- /** @see #resolveValue(Object, Class, ExecutionContext, String) */
- public static <T> T resolveValue(Object v, Class<T> type, @Nullable ExecutionContext exec) throws ExecutionException, InterruptedException {
- return new ValueResolver<T>(v, type).context(exec).get();
- }
-
- /** attempt to resolve the given value as the given type, waiting on futures, submitting if necessary,
- * and coercing as allowed by TypeCoercions;
- * contextMessage (optional) will be displayed in status reports while it waits (e.g. the name of the config key being looked up).
- * if no execution context supplied (null) this method will throw an exception if the object is an unsubmitted task */
- public static <T> T resolveValue(Object v, Class<T> type, @Nullable ExecutionContext exec, String contextMessage) throws ExecutionException, InterruptedException {
- return new ValueResolver<T>(v, type).context(exec).description(contextMessage).get();
- }
-
- /**
- * @see #resolveDeepValue(Object, Class, ExecutionContext, String)
- */
- public static Object resolveDeepValue(Object v, Class<?> type, ExecutionContext exec) throws ExecutionException, InterruptedException {
- return resolveDeepValue(v, type, exec, null);
- }
-
- /**
- * Resolves the given object, blocking on futures and coercing it to the given type. If the object is a
- * map or iterable (or a list of map of maps, etc, etc) then walks these maps/iterables to convert all of
- * their values to the given type. For example, the following will return a list containing a map with "1"="true":
- *
- * {@code Object result = resolveDeepValue(ImmutableList.of(ImmutableMap.of(1, true)), String.class, exec)}
- *
- * To perform a deep conversion of futures contained within Iterables or Maps without coercion of each element,
- * the type should normally be Object, not the type of the collection. This differs from
- * {@link #resolveValue(Object, Class, ExecutionContext, String)} which will accept Map and Iterable
- * as the required type.
- */
- public static <T> T resolveDeepValue(Object v, Class<T> type, ExecutionContext exec, String contextMessage) throws ExecutionException, InterruptedException {
- return new ValueResolver<T>(v, type).context(exec).deep(true).description(contextMessage).get();
- }
-
- /** sets extra status details on the current task, if possible (otherwise does nothing).
- * the extra status is presented in Task.getStatusDetails(true)
- */
- public static void setExtraStatusDetails(String notes) {
- Task<?> current = current();
- if (current instanceof TaskInternal)
- ((TaskInternal<?>)current).setExtraStatusText(notes);
- }
-
- public static <T> TaskBuilder<T> builder() {
- return TaskBuilder.<T>builder();
- }
-
- private static Task<?>[] asTasks(TaskAdaptable<?> ...tasks) {
- Task<?>[] result = new Task<?>[tasks.length];
- for (int i=0; i<tasks.length; i++)
- result[i] = tasks[i].asTask();
- return result;
- }
-
- public static Task<List<?>> parallel(TaskAdaptable<?> ...tasks) {
- return parallelInternal("parallelised tasks", asTasks(tasks));
- }
- public static Task<List<?>> parallel(String name, TaskAdaptable<?> ...tasks) {
- return parallelInternal(name, asTasks(tasks));
- }
- public static Task<List<?>> parallel(Iterable<? extends TaskAdaptable<?>> tasks) {
- return parallel(asTasks(Iterables.toArray(tasks, TaskAdaptable.class)));
- }
- public static Task<List<?>> parallel(String name, Iterable<? extends TaskAdaptable<?>> tasks) {
- return parallelInternal(name, asTasks(Iterables.toArray(tasks, TaskAdaptable.class)));
- }
- private static Task<List<?>> parallelInternal(String name, Task<?>[] tasks) {
- return Tasks.<List<?>>builder().name(name).parallel(true).add(tasks).build();
- }
-
- public static Task<List<?>> sequential(TaskAdaptable<?> ...tasks) {
- return sequentialInternal("sequential tasks", asTasks(tasks));
- }
- public static Task<List<?>> sequential(String name, TaskAdaptable<?> ...tasks) {
- return sequentialInternal(name, asTasks(tasks));
- }
- public static TaskFactory<?> sequential(TaskFactory<?> ...taskFactories) {
- return sequentialInternal("sequential tasks", taskFactories);
- }
- public static TaskFactory<?> sequential(String name, TaskFactory<?> ...taskFactories) {
- return sequentialInternal(name, taskFactories);
- }
- public static Task<List<?>> sequential(List<? extends TaskAdaptable<?>> tasks) {
- return sequential(asTasks(Iterables.toArray(tasks, TaskAdaptable.class)));
- }
- public static Task<List<?>> sequential(String name, List<? extends TaskAdaptable<?>> tasks) {
- return sequential(name, asTasks(Iterables.toArray(tasks, TaskAdaptable.class)));
- }
- private static Task<List<?>> sequentialInternal(String name, Task<?>[] tasks) {
- return Tasks.<List<?>>builder().name(name).parallel(false).add(tasks).build();
- }
- private static TaskFactory<?> sequentialInternal(final String name, final TaskFactory<?> ...taskFactories) {
- return new TaskFactory<TaskAdaptable<?>>() {
- @Override
- public TaskAdaptable<?> newTask() {
- TaskBuilder<List<?>> tb = Tasks.<List<?>>builder().name(name).parallel(false);
- for (TaskFactory<?> tf: taskFactories)
- tb.add(tf.newTask().asTask());
- return tb.build();
- }
- };
- }
-
- /** returns the first tag found on the given task which matches the given type, looking up the submission hierarachy if necessary */
- @SuppressWarnings("unchecked")
- public static <T> T tag(@Nullable Task<?> task, Class<T> type, boolean recurseHierarchy) {
- // support null task to make it easier for callers to walk hierarchies
- if (task==null) return null;
- for (Object tag: task.getTags())
- if (type.isInstance(tag)) return (T)tag;
- if (!recurseHierarchy) return null;
- return tag(task.getSubmittedByTask(), type, true);
- }
-
- public static boolean isAncestorCancelled(Task<?> t) {
- if (t==null) return false;
- if (t.isCancelled()) return true;
- return isAncestorCancelled(t.getSubmittedByTask());
- }
-
- public static boolean isQueued(TaskAdaptable<?> task) {
- return ((TaskInternal<?>)task.asTask()).isQueued();
- }
-
- public static boolean isSubmitted(TaskAdaptable<?> task) {
- return ((TaskInternal<?>)task.asTask()).isSubmitted();
- }
-
- public static boolean isQueuedOrSubmitted(TaskAdaptable<?> task) {
- return ((TaskInternal<?>)task.asTask()).isQueuedOrSubmitted();
- }
-
- /**
- * Adds the given task to the given context. Does not throw an exception if the addition fails.
- * @return true if the task was added, false otherwise.
- */
- public static boolean tryQueueing(TaskQueueingContext adder, TaskAdaptable<?> task) {
- if (task==null || isQueued(task))
- return false;
- try {
- adder.queue(task.asTask());
- return true;
- } catch (Exception e) {
- if (log.isDebugEnabled())
- log.debug("Could not add task "+task+" at "+adder+": "+e);
- return false;
- }
- }
-
- /** see also {@link #resolving(Object)} which gives much more control about submission, timeout, etc */
- public static <T> Supplier<T> supplier(final TaskAdaptable<T> task) {
- return new Supplier<T>() {
- @Override
- public T get() {
- return task.asTask().getUnchecked();
- }
- };
- }
-
- /** return all children tasks of the given tasks, if it has children, else empty list */
- public static Iterable<Task<?>> children(Task<?> task) {
- if (task instanceof HasTaskChildren)
- return ((HasTaskChildren)task).getChildren();
- return Collections.emptyList();
- }
-
- /** returns failed tasks */
- public static Iterable<Task<?>> failed(Iterable<Task<?>> subtasks) {
- return Iterables.filter(subtasks, new Predicate<Task<?>>() {
- @Override
- public boolean apply(Task<?> input) {
- return input.isError();
- }
- });
- }
-
- /** returns the task, its children, and all its children, and so on;
- * @param root task whose descendants should be iterated
- * @param parentFirst whether to put parents before children or after
- */
- public static Iterable<Task<?>> descendants(Task<?> root, final boolean parentFirst) {
- Iterable<Task<?>> descs = Iterables.concat(Iterables.transform(Tasks.children(root), new Function<Task<?>,Iterable<Task<?>>>() {
- @Override
- public Iterable<Task<?>> apply(Task<?> input) {
- return descendants(input, parentFirst);
- }
- }));
- if (parentFirst) return Iterables.concat(Collections.singleton(root), descs);
- else return Iterables.concat(descs, Collections.singleton(root));
- }
-
- /** returns the error thrown by the task if {@link Task#isError()}, or null if no error or not done */
- public static Throwable getError(Task<?> t) {
- if (t==null) return null;
- if (!t.isDone()) return null;
- if (t.isCancelled()) return new CancellationException();
- try {
- t.get();
- return null;
- } catch (Throwable error) {
- // do not propagate as we are pretty much guaranteed above that it wasn't this
- // thread which originally threw the error
- return error;
- }
- }
- public static Task<Void> fail(final String name, final Throwable optionalError) {
- return Tasks.<Void>builder().dynamic(false).name(name).body(new Runnable() { public void run() {
- if (optionalError!=null) throw Exceptions.propagate(optionalError); else throw new RuntimeException("Failed: "+name);
- } }).build();
- }
- public static Task<Void> warning(final String message, final Throwable optionalError) {
- log.warn(message);
- return TaskTags.markInessential(fail(message, optionalError));
- }
-
- /** marks the current task inessential; this mainly matters if the task is running in a parent
- * {@link TaskQueueingContext} and we don't want the parent to fail if this task fails
- * <p>
- * no-op (silently ignored) if not in a task */
- public static void markInessential() {
- Task<?> task = Tasks.current();
- if (task==null) {
- TaskQueueingContext qc = DynamicTasks.getTaskQueuingContext();
- if (qc!=null) task = qc.asTask();
- }
- if (task!=null) {
- TaskTags.markInessential(task);
- }
- }
-
- /** causes failures in subtasks of the current task not to fail the parent;
- * no-op if not in a {@link TaskQueueingContext}.
- * <p>
- * essentially like a {@link #markInessential()} on all tasks in the current
- * {@link TaskQueueingContext}, including tasks queued subsequently */
- @Beta
- public static void swallowChildrenFailures() {
- Preconditions.checkNotNull(DynamicTasks.getTaskQueuingContext(), "Task queueing context required here");
- TaskQueueingContext qc = DynamicTasks.getTaskQueuingContext();
- if (qc!=null) {
- qc.swallowChildrenFailures();
- }
- }
-
- /** as {@link TaskTags#addTagDynamically(TaskAdaptable, Object)} but for current task, skipping if no current task */
- public static void addTagDynamically(Object tag) {
- Task<?> t = Tasks.current();
- if (t!=null) TaskTags.addTagDynamically(t, tag);
- }
-
- /**
- * Workaround for limitation described at {@link Task#cancel(boolean)};
- * internal method used to allow callers to wait for underlying tasks to finished in the case of cancellation.
- * <p>
- * It is irritating that {@link FutureTask} sync's object clears the runner thread,
- * so even if {@link BasicTask#getInternalFuture()} is used, there is no means of determining if the underlying object is done.
- * The {@link Task#getEndTimeUtc()} seems the only way.
- *
- * @return true if tasks ended; false if timed out
- **/
- @Beta
- public static boolean blockUntilInternalTasksEnded(Task<?> t, Duration timeout) {
- CountdownTimer timer = timeout.countdownTimer();
-
- if (t==null)
- return true;
-
- if (t instanceof ScheduledTask) {
- boolean result = ((ScheduledTask)t).blockUntilNextRunFinished(timer.getDurationRemaining());
- if (!result) return false;
- }
-
- t.blockUntilEnded(timer.getDurationRemaining());
-
- while (true) {
- if (t.getEndTimeUtc()>=0) return true;
- // above should be sufficient; but just in case, trying the below
- Thread tt = t.getThread();
- if (t instanceof ScheduledTask) {
- ((ScheduledTask)t).blockUntilNextRunFinished(timer.getDurationRemaining());
- return true;
- } else {
- if (tt==null || !tt.isAlive()) {
- if (!t.isCancelled()) {
- // may happen for a cancelled task, interrupted after submit but before start
- log.warn("Internal task thread is dead or null ("+tt+") but task not ended: "+t.getEndTimeUtc()+" ("+t+")");
- }
- return true;
- }
- }
- if (timer.isExpired())
- return false;
- Time.sleep(Repeater.DEFAULT_REAL_QUICK_PERIOD);
- }
- }
-
- /** returns true if either the current thread or the current task is interrupted/cancelled */
- public static boolean isInterrupted() {
- if (Thread.currentThread().isInterrupted()) return true;
- Task<?> t = current();
- if (t==null) return false;
- return t.isCancelled();
- }
-
- private static class WaitForRepeaterCallable implements Callable<Boolean> {
- protected Repeater repeater;
- protected boolean requireTrue;
-
- public WaitForRepeaterCallable(Repeater repeater, boolean requireTrue) {
- this.repeater = repeater;
- this.requireTrue = requireTrue;
- }
-
- @Override
- public Boolean call() {
- ReferenceWithError<Boolean> result;
- Tasks.setBlockingDetails(repeater.getDescription());
- try {
- result = repeater.runKeepingError();
- } finally {
- Tasks.resetBlockingDetails();
- }
-
- if (Boolean.TRUE.equals(result.getWithoutError()))
- return true;
- if (result.hasError())
- throw Exceptions.propagate(result.getError());
- if (requireTrue)
- throw new IllegalStateException("timeout - "+repeater.getDescription());
- return false;
- }
- }
-
- /** @return a {@link TaskBuilder} which tests whether the repeater terminates with success in its configured timeframe,
- * returning true or false depending on whether repeater succeed */
- public static TaskBuilder<Boolean> testing(Repeater repeater) {
- return Tasks.<Boolean>builder().body(new WaitForRepeaterCallable(repeater, false))
- .name("waiting for condition")
- .description("Testing whether " + getTimeoutString(repeater) + ": "+repeater.getDescription());
- }
-
- /** @return a {@link TaskBuilder} which requires that the repeater terminate with success in its configured timeframe,
- * throwing if it does not */
- public static TaskBuilder<?> requiring(Repeater repeater) {
- return Tasks.<Boolean>builder().body(new WaitForRepeaterCallable(repeater, true))
- .name("waiting for condition")
- .description("Requiring " + getTimeoutString(repeater) + ": " + repeater.getDescription());
- }
-
- private static String getTimeoutString(Repeater repeater) {
- Duration timeout = repeater.getTimeLimit();
- if (timeout==null || Duration.PRACTICALLY_FOREVER.equals(timeout))
- return "eventually";
- return "in "+timeout;
- }
-
-}
[39/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/file/ArchiveTasks.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/file/ArchiveTasks.java b/core/src/main/java/brooklyn/util/file/ArchiveTasks.java
deleted file mode 100644
index b183f62..0000000
--- a/core/src/main/java/brooklyn/util/file/ArchiveTasks.java
+++ /dev/null
@@ -1,58 +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 brooklyn.util.file;
-
-import java.util.Map;
-
-import org.apache.brooklyn.api.management.TaskAdaptable;
-import org.apache.brooklyn.api.management.TaskFactory;
-
-import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.net.Urls;
-import brooklyn.util.task.Tasks;
-
-public class ArchiveTasks {
-
- /** as {@link #deploy(ResourceUtils, Map, String, SshMachineLocation, String, String, String)} with the most common parameters */
- public static TaskFactory<?> deploy(final ResourceUtils optionalResolver, final String archiveUrl, final SshMachineLocation machine, final String destDir) {
- return deploy(optionalResolver, null, archiveUrl, machine, destDir, false, null, null);
- }
-
- /** returns a task which installs and unpacks the given archive, as per {@link ArchiveUtils#deploy(ResourceUtils, Map, String, SshMachineLocation, String, String, String)};
- * if allowNonarchivesOrKeepArchiveAfterDeploy is false, this task will fail if the item is not an archive;
- * in cases where the download type is not clear in the URL but is known by the caller, supply a optionalDestFile including the appropriate file extension */
- public static TaskFactory<?> deploy(final ResourceUtils resolver, final Map<String, ?> props, final String archiveUrl, final SshMachineLocation machine, final String destDir, final boolean allowNonarchivesOrKeepArchiveAfterDeploy, final String optionalTmpDir, final String optionalDestFile) {
- return new TaskFactory<TaskAdaptable<?>>() {
- @Override
- public TaskAdaptable<?> newTask() {
- return Tasks.<Void>builder().name("deploying "+Urls.getBasename(archiveUrl)).description("installing "+archiveUrl+" and unpacking to "+destDir).body(new Runnable() {
- @Override
- public void run() {
- boolean unpacked = ArchiveUtils.deploy(resolver, props, archiveUrl, machine, destDir, allowNonarchivesOrKeepArchiveAfterDeploy, optionalTmpDir, optionalDestFile);
- if (!unpacked && !allowNonarchivesOrKeepArchiveAfterDeploy) {
- throw new IllegalStateException("Unable to unpack archive from "+archiveUrl+"; not able to infer archive type");
- }
- }
- }).build();
- }
- };
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/file/ArchiveUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/file/ArchiveUtils.java b/core/src/main/java/brooklyn/util/file/ArchiveUtils.java
deleted file mode 100644
index d072b70..0000000
--- a/core/src/main/java/brooklyn/util/file/ArchiveUtils.java
+++ /dev/null
@@ -1,351 +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 brooklyn.util.file;
-
-import static java.lang.String.format;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.EnumSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.javalang.StackTraceSimplifier;
-import brooklyn.util.net.Urls;
-import brooklyn.util.os.Os;
-import brooklyn.util.ssh.BashCommands;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.task.ssh.SshTasks;
-import brooklyn.util.text.Strings;
-
-import com.google.common.base.Charsets;
-import com.google.common.base.Preconditions;
-import com.google.common.io.Files;
-
-public class ArchiveUtils {
-
- private static final Logger log = LoggerFactory.getLogger(ArchiveUtils.class);
-
- // TODO Make this a ConfigKey on the machine location
- /** Number of attempts when copying a file to a remote server. */
- public static final int NUM_RETRIES_FOR_COPYING = 5;
-
- /**
- * The types of archive that are supported by Brooklyn.
- */
- public static enum ArchiveType {
- TAR,
- TGZ,
- TBZ,
- ZIP,
- JAR,
- WAR,
- EAR,
- UNKNOWN;
-
- /**
- * Zip format archives used by Java.
- */
- public static Set<ArchiveType> ZIP_ARCHIVES = EnumSet.of(ArchiveType.ZIP, ArchiveType.JAR, ArchiveType.WAR, ArchiveType.EAR);
-
- public static ArchiveUtils.ArchiveType of(String filename) {
- if (filename == null) return null;
- String ext = Files.getFileExtension(filename);
- try {
- return valueOf(ext.toUpperCase());
- } catch (IllegalArgumentException iae) {
- if (filename.toLowerCase().endsWith(".tar.gz")) {
- return TGZ;
- } else if (filename.toLowerCase().endsWith(".tar.bz") ||
- filename.toLowerCase().endsWith(".tar.bz2") ||
- filename.toLowerCase().endsWith(".tar.xz")) {
- return TBZ;
- } else {
- return UNKNOWN;
- }
- }
- }
-
- @Override
- public String toString() {
- if (UNKNOWN.equals(this)) {
- return "";
- } else {
- return name().toLowerCase();
- }
- }
- }
-
- /**
- * Returns the list of commands used to install support for an archive with the given name.
- */
- public static List<String> installCommands(String fileName) {
- List<String> commands = new LinkedList<String>();
- switch (ArchiveType.of(fileName)) {
- case TAR:
- case TGZ:
- case TBZ:
- commands.add(BashCommands.INSTALL_TAR);
- break;
- case ZIP:
- commands.add(BashCommands.INSTALL_UNZIP);
- break;
- case JAR:
- case WAR:
- case EAR:
- case UNKNOWN:
- break;
- }
- return commands;
- }
-
- /**
- * Returns the list of commands used to extract the contents of the archive with the given name.
- * <p>
- * Optionally, Java archives of type
- *
- * @see #extractCommands(String, String)
- */
- public static List<String> extractCommands(String fileName, String sourceDir, String targetDir, boolean extractJar) {
- return extractCommands(fileName, sourceDir, targetDir, extractJar, true);
- }
-
- /** as {@link #extractCommands(String, String, String, boolean)}, but also with option to keep the original */
- public static List<String> extractCommands(String fileName, String sourceDir, String targetDir, boolean extractJar, boolean keepOriginal) {
- List<String> commands = new LinkedList<String>();
- commands.add("cd " + targetDir);
- String sourcePath = Os.mergePathsUnix(sourceDir, fileName);
- switch (ArchiveType.of(fileName)) {
- case TAR:
- commands.add("tar xvf " + sourcePath);
- break;
- case TGZ:
- commands.add("tar xvfz " + sourcePath);
- break;
- case TBZ:
- commands.add("tar xvfj " + sourcePath);
- break;
- case ZIP:
- commands.add("unzip " + sourcePath);
- break;
- case JAR:
- case WAR:
- case EAR:
- if (extractJar) {
- commands.add("jar -xvf " + sourcePath);
- break;
- }
- case UNKNOWN:
- if (!sourcePath.equals(Urls.mergePaths(targetDir, fileName))) {
- commands.add("cp " + sourcePath + " " + targetDir);
- } else {
- keepOriginal = true;
- // else we'd just end up deleting it!
- // this branch will often lead to errors in any case, see the allowNonarchivesOrKeepArchiveAfterDeploy parameter
- // in ArchiveTasks which calls through to here and then fails in the case corresponding to this code branch
- }
- break;
- }
- if (!keepOriginal && !commands.isEmpty())
- commands.add("rm "+sourcePath);
- return commands;
- }
-
- /**
- * Returns the list of commands used to extract the contents of the archive with the given name.
- * <p>
- * The archive will be extracted in its current directory unless it is a Java archive of type {@code .jar},
- * {@code .war} or {@code .ear}, which will be left as is.
- *
- * @see #extractCommands(String, String, String, boolean)
- */
- public static List<String> extractCommands(String fileName, String sourceDir) {
- return extractCommands(fileName, sourceDir, ".", false);
- }
-
- /**
- * Deploys an archive file to a remote machine and extracts the contents.
- */
- public static void deploy(String archiveUrl, SshMachineLocation machine, String destDir) {
- deploy(MutableMap.<String, Object>of(), archiveUrl, machine, destDir);
- }
-
- /**
- * Deploys an archive file to a remote machine and extracts the contents.
- * <p>
- * Copies the archive file from the given URL to the destination directory and extracts
- * the contents. If the URL is a local directory, the contents are packaged as a Zip archive first.
- *
- * @see #deploy(String, SshMachineLocation, String, String)
- * @see #deploy(Map, String, SshMachineLocation, String, String, String)
- */
- public static void deploy(Map<String, ?> props, String archiveUrl, SshMachineLocation machine, String destDir) {
- if (Urls.isDirectory(archiveUrl)) {
- File zipFile = ArchiveBuilder.zip().entry(".", Urls.toFile(archiveUrl)).create();
- archiveUrl = zipFile.getAbsolutePath();
- }
-
- // Determine filename
- String destFile = archiveUrl.contains("?") ? archiveUrl.substring(0, archiveUrl.indexOf('?')) : archiveUrl;
- destFile = destFile.substring(destFile.lastIndexOf('/') + 1);
-
- deploy(props, archiveUrl, machine, destDir, destFile);
- }
-
- /**
- * Deploys an archive file to a remote machine and extracts the contents.
- * <p>
- * Copies the archive file from the given URL to a file in the destination directory and extracts
- * the contents.
- *
- * @see #deploy(String, SshMachineLocation, String)
- * @see #deploy(Map, String, SshMachineLocation, String, String, String)
- */
- public static void deploy(String archiveUrl, SshMachineLocation machine, String destDir, String destFile) {
- deploy(MutableMap.<String, Object>of(), archiveUrl, machine, destDir, destDir, destFile);
- }
- public static void deploy(Map<String, ?> props, String archiveUrl, SshMachineLocation machine, String destDir, String destFile) {
- deploy(props, archiveUrl, machine, destDir, destDir, destFile);
- }
- public static void deploy(Map<String, ?> props, String archiveUrl, SshMachineLocation machine, String tmpDir, String destDir, String destFile) {
- deploy(null, props, archiveUrl, machine, destDir, true, tmpDir, destFile);
- }
-
- /**
- * Deploys an archive file to a remote machine and extracts the contents.
- * <p>
- * Copies the archive file from the given URL to a file in a temporary directory and extracts
- * the contents in the destination directory. For Java archives of type {@code .jar},
- * {@code .war} or {@code .ear} the file is simply copied.
- *
- * @return true if the archive is downloaded AND unpacked; false if it is downloaded but not unpacked;
- * throws if there was an error downloading or, for known archive types, unpacking.
- *
- * @see #deploy(String, SshMachineLocation, String)
- * @see #deploy(Map, String, SshMachineLocation, String, String, String)
- * @see #install(SshMachineLocation, String, String, int)
- */
- public static boolean deploy(ResourceUtils resolver, Map<String, ?> props, String archiveUrl, SshMachineLocation machine, String destDir, boolean keepArchiveAfterUnpacking, String optionalTmpDir, String optionalDestFile) {
- String destFile = optionalDestFile;
- if (destFile==null) destFile = Urls.getBasename(Preconditions.checkNotNull(archiveUrl, "archiveUrl"));
- if (Strings.isBlank(destFile))
- throw new IllegalStateException("Not given filename and cannot infer archive type from '"+archiveUrl+"'");
-
- String tmpDir = optionalTmpDir;
- if (tmpDir==null) tmpDir=Preconditions.checkNotNull(destDir, "destDir");
- if (props==null) props = MutableMap.of();
- String destPath = Os.mergePaths(tmpDir, destFile);
-
- // Use the location mutex to prevent package manager locking issues
- machine.acquireMutex("installing", "installing archive");
- try {
- int result = install(resolver, props, machine, archiveUrl, destPath, NUM_RETRIES_FOR_COPYING);
- if (result != 0) {
- throw new IllegalStateException(format("Unable to install archive %s to %s", archiveUrl, machine));
- }
-
- // extract, now using task if available
- MutableList<String> commands = MutableList.copyOf(installCommands(destFile))
- .appendAll(extractCommands(destFile, tmpDir, destDir, false, keepArchiveAfterUnpacking));
- if (DynamicTasks.getTaskQueuingContext()!=null) {
- result = DynamicTasks.queue(SshTasks.newSshExecTaskFactory(machine, commands.toArray(new String[0])).summary("extracting archive").requiringExitCodeZero()).get();
- } else {
- result = machine.execCommands(props, "extracting content", commands);
- }
- if (result != 0) {
- throw new IllegalStateException(format("Failed to expand archive %s on %s", archiveUrl, machine));
- }
- return ArchiveType.of(destFile)!=ArchiveType.UNKNOWN;
- } finally {
- machine.releaseMutex("installing");
- }
- }
-
- /**
- * Installs a URL onto a remote machine.
- *
- * @see #install(Map, SshMachineLocation, String, String, int)
- */
- public static int install(SshMachineLocation machine, String urlToInstall, String target) {
- return install(MutableMap.<String, Object>of(), machine, urlToInstall, target, NUM_RETRIES_FOR_COPYING);
- }
-
- /**
- * Installs a URL onto a remote machine.
- *
- * @see #install(SshMachineLocation, String, String)
- * @see SshMachineLocation#installTo(Map, String, String)
- */
- public static int install(Map<String, ?> props, SshMachineLocation machine, String urlToInstall, String target, int numAttempts) {
- return install(null, props, machine, urlToInstall, target, numAttempts);
- }
-
- public static int install(ResourceUtils resolver, Map<String, ?> props, SshMachineLocation machine, String urlToInstall, String target, int numAttempts) {
- if (resolver==null) resolver = ResourceUtils.create(machine);
- Exception lastError = null;
- int retriesRemaining = numAttempts;
- int attemptNum = 0;
- do {
- attemptNum++;
- try {
- Tasks.setBlockingDetails("Installing "+urlToInstall+" at "+machine);
- // TODO would be nice to have this in a task (and the things within it!)
- return machine.installTo(resolver, props, urlToInstall, target);
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- lastError = e;
- String stack = StackTraceSimplifier.toString(e);
- if (stack.contains("net.schmizz.sshj.sftp.RemoteFile.write")) {
- log.warn("Failed to transfer "+urlToInstall+" to "+machine+", retryable error, attempt "+attemptNum+"/"+numAttempts+": "+e);
- continue;
- }
- log.warn("Failed to transfer "+urlToInstall+" to "+machine+", not a retryable error so failing: "+e);
- throw Exceptions.propagate(e);
- } finally {
- Tasks.resetBlockingDetails();
- }
- } while (retriesRemaining --> 0);
- throw Exceptions.propagate(lastError);
- }
-
- /**
- * Copies the entire contents of a file to a String.
- *
- * @see com.google.common.io.Files#toString(File, java.nio.charset.Charset)
- */
- public static String readFullyString(File sourceFile) {
- try {
- return Files.toString(sourceFile, Charsets.UTF_8);
- } catch (IOException ioe) {
- throw Exceptions.propagate(ioe);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/flags/ClassCoercionException.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/flags/ClassCoercionException.java b/core/src/main/java/brooklyn/util/flags/ClassCoercionException.java
deleted file mode 100644
index 17385ac..0000000
--- a/core/src/main/java/brooklyn/util/flags/ClassCoercionException.java
+++ /dev/null
@@ -1,39 +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 brooklyn.util.flags;
-
-/**
- * Thrown to indicate that {@link TypeCoercions} could not cast an object from one
- * class to another.
- */
-public class ClassCoercionException extends ClassCastException {
- public ClassCoercionException() {
- super();
- }
-
- /**
- * Constructs a <code>ClassCoercionException</code> with the specified
- * detail message.
- *
- * @param s the detail message.
- */
- public ClassCoercionException(String s) {
- super(s);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/flags/FlagUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/flags/FlagUtils.java b/core/src/main/java/brooklyn/util/flags/FlagUtils.java
deleted file mode 100644
index 0e596ac..0000000
--- a/core/src/main/java/brooklyn/util/flags/FlagUtils.java
+++ /dev/null
@@ -1,587 +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 brooklyn.util.flags;
-
-import static brooklyn.util.GroovyJavaMethods.elvis;
-import static brooklyn.util.GroovyJavaMethods.truth;
-import static com.google.common.base.Preconditions.checkNotNull;
-import groovy.lang.Closure;
-import groovy.lang.GroovyObject;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.Set;
-
-import org.apache.brooklyn.api.entity.trait.Configurable;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.config.ConfigKey.HasConfigKey;
-import brooklyn.util.GroovyJavaMethods;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.guava.Maybe;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.base.Throwables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-
-
-/** class to help transfer values passed as named arguments to other well-known variables/fields/objects;
- * see the test case for example usage */
-public class FlagUtils {
-
- public static final Logger log = LoggerFactory.getLogger(FlagUtils.class);
-
- private FlagUtils() {}
-
- /** see {@link #setFieldsFromFlags(Object o, ConfigBag)} */
- public static Map<?, ?> setPublicFieldsFromFlags(Map<?, ?> flags, Object o) {
- return setFieldsFromFlagsInternal(o, Arrays.asList(o.getClass().getFields()), flags, null, true);
- }
-
- /** see {@link #setFieldsFromFlags(Object, ConfigBag)} */
- public static Map<?, ?> setFieldsFromFlags(Map<?, ?> flags, Object o) {
- return setFieldsFromFlagsInternal(o, getAllFields(o.getClass()), flags, null, true);
- }
-
- /** sets all fields (including private and static, local and inherited) annotated {@link SetFromFlag} on the given object,
- * from the given flags map, returning just those flag-value pairs passed in which do not correspond to SetFromFlags fields
- * annotated ConfigKey and HasConfigKey fields are _configured_ (and we assume the object in that case is {@link Configurable});
- * keys should be ConfigKey, HasConfigKey, or String;
- * default values are also applied unless that is specified false on one of the variants of this method which takes such an argument
- */
- public static void setFieldsFromFlags(Object o, ConfigBag configBag) {
- setFieldsFromFlagsInternal(o, getAllFields(o.getClass()), configBag.getAllConfig(), configBag, true);
- }
-
- /** as {@link #setFieldsFromFlags(Object, ConfigBag)}, but allowing control over whether default values should be set */
- public static void setFieldsFromFlags(Object o, ConfigBag configBag, boolean setDefaultVals) {
- setFieldsFromFlagsInternal(o, getAllFields(o.getClass()), configBag.getAllConfig(), configBag, setDefaultVals);
- }
-
- /** as {@link #setFieldsFromFlags(Object, ConfigBag)}, but specifying a subset of flags to use */
- public static void setFieldsFromFlagsWithBag(Object o, Map<?,?> flags, ConfigBag configBag, boolean setDefaultVals) {
- setFieldsFromFlagsInternal(o, getAllFields(o.getClass()), flags, configBag, setDefaultVals);
- }
-
- /**
- * Sets the field with the given flag (if it exists) to the given value.
- * Will attempt to coerce the value to the required type.
- * Will respect "nullable" on the SetFromFlag annotation.
- *
- * @throws IllegalArgumentException If fieldVal is null and the SetFromFlag annotation set nullable=false
- */
- public static boolean setFieldFromFlag(Object o, String flagName, Object fieldVal) {
- return setFieldFromFlagInternal(checkNotNull(flagName, "flagName"), fieldVal, o, getAllFields(o.getClass()));
- }
-
- /** get all fields (including private and static) on the given object and all supertypes,
- * that are annotated with SetFromFlags.
- */
- public static Map<String, ?> getFieldsWithFlags(Object o) {
- return getFieldsWithFlagsInternal(o, getAllFields(o.getClass()));
- }
-
- /**
- * Finds the {@link Field} on the given object annotated with the given name flag.
- */
- public static Field findFieldForFlag(String flagName, Object o) {
- return findFieldForFlagInternal(flagName, o, getAllFields(o.getClass()));
- }
-
- /** get all fields (including private and static) and their values on the given object and all supertypes,
- * where the field is annotated with SetFromFlags.
- */
- public static Map<String, Object> getFieldsWithFlagsExcludingModifiers(Object o, int excludingModifiers) {
- List<Field> filteredFields = Lists.newArrayList();
- for (Field contender : getAllFields(o.getClass())) {
- if ((contender.getModifiers() & excludingModifiers) == 0) {
- filteredFields.add(contender);
- }
- }
- return getFieldsWithFlagsInternal(o, filteredFields);
- }
-
- /** get all fields with the given modifiers, and their values on the given object and all supertypes,
- * where the field is annotated with SetFromFlags.
- */
- public static Map<String, Object> getFieldsWithFlagsWithModifiers(Object o, int requiredModifiers) {
- List<Field> filteredFields = Lists.newArrayList();
- for (Field contender : getAllFields(o.getClass())) {
- if ((contender.getModifiers() & requiredModifiers) == requiredModifiers) {
- filteredFields.add(contender);
- }
- }
- return getFieldsWithFlagsInternal(o, filteredFields);
- }
-
- /** sets _all_ accessible _{@link ConfigKey}_ and {@link HasConfigKey} fields on the given object,
- * using the indicated flags/config-bag
- * @deprecated since 0.7.0 use {@link #setAllConfigKeys(Map, Configurable, boolean)} */
- public static Map<String, ?> setAllConfigKeys(Map<String, ?> flagsOrConfig, Configurable instance) {
- return setAllConfigKeys(flagsOrConfig, instance, false);
- }
- /** sets _all_ accessible _{@link ConfigKey}_ and {@link HasConfigKey} fields on the given object,
- * using the indicated flags/config-bag */
- public static Map<String, ?> setAllConfigKeys(Map<String, ?> flagsOrConfig, Configurable instance, boolean includeFlags) {
- ConfigBag bag = new ConfigBag().putAll(flagsOrConfig);
- setAllConfigKeys(instance, bag, includeFlags);
- return bag.getUnusedConfigMutable();
- }
-
- /** sets _all_ accessible _{@link ConfigKey}_ and {@link HasConfigKey} fields on the given object,
- * using the indicated flags/config-bag
- * @deprecated since 0.7.0 use {@link #setAllConfigKeys(Configurable, ConfigBag, boolean)} */
- public static void setAllConfigKeys(Configurable o, ConfigBag bag) {
- setAllConfigKeys(o, bag, false);
- }
- /** sets _all_ accessible _{@link ConfigKey}_ and {@link HasConfigKey} fields on the given object,
- * using the indicated flags/config-bag */
- public static void setAllConfigKeys(Configurable o, ConfigBag bag, boolean includeFlags) {
- for (Field f: getAllFields(o.getClass())) {
- ConfigKey<?> key = getFieldAsConfigKey(o, f);
- if (key!=null) {
- FlagConfigKeyAndValueRecord record = getFlagConfigKeyRecord(f, key, bag);
- if ((includeFlags && record.isValuePresent()) || record.getConfigKeyMaybeValue().isPresent()) {
- setField(o, f, record.getValueOrNullPreferringConfigKey(), null);
- }
- }
- }
- }
-
- public static class FlagConfigKeyAndValueRecord {
- private String flagName = null;
- private ConfigKey<?> configKey = null;
- private Maybe<Object> flagValue = Maybe.absent();
- private Maybe<Object> configKeyValue = Maybe.absent();
-
- public String getFlagName() {
- return flagName;
- }
- public ConfigKey<?> getConfigKey() {
- return configKey;
- }
- public Maybe<Object> getFlagMaybeValue() {
- return flagValue;
- }
- public Maybe<Object> getConfigKeyMaybeValue() {
- return configKeyValue;
- }
- public Object getValueOrNullPreferringConfigKey() {
- return getConfigKeyMaybeValue().or(getFlagMaybeValue()).orNull();
- }
- public Object getValueOrNullPreferringFlag() {
- return getFlagMaybeValue().or(getConfigKeyMaybeValue()).orNull();
- }
- /** true if value is present for either flag or config key */
- public boolean isValuePresent() {
- return flagValue.isPresent() || configKeyValue.isPresent();
- }
-
- @Override
- public String toString() {
- return Objects.toStringHelper(this).omitNullValues()
- .add("flag", flagName)
- .add("configKey", configKey)
- .add("flagValue", flagValue.orNull())
- .add("configKeyValue", configKeyValue.orNull())
- .toString();
- }
- }
-
- /** gets all the flags/keys in the given config bag which are applicable to the given type's config keys and flags */
- public static <T> List<FlagConfigKeyAndValueRecord> findAllFlagsAndConfigKeys(T optionalInstance, Class<? extends T> type, ConfigBag input) {
- List<FlagConfigKeyAndValueRecord> output = new ArrayList<FlagUtils.FlagConfigKeyAndValueRecord>();
- for (Field f: getAllFields(type)) {
- ConfigKey<?> key = getFieldAsConfigKey(optionalInstance, f);
- FlagConfigKeyAndValueRecord record = getFlagConfigKeyRecord(f, key, input);
- if (record.isValuePresent())
- output.add(record);
- }
- return output;
- }
-
- /** returns the flag/config-key record for the given input */
- private static FlagConfigKeyAndValueRecord getFlagConfigKeyRecord(Field f, ConfigKey<?> key, ConfigBag input) {
- FlagConfigKeyAndValueRecord result = new FlagConfigKeyAndValueRecord();
- result.configKey = key;
- if (key!=null && input.containsKey(key))
- result.configKeyValue = Maybe.<Object>of(input.getStringKey(key.getName()));
- SetFromFlag flag = f.getAnnotation(SetFromFlag.class);
- if (flag!=null) {
- result.flagName = flag.value();
- if (input.containsKey(flag.value()))
- result.flagValue = Maybe.of(input.getStringKey(flag.value()));
- }
- return result;
- }
-
- /** returns all fields on the given class, superclasses, and interfaces thereof, in that order of preference,
- * (excluding fields on Object) */
- public static List<Field> getAllFields(Class<?> base, Closure<Boolean> filter) {
- return getAllFields(base, GroovyJavaMethods.<Field>predicateFromClosure(filter));
- }
- public static List<Field> getAllFields(Class<?> base) {
- return getAllFields(base, Predicates.<Field>alwaysTrue());
- }
- public static List<Field> getAllFields(Class<?> base, Predicate<Field> filter) {
- return getLocalFields(getAllAssignableTypes(base), filter);
- }
- /** returns all fields explicitly declared on the given classes */
- public static List<Field> getLocalFields(List<Class<?>> classes) {
- return getLocalFields(classes, Predicates.<Field>alwaysTrue());
- }
- public static List<Field> getLocalFields(List<Class<?>> classes, Closure<Boolean> filter) {
- return getLocalFields(classes, GroovyJavaMethods.<Field>predicateFromClosure(filter));
- }
- public static List<Field> getLocalFields(List<Class<?>> classes, Predicate<Field> filter) {
- List<Field> fields = Lists.newArrayList();
- for (Class<?> c : classes) {
- for (Field f : c.getDeclaredFields()) {
- if (filter.apply(f)) fields.add(f);
- }
- }
- return fields;
- }
-
- /** returns base, superclasses, then interfaces */
- public static List<Class<?>> getAllAssignableTypes(Class<?> base) {
- return getAllAssignableTypes(base, new Predicate<Class<?>>() {
- @Override public boolean apply(Class<?> it) {
- return (it != Object.class) && (it != GroovyObject.class);
- }
- });
- }
- public static List<Class<?>> getAllAssignableTypes(Class<?> base, Closure<Boolean> filter) {
- return getAllAssignableTypes(base, GroovyJavaMethods.<Class<?>>predicateFromClosure(filter));
- }
- public static List<Class<?>> getAllAssignableTypes(Class<?> base, Predicate<Class<?>> filter) {
- List<Class<?>> classes = Lists.newArrayList();
- for (Class<?> c = base; c != null; c = c.getSuperclass()) {
- if (filter.apply(c)) classes.add(c);
- }
- for (int i=0; i<classes.size(); i++) {
- for (Class<?> interf : classes.get(i).getInterfaces()) {
- if (filter.apply(interf) && !(classes.contains(interf))) classes.add(interf);
- }
- }
- return classes;
- }
-
- private static Map<String, Object> getFieldsWithFlagsInternal(Object o, Collection<Field> fields) {
- Map<String, Object> result = Maps.newLinkedHashMap();
- for (Field f: fields) {
- SetFromFlag cf = f.getAnnotation(SetFromFlag.class);
- if (cf != null) {
- String flagName = elvis(cf.value(), f.getName());
- if (truth(flagName)) {
- result.put(flagName, getField(o, f));
- } else {
- log.warn("Ignoring field {} of object {} as no flag name available", f, o);
- }
- }
- }
- return result;
- }
-
- private static Field findFieldForFlagInternal(String flagName, Object o, Collection<Field> fields) {
- for (Field f: fields) {
- SetFromFlag cf = f.getAnnotation(SetFromFlag.class);
- if (cf != null) {
- String contenderName = elvis(cf.value(), f.getName());
- if (flagName.equals(contenderName)) {
- return f;
- }
- }
- }
- throw new NoSuchElementException("Field with flag "+flagName+" not found on "+o+" of type "+(o != null ? o.getClass() : null));
- }
-
- private static boolean setFieldFromFlagInternal(String flagName, Object fieldVal, Object o, Collection<Field> fields) {
- for (Field f: fields) {
- SetFromFlag cf = f.getAnnotation(SetFromFlag.class);
- if (cf != null && flagName.equals(elvis(cf.value(), f.getName()))) {
- setField(o, f, fieldVal, cf);
- return true;
- }
- }
- return false;
- }
-
- private static Map<String, ?> setFieldsFromFlagsInternal(Object o, Collection<Field> fields, Map<?,?> flagsOrConfig, ConfigBag bag, boolean setDefaultVals) {
- if (bag==null) bag = new ConfigBag().putAll(flagsOrConfig);
- for (Field f: fields) {
- SetFromFlag cf = f.getAnnotation(SetFromFlag.class);
- if (cf!=null) setFieldFromConfig(o, f, bag, cf, setDefaultVals);
- }
- return bag.getUnusedConfigMutable();
- }
-
- private static void setFieldFromConfig(Object o, Field f, ConfigBag bag, SetFromFlag optionalAnnotation, boolean setDefaultVals) {
- String flagName = optionalAnnotation==null ? null : (String)elvis(optionalAnnotation.value(), f.getName());
- // prefer flag name, if present
- if (truth(flagName) && bag.containsKey(flagName)) {
- setField(o, f, bag.getStringKey(flagName), optionalAnnotation);
- return;
- }
- // first check whether it is a key
- ConfigKey<?> key = getFieldAsConfigKey(o, f);
- if (key!=null && bag.containsKey(key)) {
- Object uncoercedValue = bag.getStringKey(key.getName());
- setField(o, f, uncoercedValue, optionalAnnotation);
- return;
- }
- if (setDefaultVals && optionalAnnotation!=null && truth(optionalAnnotation.defaultVal())) {
- Object oldValue;
- try {
- f.setAccessible(true);
- oldValue = f.get(o);
- if (oldValue==null || oldValue.equals(getDefaultValueForType(f.getType()))) {
- setField(o, f, optionalAnnotation.defaultVal(), optionalAnnotation);
- }
- } catch (Exception e) {
- Exceptions.propagate(e);
- }
- return;
- }
- }
-
- /** returns the given field as a config key, if it is an accessible config key, otherwise null */
- private static ConfigKey<?> getFieldAsConfigKey(Object optionalInstance, Field f) {
- if (optionalInstance==null) {
- if ((f.getModifiers() & Modifier.STATIC)==0)
- // non-static field on null instance, can't be set
- return null;
- }
- if (ConfigKey.class.isAssignableFrom(f.getType())) {
- return (ConfigKey<?>) getField(optionalInstance, f);
- } else if (HasConfigKey.class.isAssignableFrom(f.getType())) {
- return ((HasConfigKey<?>)getField(optionalInstance, f)).getConfigKey();
- }
- return null;
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public static void setConfig(Object objectOfField, ConfigKey<?> key, Object value, SetFromFlag optionalAnnotation) {
- if (objectOfField instanceof Configurable) {
- ((Configurable)objectOfField).setConfig((ConfigKey)key, value);
- return;
- } else {
- if (optionalAnnotation==null) {
- log.warn("Cannot set key "+key.getName()+" on "+objectOfField+": containing class is not Configurable");
- } else if (!key.getName().equals(optionalAnnotation.value())) {
- log.warn("Cannot set key "+key.getName()+" on "+objectOfField+" from flag "+optionalAnnotation.value()+": containing class is not Configurable");
- } else {
- // if key and flag are the same, then it will probably happen automatically
- if (log.isDebugEnabled())
- log.debug("Cannot set key "+key.getName()+" on "+objectOfField+" from flag "+optionalAnnotation.value()+": containing class is not Configurable");
- }
- return;
- }
- }
-
- /** sets the field to the value, after checking whether the given value can be set
- * respecting the constraints of the annotation
- */
- public static void setField(Object objectOfField, Field f, Object value, SetFromFlag optionalAnnotation) {
- try {
- ConfigKey<?> key = getFieldAsConfigKey(objectOfField, f);
- if (key!=null) {
- setConfig(objectOfField, key, value, optionalAnnotation);
- return;
- }
-
- if (!f.isAccessible()) f.setAccessible(true);
- if (optionalAnnotation!=null && optionalAnnotation.immutable()) {
- Object oldValue = f.get(objectOfField);
- if (!Objects.equal(oldValue, getDefaultValueForType(f.getType())) && oldValue != value) {
- throw new IllegalStateException("Forbidden modification to immutable field "+
- f+" in "+objectOfField+": attempting to change to "+value+" when was already "+oldValue);
- }
- }
- if (optionalAnnotation!=null && !optionalAnnotation.nullable() && value==null) {
- throw new IllegalArgumentException("Forbidden null assignment to non-nullable field "+
- f+" in "+objectOfField);
- }
- if (optionalAnnotation!=null && (f.getModifiers() & Modifier.STATIC)==Modifier.STATIC)
- log.warn("Setting static field "+f+" in "+objectOfField+" from flag "+optionalAnnotation.value()+": discouraged");
-
- Object newValue;
- try {
- newValue = TypeCoercions.coerce(value, f.getType());
- } catch (Exception e) {
- throw new IllegalArgumentException("Cannot set "+f+" in "+objectOfField+" from type "+value.getClass()+" ("+value+"): "+e, e);
- }
- f.set(objectOfField, newValue);
- if (log.isTraceEnabled()) log.trace("FlagUtils for "+objectOfField+", setting field="+f.getName()+"; val="+value+"; newVal="+newValue+"; key="+key);
-
- } catch (IllegalAccessException e) {
- throw Throwables.propagate(e);
- }
- }
-
- /** gets the value of the field.
- */
- public static Object getField(Object objectOfField, Field f) {
- try {
- if (!f.isAccessible()) f.setAccessible(true);
- return f.get(objectOfField);
- } catch (IllegalAccessException e) {
- throw Throwables.propagate(e);
- }
- }
-
- /** returns the default/inital value that is assigned to fields of the givien type;
- * if the type is not primitive this value is null;
- * for primitive types it is obvious but not AFAIK programmatically visible
- * (e.g. 0 for int, false for boolean)
- */
- public static Object getDefaultValueForType(Class<?> t) {
- if (!t.isPrimitive()) return null;
- if (t==Integer.TYPE) return (int)0;
- if (t==Long.TYPE) return (long)0;
- if (t==Double.TYPE) return (double)0;
- if (t==Float.TYPE) return (float)0;
- if (t==Byte.TYPE) return (byte)0;
- if (t==Short.TYPE) return (short)0;
- if (t==Character.TYPE) return (char)0;
- if (t==Boolean.TYPE) return false;
- //should never happen
- throw new IllegalStateException("Class "+t+" is an unknown primitive.");
- }
-
- /** returns a map of all fields which are annotated 'SetFromFlag', along with the annotation */
- public static Map<Field,SetFromFlag> getAnnotatedFields(Class<?> type) {
- Map<Field, SetFromFlag> result = Maps.newLinkedHashMap();
- for (Field f: getAllFields(type)) {
- SetFromFlag cf = f.getAnnotation(SetFromFlag.class);
- if (truth(cf)) result.put(f, cf);
- }
- return result;
- }
-
- /** returns a map of all {@link ConfigKey} fields which are annotated 'SetFromFlag', along with the annotation */
- public static Map<ConfigKey<?>,SetFromFlag> getAnnotatedConfigKeys(Class<?> type) {
- Map<ConfigKey<?>, SetFromFlag> result = Maps.newLinkedHashMap();
- List<Field> fields = getAllFields(type, new Predicate<Field>() {
- @Override public boolean apply(Field f) {
- return (f != null) && ConfigKey.class.isAssignableFrom(f.getType()) && ((f.getModifiers() & Modifier.STATIC)!=0);
- }});
- for (Field f: fields) {
- SetFromFlag cf = f.getAnnotation(SetFromFlag.class);
- if (cf != null) {
- ConfigKey<?> key = getFieldAsConfigKey(null, f);
- if (key != null) {
- result.put(key, cf);
- }
- }
- }
- return result;
- }
-
- /** returns a map of all fields which are annotated 'SetFromFlag' with their current values;
- * useful if you want to clone settings from one object
- */
- public static Map<String,Object> getFieldsWithValues(Object o) {
- try {
- Map<String, Object> result = Maps.newLinkedHashMap();
- for (Map.Entry<Field, SetFromFlag> entry : getAnnotatedFields(o.getClass()).entrySet()) {
- Field f = entry.getKey();
- SetFromFlag cf = entry.getValue();
- String flagName = elvis(cf.value(), f.getName());
- if (truth(flagName)) {
- if (!f.isAccessible()) f.setAccessible(true);
- result.put(flagName, f.get(o));
- }
- }
- return result;
- } catch (IllegalAccessException e) {
- throw Throwables.propagate(e);
- }
- }
-
- /**
- * @throws an IllegalStateException if there are fields required (nullable=false) which are unset
- * @throws wrapped IllegalAccessException
- */
- public static void checkRequiredFields(Object o) {
- try {
- Set<String> unsetFields = Sets.newLinkedHashSet();
- for (Map.Entry<Field, SetFromFlag> entry : getAnnotatedFields(o.getClass()).entrySet()) {
- Field f = entry.getKey();
- SetFromFlag cf = entry.getValue();
- if (!cf.nullable()) {
- String flagName = elvis(cf.value(), f.getName());
- if (!f.isAccessible()) f.setAccessible(true);
- Object v = f.get(o);
- if (v==null) unsetFields.add(flagName);
- }
- }
- if (truth(unsetFields)) {
- throw new IllegalStateException("Missing required "+(unsetFields.size()>1 ? "fields" : "field")+": "+unsetFields);
- }
- } catch (IllegalAccessException e) {
- throw Throwables.propagate(e);
- }
- }
-
-// /** sets all fields in target annotated with @SetFromFlag using the configuration in the given config bag */
-// public static void setFieldsFromConfigFlags(Object target, ConfigBag configBag) {
-// setFieldsFromConfigFlags(target, configBag.getAllConfig(), configBag);
-// }
-//
-//
-// /** sets all fields in target annotated with @SetFromFlag using the configuration in the given configToUse,
-// * marking used in the given configBag */
-// public static void setFieldsFromConfigFlags(Object target, Map<?,?> configToUse, ConfigBag configBag) {
-// for (Map.Entry<?,?> entry: configToUse.entrySet()) {
-// setFieldFromConfigFlag(target, entry.getKey(), entry.getValue(), configBag);
-// }
-// }
-//
-// public static void setFieldFromConfigFlag(Object target, Object key, Object value, ConfigBag optionalConfigBag) {
-// String name = null;
-// if (key instanceof String) name = (String)key;
-// else if (key instanceof ConfigKey<?>) name = ((ConfigKey<?>)key).getName();
-// else if (key instanceof HasConfigKey<?>) name = ((HasConfigKey<?>)key).getConfigKey().getName();
-// else {
-// if (key!=null) {
-// log.warn("Invalid config type "+key.getClass().getCanonicalName()+" ("+key+") when configuring "+target+"; ignoring");
-// }
-// return;
-// }
-// if (setFieldFromFlag(name, value, target)) {
-// if (optionalConfigBag!=null)
-// optionalConfigBag.markUsed(name);
-// }
-// }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/flags/MethodCoercions.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/flags/MethodCoercions.java b/core/src/main/java/brooklyn/util/flags/MethodCoercions.java
deleted file mode 100644
index c9f00fe..0000000
--- a/core/src/main/java/brooklyn/util/flags/MethodCoercions.java
+++ /dev/null
@@ -1,183 +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 brooklyn.util.flags;
-
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.guava.Maybe;
-import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Iterables;
-import com.google.common.reflect.TypeToken;
-
-import javax.annotation.Nullable;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Type;
-import java.util.Arrays;
-import java.util.List;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * A way of binding a loosely-specified method call into a strongly-typed Java method call.
- */
-public class MethodCoercions {
-
- /**
- * Returns a predicate that matches a method with the given name, and a single parameter that
- * {@link brooklyn.util.flags.TypeCoercions#tryCoerce(Object, com.google.common.reflect.TypeToken)} can process
- * from the given argument.
- *
- * @param methodName name of the method
- * @param argument argument that is intended to be given
- * @return a predicate that will match a compatible method
- */
- public static Predicate<Method> matchSingleParameterMethod(final String methodName, final Object argument) {
- checkNotNull(methodName, "methodName");
- checkNotNull(argument, "argument");
-
- return new Predicate<Method>() {
- @Override
- public boolean apply(@Nullable Method input) {
- if (input == null) return false;
- if (!input.getName().equals(methodName)) return false;
- Type[] parameterTypes = input.getGenericParameterTypes();
- return parameterTypes.length == 1
- && TypeCoercions.tryCoerce(argument, TypeToken.of(parameterTypes[0])).isPresentAndNonNull();
-
- }
- };
- }
-
- /**
- * Tries to find a single-parameter method with a parameter compatible with (can be coerced to) the argument, and
- * invokes it.
- *
- * @param instance the object to invoke the method on
- * @param methodName the name of the method to invoke
- * @param argument the argument to the method's parameter.
- * @return the result of the method call, or {@link brooklyn.util.guava.Maybe#absent()} if method could not be matched.
- */
- public static Maybe<?> tryFindAndInvokeSingleParameterMethod(final Object instance, final String methodName, final Object argument) {
- Class<?> clazz = instance.getClass();
- Iterable<Method> methods = Arrays.asList(clazz.getMethods());
- Optional<Method> matchingMethod = Iterables.tryFind(methods, matchSingleParameterMethod(methodName, argument));
- if (matchingMethod.isPresent()) {
- Method method = matchingMethod.get();
- try {
- Type paramType = method.getGenericParameterTypes()[0];
- Object coercedArgument = TypeCoercions.coerce(argument, TypeToken.of(paramType));
- return Maybe.of(method.invoke(instance, coercedArgument));
- } catch (IllegalAccessException | InvocationTargetException e) {
- throw Exceptions.propagate(e);
- }
- } else {
- return Maybe.absent();
- }
- }
-
- /**
- * Returns a predicate that matches a method with the given name, and parameters that
- * {@link brooklyn.util.flags.TypeCoercions#tryCoerce(Object, com.google.common.reflect.TypeToken)} can process
- * from the given list of arguments.
- *
- * @param methodName name of the method
- * @param arguments arguments that is intended to be given
- * @return a predicate that will match a compatible method
- */
- public static Predicate<Method> matchMultiParameterMethod(final String methodName, final List<?> arguments) {
- checkNotNull(methodName, "methodName");
- checkNotNull(arguments, "arguments");
-
- return new Predicate<Method>() {
- @Override
- public boolean apply(@Nullable Method input) {
- if (input == null) return false;
- if (!input.getName().equals(methodName)) return false;
- int numOptionParams = arguments.size();
- Type[] parameterTypes = input.getGenericParameterTypes();
- if (parameterTypes.length != numOptionParams) return false;
-
- for (int paramCount = 0; paramCount < numOptionParams; paramCount++) {
- if (!TypeCoercions.tryCoerce(((List) arguments).get(paramCount),
- TypeToken.of(parameterTypes[paramCount])).isPresentAndNonNull()) return false;
- }
- return true;
- }
- };
- }
-
- /**
- * Tries to find a multiple-parameter method with each parameter compatible with (can be coerced to) the
- * corresponding argument, and invokes it.
- *
- * @param instance the object to invoke the method on
- * @param methodName the name of the method to invoke
- * @param argument a list of the arguments to the method's parameters.
- * @return the result of the method call, or {@link brooklyn.util.guava.Maybe#absent()} if method could not be matched.
- */
- public static Maybe<?> tryFindAndInvokeMultiParameterMethod(final Object instance, final String methodName, final List<?> arguments) {
- Class<?> clazz = instance.getClass();
- Iterable<Method> methods = Arrays.asList(clazz.getMethods());
- Optional<Method> matchingMethod = Iterables.tryFind(methods, matchMultiParameterMethod(methodName, arguments));
- if (matchingMethod.isPresent()) {
- Method method = matchingMethod.get();
- try {
- int numOptionParams = ((List)arguments).size();
- Object[] coercedArguments = new Object[numOptionParams];
- for (int paramCount = 0; paramCount < numOptionParams; paramCount++) {
- Object argument = arguments.get(paramCount);
- Type paramType = method.getGenericParameterTypes()[paramCount];
- coercedArguments[paramCount] = TypeCoercions.coerce(argument, TypeToken.of(paramType));
- }
- return Maybe.of(method.invoke(instance, coercedArguments));
- } catch (IllegalAccessException | InvocationTargetException e) {
- throw Exceptions.propagate(e);
- }
- } else {
- return Maybe.absent();
- }
- }
-
- /**
- * Tries to find a method with each parameter compatible with (can be coerced to) the corresponding argument, and invokes it.
- *
- * @param instance the object to invoke the method on
- * @param methodName the name of the method to invoke
- * @param argument a list of the arguments to the method's parameters, or a single argument for a single-parameter method.
- * @return the result of the method call, or {@link brooklyn.util.guava.Maybe#absent()} if method could not be matched.
- */
- public static Maybe<?> tryFindAndInvokeBestMatchingMethod(final Object instance, final String methodName, final Object argument) {
- if (argument instanceof List) {
- List<?> arguments = (List<?>) argument;
-
- // ambiguous case: we can't tell if the user is using the multi-parameter syntax, or the single-parameter
- // syntax for a method which takes a List parameter. So we try one, then fall back to the other.
-
- Maybe<?> maybe = tryFindAndInvokeMultiParameterMethod(instance, methodName, arguments);
- if (maybe.isAbsent())
- maybe = tryFindAndInvokeSingleParameterMethod(instance, methodName, argument);
-
- return maybe;
- } else {
- return tryFindAndInvokeSingleParameterMethod(instance, methodName, argument);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/flags/SetFromFlag.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/flags/SetFromFlag.java b/core/src/main/java/brooklyn/util/flags/SetFromFlag.java
deleted file mode 100644
index c7d588e..0000000
--- a/core/src/main/java/brooklyn/util/flags/SetFromFlag.java
+++ /dev/null
@@ -1,71 +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 brooklyn.util.flags;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Annotation to indicate that a variable may be set through the use of a named argument,
- * looking for the name specified here or inferred from the annotated field/argument/object.
- * <p>
- * This is used to automate the processing where named arguments are passed in constructors
- * and other methods, and the values of those named arguments should be transferred to
- * other known fields/arguments/objects at runtime.
- * <p>
- * Fields on a class are typically set from values in a map with a call to
- * {@link FlagUtils#setFieldsFromFlags(java.util.Map, Object)}.
- * That method (and related, in the same class) will attend to the arguments here.
- */
-@Retention(RetentionPolicy.RUNTIME)
-public @interface SetFromFlag {
-
- /** the flag (key) which should be used to find the value; if empty defaults to field/argument/object name */
- String value() default "";
-
- /** whether the object should not be changed once set; defaults to false
- * <p>
- * this is partially tested for in many routines, but not all;
- * when nullable=false the testing (when done) is guaranteed.
- * however if nullable is allowed we do not distinguish between null and unset
- * so explicitly setting null then setting to a value is not detected as an illegal mutating.
- */
- boolean immutable() default false;
-
- /** whether the object is required & should not be set to null; defaults to true.
- * (there is no 'required' parameter, but setting nullable false then invoking
- * e.g. {@link FlagUtils#checkRequiredFields(Object)} has the effect of requiring a value)
- * <p>
- * code should call that method explicitly to enforce nullable false;
- * errors are not done during a call to setFieldsFromFlags
- * because fields may be initialised in multiple passes.)
- * <p>
- * this is partially tested for in many routines, but not all
- */
- boolean nullable() default true;
-
- /** The default value, if it is not explicitly set.
- * <p>
- * The value will be coerced from String where required, for types supported by {@link TypeCoercions}.
- * <p>
- * The field will be initialised with its default value on the first call to setFieldsFromFlags
- * (or related). (The field will not be initialised if that method is not called.)
- */
- String defaultVal() default "";
-}
[03/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/policy
Posted by ha...@apache.org.
[BROOKLYN-162] Refactor package in ./core/policy
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/6eacb3c3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/6eacb3c3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/6eacb3c3
Branch: refs/heads/master
Commit: 6eacb3c38337d3c8733221b89b42fea3cdd93a23
Parents: a4c0e5f
Author: Hadrian Zbarcea <ha...@apache.org>
Authored: Mon Aug 17 02:03:16 2015 -0400
Committer: Hadrian Zbarcea <ha...@apache.org>
Committed: Mon Aug 17 14:52:04 2015 -0400
----------------------------------------------------------------------
.../main/java/brooklyn/basic/BrooklynTypes.java | 2 +-
.../enricher/basic/AbstractEnricher.java | 2 +-
.../brooklyn/entity/basic/AbstractEntity.java | 6 +-
.../group/AbstractMembershipTrackingPolicy.java | 2 +-
.../entity/proxying/InternalEntityFactory.java | 2 +-
.../entity/proxying/InternalPolicyFactory.java | 2 +-
.../AbstractBrooklynObjectRebindSupport.java | 2 +-
.../entity/rebind/BasicEntityRebindSupport.java | 2 +-
.../entity/rebind/BasicPolicyRebindSupport.java | 3 +-
.../brooklyn/entity/rebind/RebindIteration.java | 2 +-
.../entity/rebind/dto/MementosGenerators.java | 2 +-
.../java/brooklyn/event/feed/AbstractFeed.java | 2 +-
.../policy/basic/AbstractEntityAdjunct.java | 510 -------------------
.../brooklyn/policy/basic/AbstractPolicy.java | 119 -----
.../java/brooklyn/policy/basic/AdjunctType.java | 174 -------
.../brooklyn/policy/basic/ConfigMapImpl.java | 140 -----
.../policy/basic/GeneralPurposePolicy.java | 36 --
.../java/brooklyn/policy/basic/Policies.java | 73 ---
.../policy/basic/PolicyDynamicType.java | 44 --
.../policy/basic/PolicyTypeSnapshot.java | 40 --
.../policy/basic/AbstractEntityAdjunct.java | 510 +++++++++++++++++++
.../core/policy/basic/AbstractPolicy.java | 119 +++++
.../brooklyn/core/policy/basic/AdjunctType.java | 174 +++++++
.../core/policy/basic/ConfigMapImpl.java | 140 +++++
.../core/policy/basic/GeneralPurposePolicy.java | 36 ++
.../brooklyn/core/policy/basic/Policies.java | 73 +++
.../core/policy/basic/PolicyDynamicType.java | 44 ++
.../core/policy/basic/PolicyTypeSnapshot.java | 40 ++
.../entity/EntityPreManagementTest.java | 2 +-
.../brooklyn/entity/basic/EntitySpecTest.java | 2 +-
.../entity/basic/PolicyRegistrationTest.java | 2 +-
.../entity/group/GroupPickUpEntitiesTest.java | 2 +-
.../entity/rebind/RebindCatalogItemTest.java | 3 +-
.../entity/rebind/RebindFailuresTest.java | 2 +-
.../entity/rebind/RebindPolicyTest.java | 2 +-
.../brooklyn/policy/basic/BasicPolicyTest.java | 89 ----
.../brooklyn/policy/basic/EnricherTypeTest.java | 59 ---
.../brooklyn/policy/basic/PolicyConfigTest.java | 202 --------
.../policy/basic/PolicySubscriptionTest.java | 125 -----
.../brooklyn/policy/basic/PolicyTypeTest.java | 58 ---
.../java/brooklyn/test/policy/TestPolicy.java | 2 +-
.../core/policy/basic/BasicPolicyTest.java | 90 ++++
.../core/policy/basic/EnricherTypeTest.java | 59 +++
.../core/policy/basic/PolicyConfigTest.java | 202 ++++++++
.../policy/basic/PolicySubscriptionTest.java | 128 +++++
.../core/policy/basic/PolicyTypeTest.java | 59 +++
.../policy/os/AdvertiseWinrmLoginPolicy.java | 3 +-
.../brooklyn/policy/os/CreateUserPolicy.java | 2 +-
.../policy/autoscaling/AutoScalerPolicy.java | 2 +-
.../policy/followthesun/FollowTheSunPolicy.java | 2 +-
.../policy/ha/AbstractFailureDetector.java | 2 +-
.../policy/ha/ConditionalSuspendPolicy.java | 2 +-
.../brooklyn/policy/ha/ServiceReplacer.java | 2 +-
.../brooklyn/policy/ha/ServiceRestarter.java | 2 +-
.../loadbalancing/LoadBalancingPolicy.java | 2 +-
.../camp/brooklyn/TestReferencingPolicy.java | 2 +-
.../apache/brooklyn/cli/lister/ClassFinder.java | 2 +-
.../brooklyn/rest/resources/PolicyResource.java | 4 +-
.../rest/transform/PolicyTransformer.java | 2 +-
.../rest/util/BrooklynRestResourceUtils.java | 2 +-
.../rest/testing/mocks/CapitalizePolicy.java | 3 +-
.../testing/mocks/RestMockSimplePolicy.java | 2 +-
.../util/BrooklynRestResourceUtilsTest.java | 2 +-
.../java/brooklyn/osgi/tests/SimplePolicy.java | 2 +-
.../brooklyn/osgi/tests/more/MorePolicy.java | 3 +-
.../brooklyn/osgi/tests/more/MorePolicy.java | 2 +-
66 files changed, 1716 insertions(+), 1718 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/main/java/brooklyn/basic/BrooklynTypes.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/basic/BrooklynTypes.java b/core/src/main/java/brooklyn/basic/BrooklynTypes.java
index 64dbcd0..780349f 100644
--- a/core/src/main/java/brooklyn/basic/BrooklynTypes.java
+++ b/core/src/main/java/brooklyn/basic/BrooklynTypes.java
@@ -26,11 +26,11 @@ import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.policy.basic.PolicyDynamicType;
import brooklyn.config.ConfigKey;
import brooklyn.enricher.basic.EnricherDynamicType;
import brooklyn.entity.basic.EntityDynamicType;
-import brooklyn.policy.basic.PolicyDynamicType;
import brooklyn.util.exceptions.Exceptions;
import com.google.common.collect.Maps;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/main/java/brooklyn/enricher/basic/AbstractEnricher.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/enricher/basic/AbstractEnricher.java b/core/src/main/java/brooklyn/enricher/basic/AbstractEnricher.java
index 5bca143..651ea56 100644
--- a/core/src/main/java/brooklyn/enricher/basic/AbstractEnricher.java
+++ b/core/src/main/java/brooklyn/enricher/basic/AbstractEnricher.java
@@ -29,6 +29,7 @@ import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.mementos.EnricherMemento;
import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.EnricherType;
+import org.apache.brooklyn.core.policy.basic.AbstractEntityAdjunct;
import org.apache.brooklyn.core.util.flags.TypeCoercions;
import brooklyn.config.ConfigKey;
@@ -36,7 +37,6 @@ import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.rebind.BasicEnricherRebindSupport;
-import brooklyn.policy.basic.AbstractEntityAdjunct;
import com.google.common.base.Objects;
import com.google.common.collect.Maps;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java b/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
index 4bdae46..b004754 100644
--- a/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
+++ b/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
@@ -60,6 +60,9 @@ import org.apache.brooklyn.core.management.internal.EffectorUtils;
import org.apache.brooklyn.core.management.internal.EntityManagementSupport;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.core.management.internal.SubscriptionTracker;
+import org.apache.brooklyn.core.policy.basic.AbstractEntityAdjunct;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
+import org.apache.brooklyn.core.policy.basic.AbstractEntityAdjunct.AdjunctTagSupport;
import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.core.util.flags.FlagUtils;
import org.apache.brooklyn.core.util.flags.TypeCoercions;
@@ -88,9 +91,6 @@ import brooklyn.internal.storage.impl.BasicReference;
import org.apache.brooklyn.location.basic.Locations;
-import brooklyn.policy.basic.AbstractEntityAdjunct;
-import brooklyn.policy.basic.AbstractEntityAdjunct.AdjunctTagSupport;
-import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/main/java/brooklyn/entity/group/AbstractMembershipTrackingPolicy.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/group/AbstractMembershipTrackingPolicy.java b/core/src/main/java/brooklyn/entity/group/AbstractMembershipTrackingPolicy.java
index 5647975..400506f 100644
--- a/core/src/main/java/brooklyn/entity/group/AbstractMembershipTrackingPolicy.java
+++ b/core/src/main/java/brooklyn/entity/group/AbstractMembershipTrackingPolicy.java
@@ -29,6 +29,7 @@ import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -37,7 +38,6 @@ import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.Attributes;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.DynamicGroup;
-import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.javalang.JavaClassNames;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java b/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
index 1c1a920..eb601ed 100644
--- a/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
+++ b/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
@@ -37,6 +37,7 @@ import org.apache.brooklyn.api.policy.EnricherSpec;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import org.apache.brooklyn.core.util.flags.FlagUtils;
import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
@@ -48,7 +49,6 @@ import brooklyn.entity.basic.AbstractEntity;
import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityInternal;
-import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
import brooklyn.util.exceptions.Exceptions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/main/java/brooklyn/entity/proxying/InternalPolicyFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/proxying/InternalPolicyFactory.java b/core/src/main/java/brooklyn/entity/proxying/InternalPolicyFactory.java
index 7c53404..c174dcb 100644
--- a/core/src/main/java/brooklyn/entity/proxying/InternalPolicyFactory.java
+++ b/core/src/main/java/brooklyn/entity/proxying/InternalPolicyFactory.java
@@ -27,12 +27,12 @@ import org.apache.brooklyn.api.policy.EnricherSpec;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import org.apache.brooklyn.core.util.config.ConfigBag;
import brooklyn.config.ConfigKey;
import brooklyn.enricher.basic.AbstractEnricher;
import brooklyn.entity.basic.AbstractEntity;
-import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/main/java/brooklyn/entity/rebind/AbstractBrooklynObjectRebindSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/AbstractBrooklynObjectRebindSupport.java b/core/src/main/java/brooklyn/entity/rebind/AbstractBrooklynObjectRebindSupport.java
index 19a6cd6..000a651 100644
--- a/core/src/main/java/brooklyn/entity/rebind/AbstractBrooklynObjectRebindSupport.java
+++ b/core/src/main/java/brooklyn/entity/rebind/AbstractBrooklynObjectRebindSupport.java
@@ -22,12 +22,12 @@ import org.apache.brooklyn.api.entity.rebind.RebindContext;
import org.apache.brooklyn.api.entity.rebind.RebindSupport;
import org.apache.brooklyn.api.mementos.Memento;
import org.apache.brooklyn.api.policy.EntityAdjunct;
+import org.apache.brooklyn.core.policy.basic.AbstractEntityAdjunct.AdjunctTagSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.basic.AbstractBrooklynObject;
import brooklyn.entity.rebind.dto.MementosGenerators;
-import brooklyn.policy.basic.AbstractEntityAdjunct.AdjunctTagSupport;
import brooklyn.util.text.Strings;
public abstract class AbstractBrooklynObjectRebindSupport<T extends Memento> implements RebindSupport<T> {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/main/java/brooklyn/entity/rebind/BasicEntityRebindSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/BasicEntityRebindSupport.java b/core/src/main/java/brooklyn/entity/rebind/BasicEntityRebindSupport.java
index 3a29595..f059a83 100644
--- a/core/src/main/java/brooklyn/entity/rebind/BasicEntityRebindSupport.java
+++ b/core/src/main/java/brooklyn/entity/rebind/BasicEntityRebindSupport.java
@@ -31,6 +31,7 @@ import org.apache.brooklyn.api.entity.rebind.RebindContext;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.mementos.EntityMemento;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -41,7 +42,6 @@ import brooklyn.entity.basic.AbstractGroupImpl;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.rebind.dto.MementosGenerators;
import brooklyn.event.feed.AbstractFeed;
-import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.util.exceptions.Exceptions;
import com.google.common.base.Throwables;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/main/java/brooklyn/entity/rebind/BasicPolicyRebindSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/BasicPolicyRebindSupport.java b/core/src/main/java/brooklyn/entity/rebind/BasicPolicyRebindSupport.java
index 4623225..e511ce2 100644
--- a/core/src/main/java/brooklyn/entity/rebind/BasicPolicyRebindSupport.java
+++ b/core/src/main/java/brooklyn/entity/rebind/BasicPolicyRebindSupport.java
@@ -20,11 +20,10 @@ package brooklyn.entity.rebind;
import org.apache.brooklyn.api.entity.rebind.RebindContext;
import org.apache.brooklyn.api.mementos.PolicyMemento;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.core.util.flags.FlagUtils;
-import brooklyn.policy.basic.AbstractPolicy;
-
public class BasicPolicyRebindSupport extends AbstractBrooklynObjectRebindSupport<PolicyMemento> {
private final AbstractPolicy policy;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java b/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
index 67d20ae..eb1a461 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
@@ -73,6 +73,7 @@ import org.apache.brooklyn.core.management.internal.EntityManagerInternal;
import org.apache.brooklyn.core.management.internal.LocationManagerInternal;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.core.management.internal.ManagementTransitionMode;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import org.apache.brooklyn.core.util.flags.FlagUtils;
import brooklyn.config.BrooklynLogging;
@@ -92,7 +93,6 @@ import brooklyn.event.feed.AbstractFeed;
import org.apache.brooklyn.location.basic.AbstractLocation;
import org.apache.brooklyn.location.basic.LocationInternal;
-import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java b/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java
index 5c52788..301211d 100644
--- a/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java
+++ b/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java
@@ -50,6 +50,7 @@ import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.EntityAdjunct;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.core.catalog.internal.CatalogItemDo;
+import org.apache.brooklyn.core.policy.basic.AbstractPolicy;
import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.core.util.flags.FlagUtils;
@@ -64,7 +65,6 @@ import brooklyn.event.feed.AbstractFeed;
import org.apache.brooklyn.location.basic.LocationInternal;
-import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.util.collections.MutableMap;
import com.google.common.annotations.Beta;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/main/java/brooklyn/event/feed/AbstractFeed.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/feed/AbstractFeed.java b/core/src/main/java/brooklyn/event/feed/AbstractFeed.java
index 23037a7..59ed4f7 100644
--- a/core/src/main/java/brooklyn/event/feed/AbstractFeed.java
+++ b/core/src/main/java/brooklyn/event/feed/AbstractFeed.java
@@ -27,6 +27,7 @@ import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.entity.rebind.RebindSupport;
import org.apache.brooklyn.api.mementos.FeedMemento;
import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
+import org.apache.brooklyn.core.policy.basic.AbstractEntityAdjunct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -34,7 +35,6 @@ import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.rebind.BasicFeedRebindSupport;
-import brooklyn.policy.basic.AbstractEntityAdjunct;
import brooklyn.util.javalang.JavaClassNames;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java b/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
deleted file mode 100644
index afa015f..0000000
--- a/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
+++ /dev/null
@@ -1,510 +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 brooklyn.policy.basic;
-
-import static brooklyn.util.GroovyJavaMethods.truth;
-import static com.google.common.base.Preconditions.checkState;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.Group;
-import org.apache.brooklyn.api.entity.basic.EntityLocal;
-import org.apache.brooklyn.api.entity.trait.Configurable;
-import org.apache.brooklyn.api.event.AttributeSensor;
-import org.apache.brooklyn.api.event.Sensor;
-import org.apache.brooklyn.api.event.SensorEventListener;
-import org.apache.brooklyn.api.management.ExecutionContext;
-import org.apache.brooklyn.api.management.SubscriptionContext;
-import org.apache.brooklyn.api.management.SubscriptionHandle;
-import org.apache.brooklyn.api.management.Task;
-import org.apache.brooklyn.api.policy.EntityAdjunct;
-import org.apache.brooklyn.core.management.internal.SubscriptionTracker;
-import org.apache.brooklyn.core.util.config.ConfigBag;
-import org.apache.brooklyn.core.util.flags.FlagUtils;
-import org.apache.brooklyn.core.util.flags.SetFromFlag;
-import org.apache.brooklyn.core.util.flags.TypeCoercions;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.basic.AbstractBrooklynObject;
-import brooklyn.basic.BrooklynObjectInternal;
-import brooklyn.config.ConfigKey;
-import brooklyn.config.ConfigKey.HasConfigKey;
-import brooklyn.config.ConfigMap;
-import brooklyn.enricher.basic.AbstractEnricher;
-import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.entity.basic.Entities;
-import brooklyn.entity.basic.EntityInternal;
-import brooklyn.util.guava.Maybe;
-import brooklyn.util.text.Strings;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Maps;
-
-
-/**
- * Common functionality for policies and enrichers
- */
-public abstract class AbstractEntityAdjunct extends AbstractBrooklynObject implements BrooklynObjectInternal, EntityAdjunct, Configurable {
- private static final Logger log = LoggerFactory.getLogger(AbstractEntityAdjunct.class);
-
- private boolean _legacyNoConstructionInit;
-
- /**
- * @deprecated since 0.7.0; leftover properties are put into config, since when coming from yaml this is normal.
- */
- @Deprecated
- protected Map<String,Object> leftoverProperties = Maps.newLinkedHashMap();
-
- protected transient ExecutionContext execution;
-
- private final BasicConfigurationSupport config = new BasicConfigurationSupport();
-
- /**
- * The config values of this entity. Updating this map should be done
- * via {@link #config()}.
- *
- * @deprecated since 0.7.0; use {@link #config()} instead; this field may be made private or deleted in a future release.
- */
- @Deprecated
- protected final ConfigMapImpl configsInternal = new ConfigMapImpl(this);
-
- /**
- * @deprecated since 0.7.0; use {@link #getAdjunctType()} instead; this field may be made private or deleted in a future release.
- */
- @Deprecated
- protected final AdjunctType adjunctType = new AdjunctType(this);
-
- @SetFromFlag
- protected String name;
-
- protected transient EntityLocal entity;
-
- /** not for direct access; refer to as 'subscriptionTracker' via getter so that it is initialized */
- protected transient SubscriptionTracker _subscriptionTracker;
-
- private AtomicBoolean destroyed = new AtomicBoolean(false);
-
- @SetFromFlag(value="uniqueTag")
- protected String uniqueTag;
-
- public AbstractEntityAdjunct() {
- this(Collections.emptyMap());
- }
-
- public AbstractEntityAdjunct(@SuppressWarnings("rawtypes") Map properties) {
- super(properties);
- _legacyNoConstructionInit = (properties != null) && Boolean.TRUE.equals(properties.get("noConstructionInit"));
-
- if (isLegacyConstruction()) {
- AbstractBrooklynObject checkWeGetThis = configure(properties);
- assert this.equals(checkWeGetThis) : this+" configure method does not return itself; returns "+checkWeGetThis+" instead of "+this;
-
- boolean deferConstructionChecks = (properties.containsKey("deferConstructionChecks") && TypeCoercions.coerce(properties.get("deferConstructionChecks"), Boolean.class));
- if (!deferConstructionChecks) {
- FlagUtils.checkRequiredFields(this);
- }
- }
- }
-
- /**
- * @deprecated since 0.7.0; only used for legacy brooklyn types where constructor is called directly
- */
- @Override
- @Deprecated
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public AbstractEntityAdjunct configure(Map flags) {
- // TODO only set on first time through
- boolean isFirstTime = true;
-
- // allow config keys, and fields, to be set from these flags if they have a SetFromFlag annotation
- // or if the value is a config key
- for (Iterator<Map.Entry> iter = flags.entrySet().iterator(); iter.hasNext();) {
- Map.Entry entry = iter.next();
- if (entry.getKey() instanceof ConfigKey) {
- ConfigKey key = (ConfigKey)entry.getKey();
- if (adjunctType.getConfigKeys().contains(key)) {
- setConfig(key, entry.getValue());
- } else {
- log.warn("Unknown configuration key {} for policy {}; ignoring", key, this);
- iter.remove();
- }
- }
- }
-
- ConfigBag bag = new ConfigBag().putAll(flags);
- FlagUtils.setFieldsFromFlags(this, bag, isFirstTime);
- FlagUtils.setAllConfigKeys(this, bag, false);
- leftoverProperties.putAll(bag.getUnusedConfig());
-
- //replace properties _contents_ with leftovers so subclasses see leftovers only
- flags.clear();
- flags.putAll(leftoverProperties);
- leftoverProperties = flags;
-
- if (!truth(name) && flags.containsKey("displayName")) {
- //TODO inconsistent with entity and location, where name is legacy and displayName is encouraged!
- //'displayName' is a legacy way to refer to a policy's name
- Preconditions.checkArgument(flags.get("displayName") instanceof CharSequence, "'displayName' property should be a string");
- setDisplayName(flags.remove("displayName").toString());
- }
-
- // set leftover flags should as config items; particularly useful when these have come from a brooklyn.config map
- for (Object flag: flags.keySet()) {
- ConfigKey<Object> key = ConfigKeys.newConfigKey(Object.class, Strings.toString(flag));
- if (config().getRaw(key).isPresent()) {
- log.warn("Config '"+flag+"' on "+this+" conflicts with key already set; ignoring");
- } else {
- config().set(key, flags.get(flag));
- }
- }
-
- return this;
- }
-
- /**
- * Used for legacy-style policies/enrichers on rebind, to indicate that init() should not be called.
- * Will likely be deleted in a future release; should not be called apart from by framework code.
- */
- @Beta
- protected boolean isLegacyNoConstructionInit() {
- return _legacyNoConstructionInit;
- }
-
- @Override
- public ConfigurationSupportInternal config() {
- return config;
- }
-
- private class BasicConfigurationSupport implements ConfigurationSupportInternal {
-
- @Override
- public <T> T get(ConfigKey<T> key) {
- return configsInternal.getConfig(key);
- }
-
- @Override
- public <T> T get(HasConfigKey<T> key) {
- return get(key.getConfigKey());
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public <T> T set(ConfigKey<T> key, T val) {
- if (entity != null && isRunning()) {
- doReconfigureConfig(key, val);
- }
- T result = (T) configsInternal.setConfig(key, val);
- onChanged();
- return result;
- }
-
- @Override
- public <T> T set(HasConfigKey<T> key, T val) {
- return setConfig(key.getConfigKey(), val);
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public <T> T set(ConfigKey<T> key, Task<T> val) {
- if (entity != null && isRunning()) {
- // TODO Support for AbstractEntityAdjunct
- throw new UnsupportedOperationException();
- }
- T result = (T) configsInternal.setConfig(key, val);
- onChanged();
- return result;
- }
-
- @Override
- public <T> T set(HasConfigKey<T> key, Task<T> val) {
- return set(key.getConfigKey(), val);
- }
-
- @Override
- public ConfigBag getBag() {
- return getLocalBag();
- }
-
- @Override
- public ConfigBag getLocalBag() {
- return ConfigBag.newInstance(configsInternal.getAllConfig());
- }
-
- @Override
- public Maybe<Object> getRaw(ConfigKey<?> key) {
- return configsInternal.getConfigRaw(key, true);
- }
-
- @Override
- public Maybe<Object> getRaw(HasConfigKey<?> key) {
- return getRaw(key.getConfigKey());
- }
-
- @Override
- public Maybe<Object> getLocalRaw(ConfigKey<?> key) {
- return configsInternal.getConfigRaw(key, false);
- }
-
- @Override
- public Maybe<Object> getLocalRaw(HasConfigKey<?> key) {
- return getLocalRaw(key.getConfigKey());
- }
-
- @Override
- public void addToLocalBag(Map<String, ?> vals) {
- configsInternal.addToLocalBag(vals);
- }
-
- @Override
- public void removeFromLocalBag(String key) {
- configsInternal.removeFromLocalBag(key);
- }
-
- @Override
- public void refreshInheritedConfig() {
- // no-op for location
- }
-
- @Override
- public void refreshInheritedConfigOfChildren() {
- // no-op for location
- }
- }
-
- public <T> T getConfig(ConfigKey<T> key) {
- return config().get(key);
- }
-
- protected <K> K getRequiredConfig(ConfigKey<K> key) {
- K result = config().get(key);
- if (result==null)
- throw new NullPointerException("Value required for '"+key.getName()+"' in "+this);
- return result;
- }
-
- @Override
- @Deprecated
- public <T> T setConfig(ConfigKey<T> key, T val) {
- return config().set(key, val);
- }
-
- // TODO make immutable
- /** for inspection only */
- @Beta
- @Deprecated
- public ConfigMap getConfigMap() {
- return configsInternal;
- }
-
- /**
- * Invoked whenever a config change is applied after management is started.
- * Default implementation throws an exception to disallow the change.
- * Can be overridden to return (allowing the change) or to make other changes
- * (if necessary), and of course it can do this selectively and call the super to disallow any others. */
- protected <T> void doReconfigureConfig(ConfigKey<T> key, T val) {
- throw new UnsupportedOperationException("reconfiguring "+key+" unsupported for "+this);
- }
-
- @Override
- protected void onTagsChanged() {
- onChanged();
- }
-
- protected abstract void onChanged();
-
- protected AdjunctType getAdjunctType() {
- return adjunctType;
- }
-
- @Override
- public String getDisplayName() {
- if (name!=null && name.length()>0) return name;
- return getClass().getCanonicalName();
- }
-
- public void setDisplayName(String name) {
- this.name = name;
- }
-
- public void setEntity(EntityLocal entity) {
- if (destroyed.get()) throw new IllegalStateException("Cannot set entity on a destroyed entity adjunct");
- this.entity = entity;
- if (entity!=null && getCatalogItemId() == null) {
- setCatalogItemId(entity.getCatalogItemId());
- }
- }
-
- /** @deprecated since 0.7.0 only {@link AbstractEnricher} has emit convenience */
- protected <T> void emit(Sensor<T> sensor, Object val) {
- checkState(entity != null, "entity must first be set");
- if (val == Entities.UNCHANGED) {
- return;
- }
- if (val == Entities.REMOVE) {
- ((EntityInternal)entity).removeAttribute((AttributeSensor<T>) sensor);
- return;
- }
-
- T newVal = TypeCoercions.coerce(val, sensor.getTypeToken());
- if (sensor instanceof AttributeSensor) {
- entity.setAttribute((AttributeSensor<T>)sensor, newVal);
- } else {
- entity.emit(sensor, newVal);
- }
- }
-
- protected synchronized SubscriptionTracker getSubscriptionTracker() {
- if (_subscriptionTracker!=null) return _subscriptionTracker;
- if (entity==null) return null;
- _subscriptionTracker = new SubscriptionTracker(((EntityInternal)entity).getManagementSupport().getSubscriptionContext());
- return _subscriptionTracker;
- }
-
- /** @see SubscriptionContext#subscribe(Entity, Sensor, SensorEventListener) */
- protected <T> SubscriptionHandle subscribe(Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener) {
- if (!checkCanSubscribe()) return null;
- return getSubscriptionTracker().subscribe(producer, sensor, listener);
- }
-
- /** @see SubscriptionContext#subscribe(Entity, Sensor, SensorEventListener) */
- protected <T> SubscriptionHandle subscribeToMembers(Group producerGroup, Sensor<T> sensor, SensorEventListener<? super T> listener) {
- if (!checkCanSubscribe(producerGroup)) return null;
- return getSubscriptionTracker().subscribeToMembers(producerGroup, sensor, listener);
- }
-
- /** @see SubscriptionContext#subscribe(Entity, Sensor, SensorEventListener) */
- protected <T> SubscriptionHandle subscribeToChildren(Entity producerParent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
- if (!checkCanSubscribe(producerParent)) return null;
- return getSubscriptionTracker().subscribeToChildren(producerParent, sensor, listener);
- }
-
- /** @deprecated since 0.7.0 use {@link #checkCanSubscribe(Entity)} */
- @Deprecated
- protected boolean check(Entity requiredEntity) {
- return checkCanSubscribe(requiredEntity);
- }
- /** returns false if deleted, throws exception if invalid state, otherwise true.
- * okay if entity is not yet managed (but not if entity is no longer managed). */
- protected boolean checkCanSubscribe(Entity producer) {
- if (destroyed.get()) return false;
- if (producer==null) throw new IllegalStateException(this+" given a null target for subscription");
- if (entity==null) throw new IllegalStateException(this+" cannot subscribe to "+producer+" because it is not associated to an entity");
- if (((EntityInternal)entity).getManagementSupport().isNoLongerManaged()) throw new IllegalStateException(this+" cannot subscribe to "+producer+" because the associated entity "+entity+" is no longer managed");
- return true;
- }
- protected boolean checkCanSubscribe() {
- if (destroyed.get()) return false;
- if (entity==null) throw new IllegalStateException(this+" cannot subscribe because it is not associated to an entity");
- if (((EntityInternal)entity).getManagementSupport().isNoLongerManaged()) throw new IllegalStateException(this+" cannot subscribe because the associated entity "+entity+" is no longer managed");
- return true;
- }
-
- /**
- * Unsubscribes the given producer.
- *
- * @see SubscriptionContext#unsubscribe(SubscriptionHandle)
- */
- protected boolean unsubscribe(Entity producer) {
- if (destroyed.get()) return false;
- return getSubscriptionTracker().unsubscribe(producer);
- }
-
- /**
- * Unsubscribes the given producer.
- *
- * @see SubscriptionContext#unsubscribe(SubscriptionHandle)
- */
- protected boolean unsubscribe(Entity producer, SubscriptionHandle handle) {
- if (destroyed.get()) return false;
- return getSubscriptionTracker().unsubscribe(producer, handle);
- }
-
- /**
- * @return a list of all subscription handles
- */
- protected Collection<SubscriptionHandle> getAllSubscriptions() {
- SubscriptionTracker tracker = getSubscriptionTracker();
- return (tracker != null) ? tracker.getAllSubscriptions() : Collections.<SubscriptionHandle>emptyList();
- }
-
- /**
- * Unsubscribes and clears all managed subscriptions; is called by the owning entity when a policy is removed
- * and should always be called by any subclasses overriding this method
- */
- public void destroy() {
- destroyed.set(true);
- SubscriptionTracker tracker = getSubscriptionTracker();
- if (tracker != null) tracker.unsubscribeAll();
- }
-
- @Override
- public boolean isDestroyed() {
- return destroyed.get();
- }
-
- @Override
- public boolean isRunning() {
- return !isDestroyed();
- }
-
- @Override
- public String getUniqueTag() {
- return uniqueTag;
- }
-
- public TagSupport tags() {
- return new AdjunctTagSupport();
- }
-
- public class AdjunctTagSupport extends BasicTagSupport {
- @Override
- public Set<Object> getTags() {
- ImmutableSet.Builder<Object> rb = ImmutableSet.builder().addAll(super.getTags());
- if (getUniqueTag()!=null) rb.add(getUniqueTag());
- return rb.build();
- }
- public String getUniqueTag() {
- return AbstractEntityAdjunct.this.getUniqueTag();
- }
- public void setUniqueTag(String uniqueTag) {
- AbstractEntityAdjunct.this.uniqueTag = uniqueTag;
- }
- }
-
- @Override
- public String toString() {
- return Objects.toStringHelper(getClass()).omitNullValues()
- .add("name", name)
- .add("uniqueTag", uniqueTag)
- .add("running", isRunning())
- .add("entity", entity)
- .add("id", getId())
- .toString();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/main/java/brooklyn/policy/basic/AbstractPolicy.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/policy/basic/AbstractPolicy.java b/core/src/main/java/brooklyn/policy/basic/AbstractPolicy.java
deleted file mode 100644
index e935e4b..0000000
--- a/core/src/main/java/brooklyn/policy/basic/AbstractPolicy.java
+++ /dev/null
@@ -1,119 +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 brooklyn.policy.basic;
-
-import java.util.Collections;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.apache.brooklyn.api.entity.rebind.RebindSupport;
-import org.apache.brooklyn.api.entity.trait.Configurable;
-import org.apache.brooklyn.api.mementos.PolicyMemento;
-import org.apache.brooklyn.api.policy.Policy;
-import org.apache.brooklyn.api.policy.PolicyType;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.entity.rebind.BasicPolicyRebindSupport;
-
-import com.google.common.base.Objects;
-
-/**
- * Base {@link Policy} implementation; all policies should extend this or its children
- */
-public abstract class AbstractPolicy extends AbstractEntityAdjunct implements Policy, Configurable {
- @SuppressWarnings("unused")
- private static final Logger log = LoggerFactory.getLogger(AbstractPolicy.class);
-
- protected String policyStatus;
- protected AtomicBoolean suspended = new AtomicBoolean(false);
-
- private final PolicyDynamicType policyType;
-
- public AbstractPolicy() {
- this(Collections.emptyMap());
- }
-
- public AbstractPolicy(Map<?,?> flags) {
- super(flags);
-
- // TODO Don't let `this` reference escape during construction
- policyType = new PolicyDynamicType(this);
-
- if (isLegacyConstruction() && !isLegacyNoConstructionInit()) {
- init();
- }
- }
-
- @Override
- public PolicyType getPolicyType() {
- return policyType.getSnapshot();
- }
-
- @Override
- public void suspend() {
- suspended.set(true);
- }
-
- @Override
- public void resume() {
- suspended.set(false);
- }
-
- @Override
- public boolean isSuspended() {
- if (suspended==null) {
- // only if accessed during construction in super, e.g. by a call to toString in configure
- return true;
- }
- return suspended.get();
- }
-
- @Override
- public void destroy(){
- suspend();
- super.destroy();
- }
-
- @Override
- public boolean isRunning() {
- return !isSuspended() && !isDestroyed();
- }
-
- @Override
- protected void onChanged() {
- // currently changes simply trigger re-persistence; there is no intermediate listener as we do for EntityChangeListener
- if (getManagementContext() != null) {
- getManagementContext().getRebindManager().getChangeListener().onChanged(this);
- }
- }
-
- @Override
- public RebindSupport<PolicyMemento> getRebindSupport() {
- return new BasicPolicyRebindSupport(this);
- }
-
- @Override
- public String toString() {
- return Objects.toStringHelper(getClass())
- .add("name", name)
- .add("running", isRunning())
- .toString();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/main/java/brooklyn/policy/basic/AdjunctType.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/policy/basic/AdjunctType.java b/core/src/main/java/brooklyn/policy/basic/AdjunctType.java
deleted file mode 100644
index f53f822..0000000
--- a/core/src/main/java/brooklyn/policy/basic/AdjunctType.java
+++ /dev/null
@@ -1,174 +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 brooklyn.policy.basic;
-
-import java.io.Serializable;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.brooklyn.api.policy.EntityAdjunct;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.config.ConfigKey.HasConfigKey;
-
-import com.google.common.base.Joiner;
-import com.google.common.base.Objects;
-import com.google.common.base.Throwables;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Maps;
-
-/**
- * This is the actual type of a policy instance at runtime.
- */
-public class AdjunctType implements Serializable {
- private static final long serialVersionUID = -662979234559595903L;
-
- private static final Logger LOG = LoggerFactory.getLogger(AdjunctType.class);
-
- private final String name;
- private final Map<String, ConfigKey<?>> configKeys;
- private final Set<ConfigKey<?>> configKeysSet;
-
- public AdjunctType(AbstractEntityAdjunct adjunct) {
- this(adjunct.getClass(), adjunct);
- }
-
- protected AdjunctType(Class<? extends EntityAdjunct> clazz) {
- this(clazz, null);
- }
-
- private AdjunctType(Class<? extends EntityAdjunct> clazz, AbstractEntityAdjunct adjunct) {
- name = clazz.getCanonicalName();
- configKeys = Collections.unmodifiableMap(findConfigKeys(clazz, null));
- configKeysSet = ImmutableSet.copyOf(this.configKeys.values());
- if (LOG.isTraceEnabled())
- LOG.trace("Policy {} config keys: {}", name, Joiner.on(", ").join(configKeys.keySet()));
- }
-
- AdjunctType(String name, Map<String, ConfigKey<?>> configKeys) {
- this.name = name;
- this.configKeys = ImmutableMap.copyOf(configKeys);
- this.configKeysSet = ImmutableSet.copyOf(this.configKeys.values());
- }
-
- public String getName() {
- return name;
- }
-
- public Set<ConfigKey<?>> getConfigKeys() {
- return configKeysSet;
- }
-
- public ConfigKey<?> getConfigKey(String name) {
- return configKeys.get(name);
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(name, configKeys);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) return true;
- if (getClass() != obj.getClass()) return false;
- AdjunctType o = (AdjunctType) obj;
- if (!Objects.equal(name, o.getName())) return false;
- if (!Objects.equal(getConfigKeys(), o.getConfigKeys())) return false;
- return true;
- }
-
- @Override
- public String toString() {
- return Objects.toStringHelper(name)
- .add("configKeys", configKeys)
- .toString();
- }
-
- /**
- * Finds the config keys defined on the entity's class, statics and optionally any non-static (discouraged).
- */
- // TODO Remove duplication from EntityDynamicType
- protected static Map<String,ConfigKey<?>> findConfigKeys(Class<? extends EntityAdjunct> clazz, EntityAdjunct optionalInstance) {
- try {
- Map<String,ConfigKey<?>> result = Maps.newLinkedHashMap();
- Map<String,Field> configFields = Maps.newLinkedHashMap();
- for (Field f : clazz.getFields()) {
- boolean isConfigKey = ConfigKey.class.isAssignableFrom(f.getType());
- if (!isConfigKey) {
- if (!HasConfigKey.class.isAssignableFrom(f.getType())) {
- // neither ConfigKey nor HasConfigKey
- continue;
- }
- }
- if (!Modifier.isStatic(f.getModifiers())) {
- // require it to be static or we have an instance
- LOG.warn("Discouraged use of non-static config key "+f+" defined in " + (optionalInstance!=null ? optionalInstance : clazz));
- if (optionalInstance==null) continue;
- }
- ConfigKey<?> k = isConfigKey ? (ConfigKey<?>) f.get(optionalInstance) :
- ((HasConfigKey<?>)f.get(optionalInstance)).getConfigKey();
-
- Field alternativeField = configFields.get(k.getName());
- // Allow overriding config keys (e.g. to set default values) when there is an assignable-from relationship between classes
- Field definitiveField = alternativeField != null ? inferSubbestField(alternativeField, f) : f;
- boolean skip = false;
- if (definitiveField != f) {
- // If they refer to the _same_ instance, just keep the one we already have
- if (alternativeField.get(optionalInstance) == f.get(optionalInstance)) skip = true;
- }
- if (skip) {
- //nothing
- } else if (definitiveField == f) {
- result.put(k.getName(), k);
- configFields.put(k.getName(), f);
- } else if (definitiveField != null) {
- if (LOG.isDebugEnabled()) LOG.debug("multiple definitions for config key {} on {}; preferring that in sub-class: {} to {}", new Object[] {
- k.getName(), optionalInstance!=null ? optionalInstance : clazz, alternativeField, f});
- } else if (definitiveField == null) {
- LOG.warn("multiple definitions for config key {} on {}; preferring {} to {}", new Object[] {
- k.getName(), optionalInstance!=null ? optionalInstance : clazz, alternativeField, f});
- }
- }
-
- return result;
- } catch (IllegalAccessException e) {
- throw Throwables.propagate(e);
- }
- }
-
- /**
- * Gets the field that is in the sub-class; or null if one field does not come from a sub-class of the other field's class
- */
- // TODO Remove duplication from EntityDynamicType
- private static Field inferSubbestField(Field f1, Field f2) {
- Class<?> c1 = f1.getDeclaringClass();
- Class<?> c2 = f2.getDeclaringClass();
- boolean isSuper1 = c1.isAssignableFrom(c2);
- boolean isSuper2 = c2.isAssignableFrom(c1);
- return (isSuper1) ? (isSuper2 ? null : f2) : (isSuper2 ? f1 : null);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/main/java/brooklyn/policy/basic/ConfigMapImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/policy/basic/ConfigMapImpl.java b/core/src/main/java/brooklyn/policy/basic/ConfigMapImpl.java
deleted file mode 100644
index 467eb05..0000000
--- a/core/src/main/java/brooklyn/policy/basic/ConfigMapImpl.java
+++ /dev/null
@@ -1,140 +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 brooklyn.policy.basic;
-
-import static brooklyn.util.GroovyJavaMethods.elvis;
-
-import java.util.Collections;
-import java.util.Map;
-
-import org.apache.brooklyn.api.entity.basic.EntityLocal;
-import org.apache.brooklyn.api.management.ExecutionContext;
-import org.apache.brooklyn.core.util.flags.TypeCoercions;
-import org.apache.brooklyn.core.util.internal.ConfigKeySelfExtracting;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Maps;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.config.internal.AbstractConfigMapImpl;
-import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.entity.basic.EntityInternal;
-import brooklyn.entity.basic.Sanitizer;
-import brooklyn.event.basic.StructuredConfigKey;
-import brooklyn.util.guava.Maybe;
-
-public class ConfigMapImpl extends AbstractConfigMapImpl {
-
- private static final Logger LOG = LoggerFactory.getLogger(ConfigMapImpl.class);
-
- /** policy against which config resolution / task execution will occur */
- private final AbstractEntityAdjunct adjunct;
-
- /*
- * TODO An alternative implementation approach would be to have:
- * setParent(Entity o, Map<ConfigKey,Object> inheritedConfig=[:])
- * The idea is that the parent could in theory decide explicitly what in its config
- * would be shared.
- * I (Aled) am undecided as to whether that would be better...
- *
- * (Alex) i lean toward the config key getting to make the decision
- */
-
- public ConfigMapImpl(AbstractEntityAdjunct adjunct) {
- this.adjunct = Preconditions.checkNotNull(adjunct, "AbstractEntityAdjunct must be specified");
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public <T> T getConfig(ConfigKey<T> key, T defaultValue) {
- // FIXME What about inherited task in config?!
- // alex says: think that should work, no?
- // FIXME What if someone calls getConfig on a task, before setting parent app?
- // alex says: not supported (throw exception, or return the task)
-
- // In case this entity class has overridden the given key (e.g. to set default), then retrieve this entity's key
- // TODO If ask for a config value that's not in our configKeys, should we really continue with rest of method and return key.getDefaultValue?
- // e.g. SshBasedJavaAppSetup calls setAttribute(JMX_USER), which calls getConfig(JMX_USER)
- // but that example doesn't have a default...
- ConfigKey<T> ownKey = adjunct!=null ? (ConfigKey<T>)elvis(adjunct.getAdjunctType().getConfigKey(key.getName()), key) : key;
-
- // Don't use groovy truth: if the set value is e.g. 0, then would ignore set value and return default!
- if (ownKey instanceof ConfigKeySelfExtracting) {
- if (((ConfigKeySelfExtracting<T>)ownKey).isSet(ownConfig)) {
- // FIXME Should we support config from futures? How to get execution context before setEntity?
- EntityLocal entity = adjunct.entity;
- ExecutionContext exec = (entity != null) ? ((EntityInternal)entity).getExecutionContext() : null;
- return ((ConfigKeySelfExtracting<T>)ownKey).extractValue(ownConfig, exec);
- }
- } else {
- LOG.warn("Config key {} of {} is not a ConfigKeySelfExtracting; cannot retrieve value; returning default", ownKey, this);
- }
- return TypeCoercions.coerce((defaultValue != null) ? defaultValue : ownKey.getDefaultValue(), key.getTypeToken());
- }
-
- @Override
- public Maybe<Object> getConfigRaw(ConfigKey<?> key, boolean includeInherited) {
- if (ownConfig.containsKey(key)) return Maybe.of(ownConfig.get(key));
- return Maybe.absent();
- }
-
- /** returns the config of this policy */
- @Override
- public Map<ConfigKey<?>,Object> getAllConfig() {
- // Don't use ImmutableMap because valide for values to be null
- return Collections.unmodifiableMap(Maps.newLinkedHashMap(ownConfig));
- }
-
- public Object setConfig(ConfigKey<?> key, Object v) {
- Object val = coerceConfigVal(key, v);
- if (key instanceof StructuredConfigKey) {
- return ((StructuredConfigKey)key).applyValueToMap(val, ownConfig);
- } else {
- return ownConfig.put(key, val);
- }
- }
-
- public void addToLocalBag(Map<String, ?> vals) {
- for (Map.Entry<String, ?> entry : vals.entrySet()) {
- setConfig(ConfigKeys.newConfigKey(Object.class, entry.getKey()), entry.getValue());
- }
- }
-
- public void removeFromLocalBag(String key) {
- ownConfig.remove(key);
- }
-
- @Override
- public ConfigMapImpl submap(Predicate<ConfigKey<?>> filter) {
- ConfigMapImpl m = new ConfigMapImpl(adjunct);
- for (Map.Entry<ConfigKey<?>,Object> entry: ownConfig.entrySet())
- if (filter.apply(entry.getKey()))
- m.ownConfig.put(entry.getKey(), entry.getValue());
- return m;
- }
-
- @Override
- public String toString() {
- return super.toString()+"[own="+Sanitizer.sanitize(ownConfig)+"]";
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/main/java/brooklyn/policy/basic/GeneralPurposePolicy.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/policy/basic/GeneralPurposePolicy.java b/core/src/main/java/brooklyn/policy/basic/GeneralPurposePolicy.java
deleted file mode 100644
index 0600006..0000000
--- a/core/src/main/java/brooklyn/policy/basic/GeneralPurposePolicy.java
+++ /dev/null
@@ -1,36 +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 brooklyn.policy.basic;
-
-import java.util.Collections;
-import java.util.Map;
-
-/**
- * @deprecated since 0.7.0; will be either deleted or moved to tests
- */
-@Deprecated
-public class GeneralPurposePolicy extends AbstractPolicy {
- public GeneralPurposePolicy() {
- this(Collections.emptyMap());
- }
- public GeneralPurposePolicy(Map properties) {
- super(properties);
- }
-}
-
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/main/java/brooklyn/policy/basic/Policies.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/policy/basic/Policies.java b/core/src/main/java/brooklyn/policy/basic/Policies.java
deleted file mode 100644
index 887546a..0000000
--- a/core/src/main/java/brooklyn/policy/basic/Policies.java
+++ /dev/null
@@ -1,73 +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 brooklyn.policy.basic;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.basic.EntityLocal;
-import org.apache.brooklyn.api.event.Sensor;
-import org.apache.brooklyn.api.event.SensorEvent;
-import org.apache.brooklyn.api.event.SensorEventListener;
-import org.apache.brooklyn.api.policy.Policy;
-
-import groovy.lang.Closure;
-import brooklyn.entity.basic.Lifecycle;
-import brooklyn.policy.basic.AbstractPolicy;
-
-@SuppressWarnings({"rawtypes","unchecked"})
-public class Policies {
-
- public static SensorEventListener listenerFromValueClosure(final Closure code) {
- return new SensorEventListener() {
- @Override
- public void onEvent(SensorEvent event) {
- code.call(event.getValue());
- }
- };
- }
-
- public static <T> Policy newSingleSensorValuePolicy(final Sensor<T> sensor, final Closure code) {
- return new AbstractPolicy() {
- @Override
- public void setEntity(EntityLocal entity) {
- super.setEntity(entity);
- entity.subscribe(entity, sensor, listenerFromValueClosure(code));
- }
- };
- }
-
- public static <S,T> Policy newSingleSensorValuePolicy(final Entity remoteEntity, final Sensor<T> remoteSensor,
- final Closure code) {
- return new AbstractPolicy() {
- @Override
- public void setEntity(EntityLocal entity) {
- super.setEntity(entity);
- entity.subscribe(remoteEntity, remoteSensor, listenerFromValueClosure(code));
- }
- };
- }
-
- public static Lifecycle getPolicyStatus(Policy p) {
- if (p.isRunning()) return Lifecycle.RUNNING;
- if (p.isDestroyed()) return Lifecycle.DESTROYED;
- if (p.isSuspended()) return Lifecycle.STOPPED;
- // TODO could policy be in an error state?
- return Lifecycle.CREATED;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/main/java/brooklyn/policy/basic/PolicyDynamicType.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/policy/basic/PolicyDynamicType.java b/core/src/main/java/brooklyn/policy/basic/PolicyDynamicType.java
deleted file mode 100644
index b6d3c6d..0000000
--- a/core/src/main/java/brooklyn/policy/basic/PolicyDynamicType.java
+++ /dev/null
@@ -1,44 +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 brooklyn.policy.basic;
-
-import org.apache.brooklyn.api.policy.Policy;
-import org.apache.brooklyn.api.policy.PolicyType;
-
-import brooklyn.basic.BrooklynDynamicType;
-
-public class PolicyDynamicType extends BrooklynDynamicType<Policy, AbstractPolicy> {
-
- public PolicyDynamicType(Class<? extends Policy> type) {
- super(type);
- }
-
- public PolicyDynamicType(AbstractPolicy policy) {
- super(policy);
- }
-
- public PolicyType getSnapshot() {
- return (PolicyType) super.getSnapshot();
- }
-
- @Override
- protected PolicyTypeSnapshot newSnapshot() {
- return new PolicyTypeSnapshot(name, value(configKeys));
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/main/java/brooklyn/policy/basic/PolicyTypeSnapshot.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/policy/basic/PolicyTypeSnapshot.java b/core/src/main/java/brooklyn/policy/basic/PolicyTypeSnapshot.java
deleted file mode 100644
index b6d2f33..0000000
--- a/core/src/main/java/brooklyn/policy/basic/PolicyTypeSnapshot.java
+++ /dev/null
@@ -1,40 +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 brooklyn.policy.basic;
-
-import java.util.Map;
-
-import org.apache.brooklyn.api.policy.PolicyType;
-
-import brooklyn.basic.BrooklynTypeSnapshot;
-import brooklyn.config.ConfigKey;
-
-public class PolicyTypeSnapshot extends BrooklynTypeSnapshot implements PolicyType {
- private static final long serialVersionUID = 4670930188951106009L;
-
- PolicyTypeSnapshot(String name, Map<String, ConfigKey<?>> configKeys) {
- super(name, configKeys);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) return true;
- return (obj instanceof PolicyTypeSnapshot) && super.equals(obj);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6eacb3c3/core/src/main/java/org/apache/brooklyn/core/policy/basic/AbstractEntityAdjunct.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/policy/basic/AbstractEntityAdjunct.java b/core/src/main/java/org/apache/brooklyn/core/policy/basic/AbstractEntityAdjunct.java
new file mode 100644
index 0000000..eda106f
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/policy/basic/AbstractEntityAdjunct.java
@@ -0,0 +1,510 @@
+/*
+ * 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.policy.basic;
+
+import static brooklyn.util.GroovyJavaMethods.truth;
+import static com.google.common.base.Preconditions.checkState;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.Group;
+import org.apache.brooklyn.api.entity.basic.EntityLocal;
+import org.apache.brooklyn.api.entity.trait.Configurable;
+import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.api.event.Sensor;
+import org.apache.brooklyn.api.event.SensorEventListener;
+import org.apache.brooklyn.api.management.ExecutionContext;
+import org.apache.brooklyn.api.management.SubscriptionContext;
+import org.apache.brooklyn.api.management.SubscriptionHandle;
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.api.policy.EntityAdjunct;
+import org.apache.brooklyn.core.management.internal.SubscriptionTracker;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.FlagUtils;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.basic.AbstractBrooklynObject;
+import brooklyn.basic.BrooklynObjectInternal;
+import brooklyn.config.ConfigKey;
+import brooklyn.config.ConfigKey.HasConfigKey;
+import brooklyn.config.ConfigMap;
+import brooklyn.enricher.basic.AbstractEnricher;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.util.guava.Maybe;
+import brooklyn.util.text.Strings;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+
+
+/**
+ * Common functionality for policies and enrichers
+ */
+public abstract class AbstractEntityAdjunct extends AbstractBrooklynObject implements BrooklynObjectInternal, EntityAdjunct, Configurable {
+ private static final Logger log = LoggerFactory.getLogger(AbstractEntityAdjunct.class);
+
+ private boolean _legacyNoConstructionInit;
+
+ /**
+ * @deprecated since 0.7.0; leftover properties are put into config, since when coming from yaml this is normal.
+ */
+ @Deprecated
+ protected Map<String,Object> leftoverProperties = Maps.newLinkedHashMap();
+
+ protected transient ExecutionContext execution;
+
+ private final BasicConfigurationSupport config = new BasicConfigurationSupport();
+
+ /**
+ * The config values of this entity. Updating this map should be done
+ * via {@link #config()}.
+ *
+ * @deprecated since 0.7.0; use {@link #config()} instead; this field may be made private or deleted in a future release.
+ */
+ @Deprecated
+ protected final ConfigMapImpl configsInternal = new ConfigMapImpl(this);
+
+ /**
+ * @deprecated since 0.7.0; use {@link #getAdjunctType()} instead; this field may be made private or deleted in a future release.
+ */
+ @Deprecated
+ protected final AdjunctType adjunctType = new AdjunctType(this);
+
+ @SetFromFlag
+ protected String name;
+
+ protected transient EntityLocal entity;
+
+ /** not for direct access; refer to as 'subscriptionTracker' via getter so that it is initialized */
+ protected transient SubscriptionTracker _subscriptionTracker;
+
+ private AtomicBoolean destroyed = new AtomicBoolean(false);
+
+ @SetFromFlag(value="uniqueTag")
+ protected String uniqueTag;
+
+ public AbstractEntityAdjunct() {
+ this(Collections.emptyMap());
+ }
+
+ public AbstractEntityAdjunct(@SuppressWarnings("rawtypes") Map properties) {
+ super(properties);
+ _legacyNoConstructionInit = (properties != null) && Boolean.TRUE.equals(properties.get("noConstructionInit"));
+
+ if (isLegacyConstruction()) {
+ AbstractBrooklynObject checkWeGetThis = configure(properties);
+ assert this.equals(checkWeGetThis) : this+" configure method does not return itself; returns "+checkWeGetThis+" instead of "+this;
+
+ boolean deferConstructionChecks = (properties.containsKey("deferConstructionChecks") && TypeCoercions.coerce(properties.get("deferConstructionChecks"), Boolean.class));
+ if (!deferConstructionChecks) {
+ FlagUtils.checkRequiredFields(this);
+ }
+ }
+ }
+
+ /**
+ * @deprecated since 0.7.0; only used for legacy brooklyn types where constructor is called directly
+ */
+ @Override
+ @Deprecated
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public AbstractEntityAdjunct configure(Map flags) {
+ // TODO only set on first time through
+ boolean isFirstTime = true;
+
+ // allow config keys, and fields, to be set from these flags if they have a SetFromFlag annotation
+ // or if the value is a config key
+ for (Iterator<Map.Entry> iter = flags.entrySet().iterator(); iter.hasNext();) {
+ Map.Entry entry = iter.next();
+ if (entry.getKey() instanceof ConfigKey) {
+ ConfigKey key = (ConfigKey)entry.getKey();
+ if (adjunctType.getConfigKeys().contains(key)) {
+ setConfig(key, entry.getValue());
+ } else {
+ log.warn("Unknown configuration key {} for policy {}; ignoring", key, this);
+ iter.remove();
+ }
+ }
+ }
+
+ ConfigBag bag = new ConfigBag().putAll(flags);
+ FlagUtils.setFieldsFromFlags(this, bag, isFirstTime);
+ FlagUtils.setAllConfigKeys(this, bag, false);
+ leftoverProperties.putAll(bag.getUnusedConfig());
+
+ //replace properties _contents_ with leftovers so subclasses see leftovers only
+ flags.clear();
+ flags.putAll(leftoverProperties);
+ leftoverProperties = flags;
+
+ if (!truth(name) && flags.containsKey("displayName")) {
+ //TODO inconsistent with entity and location, where name is legacy and displayName is encouraged!
+ //'displayName' is a legacy way to refer to a policy's name
+ Preconditions.checkArgument(flags.get("displayName") instanceof CharSequence, "'displayName' property should be a string");
+ setDisplayName(flags.remove("displayName").toString());
+ }
+
+ // set leftover flags should as config items; particularly useful when these have come from a brooklyn.config map
+ for (Object flag: flags.keySet()) {
+ ConfigKey<Object> key = ConfigKeys.newConfigKey(Object.class, Strings.toString(flag));
+ if (config().getRaw(key).isPresent()) {
+ log.warn("Config '"+flag+"' on "+this+" conflicts with key already set; ignoring");
+ } else {
+ config().set(key, flags.get(flag));
+ }
+ }
+
+ return this;
+ }
+
+ /**
+ * Used for legacy-style policies/enrichers on rebind, to indicate that init() should not be called.
+ * Will likely be deleted in a future release; should not be called apart from by framework code.
+ */
+ @Beta
+ protected boolean isLegacyNoConstructionInit() {
+ return _legacyNoConstructionInit;
+ }
+
+ @Override
+ public ConfigurationSupportInternal config() {
+ return config;
+ }
+
+ private class BasicConfigurationSupport implements ConfigurationSupportInternal {
+
+ @Override
+ public <T> T get(ConfigKey<T> key) {
+ return configsInternal.getConfig(key);
+ }
+
+ @Override
+ public <T> T get(HasConfigKey<T> key) {
+ return get(key.getConfigKey());
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T set(ConfigKey<T> key, T val) {
+ if (entity != null && isRunning()) {
+ doReconfigureConfig(key, val);
+ }
+ T result = (T) configsInternal.setConfig(key, val);
+ onChanged();
+ return result;
+ }
+
+ @Override
+ public <T> T set(HasConfigKey<T> key, T val) {
+ return setConfig(key.getConfigKey(), val);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T set(ConfigKey<T> key, Task<T> val) {
+ if (entity != null && isRunning()) {
+ // TODO Support for AbstractEntityAdjunct
+ throw new UnsupportedOperationException();
+ }
+ T result = (T) configsInternal.setConfig(key, val);
+ onChanged();
+ return result;
+ }
+
+ @Override
+ public <T> T set(HasConfigKey<T> key, Task<T> val) {
+ return set(key.getConfigKey(), val);
+ }
+
+ @Override
+ public ConfigBag getBag() {
+ return getLocalBag();
+ }
+
+ @Override
+ public ConfigBag getLocalBag() {
+ return ConfigBag.newInstance(configsInternal.getAllConfig());
+ }
+
+ @Override
+ public Maybe<Object> getRaw(ConfigKey<?> key) {
+ return configsInternal.getConfigRaw(key, true);
+ }
+
+ @Override
+ public Maybe<Object> getRaw(HasConfigKey<?> key) {
+ return getRaw(key.getConfigKey());
+ }
+
+ @Override
+ public Maybe<Object> getLocalRaw(ConfigKey<?> key) {
+ return configsInternal.getConfigRaw(key, false);
+ }
+
+ @Override
+ public Maybe<Object> getLocalRaw(HasConfigKey<?> key) {
+ return getLocalRaw(key.getConfigKey());
+ }
+
+ @Override
+ public void addToLocalBag(Map<String, ?> vals) {
+ configsInternal.addToLocalBag(vals);
+ }
+
+ @Override
+ public void removeFromLocalBag(String key) {
+ configsInternal.removeFromLocalBag(key);
+ }
+
+ @Override
+ public void refreshInheritedConfig() {
+ // no-op for location
+ }
+
+ @Override
+ public void refreshInheritedConfigOfChildren() {
+ // no-op for location
+ }
+ }
+
+ public <T> T getConfig(ConfigKey<T> key) {
+ return config().get(key);
+ }
+
+ protected <K> K getRequiredConfig(ConfigKey<K> key) {
+ K result = config().get(key);
+ if (result==null)
+ throw new NullPointerException("Value required for '"+key.getName()+"' in "+this);
+ return result;
+ }
+
+ @Override
+ @Deprecated
+ public <T> T setConfig(ConfigKey<T> key, T val) {
+ return config().set(key, val);
+ }
+
+ // TODO make immutable
+ /** for inspection only */
+ @Beta
+ @Deprecated
+ public ConfigMap getConfigMap() {
+ return configsInternal;
+ }
+
+ /**
+ * Invoked whenever a config change is applied after management is started.
+ * Default implementation throws an exception to disallow the change.
+ * Can be overridden to return (allowing the change) or to make other changes
+ * (if necessary), and of course it can do this selectively and call the super to disallow any others. */
+ protected <T> void doReconfigureConfig(ConfigKey<T> key, T val) {
+ throw new UnsupportedOperationException("reconfiguring "+key+" unsupported for "+this);
+ }
+
+ @Override
+ protected void onTagsChanged() {
+ onChanged();
+ }
+
+ protected abstract void onChanged();
+
+ protected AdjunctType getAdjunctType() {
+ return adjunctType;
+ }
+
+ @Override
+ public String getDisplayName() {
+ if (name!=null && name.length()>0) return name;
+ return getClass().getCanonicalName();
+ }
+
+ public void setDisplayName(String name) {
+ this.name = name;
+ }
+
+ public void setEntity(EntityLocal entity) {
+ if (destroyed.get()) throw new IllegalStateException("Cannot set entity on a destroyed entity adjunct");
+ this.entity = entity;
+ if (entity!=null && getCatalogItemId() == null) {
+ setCatalogItemId(entity.getCatalogItemId());
+ }
+ }
+
+ /** @deprecated since 0.7.0 only {@link AbstractEnricher} has emit convenience */
+ protected <T> void emit(Sensor<T> sensor, Object val) {
+ checkState(entity != null, "entity must first be set");
+ if (val == Entities.UNCHANGED) {
+ return;
+ }
+ if (val == Entities.REMOVE) {
+ ((EntityInternal)entity).removeAttribute((AttributeSensor<T>) sensor);
+ return;
+ }
+
+ T newVal = TypeCoercions.coerce(val, sensor.getTypeToken());
+ if (sensor instanceof AttributeSensor) {
+ entity.setAttribute((AttributeSensor<T>)sensor, newVal);
+ } else {
+ entity.emit(sensor, newVal);
+ }
+ }
+
+ protected synchronized SubscriptionTracker getSubscriptionTracker() {
+ if (_subscriptionTracker!=null) return _subscriptionTracker;
+ if (entity==null) return null;
+ _subscriptionTracker = new SubscriptionTracker(((EntityInternal)entity).getManagementSupport().getSubscriptionContext());
+ return _subscriptionTracker;
+ }
+
+ /** @see SubscriptionContext#subscribe(Entity, Sensor, SensorEventListener) */
+ protected <T> SubscriptionHandle subscribe(Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+ if (!checkCanSubscribe()) return null;
+ return getSubscriptionTracker().subscribe(producer, sensor, listener);
+ }
+
+ /** @see SubscriptionContext#subscribe(Entity, Sensor, SensorEventListener) */
+ protected <T> SubscriptionHandle subscribeToMembers(Group producerGroup, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+ if (!checkCanSubscribe(producerGroup)) return null;
+ return getSubscriptionTracker().subscribeToMembers(producerGroup, sensor, listener);
+ }
+
+ /** @see SubscriptionContext#subscribe(Entity, Sensor, SensorEventListener) */
+ protected <T> SubscriptionHandle subscribeToChildren(Entity producerParent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+ if (!checkCanSubscribe(producerParent)) return null;
+ return getSubscriptionTracker().subscribeToChildren(producerParent, sensor, listener);
+ }
+
+ /** @deprecated since 0.7.0 use {@link #checkCanSubscribe(Entity)} */
+ @Deprecated
+ protected boolean check(Entity requiredEntity) {
+ return checkCanSubscribe(requiredEntity);
+ }
+ /** returns false if deleted, throws exception if invalid state, otherwise true.
+ * okay if entity is not yet managed (but not if entity is no longer managed). */
+ protected boolean checkCanSubscribe(Entity producer) {
+ if (destroyed.get()) return false;
+ if (producer==null) throw new IllegalStateException(this+" given a null target for subscription");
+ if (entity==null) throw new IllegalStateException(this+" cannot subscribe to "+producer+" because it is not associated to an entity");
+ if (((EntityInternal)entity).getManagementSupport().isNoLongerManaged()) throw new IllegalStateException(this+" cannot subscribe to "+producer+" because the associated entity "+entity+" is no longer managed");
+ return true;
+ }
+ protected boolean checkCanSubscribe() {
+ if (destroyed.get()) return false;
+ if (entity==null) throw new IllegalStateException(this+" cannot subscribe because it is not associated to an entity");
+ if (((EntityInternal)entity).getManagementSupport().isNoLongerManaged()) throw new IllegalStateException(this+" cannot subscribe because the associated entity "+entity+" is no longer managed");
+ return true;
+ }
+
+ /**
+ * Unsubscribes the given producer.
+ *
+ * @see SubscriptionContext#unsubscribe(SubscriptionHandle)
+ */
+ protected boolean unsubscribe(Entity producer) {
+ if (destroyed.get()) return false;
+ return getSubscriptionTracker().unsubscribe(producer);
+ }
+
+ /**
+ * Unsubscribes the given producer.
+ *
+ * @see SubscriptionContext#unsubscribe(SubscriptionHandle)
+ */
+ protected boolean unsubscribe(Entity producer, SubscriptionHandle handle) {
+ if (destroyed.get()) return false;
+ return getSubscriptionTracker().unsubscribe(producer, handle);
+ }
+
+ /**
+ * @return a list of all subscription handles
+ */
+ protected Collection<SubscriptionHandle> getAllSubscriptions() {
+ SubscriptionTracker tracker = getSubscriptionTracker();
+ return (tracker != null) ? tracker.getAllSubscriptions() : Collections.<SubscriptionHandle>emptyList();
+ }
+
+ /**
+ * Unsubscribes and clears all managed subscriptions; is called by the owning entity when a policy is removed
+ * and should always be called by any subclasses overriding this method
+ */
+ public void destroy() {
+ destroyed.set(true);
+ SubscriptionTracker tracker = getSubscriptionTracker();
+ if (tracker != null) tracker.unsubscribeAll();
+ }
+
+ @Override
+ public boolean isDestroyed() {
+ return destroyed.get();
+ }
+
+ @Override
+ public boolean isRunning() {
+ return !isDestroyed();
+ }
+
+ @Override
+ public String getUniqueTag() {
+ return uniqueTag;
+ }
+
+ public TagSupport tags() {
+ return new AdjunctTagSupport();
+ }
+
+ public class AdjunctTagSupport extends BasicTagSupport {
+ @Override
+ public Set<Object> getTags() {
+ ImmutableSet.Builder<Object> rb = ImmutableSet.builder().addAll(super.getTags());
+ if (getUniqueTag()!=null) rb.add(getUniqueTag());
+ return rb.build();
+ }
+ public String getUniqueTag() {
+ return AbstractEntityAdjunct.this.getUniqueTag();
+ }
+ public void setUniqueTag(String uniqueTag) {
+ AbstractEntityAdjunct.this.uniqueTag = uniqueTag;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return Objects.toStringHelper(getClass()).omitNullValues()
+ .add("name", name)
+ .add("uniqueTag", uniqueTag)
+ .add("running", isRunning())
+ .add("entity", entity)
+ .add("id", getId())
+ .toString();
+ }
+}
[16/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/internal/ssh/sshj/SshjToolAsyncStubIntegrationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/internal/ssh/sshj/SshjToolAsyncStubIntegrationTest.java b/core/src/test/java/brooklyn/util/internal/ssh/sshj/SshjToolAsyncStubIntegrationTest.java
deleted file mode 100644
index df0330a..0000000
--- a/core/src/test/java/brooklyn/util/internal/ssh/sshj/SshjToolAsyncStubIntegrationTest.java
+++ /dev/null
@@ -1,177 +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 brooklyn.util.internal.ssh.sshj;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.List;
-
-import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.internal.ssh.SshAbstractTool.SshAction;
-import brooklyn.util.internal.ssh.sshj.SshjTool.ShellAction;
-import brooklyn.util.time.Duration;
-
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
-
-/**
- * Tests for async-exec with {@link SshjTool}, where it stubs out the actual ssh commands
- * to return a controlled sequence of responses.
- */
-public class SshjToolAsyncStubIntegrationTest {
-
- static class InjectedResult {
- Predicate<SshjTool.ShellAction> expected;
- Function<SshjTool.ShellAction, Integer> result;
-
- InjectedResult(Predicate<SshjTool.ShellAction> expected, Function<SshjTool.ShellAction, Integer> result) {
- this.expected = expected;
- this.result = result;
- }
- }
-
- private SshjTool tool;
- private List<InjectedResult> sequence;
- int counter = 0;
- private boolean origFeatureEnablement;
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() throws Exception {
- origFeatureEnablement = BrooklynFeatureEnablement.enable(BrooklynFeatureEnablement.FEATURE_SSH_ASYNC_EXEC);
- sequence = Lists.newArrayList();
- counter = 0;
-
- tool = new SshjTool(ImmutableMap.<String,Object>of("host", "localhost")) {
- @SuppressWarnings("unchecked")
- protected <T, C extends SshAction<T>> T acquire(C action, int sshTries, Duration sshTriesTimeout) {
- if (action instanceof SshjTool.ShellAction) {
- SshjTool.ShellAction shellAction = (SshjTool.ShellAction) action;
- InjectedResult injectedResult = sequence.get(counter);
- assertTrue(injectedResult.expected.apply(shellAction), "counter="+counter+"; cmds="+shellAction.commands);
- counter++;
- return (T) injectedResult.result.apply(shellAction);
- }
- return super.acquire(action, sshTries, sshTriesTimeout);
- }
- };
- }
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws Exception {
- try {
- if (tool != null) tool.disconnect();
- } finally {
- BrooklynFeatureEnablement.setEnablement(BrooklynFeatureEnablement.FEATURE_SSH_ASYNC_EXEC, origFeatureEnablement);
- }
- }
-
- private Predicate<SshjTool.ShellAction> containsCmd(final String cmd) {
- return new Predicate<SshjTool.ShellAction>() {
- @Override public boolean apply(ShellAction input) {
- return input != null && input.commands.toString().contains(cmd);
- }
- };
- }
-
- private Function<SshjTool.ShellAction, Integer> returning(final int result, final String stdout, final String stderr) {
- return new Function<SshjTool.ShellAction, Integer>() {
- @Override public Integer apply(ShellAction input) {
- try {
- if (stdout != null && input.out != null) input.out.write(stdout.getBytes());
- if (stderr != null && input.err != null) input.err.write(stderr.getBytes());
- } catch (IOException e) {
- throw Exceptions.propagate(e);
- }
- return result;
- }
- };
- }
-
- @Test(groups="Integration")
- public void testPolls() throws Exception {
- sequence = ImmutableList.of(
- new InjectedResult(containsCmd("nohup"), returning(0, "", "")),
- new InjectedResult(containsCmd("# Long poll"), returning(0, "mystringToStdout", "mystringToStderr")));
-
- runTest(0, "mystringToStdout", "mystringToStderr");
- assertEquals(counter, sequence.size());
- }
-
- @Test(groups="Integration")
- public void testPollsAndReturnsNonZeroExitCode() throws Exception {
- sequence = ImmutableList.of(
- new InjectedResult(containsCmd("nohup"), returning(0, "", "")),
- new InjectedResult(containsCmd("# Long poll"), returning(123, "mystringToStdout", "mystringToStderr")),
- new InjectedResult(containsCmd("# Retrieve status"), returning(0, "123", "")));
-
- runTest(123, "mystringToStdout", "mystringToStderr");
- assertEquals(counter, sequence.size());
- }
-
- @Test(groups="Integration")
- public void testPollsRepeatedly() throws Exception {
- sequence = ImmutableList.of(
- new InjectedResult(containsCmd("nohup"), returning(0, "", "")),
- new InjectedResult(containsCmd("# Long poll"), returning(125, "mystringToStdout", "mystringToStderr")),
- new InjectedResult(containsCmd("# Retrieve status"), returning(0, "", "")),
- new InjectedResult(containsCmd("# Long poll"), returning(125, "mystringToStdout2", "mystringToStderr2")),
- new InjectedResult(containsCmd("# Retrieve status"), returning(0, "", "")),
- new InjectedResult(containsCmd("# Long poll"), returning(-1, "mystringToStdout3", "mystringToStderr3")),
- new InjectedResult(containsCmd("# Long poll"), returning(125, "mystringToStdout4", "mystringToStderr4")),
- new InjectedResult(containsCmd("# Retrieve status"), returning(0, "", "")),
- new InjectedResult(containsCmd("# Long poll"), returning(0, "mystringToStdout5", "mystringToStderr5")));
-
- runTest(0,
- "mystringToStdout"+"mystringToStdout2"+"mystringToStdout3"+"mystringToStdout4"+"mystringToStdout5",
- "mystringToStderr"+"mystringToStderr2"+"mystringToStderr3"+"mystringToStderr4"+"mystringToStderr5");
- assertEquals(counter, sequence.size());
- }
-
- protected void runTest(int expectedExit, String expectedStdout, String expectedStderr) throws Exception {
- List<String> cmds = ImmutableList.of("abc");
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ByteArrayOutputStream err = new ByteArrayOutputStream();
- int exitCode = tool.execScript(
- ImmutableMap.of(
- "out", out,
- "err", err,
- SshjTool.PROP_EXEC_ASYNC.getName(), true,
- SshjTool.PROP_NO_EXTRA_OUTPUT.getName(), true,
- SshjTool.PROP_EXEC_ASYNC_POLLING_TIMEOUT.getName(), Duration.ONE_MILLISECOND),
- cmds,
- ImmutableMap.<String,String>of());
- String outStr = new String(out.toByteArray());
- String errStr = new String(err.toByteArray());
-
- assertEquals(exitCode, expectedExit);
- assertEquals(outStr.trim(), expectedStdout);
- assertEquals(errStr.trim(), expectedStderr);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/internal/ssh/sshj/SshjToolIntegrationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/internal/ssh/sshj/SshjToolIntegrationTest.java b/core/src/test/java/brooklyn/util/internal/ssh/sshj/SshjToolIntegrationTest.java
deleted file mode 100644
index f1e354c..0000000
--- a/core/src/test/java/brooklyn/util/internal/ssh/sshj/SshjToolIntegrationTest.java
+++ /dev/null
@@ -1,313 +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 brooklyn.util.internal.ssh.sshj;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-
-import net.schmizz.sshj.connection.channel.direct.Session;
-
-import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
-import org.testng.annotations.Test;
-
-import brooklyn.test.Asserts;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.exceptions.RuntimeTimeoutException;
-import brooklyn.util.internal.ssh.SshException;
-import brooklyn.util.internal.ssh.SshTool;
-import brooklyn.util.internal.ssh.SshToolAbstractIntegrationTest;
-import brooklyn.util.os.Os;
-import brooklyn.util.time.Duration;
-
-import com.google.common.base.Stopwatch;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-
-/**
- * Test the operation of the {@link SshJschTool} utility class.
- */
-public class SshjToolIntegrationTest extends SshToolAbstractIntegrationTest {
-
- @Override
- protected SshTool newUnregisteredTool(Map<String,?> flags) {
- return new SshjTool(flags);
- }
-
- // TODO requires vt100 terminal emulation to work?
- @Test(enabled = false, groups = {"Integration"})
- public void testExecShellWithCommandTakingStdin() throws Exception {
- // Uses `tee` to redirect stdin to the given file; cntr-d (i.e. char 4) stops tee with exit code 0
- String content = "blah blah";
- String out = execShellDirectWithTerminalEmulation("tee "+remoteFilePath, content, ""+(char)4, "echo file contents: `cat "+remoteFilePath+"`");
-
- assertTrue(out.contains("file contents: blah blah"), "out="+out);
- }
-
- @Test(groups = {"Integration"})
- public void testGivesUpAfterMaxRetries() throws Exception {
- final AtomicInteger callCount = new AtomicInteger();
-
- final SshTool localtool = new SshjTool(ImmutableMap.of("sshTries", 3, "host", "localhost", "privateKeyFile", "~/.ssh/id_rsa")) {
- protected SshAction<Session> newSessionAction() {
- callCount.incrementAndGet();
- throw new RuntimeException("Simulating ssh execution failure");
- }
- };
-
- tools.add(localtool);
- try {
- localtool.execScript(ImmutableMap.<String,Object>of(), ImmutableList.of("true"));
- fail();
- } catch (SshException e) {
- if (!e.toString().contains("out of retries")) throw e;
- assertEquals(callCount.get(), 3);
- }
- }
-
- @Test(groups = {"Integration"})
- public void testReturnsOnSuccessWhenRetrying() throws Exception {
- final AtomicInteger callCount = new AtomicInteger();
- final int successOnAttempt = 2;
- final SshTool localtool = new SshjTool(ImmutableMap.of("sshTries", 3, "host", "localhost", "privateKeyFile", "~/.ssh/id_rsa")) {
- protected SshAction<Session> newSessionAction() {
- callCount.incrementAndGet();
- if (callCount.incrementAndGet() >= successOnAttempt) {
- return super.newSessionAction();
- } else {
- throw new RuntimeException("Simulating ssh execution failure");
- }
- }
- };
-
- tools.add(localtool);
- localtool.execScript(ImmutableMap.<String,Object>of(), ImmutableList.of("true"));
- assertEquals(callCount.get(), successOnAttempt);
- }
-
- @Test(groups = {"Integration"})
- public void testGivesUpAfterMaxTime() throws Exception {
- final AtomicInteger callCount = new AtomicInteger();
- final SshTool localtool = new SshjTool(ImmutableMap.of("sshTriesTimeout", 1000, "host", "localhost", "privateKeyFile", "~/.ssh/id_rsa")) {
- protected SshAction<Session> newSessionAction() {
- callCount.incrementAndGet();
- try {
- Thread.sleep(600);
- } catch (InterruptedException e) {
- throw Exceptions.propagate(e);
- }
- throw new RuntimeException("Simulating ssh execution failure");
- }
- };
-
- tools.add(localtool);
- try {
- localtool.execScript(ImmutableMap.<String,Object>of(), ImmutableList.of("true"));
- fail();
- } catch (RuntimeTimeoutException e) {
- if (!e.toString().contains("out of time")) throw e;
- assertEquals(callCount.get(), 2);
- }
- }
-
- @Test(groups = {"Integration"})
- public void testUsesCustomLocalTempDir() throws Exception {
- class SshjToolForTest extends SshjTool {
- public SshjToolForTest(Map<String, ?> map) {
- super(map);
- }
- public File getLocalTempDir() {
- return localTempDir;
- }
- };
-
- final SshjToolForTest localtool = new SshjToolForTest(ImmutableMap.<String, Object>of("host", "localhost"));
- assertNotNull(localtool.getLocalTempDir());
- assertEquals(localtool.getLocalTempDir(), new File(Os.tidyPath(SshjTool.PROP_LOCAL_TEMP_DIR.getDefaultValue())));
-
- String customTempDir = Os.tmp();
- final SshjToolForTest localtool2 = new SshjToolForTest(ImmutableMap.of(
- "host", "localhost",
- SshjTool.PROP_LOCAL_TEMP_DIR.getName(), customTempDir));
- assertEquals(localtool2.getLocalTempDir(), new File(customTempDir));
-
- String customRelativeTempDir = "~/tmp";
- final SshjToolForTest localtool3 = new SshjToolForTest(ImmutableMap.of(
- "host", "localhost",
- SshjTool.PROP_LOCAL_TEMP_DIR.getName(), customRelativeTempDir));
- assertEquals(localtool3.getLocalTempDir(), new File(Os.tidyPath(customRelativeTempDir)));
- }
-
- @Test(groups = {"Integration"})
- public void testAsyncExecStdoutAndStderr() throws Exception {
- boolean origFeatureEnablement = BrooklynFeatureEnablement.enable(BrooklynFeatureEnablement.FEATURE_SSH_ASYNC_EXEC);
- try {
- // Include a sleep, to ensure that the contents retrieved in first poll and subsequent polls are appended
- List<String> cmds = ImmutableList.of(
- "echo mystringToStdout",
- "echo mystringToStderr 1>&2",
- "sleep 5",
- "echo mystringPostSleepToStdout",
- "echo mystringPostSleepToStderr 1>&2");
-
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ByteArrayOutputStream err = new ByteArrayOutputStream();
- int exitCode = tool.execScript(
- ImmutableMap.of(
- "out", out,
- "err", err,
- SshjTool.PROP_EXEC_ASYNC.getName(), true,
- SshjTool.PROP_NO_EXTRA_OUTPUT.getName(), true,
- SshjTool.PROP_EXEC_ASYNC_POLLING_TIMEOUT.getName(), Duration.ONE_SECOND),
- cmds,
- ImmutableMap.<String,String>of());
- String outStr = new String(out.toByteArray());
- String errStr = new String(err.toByteArray());
-
- assertEquals(exitCode, 0);
- assertEquals(outStr.trim(), "mystringToStdout\nmystringPostSleepToStdout");
- assertEquals(errStr.trim(), "mystringToStderr\nmystringPostSleepToStderr");
- } finally {
- BrooklynFeatureEnablement.setEnablement(BrooklynFeatureEnablement.FEATURE_SSH_ASYNC_EXEC, origFeatureEnablement);
- }
- }
-
- @Test(groups = {"Integration"})
- public void testAsyncExecReturnsExitCode() throws Exception {
- boolean origFeatureEnablement = BrooklynFeatureEnablement.enable(BrooklynFeatureEnablement.FEATURE_SSH_ASYNC_EXEC);
- try {
- int exitCode = tool.execScript(
- ImmutableMap.of(SshjTool.PROP_EXEC_ASYNC.getName(), true),
- ImmutableList.of("exit 123"),
- ImmutableMap.<String,String>of());
- assertEquals(exitCode, 123);
- } finally {
- BrooklynFeatureEnablement.setEnablement(BrooklynFeatureEnablement.FEATURE_SSH_ASYNC_EXEC, origFeatureEnablement);
- }
- }
-
- @Test(groups = {"Integration"})
- public void testAsyncExecTimesOut() throws Exception {
- Stopwatch stopwatch = Stopwatch.createStarted();
- boolean origFeatureEnablement = BrooklynFeatureEnablement.enable(BrooklynFeatureEnablement.FEATURE_SSH_ASYNC_EXEC);
- try {
- tool.execScript(
- ImmutableMap.of(SshjTool.PROP_EXEC_ASYNC.getName(), true, SshjTool.PROP_EXEC_TIMEOUT.getName(), Duration.millis(1)),
- ImmutableList.of("sleep 60"),
- ImmutableMap.<String,String>of());
- fail();
- } catch (Exception e) {
- TimeoutException te = Exceptions.getFirstThrowableOfType(e, TimeoutException.class);
- if (te == null) throw e;
- } finally {
- BrooklynFeatureEnablement.setEnablement(BrooklynFeatureEnablement.FEATURE_SSH_ASYNC_EXEC, origFeatureEnablement);
- }
-
- long seconds = stopwatch.elapsed(TimeUnit.SECONDS);
- assertTrue(seconds < 30, "exec took "+seconds+" seconds");
- }
-
- @Test(groups = {"Integration"})
- public void testAsyncExecAbortsIfProcessFails() throws Exception {
- final AtomicReference<Throwable> error = new AtomicReference<Throwable>();
- Thread thread = new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- Stopwatch stopwatch = Stopwatch.createStarted();
- int exitStatus = tool.execScript(
- ImmutableMap.of(SshjTool.PROP_EXEC_ASYNC.getName(), true, SshjTool.PROP_EXEC_TIMEOUT.getName(), Duration.millis(1)),
- ImmutableList.of("sleep 63"),
- ImmutableMap.<String,String>of());
-
- assertEquals(exitStatus, 143 /* 128 + Signal number (SIGTERM) */);
-
- long seconds = stopwatch.elapsed(TimeUnit.SECONDS);
- assertTrue(seconds < 30, "exec took "+seconds+" seconds");
- } catch (Throwable t) {
- error.set(t);
- }
- }});
-
- boolean origFeatureEnablement = BrooklynFeatureEnablement.enable(BrooklynFeatureEnablement.FEATURE_SSH_ASYNC_EXEC);
- try {
- thread.start();
-
- Asserts.succeedsEventually(new Runnable() {
- @Override
- public void run() {
- int exitStatus = tool.execCommands(ImmutableMap.<String,Object>of(), ImmutableList.of("ps aux| grep \"sleep 63\" | grep -v grep"));
- assertEquals(exitStatus, 0);
- }});
-
- tool.execCommands(ImmutableMap.<String,Object>of(), ImmutableList.of("ps aux| grep \"sleep 63\" | grep -v grep | awk '{print($2)}' | xargs kill"));
-
- thread.join(30*1000);
- assertFalse(thread.isAlive());
- if (error.get() != null) {
- throw Exceptions.propagate(error.get());
- }
- } finally {
- thread.interrupt();
- BrooklynFeatureEnablement.setEnablement(BrooklynFeatureEnablement.FEATURE_SSH_ASYNC_EXEC, origFeatureEnablement);
- }
- }
-
-
- protected String execShellDirect(List<String> cmds) {
- return execShellDirect(cmds, ImmutableMap.<String,Object>of());
- }
-
- protected String execShellDirect(List<String> cmds, Map<String,?> env) {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- int exitcode = ((SshjTool)tool).execShellDirect(ImmutableMap.of("out", out), cmds, env);
- String outstr = new String(out.toByteArray());
- assertEquals(exitcode, 0, outstr);
- return outstr;
- }
-
- private String execShellDirectWithTerminalEmulation(String... cmds) {
- return execShellDirectWithTerminalEmulation(Arrays.asList(cmds));
- }
-
- private String execShellDirectWithTerminalEmulation(List<String> cmds) {
- return execShellDirectWithTerminalEmulation(cmds, ImmutableMap.<String,Object>of());
- }
-
- private String execShellDirectWithTerminalEmulation(List<String> cmds, Map<String,?> env) {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- int exitcode = ((SshjTool)tool).execShellDirect(ImmutableMap.of("allocatePTY", true, "out", out), cmds, env);
- String outstr = new String(out.toByteArray());
- assertEquals(exitcode, 0, outstr);
- return outstr;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/internal/ssh/sshj/SshjToolPerformanceTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/internal/ssh/sshj/SshjToolPerformanceTest.java b/core/src/test/java/brooklyn/util/internal/ssh/sshj/SshjToolPerformanceTest.java
deleted file mode 100644
index 0c79bf1..0000000
--- a/core/src/test/java/brooklyn/util/internal/ssh/sshj/SshjToolPerformanceTest.java
+++ /dev/null
@@ -1,44 +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 brooklyn.util.internal.ssh.sshj;
-
-import java.util.Map;
-
-import org.testng.annotations.Test;
-
-import brooklyn.util.internal.ssh.SshTool;
-import brooklyn.util.internal.ssh.SshToolAbstractPerformanceTest;
-
-/**
- * Test the performance of different variants of invoking the sshj tool.
- *
- * Intended for human-invocation and inspection, to see which parts are most expensive.
- */
-public class SshjToolPerformanceTest extends SshToolAbstractPerformanceTest {
-
- @Override
- protected SshTool newSshTool(Map<String,?> flags) {
- return new SshjTool(flags);
- }
-
- // Need to have at least one test method here (rather than just inherited) for eclipse to recognize it
- @Test(enabled = false)
- public void testDummy() throws Exception {
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/mutex/WithMutexesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/mutex/WithMutexesTest.java b/core/src/test/java/brooklyn/util/mutex/WithMutexesTest.java
deleted file mode 100644
index cde25d3..0000000
--- a/core/src/test/java/brooklyn/util/mutex/WithMutexesTest.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 brooklyn.util.mutex;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Map;
-
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-public class WithMutexesTest {
-
- @Test
- public void testOneAcquisitionAndRelease() throws InterruptedException {
- MutexSupport m = new MutexSupport();
- Map<String, SemaphoreWithOwners> sems;
- SemaphoreWithOwners s;
- try {
- m.acquireMutex("foo", "something foo");
- sems = m.getAllSemaphores();
- Assert.assertEquals(sems.size(), 1);
- s = sems.get("foo");
- Assert.assertEquals(s.getDescription(), "something foo");
- Assert.assertEquals(s.getOwningThreads(), Arrays.asList(Thread.currentThread()));
- Assert.assertEquals(s.getRequestingThreads(), Collections.emptyList());
- Assert.assertTrue(s.isInUse());
- Assert.assertTrue(s.isCallingThreadAnOwner());
- } finally {
- m.releaseMutex("foo");
- }
- Assert.assertFalse(s.isInUse());
- Assert.assertFalse(s.isCallingThreadAnOwner());
- Assert.assertEquals(s.getDescription(), "something foo");
- Assert.assertEquals(s.getOwningThreads(), Collections.emptyList());
- Assert.assertEquals(s.getRequestingThreads(), Collections.emptyList());
-
- sems = m.getAllSemaphores();
- Assert.assertEquals(sems, Collections.emptyMap());
- }
-
- @Test(groups = "Integration") //just because it takes a wee while
- public void testBlockingAcquisition() throws InterruptedException {
- final MutexSupport m = new MutexSupport();
- m.acquireMutex("foo", "something foo");
-
- Assert.assertFalse(m.tryAcquireMutex("foo", "something else"));
-
- Thread t = new Thread() {
- public void run() {
- try {
- m.acquireMutex("foo", "thread 2 foo");
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- m.releaseMutex("foo");
- }
- };
- t.start();
-
- t.join(500);
- Assert.assertTrue(t.isAlive());
- Assert.assertEquals(m.getSemaphore("foo").getRequestingThreads(), Arrays.asList(t));
-
- m.releaseMutex("foo");
-
- t.join(1000);
- Assert.assertFalse(t.isAlive());
-
- Assert.assertEquals(m.getAllSemaphores(), Collections.emptyMap());
- }
-
-
- public static class SampleWithMutexesDelegatingMixin implements WithMutexes {
-
- /* other behaviour would typically go here... */
-
- WithMutexes mutexSupport = new MutexSupport();
-
- @Override
- public void acquireMutex(String mutexId, String description) throws InterruptedException {
- mutexSupport.acquireMutex(mutexId, description);
- }
-
- @Override
- public boolean tryAcquireMutex(String mutexId, String description) {
- return mutexSupport.tryAcquireMutex(mutexId, description);
- }
-
- @Override
- public void releaseMutex(String mutexId) {
- mutexSupport.releaseMutex(mutexId);
- }
-
- @Override
- public boolean hasMutex(String mutexId) {
- return mutexSupport.hasMutex(mutexId);
- }
- }
-
- @Test
- public void testDelegatingMixinPattern() throws InterruptedException {
- WithMutexes m = new SampleWithMutexesDelegatingMixin();
- m.acquireMutex("foo", "sample");
- Assert.assertTrue(m.hasMutex("foo"));
- Assert.assertFalse(m.hasMutex("bar"));
- m.releaseMutex("foo");
- Assert.assertFalse(m.hasMutex("foo"));
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/osgi/OsgisTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/osgi/OsgisTest.java b/core/src/test/java/brooklyn/util/osgi/OsgisTest.java
deleted file mode 100644
index 49f8017..0000000
--- a/core/src/test/java/brooklyn/util/osgi/OsgisTest.java
+++ /dev/null
@@ -1,41 +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 brooklyn.util.osgi;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-
-import org.osgi.framework.Version;
-import org.testng.annotations.Test;
-
-import brooklyn.util.osgi.Osgis.VersionedName;
-
-public class OsgisTest {
-
- @Test
- public void testParseOsgiIdentifier() throws Exception {
- assertEquals(Osgis.parseOsgiIdentifier("a.b").get(), new VersionedName("a.b", null));
- assertEquals(Osgis.parseOsgiIdentifier("a.b:0.1.2").get(), new VersionedName("a.b", Version.parseVersion("0.1.2")));
- assertEquals(Osgis.parseOsgiIdentifier("a.b:0.0.0.SNAPSHOT").get(), new VersionedName("a.b", Version.parseVersion("0.0.0.SNAPSHOT")));
- assertFalse(Osgis.parseOsgiIdentifier("a.b:0.notanumber.2").isPresent()); // invalid version
- assertFalse(Osgis.parseOsgiIdentifier("a.b:0.1.2:3.4.5").isPresent()); // too many colons
- assertFalse(Osgis.parseOsgiIdentifier("a.b:0.0.0_SNAPSHOT").isPresent()); // invalid version
- assertFalse(Osgis.parseOsgiIdentifier("").isPresent());
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/ssh/BashCommandsIntegrationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/ssh/BashCommandsIntegrationTest.java b/core/src/test/java/brooklyn/util/ssh/BashCommandsIntegrationTest.java
deleted file mode 100644
index accac56..0000000
--- a/core/src/test/java/brooklyn/util/ssh/BashCommandsIntegrationTest.java
+++ /dev/null
@@ -1,501 +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 brooklyn.util.ssh;
-
-import static brooklyn.util.ssh.BashCommands.sudo;
-import static java.lang.String.format;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertNotEquals;
-import static org.testng.Assert.assertTrue;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.net.ServerSocket;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
-import org.apache.commons.io.FileUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.Assert;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.entity.basic.Entities;
-import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
-import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.javalang.JavaClassNames;
-import brooklyn.util.net.Networking;
-import brooklyn.util.os.Os;
-import brooklyn.util.task.BasicExecutionContext;
-import brooklyn.util.task.ssh.SshTasks;
-import brooklyn.util.task.system.ProcessTaskWrapper;
-import brooklyn.util.text.Identifiers;
-import brooklyn.util.text.Strings;
-import brooklyn.util.time.Duration;
-
-import com.google.common.base.Charsets;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.io.Files;
-
-public class BashCommandsIntegrationTest {
-
- private static final Logger log = LoggerFactory.getLogger(BashCommandsIntegrationTest.class);
-
- private ManagementContext mgmt;
- private BasicExecutionContext exec;
-
- private File destFile;
- private File sourceNonExistantFile;
- private File sourceFile1;
- private File sourceFile2;
- private String sourceNonExistantFileUrl;
- private String sourceFileUrl1;
- private String sourceFileUrl2;
- private SshMachineLocation loc;
-
- private String localRepoFilename = "localrepofile.txt";
- private File localRepoBasePath;
- private File localRepoEntityBasePath;
- private String localRepoEntityVersionPath;
- private File localRepoEntityFile;
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() throws Exception {
- mgmt = new LocalManagementContextForTests();
- exec = new BasicExecutionContext(mgmt.getExecutionManager());
-
- destFile = Os.newTempFile(getClass(), "commoncommands-test-dest.txt");
-
- sourceNonExistantFile = new File("/this/does/not/exist/ERQBETJJIG1234");
- sourceNonExistantFileUrl = sourceNonExistantFile.toURI().toString();
-
- sourceFile1 = Os.newTempFile(getClass(), "commoncommands-test.txt");
- sourceFileUrl1 = sourceFile1.toURI().toString();
- Files.write("mysource1".getBytes(), sourceFile1);
-
- sourceFile2 = Os.newTempFile(getClass(), "commoncommands-test2.txt");
- sourceFileUrl2 = sourceFile2.toURI().toString();
- Files.write("mysource2".getBytes(), sourceFile2);
-
- localRepoEntityVersionPath = JavaClassNames.simpleClassName(this)+"-test-dest-"+Identifiers.makeRandomId(8);
- localRepoBasePath = new File(format("%s/.brooklyn/repository", System.getProperty("user.home")));
- localRepoEntityBasePath = new File(localRepoBasePath, localRepoEntityVersionPath);
- localRepoEntityFile = new File(localRepoEntityBasePath, localRepoFilename);
- localRepoEntityBasePath.mkdirs();
- Files.write("mylocal1".getBytes(), localRepoEntityFile);
-
- loc = mgmt.getLocationManager().createLocation(LocalhostMachineProvisioningLocation.spec()).obtain();
- }
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws Exception {
- if (sourceFile1 != null) sourceFile1.delete();
- if (sourceFile2 != null) sourceFile2.delete();
- if (destFile != null) destFile.delete();
- if (localRepoEntityFile != null) localRepoEntityFile.delete();
- if (localRepoEntityBasePath != null) FileUtils.deleteDirectory(localRepoEntityBasePath);
- if (loc != null) loc.close();
- if (mgmt != null) Entities.destroyAll(mgmt);
- }
-
- @Test(groups="Integration")
- public void testSudo() throws Exception {
- ByteArrayOutputStream outStream = new ByteArrayOutputStream();
- ByteArrayOutputStream errStream = new ByteArrayOutputStream();
- String cmd = sudo("whoami");
- int exitcode = loc.execCommands(ImmutableMap.of("out", outStream, "err", errStream), "test", ImmutableList.of(cmd));
- String outstr = new String(outStream.toByteArray());
- String errstr = new String(errStream.toByteArray());
-
- assertEquals(exitcode, 0, "out="+outstr+"; err="+errstr);
- assertTrue(outstr.contains("root"), "out="+outstr+"; err="+errstr);
- }
-
- public void testDownloadUrl() throws Exception {
- List<String> cmds = BashCommands.commandsToDownloadUrlsAs(
- ImmutableList.of(sourceFileUrl1),
- destFile.getAbsolutePath());
- int exitcode = loc.execCommands("test", cmds);
-
- assertEquals(0, exitcode);
- assertEquals(Files.readLines(destFile, Charsets.UTF_8), ImmutableList.of("mysource1"));
- }
-
- @Test(groups="Integration")
- public void testDownloadFirstSuccessfulFile() throws Exception {
- List<String> cmds = BashCommands.commandsToDownloadUrlsAs(
- ImmutableList.of(sourceNonExistantFileUrl, sourceFileUrl1, sourceFileUrl2),
- destFile.getAbsolutePath());
- int exitcode = loc.execCommands("test", cmds);
-
- assertEquals(0, exitcode);
- assertEquals(Files.readLines(destFile, Charsets.UTF_8), ImmutableList.of("mysource1"));
- }
-
- @Test(groups="Integration")
- public void testDownloadToStdout() throws Exception {
- ProcessTaskWrapper<String> t = SshTasks.newSshExecTaskFactory(loc,
- "cd "+destFile.getParentFile().getAbsolutePath(),
- BashCommands.downloadToStdout(Arrays.asList(sourceFileUrl1))+" | sed s/my/your/")
- .requiringZeroAndReturningStdout().newTask();
-
- String result = exec.submit(t).get();
- assertTrue(result.trim().equals("yoursource1"), "Wrong contents of stdout download: "+result);
- }
-
- @Test(groups="Integration")
- public void testAlternativesWhereFirstSucceeds() throws Exception {
- ProcessTaskWrapper<Integer> t = SshTasks.newSshExecTaskFactory(loc)
- .add(BashCommands.alternatives(Arrays.asList("echo first", "exit 88")))
- .newTask();
-
- Integer returnCode = exec.submit(t).get();
- String stdout = t.getStdout();
- String stderr = t.getStderr();
- log.info("alternatives for good first command gave: "+returnCode+"; err="+stderr+"; out="+stdout);
- assertTrue(stdout.contains("first"), "errcode="+returnCode+"; stdout="+stdout+"; stderr="+stderr);
- assertEquals(returnCode, (Integer)0);
- }
-
- @Test(groups="Integration")
- public void testAlternatives() throws Exception {
- ProcessTaskWrapper<Integer> t = SshTasks.newSshExecTaskFactory(loc)
- .add(BashCommands.alternatives(Arrays.asList("asdfj_no_such_command_1", "exit 88")))
- .newTask();
-
- Integer returnCode = exec.submit(t).get();
- log.info("alternatives for bad commands gave: "+returnCode+"; err="+new String(t.getStderr())+"; out="+new String(t.getStdout()));
- assertEquals(returnCode, (Integer)88);
- }
-
- @Test(groups="Integration")
- public void testRequireTestHandlesFailure() throws Exception {
- ProcessTaskWrapper<?> t = SshTasks.newSshExecTaskFactory(loc)
- .add(BashCommands.requireTest("-f "+sourceNonExistantFile.getPath(),
- "The requested file does not exist")).newTask();
-
- exec.submit(t).get();
- assertNotEquals(t.getExitCode(), (Integer)0);
- assertTrue(t.getStderr().contains("The requested file"), "Expected message in: "+t.getStderr());
- assertTrue(t.getStdout().contains("The requested file"), "Expected message in: "+t.getStdout());
- }
-
- @Test(groups="Integration")
- public void testRequireTestHandlesSuccess() throws Exception {
- ProcessTaskWrapper<?> t = SshTasks.newSshExecTaskFactory(loc)
- .add(BashCommands.requireTest("-f "+sourceFile1.getPath(),
- "The requested file does not exist")).newTask();
-
- exec.submit(t).get();
- assertEquals(t.getExitCode(), (Integer)0);
- assertTrue(t.getStderr().equals(""), "Expected no stderr messages, but got: "+t.getStderr());
- }
-
- @Test(groups="Integration")
- public void testRequireFileHandlesFailure() throws Exception {
- ProcessTaskWrapper<?> t = SshTasks.newSshExecTaskFactory(loc)
- .add(BashCommands.requireFile(sourceNonExistantFile.getPath())).newTask();
-
- exec.submit(t).get();
- assertNotEquals(t.getExitCode(), (Integer)0);
- assertTrue(t.getStderr().contains("required file"), "Expected message in: "+t.getStderr());
- assertTrue(t.getStderr().contains(sourceNonExistantFile.getPath()), "Expected message in: "+t.getStderr());
- assertTrue(t.getStdout().contains("required file"), "Expected message in: "+t.getStdout());
- assertTrue(t.getStdout().contains(sourceNonExistantFile.getPath()), "Expected message in: "+t.getStdout());
- }
-
- @Test(groups="Integration")
- public void testRequireFileHandlesSuccess() throws Exception {
- ProcessTaskWrapper<?> t = SshTasks.newSshExecTaskFactory(loc)
- .add(BashCommands.requireFile(sourceFile1.getPath())).newTask();
-
- exec.submit(t).get();
- assertEquals(t.getExitCode(), (Integer)0);
- assertTrue(t.getStderr().equals(""), "Expected no stderr messages, but got: "+t.getStderr());
- }
-
- @Test(groups="Integration")
- public void testRequireFailureExitsImmediately() throws Exception {
- ProcessTaskWrapper<?> t = SshTasks.newSshExecTaskFactory(loc)
- .add(BashCommands.requireTest("-f "+sourceNonExistantFile.getPath(),
- "The requested file does not exist"))
- .add("echo shouldnae come here").newTask();
-
- exec.submit(t).get();
- assertNotEquals(t.getExitCode(), (Integer)0);
- assertTrue(t.getStderr().contains("The requested file"), "Expected message in: "+t.getStderr());
- assertTrue(t.getStdout().contains("The requested file"), "Expected message in: "+t.getStdout());
- Assert.assertFalse(t.getStdout().contains("shouldnae"), "Expected message in: "+t.getStdout());
- }
-
- @Test(groups="Integration")
- public void testPipeMultiline() throws Exception {
- String output = execRequiringZeroAndReturningStdout(loc,
- BashCommands.pipeTextTo("hello world\n"+"and goodbye\n", "wc")).get();
-
- assertEquals(Strings.replaceAllRegex(output, "\\s+", " ").trim(), "3 4 25");
- }
-
- @Test(groups="Integration")
- public void testWaitForFileContentsWhenAbortingOnFail() throws Exception {
- String fileContent = "mycontents";
- String cmd = BashCommands.waitForFileContents(destFile.getAbsolutePath(), fileContent, Duration.ONE_SECOND, true);
-
- int exitcode = loc.execCommands("test", ImmutableList.of(cmd));
- assertEquals(exitcode, 1);
-
- Files.write(fileContent, destFile, Charsets.UTF_8);
- int exitcode2 = loc.execCommands("test", ImmutableList.of(cmd));
- assertEquals(exitcode2, 0);
- }
-
- @Test(groups="Integration")
- public void testWaitForFileContentsWhenNotAbortingOnFail() throws Exception {
- String fileContent = "mycontents";
- String cmd = BashCommands.waitForFileContents(destFile.getAbsolutePath(), fileContent, Duration.ONE_SECOND, false);
-
- String output = execRequiringZeroAndReturningStdout(loc, cmd).get();
- assertTrue(output.contains("Couldn't find"), "output="+output);
-
- Files.write(fileContent, destFile, Charsets.UTF_8);
- String output2 = execRequiringZeroAndReturningStdout(loc, cmd).get();
- assertFalse(output2.contains("Couldn't find"), "output="+output2);
- }
-
- @Test(groups="Integration")
- public void testWaitForFileContentsWhenContentsAppearAfterStart() throws Exception {
- String fileContent = "mycontents";
-
- String cmd = BashCommands.waitForFileContents(destFile.getAbsolutePath(), fileContent, Duration.THIRTY_SECONDS, false);
- ProcessTaskWrapper<String> t = execRequiringZeroAndReturningStdout(loc, cmd);
- exec.submit(t);
-
- // sleep for long enough to ensure the ssh command is definitely executing
- Thread.sleep(5*1000);
- assertFalse(t.isDone());
-
- Files.write(fileContent, destFile, Charsets.UTF_8);
- String output = t.get();
- assertFalse(output.contains("Couldn't find"), "output="+output);
- }
-
- @Test(groups="Integration", dependsOnMethods="testSudo")
- public void testWaitForPortFreeWhenAbortingOnTimeout() throws Exception {
- ServerSocket serverSocket = openServerSocket();
- try {
- int port = serverSocket.getLocalPort();
- String cmd = BashCommands.waitForPortFree(port, Duration.ONE_SECOND, true);
-
- int exitcode = loc.execCommands("test", ImmutableList.of(cmd));
- assertEquals(exitcode, 1);
-
- serverSocket.close();
- assertTrue(Networking.isPortAvailable(port));
- int exitcode2 = loc.execCommands("test", ImmutableList.of(cmd));
- assertEquals(exitcode2, 0);
- } finally {
- serverSocket.close();
- }
- }
-
- @Test(groups="Integration", dependsOnMethods="testSudo")
- public void testWaitForPortFreeWhenNotAbortingOnTimeout() throws Exception {
- ServerSocket serverSocket = openServerSocket();
- try {
- int port = serverSocket.getLocalPort();
- String cmd = BashCommands.waitForPortFree(port, Duration.ONE_SECOND, false);
-
- String output = execRequiringZeroAndReturningStdout(loc, cmd).get();
- assertTrue(output.contains(port+" still in use"), "output="+output);
-
- serverSocket.close();
- assertTrue(Networking.isPortAvailable(port));
- String output2 = execRequiringZeroAndReturningStdout(loc, cmd).get();
- assertFalse(output2.contains("still in use"), "output="+output2);
- } finally {
- serverSocket.close();
- }
- }
-
- @Test(groups="Integration", dependsOnMethods="testSudo")
- public void testWaitForPortFreeWhenFreedAfterStart() throws Exception {
- ServerSocket serverSocket = openServerSocket();
- try {
- int port = serverSocket.getLocalPort();
-
- String cmd = BashCommands.waitForPortFree(port, Duration.THIRTY_SECONDS, false);
- ProcessTaskWrapper<String> t = execRequiringZeroAndReturningStdout(loc, cmd);
- exec.submit(t);
-
- // sleep for long enough to ensure the ssh command is definitely executing
- Thread.sleep(5*1000);
- assertFalse(t.isDone());
-
- serverSocket.close();
- assertTrue(Networking.isPortAvailable(port));
- String output = t.get();
- assertFalse(output.contains("still in use"), "output="+output);
- } finally {
- serverSocket.close();
- }
- }
-
-
- // Disabled by default because of risk of overriding /etc/hosts in really bad way if doesn't work properly!
- // As a manual visual inspection test, consider first manually creating /etc/hostname and /etc/sysconfig/network
- // so that it looks like debian+ubuntu / CentOS/RHEL.
- @Test(groups={"Integration"}, enabled=false)
- public void testSetHostnameUnqualified() throws Exception {
- runSetHostname("br-"+Identifiers.makeRandomId(8).toLowerCase(), null, false);
- }
-
- @Test(groups={"Integration"}, enabled=false)
- public void testSetHostnameQualified() throws Exception {
- runSetHostname("br-"+Identifiers.makeRandomId(8).toLowerCase()+".brooklyn.incubator.apache.org", null, false);
- }
-
- @Test(groups={"Integration"}, enabled=false)
- public void testSetHostnameNullDomain() throws Exception {
- runSetHostname("br-"+Identifiers.makeRandomId(8).toLowerCase(), null, true);
- }
-
- @Test(groups={"Integration"}, enabled=false)
- public void testSetHostnameNonNullDomain() throws Exception {
- runSetHostname("br-"+Identifiers.makeRandomId(8).toLowerCase(), "brooklyn.incubator.apache.org", true);
- }
-
- protected void runSetHostname(String newHostname, String newDomain, boolean includeDomain) throws Exception {
- String fqdn = (includeDomain && Strings.isNonBlank(newDomain)) ? newHostname + "." + newDomain : newHostname;
-
- LocalManagementContextForTests mgmt = new LocalManagementContextForTests();
- SshMachineLocation loc = mgmt.getLocationManager().createLocation(LocalhostMachineProvisioningLocation.spec()).obtain();
-
- execRequiringZeroAndReturningStdout(loc, sudo("cp /etc/hosts /etc/hosts-orig-testSetHostname")).get();
- execRequiringZeroAndReturningStdout(loc, BashCommands.ifFileExistsElse0("/etc/hostname", sudo("cp /etc/hostname /etc/hostname-orig-testSetHostname"))).get();
- execRequiringZeroAndReturningStdout(loc, BashCommands.ifFileExistsElse0("/etc/sysconfig/network", sudo("cp /etc/sysconfig/network /etc/sysconfig/network-orig-testSetHostname"))).get();
-
- String origHostname = getHostnameNoArgs(loc);
- assertTrue(Strings.isNonBlank(origHostname));
-
- try {
- List<String> cmd = (includeDomain) ? BashCommands.setHostname(newHostname, newDomain) : BashCommands.setHostname(newHostname);
- execRequiringZeroAndReturningStdout(loc, cmd).get();
-
- String actualHostnameUnqualified = getHostnameUnqualified(loc);
- String actualHostnameFullyQualified = getHostnameFullyQualified(loc);
-
- // TODO On OS X at least, we aren't actually setting the domain name; we're just letting
- // the user pass in what the domain name is. We do add this properly to /etc/hosts
- // (e.g. first line is "127.0.0.1 br-g4x5wgx8.brooklyn.incubator.apache.org br-g4x5wgx8 localhost")
- // but subsequent calls to `hostname -f` returns the unqualified. Similarly, `domainname`
- // returns blank. Therefore we can't assert that it equals our expected val (because we just made
- // it up - "brooklyn.incubator.apache.org").
- // assertEquals(actualHostnameFullyQualified, fqdn);
- assertEquals(actualHostnameUnqualified, Strings.getFragmentBetween(newHostname, null, "."));
- execRequiringZeroAndReturningStdout(loc, "ping -c1 -n -q "+actualHostnameUnqualified).get();
- execRequiringZeroAndReturningStdout(loc, "ping -c1 -n -q "+actualHostnameFullyQualified).get();
-
- String result = execRequiringZeroAndReturningStdout(loc, "grep -n "+fqdn+" /etc/hosts").get();
- assertTrue(result.contains("localhost"), "line="+result);
- log.info("result="+result);
-
- } finally {
- execRequiringZeroAndReturningStdout(loc, sudo("cp /etc/hosts-orig-testSetHostname /etc/hosts")).get();
- execRequiringZeroAndReturningStdout(loc, BashCommands.ifFileExistsElse0("/etc/hostname-orig-testSetHostname", sudo("cp /etc/hostname-orig-testSetHostname /etc/hostname"))).get();
- execRequiringZeroAndReturningStdout(loc, BashCommands.ifFileExistsElse0("/etc/sysconfig/network-orig-testSetHostname", sudo("cp /etc/sysconfig/network-orig-testSetHostname /etc/sysconfig/network"))).get();
- execRequiringZeroAndReturningStdout(loc, sudo("hostname "+origHostname)).get();
- }
- }
-
- // Marked disabled because not safe to run on your normal machine! It modifies /etc/hosts, which is dangerous if things go wrong!
- @Test(groups={"Integration"}, enabled=false)
- public void testModifyEtcHosts() throws Exception {
- LocalManagementContextForTests mgmt = new LocalManagementContextForTests();
- SshMachineLocation loc = mgmt.getLocationManager().createLocation(LocalhostMachineProvisioningLocation.spec()).obtain();
-
- execRequiringZeroAndReturningStdout(loc, sudo("cp /etc/hosts /etc/hosts-orig-testModifyEtcHosts")).get();
- int numLinesOrig = Integer.parseInt(execRequiringZeroAndReturningStdout(loc, "wc -l /etc/hosts").get().trim().split("\\s")[0]);
-
- try {
- String cmd = BashCommands.prependToEtcHosts("1.2.3.4", "myhostnamefor1234.at.start", "myhostnamefor1234b");
- execRequiringZeroAndReturningStdout(loc, cmd).get();
-
- String cmd2 = BashCommands.appendToEtcHosts("5.6.7.8", "myhostnamefor5678.at.end", "myhostnamefor5678");
- execRequiringZeroAndReturningStdout(loc, cmd2).get();
-
- String grepFirst = execRequiringZeroAndReturningStdout(loc, "grep -n myhostnamefor1234 /etc/hosts").get();
- String grepLast = execRequiringZeroAndReturningStdout(loc, "grep -n myhostnamefor5678 /etc/hosts").get();
- int numLinesAfter = Integer.parseInt(execRequiringZeroAndReturningStdout(loc, "wc -l /etc/hosts").get().trim().split("\\s")[0]);
- log.info("result: numLinesBefore="+numLinesOrig+"; numLinesAfter="+numLinesAfter+"; first="+grepFirst+"; last="+grepLast);
-
- assertTrue(grepFirst.startsWith("1:") && grepFirst.contains("1.2.3.4 myhostnamefor1234.at.start myhostnamefor1234"), "first="+grepFirst);
- assertTrue(grepLast.startsWith((numLinesOrig+2)+":") && grepLast.contains("5.6.7.8 myhostnamefor5678.at.end myhostnamefor5678"), "last="+grepLast);
- assertEquals(numLinesOrig + 2, numLinesAfter, "lines orig="+numLinesOrig+", after="+numLinesAfter);
- } finally {
- execRequiringZeroAndReturningStdout(loc, sudo("cp /etc/hosts-orig-testModifyEtcHosts /etc/hosts")).get();
- }
- }
-
- private String getHostnameNoArgs(SshMachineLocation machine) {
- String hostnameStdout = execRequiringZeroAndReturningStdout(machine, "echo FOREMARKER; hostname; echo AFTMARKER").get();
- return Strings.getFragmentBetween(hostnameStdout, "FOREMARKER", "AFTMARKER").trim();
- }
-
- private String getHostnameUnqualified(SshMachineLocation machine) {
- String hostnameStdout = execRequiringZeroAndReturningStdout(machine, "echo FOREMARKER; hostname -s 2> /dev/null || hostname; echo AFTMARKER").get();
- return Strings.getFragmentBetween(hostnameStdout, "FOREMARKER", "AFTMARKER").trim();
- }
-
- private String getHostnameFullyQualified(SshMachineLocation machine) {
- String hostnameStdout = execRequiringZeroAndReturningStdout(machine, "echo FOREMARKER; hostname --fqdn 2> /dev/null || hostname -f; echo AFTMARKER").get();
- return Strings.getFragmentBetween(hostnameStdout, "FOREMARKER", "AFTMARKER").trim();
- }
-
- private ProcessTaskWrapper<String> execRequiringZeroAndReturningStdout(SshMachineLocation loc, Collection<String> cmds) {
- return execRequiringZeroAndReturningStdout(loc, cmds.toArray(new String[cmds.size()]));
- }
-
- private ProcessTaskWrapper<String> execRequiringZeroAndReturningStdout(SshMachineLocation loc, String... cmds) {
- ProcessTaskWrapper<String> t = SshTasks.newSshExecTaskFactory(loc, cmds)
- .requiringZeroAndReturningStdout().newTask();
- exec.submit(t);
- return t;
- }
-
- private ServerSocket openServerSocket() {
- int lowerBound = 40000;
- int upperBound = 40100;
- for (int i = lowerBound; i < upperBound; i++) {
- try {
- return new ServerSocket(i);
- } catch (IOException e) {
- // try next number
- }
- }
- throw new IllegalStateException("No ports available in range "+lowerBound+" to "+upperBound);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/task/BasicTaskExecutionPerformanceTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/task/BasicTaskExecutionPerformanceTest.java b/core/src/test/java/brooklyn/util/task/BasicTaskExecutionPerformanceTest.java
deleted file mode 100644
index 574c8c7..0000000
--- a/core/src/test/java/brooklyn/util/task/BasicTaskExecutionPerformanceTest.java
+++ /dev/null
@@ -1,206 +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 brooklyn.util.task;
-
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertTrue;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.brooklyn.api.management.Task;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.util.collections.MutableMap;
-
-import com.google.common.base.Predicate;
-import com.google.common.base.Stopwatch;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.util.concurrent.Callables;
-
-/**
- * Test the operation of the {@link BasicTask} class.
- *
- * TODO clarify test purpose
- */
-public class BasicTaskExecutionPerformanceTest {
- private static final Logger log = LoggerFactory.getLogger(BasicTaskExecutionPerformanceTest.class);
-
- private static final int TIMEOUT_MS = 10*1000;
-
- private BasicExecutionManager em;
-
- public static final int MAX_OVERHEAD_MS = 1500; // was 750ms but saw 1.3s on buildhive
- public static final int EARLY_RETURN_GRACE = 25; // saw 13ms early return on jenkins!
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() throws Exception {
- em = new BasicExecutionManager("mycontext");
- }
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws Exception {
- if (em != null) em.shutdownNow();
- }
-
- @SuppressWarnings("unchecked")
- @Test
- public void testScheduledTaskExecutedAfterDelay() throws Exception {
- int delay = 100;
- final CountDownLatch latch = new CountDownLatch(1);
-
- Callable<Task<?>> taskFactory = new Callable<Task<?>>() {
- @Override public Task<?> call() {
- return new BasicTask<Void>(new Runnable() {
- @Override public void run() {
- latch.countDown();
- }});
- }};
- ScheduledTask t = new ScheduledTask(taskFactory).delay(delay);
-
- Stopwatch stopwatch = Stopwatch.createStarted();
- em.submit(t);
-
- assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
- long actualDelay = stopwatch.elapsed(TimeUnit.MILLISECONDS);
-
- assertTrue(actualDelay > (delay-EARLY_RETURN_GRACE), "actualDelay="+actualDelay+"; delay="+delay);
- assertTrue(actualDelay < (delay+MAX_OVERHEAD_MS), "actualDelay="+actualDelay+"; delay="+delay);
- }
-
- @SuppressWarnings("unchecked")
- @Test
- public void testScheduledTaskExecutedAtRegularPeriod() throws Exception {
- final int period = 100;
- final int numTimestamps = 4;
- final CountDownLatch latch = new CountDownLatch(1);
- final List<Long> timestamps = Collections.synchronizedList(Lists.<Long>newArrayList());
- final Stopwatch stopwatch = Stopwatch.createStarted();
-
- Callable<Task<?>> taskFactory = new Callable<Task<?>>() {
- @Override public Task<?> call() {
- return new BasicTask<Void>(new Runnable() {
- @Override public void run() {
- timestamps.add(stopwatch.elapsed(TimeUnit.MILLISECONDS));
- if (timestamps.size() >= numTimestamps) latch.countDown();
- }});
- }};
- ScheduledTask t = new ScheduledTask(taskFactory).delay(1).period(period);
- em.submit(t);
-
- assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-
- synchronized (timestamps) {
- long prev = timestamps.get(0);
- for (long timestamp : timestamps.subList(1, timestamps.size())) {
- assertTrue(timestamp > prev+period-EARLY_RETURN_GRACE, "timestamps="+timestamps);
- assertTrue(timestamp < prev+period+MAX_OVERHEAD_MS, "timestamps="+timestamps);
- prev = timestamp;
- }
- }
- }
-
- @SuppressWarnings("unchecked")
- @Test
- public void testCanCancelScheduledTask() throws Exception {
- final int period = 1;
- final long checkPeriod = 250;
- final List<Long> timestamps = Collections.synchronizedList(Lists.<Long>newArrayList());
-
- Callable<Task<?>> taskFactory = new Callable<Task<?>>() {
- @Override public Task<?> call() {
- return new BasicTask<Void>(new Runnable() {
- @Override public void run() {
- timestamps.add(System.currentTimeMillis());
- }});
- }};
- ScheduledTask t = new ScheduledTask(taskFactory).period(period);
- em.submit(t);
-
- t.cancel();
- long cancelTime = System.currentTimeMillis();
- int countImmediatelyAfterCancel = timestamps.size();
- Thread.sleep(checkPeriod);
- int countWellAfterCancel = timestamps.size();
-
- // should have at most 1 more execution after cancel
- log.info("testCanCancelScheduledTask saw "+countImmediatelyAfterCancel+" then cancel then "+countWellAfterCancel+" total");
- assertTrue(countWellAfterCancel - countImmediatelyAfterCancel <= 2, "timestamps="+timestamps+"; cancelTime="+cancelTime);
- }
-
- // Previously, when we used a CopyOnWriteArraySet, performance for submitting new tasks was
- // terrible, and it degraded significantly as the number of previously executed tasks increased
- // (e.g. 9s for first 1000; 26s for next 1000; 42s for next 1000).
- @Test
- public void testExecutionManagerPerformance() throws Exception {
- // Was fixed at 1000 tasks, but was running out of virtual memory due to excessive thread creation
- // on machines which were not able to execute the threads quickly.
- final int NUM_TASKS = Math.min(500 * Runtime.getRuntime().availableProcessors(), 1000);
- final int NUM_TIMES = 10;
- final int MAX_ACCEPTABLE_TIME = 7500; // saw 5601ms on buildhive
-
- long tWarmup = execTasksAndWaitForDone(NUM_TASKS, ImmutableList.of("A"));
-
- List<Long> times = Lists.newArrayList();
- for (int i = 1; i <= NUM_TIMES; i++) {
- times.add(execTasksAndWaitForDone(NUM_TASKS, ImmutableList.of("A")));
- }
-
- Long toobig = Iterables.find(
- times,
- new Predicate<Long>() {
- public boolean apply(Long input) {
- return input > MAX_ACCEPTABLE_TIME;
- }},
- null);
- assertNull(toobig, "warmup="+tWarmup+"; times="+times);
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- private long execTasksAndWaitForDone(int numTasks, List<?> tags) throws Exception {
- List<Task<?>> tasks = Lists.newArrayList();
- long startTimestamp = System.currentTimeMillis();
- for (int i = 1; i < numTasks; i++) {
- Task<?> t = new BasicTask(Callables.returning(null)); // no-op
- em.submit(MutableMap.of("tags", tags), t);
- tasks.add(t);
- }
- long submittedTimestamp = System.currentTimeMillis();
-
- for (Task t : tasks) {
- t.get();
- }
- long endTimestamp = System.currentTimeMillis();
- long submitTime = submittedTimestamp - startTimestamp;
- long totalTime = endTimestamp - startTimestamp;
-
- log.info("Executed {} tasks; {}ms total; {}ms to submit", new Object[] {numTasks, totalTime, submitTime});
-
- return totalTime;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/task/BasicTaskExecutionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/task/BasicTaskExecutionTest.java b/core/src/test/java/brooklyn/util/task/BasicTaskExecutionTest.java
deleted file mode 100644
index 40660d4..0000000
--- a/core/src/test/java/brooklyn/util/task/BasicTaskExecutionTest.java
+++ /dev/null
@@ -1,460 +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 brooklyn.util.task;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.brooklyn.api.management.Task;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.test.Asserts;
-import brooklyn.util.collections.MutableMap;
-
-import com.google.common.base.Throwables;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-import com.google.common.util.concurrent.Callables;
-
-/**
- * Test the operation of the {@link BasicTask} class.
- *
- * TODO clarify test purpose
- */
-public class BasicTaskExecutionTest {
- private static final Logger log = LoggerFactory.getLogger(BasicTaskExecutionTest.class);
-
- private static final int TIMEOUT_MS = 10*1000;
-
- private BasicExecutionManager em;
- private Map<Object, Object> data;
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() {
- em = new BasicExecutionManager("mycontext");
- data = Collections.synchronizedMap(new HashMap<Object, Object>());
- data.clear();
- }
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws Exception {
- if (em != null) em.shutdownNow();
- if (data != null) data.clear();
- }
-
- @Test
- public void runSimpleBasicTask() throws Exception {
- BasicTask<Object> t = new BasicTask<Object>(newPutCallable(1, "b"));
- data.put(1, "a");
- Task<Object> t2 = em.submit(MutableMap.of("tag", "A"), t);
- assertEquals("a", t.get());
- assertEquals("a", t2.get());
- assertEquals("b", data.get(1));
- }
-
- @Test
- public void runSimpleRunnable() throws Exception {
- data.put(1, "a");
- Task<?> t = em.submit(MutableMap.of("tag", "A"), newPutRunnable(1, "b"));
- assertEquals(null, t.get());
- assertEquals("b", data.get(1));
- }
-
- @Test
- public void runSimpleCallable() throws Exception {
- data.put(1, "a");
- Task<?> t = em.submit(MutableMap.of("tag", "A"), newPutCallable(1, "b"));
- assertEquals("a", t.get());
- assertEquals("b", data.get(1));
- }
-
- @Test
- public void runBasicTaskWithWaits() throws Exception {
- final CountDownLatch signalStarted = new CountDownLatch(1);
- final CountDownLatch allowCompletion = new CountDownLatch(1);
- final BasicTask<Object> t = new BasicTask<Object>(new Callable<Object>() {
- public Object call() throws Exception {
- Object result = data.put(1, "b");
- signalStarted.countDown();
- assertTrue(allowCompletion.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
- return result;
- }});
- data.put(1, "a");
-
- Task<?> t2 = em.submit(MutableMap.of("tag", "A"), t);
- assertEquals(t, t2);
- assertFalse(t.isDone());
-
- assertTrue(signalStarted.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
- assertEquals("b", data.get(1));
- assertFalse(t.isDone());
-
- log.debug("runBasicTaskWithWaits, BasicTask status: {}", t.getStatusDetail(false));
-
- Asserts.succeedsEventually(new Runnable() {
- public void run() {
- String status = t.getStatusDetail(false);
- assertTrue(status != null && status.toLowerCase().contains("waiting"), "status="+status);
- }});
-
- allowCompletion.countDown();
- assertEquals("a", t.get());
- }
-
- @Test
- public void runMultipleBasicTasks() throws Exception {
- data.put(1, 1);
- BasicExecutionManager em = new BasicExecutionManager("mycontext");
- for (int i = 0; i < 2; i++) {
- em.submit(MutableMap.of("tag", "A"), new BasicTask<Integer>(newIncrementCallable(1)));
- em.submit(MutableMap.of("tag", "B"), new BasicTask<Integer>(newIncrementCallable((1))));
- }
- int total = 0;
- for (Object tag : em.getTaskTags()) {
- log.debug("tag {}", tag);
- for (Task<?> task : em.getTasksWithTag(tag)) {
- log.debug("BasicTask {}, has {}", task, task.get());
- total += (Integer)task.get();
- }
- }
- assertEquals(10, total);
- //now that all have completed:
- assertEquals(5, data.get(1));
- }
-
- @Test
- public void runMultipleBasicTasksMultipleTags() throws Exception {
- data.put(1, 1);
- Collection<Task<Integer>> tasks = Lists.newArrayList();
- tasks.add(em.submit(MutableMap.of("tag", "A"), new BasicTask<Integer>(newIncrementCallable(1))));
- tasks.add(em.submit(MutableMap.of("tags", ImmutableList.of("A","B")), new BasicTask<Integer>(newIncrementCallable(1))));
- tasks.add(em.submit(MutableMap.of("tags", ImmutableList.of("B","C")), new BasicTask<Integer>(newIncrementCallable(1))));
- tasks.add(em.submit(MutableMap.of("tags", ImmutableList.of("D")), new BasicTask<Integer>(newIncrementCallable(1))));
- int total = 0;
-
- for (Task<Integer> t : tasks) {
- log.debug("BasicTask {}, has {}", t, t.get());
- total += t.get();
- }
- assertEquals(10, total);
-
- //now that all have completed:
- assertEquals(data.get(1), 5);
- assertEquals(em.getTasksWithTag("A").size(), 2);
- assertEquals(em.getTasksWithAnyTag(ImmutableList.of("A")).size(), 2);
- assertEquals(em.getTasksWithAllTags(ImmutableList.of("A")).size(), 2);
-
- assertEquals(em.getTasksWithAnyTag(ImmutableList.of("A", "B")).size(), 3);
- assertEquals(em.getTasksWithAllTags(ImmutableList.of("A", "B")).size(), 1);
- assertEquals(em.getTasksWithAllTags(ImmutableList.of("B", "C")).size(), 1);
- assertEquals(em.getTasksWithAnyTag(ImmutableList.of("A", "D")).size(), 3);
- }
-
- @Test
- public void testGetTaskById() throws Exception {
- Task<?> t = new BasicTask<Void>(newNoop());
- em.submit(MutableMap.of("tag", "A"), t);
- assertEquals(em.getTask(t.getId()), t);
- }
-
- @Test
- public void testRetrievingTasksWithTagsReturnsExpectedTask() throws Exception {
- Task<?> t = new BasicTask<Void>(newNoop());
- em.submit(MutableMap.of("tag", "A"), t);
- t.get();
-
- assertEquals(em.getTasksWithTag("A"), ImmutableList.of(t));
- assertEquals(em.getTasksWithAnyTag(ImmutableList.of("A")), ImmutableList.of(t));
- assertEquals(em.getTasksWithAnyTag(ImmutableList.of("A", "B")), ImmutableList.of(t));
- assertEquals(em.getTasksWithAllTags(ImmutableList.of("A")), ImmutableList.of(t));
- }
-
- @Test
- public void testRetrievingTasksWithTagsExcludesNonMatchingTasks() throws Exception {
- Task<?> t = new BasicTask<Void>(newNoop());
- em.submit(MutableMap.of("tag", "A"), t);
- t.get();
-
- assertEquals(em.getTasksWithTag("B"), ImmutableSet.of());
- assertEquals(em.getTasksWithAnyTag(ImmutableList.of("B")), ImmutableSet.of());
- assertEquals(em.getTasksWithAllTags(ImmutableList.of("A", "B")), ImmutableSet.of());
- }
-
- @Test
- public void testRetrievingTasksWithMultipleTags() throws Exception {
- Task<?> t = new BasicTask<Void>(newNoop());
- em.submit(MutableMap.of("tags", ImmutableList.of("A", "B")), t);
- t.get();
-
- assertEquals(em.getTasksWithTag("A"), ImmutableList.of(t));
- assertEquals(em.getTasksWithTag("B"), ImmutableList.of(t));
- assertEquals(em.getTasksWithAnyTag(ImmutableList.of("A")), ImmutableList.of(t));
- assertEquals(em.getTasksWithAnyTag(ImmutableList.of("B")), ImmutableList.of(t));
- assertEquals(em.getTasksWithAnyTag(ImmutableList.of("A", "B")), ImmutableList.of(t));
- assertEquals(em.getTasksWithAllTags(ImmutableList.of("A", "B")), ImmutableList.of(t));
- assertEquals(em.getTasksWithAllTags(ImmutableList.of("A")), ImmutableList.of(t));
- assertEquals(em.getTasksWithAllTags(ImmutableList.of("B")), ImmutableList.of(t));
- }
-
- // ENGR-1796: if nothing matched first tag, then returned whatever matched second tag!
- @Test
- public void testRetrievingTasksWithAllTagsWhenFirstNotMatched() throws Exception {
- Task<?> t = new BasicTask<Void>(newNoop());
- em.submit(MutableMap.of("tags", ImmutableList.of("A")), t);
- t.get();
-
- assertEquals(em.getTasksWithAllTags(ImmutableList.of("not_there","A")), ImmutableSet.of());
- }
-
- @Test
- public void testRetrievedTasksIncludesTasksInProgress() throws Exception {
- final CountDownLatch runningLatch = new CountDownLatch(1);
- final CountDownLatch finishLatch = new CountDownLatch(1);
- Task<Void> t = new BasicTask<Void>(new Callable<Void>() {
- public Void call() throws Exception {
- runningLatch.countDown();
- finishLatch.await();
- return null;
- }});
- em.submit(MutableMap.of("tags", ImmutableList.of("A")), t);
-
- try {
- runningLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
-
- assertEquals(em.getTasksWithTag("A"), ImmutableList.of(t));
- } finally {
- finishLatch.countDown();
- }
- }
-
- @Test
- public void cancelBeforeRun() throws Exception {
- final CountDownLatch blockForever = new CountDownLatch(1);
-
- BasicTask<Integer> t = new BasicTask<Integer>(new Callable<Integer>() {
- public Integer call() throws Exception {
- blockForever.await(); return 42;
- }});
- t.cancel(true);
- assertTrue(t.isCancelled());
- assertTrue(t.isDone());
- assertTrue(t.isError());
- em.submit(MutableMap.of("tag", "A"), t);
- try {
- t.get();
- fail("get should have failed due to cancel");
- } catch (CancellationException e) {
- // expected
- }
- assertTrue(t.isCancelled());
- assertTrue(t.isDone());
- assertTrue(t.isError());
-
- log.debug("cancelBeforeRun status: {}", t.getStatusDetail(false));
- assertTrue(t.getStatusDetail(false).toLowerCase().contains("cancel"));
- }
-
- @Test
- public void cancelDuringRun() throws Exception {
- final CountDownLatch signalStarted = new CountDownLatch(1);
- final CountDownLatch blockForever = new CountDownLatch(1);
-
- BasicTask<Integer> t = new BasicTask<Integer>(new Callable<Integer>() {
- public Integer call() throws Exception {
- synchronized (data) {
- signalStarted.countDown();
- blockForever.await();
- }
- return 42;
- }});
- em.submit(MutableMap.of("tag", "A"), t);
- assertFalse(t.isCancelled());
- assertFalse(t.isDone());
- assertFalse(t.isError());
-
- assertTrue(signalStarted.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
- t.cancel(true);
-
- assertTrue(t.isCancelled());
- assertTrue(t.isError());
- try {
- t.get();
- fail("get should have failed due to cancel");
- } catch (CancellationException e) {
- // expected
- }
- assertTrue(t.isCancelled());
- assertTrue(t.isDone());
- assertTrue(t.isError());
- }
-
- @Test
- public void cancelAfterRun() throws Exception {
- BasicTask<Integer> t = new BasicTask<Integer>(Callables.returning(42));
- em.submit(MutableMap.of("tag", "A"), t);
-
- assertEquals(t.get(), (Integer)42);
- t.cancel(true);
- assertFalse(t.isCancelled());
- assertFalse(t.isError());
- assertTrue(t.isDone());
- }
-
- @Test
- public void errorDuringRun() throws Exception {
- BasicTask<Void> t = new BasicTask<Void>(new Callable<Void>() {
- public Void call() throws Exception {
- throw new IllegalStateException("Simulating failure in errorDuringRun");
- }});
-
- em.submit(MutableMap.of("tag", "A"), t);
-
- try {
- t.get();
- fail("get should have failed due to error");
- } catch (Exception eo) {
- Throwable e = Throwables.getRootCause(eo);
- assertEquals("Simulating failure in errorDuringRun", e.getMessage());
- }
-
- assertFalse(t.isCancelled());
- assertTrue(t.isError());
- assertTrue(t.isDone());
-
- log.debug("errorDuringRun status: {}", t.getStatusDetail(false));
- assertTrue(t.getStatusDetail(false).contains("Simulating failure in errorDuringRun"), "details="+t.getStatusDetail(false));
- }
-
- @Test
- public void fieldsSetForSimpleBasicTask() throws Exception {
- final CountDownLatch signalStarted = new CountDownLatch(1);
- final CountDownLatch allowCompletion = new CountDownLatch(1);
-
- BasicTask<Integer> t = new BasicTask<Integer>(new Callable<Integer>() {
- public Integer call() throws Exception {
- signalStarted.countDown();
- allowCompletion.await();
- return 42;
- }});
- assertEquals(null, t.getSubmittedByTask());
- assertEquals(-1, t.submitTimeUtc);
- assertNull(t.getInternalFuture());
-
- em.submit(MutableMap.of("tag", "A"), t);
- assertTrue(signalStarted.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-
- assertTrue(t.submitTimeUtc > 0);
- assertTrue(t.startTimeUtc >= t.submitTimeUtc);
- assertNotNull(t.getInternalFuture());
- assertEquals(-1, t.endTimeUtc);
- assertEquals(false, t.isCancelled());
-
- allowCompletion.countDown();
- assertEquals(t.get(), (Integer)42);
- assertTrue(t.endTimeUtc >= t.startTimeUtc);
-
- log.debug("BasicTask duration (millis): {}", (t.endTimeUtc - t.submitTimeUtc));
- }
-
- @Test
- public void fieldsSetForBasicTaskSubmittedBasicTask() throws Exception {
- //submitted BasicTask B is started by A, and waits for A to complete
- BasicTask<Integer> t = new BasicTask<Integer>(MutableMap.of("displayName", "sample", "description", "some descr"), new Callable<Integer>() {
- public Integer call() throws Exception {
- em.submit(MutableMap.of("tag", "B"), new Callable<Integer>() {
- public Integer call() throws Exception {
- assertEquals(45, em.getTasksWithTag("A").iterator().next().get());
- return 46;
- }});
- return 45;
- }});
- em.submit(MutableMap.of("tag", "A"), t);
-
- t.blockUntilEnded();
-
-// assertEquals(em.getAllTasks().size(), 2
-
- BasicTask<?> tb = (BasicTask<?>) em.getTasksWithTag("B").iterator().next();
- assertEquals( 46, tb.get() );
- assertEquals( t, em.getTasksWithTag("A").iterator().next() );
- assertNull( t.getSubmittedByTask() );
-
- BasicTask<?> submitter = (BasicTask<?>) tb.getSubmittedByTask();
- assertNotNull(submitter);
- assertEquals("sample", submitter.displayName);
- assertEquals("some descr", submitter.description);
- assertEquals(t, submitter);
-
- assertTrue(submitter.submitTimeUtc <= tb.submitTimeUtc);
- assertTrue(submitter.endTimeUtc <= tb.endTimeUtc);
-
- log.debug("BasicTask {} was submitted by {}", tb, submitter);
- }
-
- private Callable<Object> newPutCallable(final Object key, final Object val) {
- return new Callable<Object>() {
- public Object call() {
- return data.put(key, val);
- }
- };
- }
-
- private Callable<Integer> newIncrementCallable(final Object key) {
- return new Callable<Integer>() {
- public Integer call() {
- synchronized (data) {
- return (Integer) data.put(key, (Integer)data.get(key) + 1);
- }
- }
- };
- }
-
- private Runnable newPutRunnable(final Object key, final Object val) {
- return new Runnable() {
- public void run() {
- data.put(key, val);
- }
- };
- }
-
- private Runnable newNoop() {
- return new Runnable() {
- public void run() {
- }
- };
- }
-}
[29/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/config/ConfigBag.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/config/ConfigBag.java b/core/src/main/java/org/apache/brooklyn/core/util/config/ConfigBag.java
new file mode 100644
index 0000000..0152bb9
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/config/ConfigBag.java
@@ -0,0 +1,589 @@
+/*
+ * 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.util.config;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.ConcurrentModificationException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.config.ConfigKey.HasConfigKey;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.guava.Maybe;
+import brooklyn.util.javalang.JavaClassNames;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import com.google.common.collect.Sets;
+
+/**
+ * Stores config in such a way that usage can be tracked.
+ * Either {@link ConfigKey} or {@link String} keys can be inserted;
+ * they will be stored internally as strings.
+ * It is recommended to use {@link ConfigKey} instances to access,
+ * although in some cases (such as setting fields from flags, or copying a map)
+ * it may be necessary to mark things as used, or put, when only a string key is available.
+ * <p>
+ * This bag is order-preserving and thread-safe except where otherwise indicated,
+ * currently by synching on this instance (but that behaviour may change).
+ * <p>
+ * @author alex
+ */
+public class ConfigBag {
+
+ private static final Logger log = LoggerFactory.getLogger(ConfigBag.class);
+
+ /** an immutable, empty ConfigBag */
+ public static final ConfigBag EMPTY = new ConfigBag().setDescription("immutable empty config bag").seal();
+
+ protected String description;
+
+ private Map<String,Object> config;
+ private final Map<String,Object> unusedConfig;
+ private final boolean live;
+ private boolean sealed = false;
+
+ /** creates a new ConfigBag instance, empty and ready for population */
+ public static ConfigBag newInstance() {
+ return new ConfigBag();
+ }
+
+ /**
+ * Creates an instance that is backed by a "live map" (e.g. storage in a datagrid).
+ * The order-preserving nature of this class is only guaranteed if the
+ * provided storage has those properties. External modifications to the store can cause
+ * {@link ConcurrentModificationException} to be thrown, here or elsewhere.
+ */
+ public static ConfigBag newLiveInstance(Map<String,Object> storage) {
+ return new ConfigBag(checkNotNull(storage, "storage map must be specified"));
+ }
+
+ public static ConfigBag newInstance(Map<?, ?> config) {
+ ConfigBag result = new ConfigBag();
+ result.putAll(config);
+ return result;
+ }
+
+ /** creates a new ConfigBag instance which includes all of the supplied ConfigBag's values,
+ * but which tracks usage separately (already used values are marked as such,
+ * but uses in the original set will not be marked here, and vice versa) */
+ public static ConfigBag newInstanceCopying(final ConfigBag configBag) {
+ return new ConfigBag().copy(configBag).setDescription(configBag.getDescription());
+ }
+
+ /** creates a new ConfigBag instance which includes all of the supplied ConfigBag's values,
+ * plus an additional set of <ConfigKey,Object> or <String,Object> pairs
+ * <p>
+ * values from the original set which are used here will be marked as used in the original set
+ * (note: this applies even for values which are overridden and the overridden value is used);
+ * however subsequent uses in the original set will not be marked here
+ */
+ @Beta
+ public static ConfigBag newInstanceExtending(final ConfigBag parentBag) {
+ return new ConfigBagExtendingParent(parentBag);
+ }
+
+ /** @see #newInstanceExtending(ConfigBag) */
+ private static class ConfigBagExtendingParent extends ConfigBag {
+ ConfigBag parentBag;
+ private ConfigBagExtendingParent(ConfigBag parentBag) {
+ this.parentBag = parentBag;
+ copy(parentBag);
+ }
+ @Override
+ public void markUsed(String key) {
+ super.markUsed(key);
+ if (parentBag!=null)
+ parentBag.markUsed(key);
+ }
+ }
+
+ /** As {@link #newInstanceExtending(ConfigBag)} but also putting the supplied values. */
+ @Beta
+ public static ConfigBag newInstanceExtending(final ConfigBag configBag, Map<?,?> optionalAdditionalValues) {
+ return newInstanceExtending(configBag).putAll(optionalAdditionalValues);
+ }
+
+ /** @deprecated since 0.7.0, not used; kept only for rebind compatibility where the inner class is used
+ * (now replaced by a static class above) */
+ @Beta @Deprecated
+ public static ConfigBag newInstanceWithInnerClass(final ConfigBag configBag, Map<?,?> optionalAdditionalValues) {
+ return new ConfigBag() {
+ @Override
+ public void markUsed(String key) {
+ super.markUsed(key);
+ configBag.markUsed(key);
+ }
+ }.copy(configBag).putAll(optionalAdditionalValues);
+ }
+
+ public ConfigBag() {
+ config = new LinkedHashMap<String,Object>();
+ unusedConfig = new LinkedHashMap<String,Object>();
+ live = false;
+ }
+
+ private ConfigBag(Map<String,Object> storage) {
+ this.config = storage;
+ unusedConfig = new LinkedHashMap<String,Object>();
+ live = true;
+ }
+
+ public ConfigBag setDescription(String description) {
+ if (sealed)
+ throw new IllegalStateException("Cannot set description to '"+description+"': this config bag has been sealed and is now immutable.");
+ this.description = description;
+ return this;
+ }
+
+ /** optional description used to provide context for operations */
+ public String getDescription() {
+ return description;
+ }
+
+ /** current values for all entries
+ * @return non-modifiable map of strings to object */
+ public synchronized Map<String,Object> getAllConfig() {
+ return MutableMap.copyOf(config).asUnmodifiable();
+ }
+
+ /** current values for all entries in a map where the keys are converted to {@link ConfigKey} instances */
+ public synchronized Map<ConfigKey<?>, ?> getAllConfigAsConfigKeyMap() {
+ Map<ConfigKey<?>,Object> result = MutableMap.of();
+ for (Map.Entry<String,Object> entry: config.entrySet()) {
+ result.put(ConfigKeys.newConfigKey(Object.class, entry.getKey()), entry.getValue());
+ }
+ return result;
+ }
+
+ /** Returns the internal map containing the current values for all entries;
+ * for use where the caller wants to modify this directly and knows it is safe to do so
+ * <p>
+ * Accesses to the returned map must be synchronized on this bag if the
+ * thread-safe behaviour is required. */
+ public Map<String,Object> getAllConfigMutable() {
+ if (live) {
+ // TODO sealed no longer works as before, because `config` is the backing storage map.
+ // Therefore returning it is dangerous! Even if we were to replace our field with an immutable copy,
+ // the underlying datagrid's map would still be modifiable. We need a way to switch the returned
+ // value's behaviour to sealable (i.e. wrapping the returned map).
+ return (sealed) ? MutableMap.copyOf(config).asUnmodifiable() : config;
+ } else {
+ return config;
+ }
+ }
+
+ /** current values for all entries which have not yet been used
+ * @return non-modifiable map of strings to object */
+ public synchronized Map<String,Object> getUnusedConfig() {
+ return MutableMap.copyOf(unusedConfig).asUnmodifiable();
+ }
+
+ /** Returns the internal map containing the current values for all entries which have not yet been used;
+ * for use where the caller wants to modify this directly and knows it is safe to do so
+ * <p>
+ * Accesses to the returned map must be synchronized on this bag if the
+ * thread-safe behaviour is required. */
+ public Map<String,Object> getUnusedConfigMutable() {
+ return unusedConfig;
+ }
+
+ public ConfigBag putAll(Map<?,?> addlConfig) {
+ if (addlConfig==null) return this;
+ for (Map.Entry<?,?> e: addlConfig.entrySet()) {
+ putAsStringKey(e.getKey(), e.getValue());
+ }
+ return this;
+ }
+
+ public ConfigBag putAll(ConfigBag addlConfig) {
+ return putAll(addlConfig.getAllConfig());
+ }
+
+ public <T> ConfigBag putIfAbsent(ConfigKey<T> key, T value) {
+ return putIfAbsent(MutableMap.of(key, value));
+ }
+
+ public ConfigBag putAsStringKeyIfAbsent(Object key, Object value) {
+ return putIfAbsent(MutableMap.of(key, value));
+ }
+
+ public synchronized ConfigBag putIfAbsent(Map<?, ?> propertiesToSet) {
+ if (propertiesToSet==null)
+ return this;
+ for (Map.Entry<?, ?> entry: propertiesToSet.entrySet()) {
+ Object key = entry.getKey();
+ if (key instanceof HasConfigKey<?>)
+ key = ((HasConfigKey<?>)key).getConfigKey();
+ if (key instanceof ConfigKey<?>) {
+ if (!containsKey((ConfigKey<?>)key))
+ putAsStringKey(key, entry.getValue());
+ } else if (key instanceof String) {
+ if (!containsKey((String)key))
+ putAsStringKey(key, entry.getValue());
+ } else {
+ logInvalidKey(key);
+ }
+ }
+ return this;
+ }
+
+ public ConfigBag putIfAbsent(ConfigBag addlConfig) {
+ return putIfAbsent(addlConfig.getAllConfig());
+ }
+
+
+ @SuppressWarnings("unchecked")
+ public <T> T put(ConfigKey<T> key, T value) {
+ return (T) putStringKey(key.getName(), value);
+ }
+
+ public <T> ConfigBag putIfNotNull(ConfigKey<T> key, T value) {
+ if (value!=null) put(key, value);
+ return this;
+ }
+
+ public <T> ConfigBag putIfAbsentAndNotNull(ConfigKey<T> key, T value) {
+ if (value!=null) putIfAbsent(key, value);
+ return this;
+ }
+
+ /** as {@link #put(ConfigKey, Object)} but returning this ConfigBag for fluent-style coding */
+ public <T> ConfigBag configure(ConfigKey<T> key, T value) {
+ putStringKey(key.getName(), value);
+ return this;
+ }
+
+ public <T> ConfigBag configureStringKey(String key, T value) {
+ putStringKey(key, value);
+ return this;
+ }
+
+ protected synchronized void putAsStringKey(Object key, Object value) {
+ if (key instanceof HasConfigKey<?>) key = ((HasConfigKey<?>)key).getConfigKey();
+ if (key instanceof ConfigKey<?>) key = ((ConfigKey<?>)key).getName();
+ if (key instanceof String) {
+ putStringKey((String)key, value);
+ } else {
+ logInvalidKey(key);
+ }
+ }
+
+ protected void logInvalidKey(Object key) {
+ String message = (key == null ? "Invalid key 'null'" : "Invalid key type "+key.getClass().getCanonicalName()+" ("+key+")") +
+ " being used for configuration, ignoring";
+ log.debug(message, new Throwable("Source of "+message));
+ log.warn(message);
+ }
+
+ /** recommended to use {@link #put(ConfigKey, Object)} but there are times
+ * (e.g. when copying a map) where we want to put a string key directly
+ */
+ public synchronized Object putStringKey(String key, Object value) {
+ if (sealed)
+ throw new IllegalStateException("Cannot insert "+key+"="+value+": this config bag has been sealed and is now immutable.");
+ boolean isNew = !config.containsKey(key);
+ boolean isUsed = !isNew && !unusedConfig.containsKey(key);
+ Object old = config.put(key, value);
+ if (!isUsed)
+ unusedConfig.put(key, value);
+ //if (!isNew && !isUsed) log.debug("updating config value which has already been used");
+ return old;
+ }
+ public Object putStringKeyIfHasValue(String key, Maybe<?> value) {
+ if (value.isPresent())
+ return putStringKey(key, value.get());
+ return null;
+ }
+ public Object putStringKeyIfNotNull(String key, Object value) {
+ if (value!=null)
+ return putStringKey(key, value);
+ return null;
+ }
+
+ public boolean containsKey(HasConfigKey<?> key) {
+ return containsKey(key.getConfigKey());
+ }
+
+ public boolean containsKey(ConfigKey<?> key) {
+ return containsKey(key.getName());
+ }
+
+ public synchronized boolean containsKey(String key) {
+ return config.containsKey(key);
+ }
+
+ /** returns the value of this config key, falling back to its default (use containsKey to see whether it was contained);
+ * also marks it as having been used (use peek to prevent marking as used)
+ */
+ public <T> T get(ConfigKey<T> key) {
+ return get(key, true);
+ }
+
+ /** gets a value from a string-valued key or null; ConfigKey is preferred, but this is useful in some contexts (e.g. setting from flags) */
+ public Object getStringKey(String key) {
+ return getStringKeyMaybe(key).orNull();
+ }
+ /** gets a {@link Maybe}-wrapped value from a string-valued key; ConfigKey is preferred, but this is useful in some contexts (e.g. setting from flags) */
+ public @Nonnull Maybe<Object> getStringKeyMaybe(String key) {
+ return getStringKeyMaybe(key, true);
+ }
+
+ /** gets a {@link Maybe}-wrapped value from a key, inferring the type of that key (e.g. {@link ConfigKey} or {@link String}) */
+ @Beta
+ public Maybe<Object> getObjKeyMaybe(Object key) {
+ if (key instanceof HasConfigKey<?>) key = ((HasConfigKey<?>)key).getConfigKey();
+ if (key instanceof ConfigKey<?>) key = ((ConfigKey<?>)key).getName();
+ if (key instanceof String) {
+ return getStringKeyMaybe((String)key, true);
+ } else {
+ logInvalidKey(key);
+ return Maybe.absent();
+ }
+ }
+
+ /** like get, but without marking it as used */
+ public <T> T peek(ConfigKey<T> key) {
+ return get(key, false);
+ }
+
+ /** returns the first key in the list for which a value is explicitly set, then defaulting to defaulting value of preferred key */
+ public synchronized <T> T getFirst(ConfigKey<T> preferredKey, ConfigKey<T> ...otherCurrentKeysInOrderOfPreference) {
+ if (containsKey(preferredKey))
+ return get(preferredKey);
+ for (ConfigKey<T> key: otherCurrentKeysInOrderOfPreference) {
+ if (containsKey(key))
+ return get(key);
+ }
+ return get(preferredKey);
+ }
+
+ /** convenience for @see #getWithDeprecation(ConfigKey[], ConfigKey...) */
+ public Object getWithDeprecation(ConfigKey<?> key, ConfigKey<?> ...deprecatedKeys) {
+ return getWithDeprecation(new ConfigKey[] { key }, deprecatedKeys);
+ }
+
+ /** returns the value for the first key in the list for which a value is set,
+ * warning if any of the deprecated keys have a value which is different to that set on the first set current key
+ * (including warning if a deprecated key has a value but no current key does) */
+ public synchronized Object getWithDeprecation(ConfigKey<?>[] currentKeysInOrderOfPreference, ConfigKey<?> ...deprecatedKeys) {
+ // Get preferred key (or null)
+ ConfigKey<?> preferredKeyProvidingValue = null;
+ Object result = null;
+ boolean found = false;
+ for (ConfigKey<?> key: currentKeysInOrderOfPreference) {
+ if (containsKey(key)) {
+ preferredKeyProvidingValue = key;
+ result = get(preferredKeyProvidingValue);
+ found = true;
+ break;
+ }
+ }
+
+ // Check if any deprecated keys are set
+ ConfigKey<?> deprecatedKeyProvidingValue = null;
+ Object deprecatedResult = null;
+ boolean foundDeprecated = false;
+ for (ConfigKey<?> deprecatedKey: deprecatedKeys) {
+ Object x = null;
+ boolean foundX = false;
+ if (containsKey(deprecatedKey)) {
+ x = get(deprecatedKey);
+ foundX = true;
+ }
+ if (foundX) {
+ if (found) {
+ if (!Objects.equal(result, x)) {
+ log.warn("Conflicting value from deprecated key " +deprecatedKey+", value "+x+
+ "; using preferred key "+preferredKeyProvidingValue+" value "+result);
+ } else {
+ log.info("Deprecated key " +deprecatedKey+" ignored; has same value as preferred key "+preferredKeyProvidingValue+" ("+result+")");
+ }
+ } else if (foundDeprecated) {
+ if (!Objects.equal(result, x)) {
+ log.warn("Conflicting values from deprecated keys: using " +deprecatedKeyProvidingValue+" instead of "+deprecatedKey+
+ " (value "+deprecatedResult+" instead of "+x+")");
+ } else {
+ log.info("Deprecated key " +deprecatedKey+" ignored; has same value as other deprecated key "+preferredKeyProvidingValue+" ("+deprecatedResult+")");
+ }
+ } else {
+ // new value, from deprecated key
+ log.warn("Deprecated key " +deprecatedKey+" detected (supplying value "+x+"), "+
+ "; recommend changing to preferred key '"+currentKeysInOrderOfPreference[0]+"'; this will not be supported in future versions");
+ deprecatedResult = x;
+ deprecatedKeyProvidingValue = deprecatedKey;
+ foundDeprecated = true;
+ }
+ }
+ }
+
+ if (found) {
+ return result;
+ } else if (foundDeprecated) {
+ return deprecatedResult;
+ } else {
+ return currentKeysInOrderOfPreference[0].getDefaultValue();
+ }
+ }
+
+ protected <T> T get(ConfigKey<T> key, boolean markUsed) {
+ // TODO for now, no evaluation -- maps / closure content / other smart (self-extracting) keys are NOT supported
+ // (need a clean way to inject that behaviour, as well as desired TypeCoercions)
+ // this method, and the coercion, is not synchronized, nor does it need to be, because the "get" is synchronized.
+ return coerceFirstNonNullKeyValue(key, getStringKey(key.getName(), markUsed));
+ }
+
+ /** returns the first non-null value to be the type indicated by the key, or the keys default value if no non-null values are supplied */
+ public static <T> T coerceFirstNonNullKeyValue(ConfigKey<T> key, Object ...values) {
+ for (Object o: values)
+ if (o!=null) return TypeCoercions.coerce(o, key.getTypeToken());
+ return TypeCoercions.coerce(key.getDefaultValue(), key.getTypeToken());
+ }
+
+ protected Object getStringKey(String key, boolean markUsed) {
+ return getStringKeyMaybe(key, markUsed).orNull();
+ }
+ protected synchronized Maybe<Object> getStringKeyMaybe(String key, boolean markUsed) {
+ if (config.containsKey(key)) {
+ if (markUsed) markUsed(key);
+ return Maybe.of(config.get(key));
+ }
+ return Maybe.absent();
+ }
+
+ /** indicates that a string key in the config map has been accessed */
+ public synchronized void markUsed(String key) {
+ unusedConfig.remove(key);
+ }
+
+ public synchronized void clear() {
+ if (sealed)
+ throw new IllegalStateException("Cannot clear this config bag has been sealed and is now immutable.");
+ config.clear();
+ unusedConfig.clear();
+ }
+
+ public ConfigBag removeAll(ConfigKey<?> ...keys) {
+ for (ConfigKey<?> key: keys) remove(key);
+ return this;
+ }
+
+ public synchronized void remove(ConfigKey<?> key) {
+ remove(key.getName());
+ }
+
+ public ConfigBag removeAll(Iterable<String> keys) {
+ for (String key: keys) remove(key);
+ return this;
+ }
+
+ public synchronized void remove(String key) {
+ if (sealed)
+ throw new IllegalStateException("Cannot remove "+key+": this config bag has been sealed and is now immutable.");
+ config.remove(key);
+ unusedConfig.remove(key);
+ }
+
+ public ConfigBag copy(ConfigBag other) {
+ // ensure locks are taken in a canonical order to prevent deadlock
+ if (other==null) {
+ synchronized (this) {
+ return copyWhileSynched(other);
+ }
+ }
+ if (System.identityHashCode(other) < System.identityHashCode(this)) {
+ synchronized (other) {
+ synchronized (this) {
+ return copyWhileSynched(other);
+ }
+ }
+ } else {
+ synchronized (this) {
+ synchronized (other) {
+ return copyWhileSynched(other);
+ }
+ }
+ }
+ }
+
+ protected ConfigBag copyWhileSynched(ConfigBag other) {
+ if (sealed)
+ throw new IllegalStateException("Cannot copy "+other+" to "+this+": this config bag has been sealed and is now immutable.");
+ putAll(other.getAllConfig());
+ markAll(Sets.difference(other.getAllConfig().keySet(), other.getUnusedConfig().keySet()));
+ setDescription(other.getDescription());
+ return this;
+ }
+
+ public synchronized int size() {
+ return config.size();
+ }
+
+ public synchronized boolean isEmpty() {
+ return config.isEmpty();
+ }
+
+ public ConfigBag markAll(Iterable<String> usedFlags) {
+ for (String flag: usedFlags)
+ markUsed(flag);
+ return this;
+ }
+
+ public synchronized boolean isUnused(ConfigKey<?> key) {
+ return unusedConfig.containsKey(key.getName());
+ }
+
+ /** makes this config bag immutable; any attempts to change subsequently
+ * (apart from marking fields as used) will throw an exception
+ * <p>
+ * copies will be unsealed however
+ * <p>
+ * returns this for convenience (fluent usage) */
+ public ConfigBag seal() {
+ sealed = true;
+ if (live) {
+ // TODO How to ensure sealed?!
+ } else {
+ config = getAllConfig();
+ }
+ return this;
+ }
+
+ // TODO why have both this and mutable
+ /** @see #getAllConfigMutable() */
+ public Map<String, Object> getAllConfigRaw() {
+ return getAllConfigMutable();
+ }
+
+ @Override
+ public String toString() {
+ return JavaClassNames.simpleClassName(this)+"["+getAllConfigRaw()+"]";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/crypto/FluentKeySigner.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/crypto/FluentKeySigner.java b/core/src/main/java/org/apache/brooklyn/core/util/crypto/FluentKeySigner.java
new file mode 100644
index 0000000..1d0b030
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/crypto/FluentKeySigner.java
@@ -0,0 +1,192 @@
+/*
+ * 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.util.crypto;
+
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.cert.CertificateParsingException;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+
+import javax.security.auth.x500.X500Principal;
+
+import org.apache.brooklyn.core.internal.BrooklynInitialization;
+import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
+import org.bouncycastle.asn1.x509.X509Extension;
+import org.bouncycastle.jce.X509Principal;
+
+import brooklyn.util.exceptions.Exceptions;
+
+/** A fluent API which simplifies generating certificates (signed keys) */
+/* NB - re deprecation - we use deprecated X509V3CertificateGenerator still
+ * because the official replacement, X509v3CertificateBuilder,
+ * drags in an add'l dependency (bcmail) and is harder to use. */
+public class FluentKeySigner {
+
+ static { BrooklynInitialization.initSecureKeysBouncyCastleProvider(); }
+
+ protected X500Principal issuerPrincipal;
+ protected KeyPair issuerKey;
+
+ protected SecureRandom srand = new SecureRandom();
+
+ protected Date validityStartDate, validityEndDate;
+ protected BigInteger serialNumber;
+
+ protected String signatureAlgorithm = "MD5WithRSAEncryption";
+ protected AuthorityKeyIdentifier authorityKeyIdentifier;
+ protected X509Certificate authorityCertificate;
+
+ public FluentKeySigner(X500Principal issuerPrincipal, KeyPair issuerKey) {
+ this.issuerPrincipal = issuerPrincipal;
+ this.issuerKey = issuerKey;
+ validFromDaysAgo(7);
+ validForYears(10);
+ }
+ public FluentKeySigner(String issuerCommonName, KeyPair issuerKey) {
+ this(SecureKeys.getX500PrincipalWithCommonName(issuerCommonName), issuerKey);
+ }
+
+ public FluentKeySigner(String issuerCommonName) {
+ this(issuerCommonName, SecureKeys.newKeyPair());
+ }
+
+ public FluentKeySigner(X509Certificate caCert, KeyPair caKey) {
+ this(caCert.getIssuerX500Principal(), caKey);
+ authorityCertificate(caCert);
+ }
+
+ public KeyPair getKey() {
+ return issuerKey;
+ }
+
+ public X500Principal getPrincipal() {
+ return issuerPrincipal;
+ }
+
+ @SuppressWarnings("deprecation")
+ public String getCommonName() {
+// TODO see deprecation note at top of file
+ // for modernising, would RFC4519Style.cn work ?
+ return (String) new X509Principal(issuerPrincipal.getName()).getValues(org.bouncycastle.asn1.x509.X509Name.CN).elementAt(0);
+ }
+
+ public X509Certificate getAuthorityCertificate() {
+ return authorityCertificate;
+ }
+
+ public FluentKeySigner validFromDaysAgo(long days) {
+ return validFrom(new Date( (System.currentTimeMillis() / (1000L*60*60*24) - days) * 1000L*60*60*24));
+ }
+
+ public FluentKeySigner validFrom(Date d) {
+ validityStartDate = d;
+ return this;
+ }
+
+ public FluentKeySigner validForYears(long years) {
+ return validUntil(new Date( (System.currentTimeMillis() / (1000L*60*60*24) + 365*years) * 1000L*60*60*24));
+ }
+
+ public FluentKeySigner validUntil(Date d) {
+ validityEndDate = d;
+ return this;
+ }
+
+ /** use a hard-coded serial number; or make one up, if null */
+ public FluentKeySigner serialNumber(BigInteger serialNumber) {
+ this.serialNumber = serialNumber;
+ return this;
+ }
+
+ public FluentKeySigner signatureAlgorithm(String signatureAlgorithm) {
+ this.signatureAlgorithm = signatureAlgorithm;
+ return this;
+ }
+
+ @SuppressWarnings("deprecation")
+ public FluentKeySigner authorityCertificate(X509Certificate certificate) {
+ try {
+ authorityKeyIdentifier(new org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure(certificate));
+ this.authorityCertificate = certificate;
+ return this;
+ } catch (CertificateParsingException e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ public FluentKeySigner authorityKeyIdentifier(AuthorityKeyIdentifier authorityKeyIdentifier) {
+ this.authorityKeyIdentifier = authorityKeyIdentifier;
+ return this;
+ }
+
+ public FluentKeySigner selfsign() {
+ if (authorityCertificate!=null) throw new IllegalStateException("Signer already has certificate");
+ authorityCertificate(newCertificateFor(getCommonName(), getKey()));
+ return this;
+ }
+
+ // TODO see note re deprecation at start of file
+ @SuppressWarnings("deprecation")
+ public X509Certificate newCertificateFor(X500Principal subject, PublicKey keyToCertify) {
+ try {
+ org.bouncycastle.x509.X509V3CertificateGenerator v3CertGen = new org.bouncycastle.x509.X509V3CertificateGenerator();
+
+ v3CertGen.setSerialNumber(
+ serialNumber != null ? serialNumber :
+ // must be positive
+ BigInteger.valueOf(srand.nextLong()).abs().add(BigInteger.ONE));
+ v3CertGen.setIssuerDN(issuerPrincipal);
+ v3CertGen.setNotBefore(validityStartDate);
+ v3CertGen.setNotAfter(validityEndDate);
+ v3CertGen.setSignatureAlgorithm(signatureAlgorithm);
+
+ v3CertGen.setSubjectDN(subject);
+ v3CertGen.setPublicKey(keyToCertify);
+
+ v3CertGen.addExtension(X509Extension.subjectKeyIdentifier, false,
+ new org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure(keyToCertify));
+
+ if (authorityKeyIdentifier!=null)
+ v3CertGen.addExtension(X509Extension.authorityKeyIdentifier, false,
+ authorityKeyIdentifier);
+
+ X509Certificate pkCertificate = v3CertGen.generate(issuerKey.getPrivate(), "BC");
+ return pkCertificate;
+
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ public X509Certificate newCertificateFor(String commonName, PublicKey key) {
+// SecureKeys.getX509PrincipalWithCommonName(commonName)
+ return newCertificateFor(
+ SecureKeys.getX500PrincipalWithCommonName(commonName)
+// new X509Principal("CN=" + commonName + ", OU=None, O=None, L=None, C=None")
+ , key);
+ }
+
+ public X509Certificate newCertificateFor(String commonName, KeyPair key) {
+ return newCertificateFor(commonName, key.getPublic());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/crypto/SecureKeys.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/crypto/SecureKeys.java b/core/src/main/java/org/apache/brooklyn/core/util/crypto/SecureKeys.java
new file mode 100644
index 0000000..5e630a8
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/crypto/SecureKeys.java
@@ -0,0 +1,186 @@
+/*
+ * 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.util.crypto;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.StringWriter;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.Security;
+
+import org.apache.brooklyn.core.internal.BrooklynInitialization;
+import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
+import org.bouncycastle.jce.X509Principal;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.openssl.PEMDecryptorProvider;
+import org.bouncycastle.openssl.PEMEncryptedKeyPair;
+import org.bouncycastle.openssl.PEMKeyPair;
+import org.bouncycastle.openssl.PEMParser;
+import org.bouncycastle.openssl.PEMWriter;
+import org.bouncycastle.openssl.PasswordFinder;
+import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
+import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.util.crypto.AuthorizedKeysParser;
+import brooklyn.util.crypto.SecureKeysWithoutBouncyCastle;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.stream.Streams;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Throwables;
+
+/**
+ * Utility methods for generating and working with keys,
+ * extending the parent class with useful things provided by BouncyCastle crypto library.
+ * (Parent class is in a different project where BC is not included as a dependency.)
+ */
+public class SecureKeys extends SecureKeysWithoutBouncyCastle {
+
+ private static final Logger log = LoggerFactory.getLogger(SecureKeys.class);
+
+ static { BrooklynInitialization.initSecureKeysBouncyCastleProvider(); }
+
+ public static void initBouncyCastleProvider() {
+ Security.addProvider(new BouncyCastleProvider());
+ }
+
+ public static class PassphraseProblem extends IllegalStateException {
+ private static final long serialVersionUID = -3382824813899223447L;
+ public PassphraseProblem(String message) { super("Passphrase problem with this key: "+message); }
+ public PassphraseProblem(String message, Exception cause) { super("Passphrase problem with this key: "+message, cause); }
+ }
+
+ private SecureKeys() {}
+
+ /** RFC1773 order, with None for other values. Normally prefer X500Principal. */
+ public static X509Principal getX509PrincipalWithCommonName(String commonName) {
+ return new X509Principal("" + "C=None," + "L=None," + "O=None," + "OU=None," + "CN=" + commonName);
+ }
+
+ /** reads RSA or DSA / pem style private key files (viz {@link #toPem(KeyPair)}), extracting also the public key if possible
+ * @throws IllegalStateException on errors, in particular {@link PassphraseProblem} if that is the problem */
+ public static KeyPair readPem(InputStream input, final String passphrase) {
+ // TODO cache is only for fallback "reader" strategy (2015-01); delete when Parser confirmed working
+ byte[] cache = Streams.readFully(input);
+ input = new ByteArrayInputStream(cache);
+
+ try {
+ PEMParser pemParser = new PEMParser(new InputStreamReader(input));
+
+ Object object = pemParser.readObject();
+ pemParser.close();
+
+ JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
+ KeyPair kp = null;
+ if (object==null) {
+ throw new IllegalStateException("PEM parsing failed: missing or invalid data");
+ } else if (object instanceof PEMEncryptedKeyPair) {
+ if (passphrase==null) throw new PassphraseProblem("passphrase required");
+ try {
+ PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(passphrase.toCharArray());
+ kp = converter.getKeyPair(((PEMEncryptedKeyPair) object).decryptKeyPair(decProv));
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ throw new PassphraseProblem("wrong passphrase", e);
+ }
+ } else if (object instanceof PEMKeyPair) {
+ kp = converter.getKeyPair((PEMKeyPair) object);
+ } else if (object instanceof PrivateKeyInfo) {
+ PrivateKey privKey = converter.getPrivateKey((PrivateKeyInfo) object);
+ kp = new KeyPair(null, privKey);
+ } else {
+ throw new IllegalStateException("PEM parser support missing for: "+object);
+ }
+
+ return kp;
+
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+
+ // older code relied on PEMReader, now deprecated
+ // replaced with above based on http://stackoverflow.com/questions/14919048/bouncy-castle-pemreader-pemparser
+ // passes the same tests (Jan 2015) but leaving the old code as a fallback for the time being
+
+ input = new ByteArrayInputStream(cache);
+ try {
+ Security.addProvider(new BouncyCastleProvider());
+ @SuppressWarnings("deprecation")
+ org.bouncycastle.openssl.PEMReader pr = new org.bouncycastle.openssl.PEMReader(new InputStreamReader(input), new PasswordFinder() {
+ public char[] getPassword() {
+ return passphrase!=null ? passphrase.toCharArray() : new char[0];
+ }
+ });
+ @SuppressWarnings("deprecation")
+ KeyPair result = (KeyPair) pr.readObject();
+ pr.close();
+ if (result==null)
+ throw Exceptions.propagate(e);
+
+ log.warn("PEMParser failed when deprecated PEMReader succeeded, with "+result+"; had: "+e);
+
+ return result;
+
+ } catch (Exception e2) {
+ Exceptions.propagateIfFatal(e2);
+ throw Exceptions.propagate(e);
+ }
+ }
+ }
+
+ /** because KeyPair.equals is not implemented :( */
+ public static boolean equal(KeyPair k1, KeyPair k2) {
+ return Objects.equal(k2.getPrivate(), k1.getPrivate()) && Objects.equal(k2.getPublic(), k1.getPublic());
+ }
+
+ /** returns the PEM (base64, ie for id_rsa) string for the private key / key pair;
+ * this starts -----BEGIN PRIVATE KEY----- and ends similarly, like id_rsa.
+ * also see {@link #readPem(InputStream, String)} */
+ public static String toPem(KeyPair key) {
+ return stringPem(key);
+ }
+
+ /** returns id_rsa.pub style file, of public key */
+ public static String toPub(KeyPair key) {
+ return AuthorizedKeysParser.encodePublicKey(key.getPublic());
+ }
+
+ /** opposite of {@link #toPub(KeyPair)}, given text */
+ public static PublicKey fromPub(String pubText) {
+ return AuthorizedKeysParser.decodePublicKey(pubText);
+ }
+
+ /** @deprecated since 0.7.0, use {@link #toPem(KeyPair)} */ @Deprecated
+ public static String stringPem(KeyPair key) {
+ try {
+ StringWriter sw = new StringWriter();
+ PEMWriter w = new PEMWriter(sw);
+ w.writeObject(key);
+ w.close();
+ return sw.toString();
+ } catch (IOException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/file/ArchiveBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/file/ArchiveBuilder.java b/core/src/main/java/org/apache/brooklyn/core/util/file/ArchiveBuilder.java
new file mode 100644
index 0000000..069f10b
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/file/ArchiveBuilder.java
@@ -0,0 +1,424 @@
+/*
+ * 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.util.file;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Collections;
+import java.util.Map;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+import java.util.zip.ZipOutputStream;
+
+import org.apache.brooklyn.core.util.file.ArchiveUtils.ArchiveType;
+
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.os.Os;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.LinkedHashMultimap;
+import com.google.common.collect.Multimap;
+import com.google.common.io.Files;
+
+/**
+ * Build a Zip or Jar archive.
+ * <p>
+ * Supports creating temporary archives that will be deleted on exit, if no name is
+ * specified. The created file must be a Java archive type, with the extension {@code .zip},
+ * {@code .jar}, {@code .war} or {@code .ear}.
+ * <p>
+ * Example:
+ * <pre> File zip = ArchiveBuilder.archive("data/archive.zip")
+ * .addAt(new File("./pom.xml"), "")
+ * .addDirContentsAt(new File("./src"), "src/")
+ * .addAt(new File("/tmp/Extra.java"), "src/main/java/")
+ * .addDirContentsAt(new File("/tmp/overlay/"), "")
+ * .create();
+ * </pre>
+ * <p>
+ */
+@Beta
+public class ArchiveBuilder {
+
+ /**
+ * Create an {@link ArchiveBuilder} for an archive with the given name.
+ */
+ public static ArchiveBuilder archive(String archive) {
+ return new ArchiveBuilder(archive);
+ }
+
+ /**
+ * Create an {@link ArchiveBuilder} for a {@link ArchiveType#ZIP Zip} format archive.
+ */
+ public static ArchiveBuilder zip() {
+ return new ArchiveBuilder(ArchiveType.ZIP);
+ }
+
+ /**
+ * Create an {@link ArchiveBuilder} for a {@link ArchiveType#JAR Jar} format archive.
+ */
+ public static ArchiveBuilder jar() {
+ return new ArchiveBuilder(ArchiveType.JAR);
+ }
+
+ // TODO would be nice to support TAR and TGZ
+ // e.g. using commons-compress
+ // TarArchiveOutputStream out = new TarArchiveOutputStream(new GZIPOutputStream(bytes));
+ // but I think the way entries are done is slightly different so we'd need a bit of refactoring
+
+ private final ArchiveType type;
+ private File archive;
+ private Manifest manifest;
+ private Multimap<String, File> entries = LinkedHashMultimap.create();
+
+ private ArchiveBuilder() {
+ this(ArchiveType.ZIP);
+ }
+
+ private ArchiveBuilder(String filename) {
+ this(ArchiveType.of(filename));
+
+ named(filename);
+ }
+
+ private ArchiveBuilder(ArchiveType type) {
+ checkNotNull(type);
+ checkArgument(ArchiveType.ZIP_ARCHIVES.contains(type));
+
+ this.type = type;
+ this.manifest = new Manifest();
+ }
+
+ /**
+ * Set the location of the generated archive file.
+ */
+ public ArchiveBuilder named(String name) {
+ checkNotNull(name);
+ String ext = Files.getFileExtension(name);
+ if (ext.isEmpty()) {
+ name = name + "." + type.toString();
+ } else if (type != ArchiveType.of(name)) {
+ throw new IllegalArgumentException(String.format("Extension for '%s' did not match archive type of %s", ext, type));
+ }
+ this.archive = new File(Os.tidyPath(name));
+ return this;
+ }
+
+ /**
+ * @see #named(String)
+ */
+ public ArchiveBuilder named(File file) {
+ checkNotNull(file);
+ return named(file.getPath());
+ }
+
+ /**
+ * Add a manifest entry with the given {@code key} and {@code value}.
+ */
+ public ArchiveBuilder manifest(Object key, Object value) {
+ checkNotNull(key, "key");
+ checkNotNull(value, "value");
+ manifest.getMainAttributes().put(key, value);
+ return this;
+ }
+
+ /**
+ * Add the file located at the {@code filePath} to the archive,
+ * with some complicated base-name strategies.
+ *
+ * @deprecated since 0.7.0 use one of the other add methods which makes the strategy explicit */ @Deprecated
+ public ArchiveBuilder add(String filePath) {
+ checkNotNull(filePath, "filePath");
+ return add(new File(Os.tidyPath(filePath)));
+ }
+
+ /**
+ * Add the {@code file} to the archive.
+ * <p>
+ * If the file path is absolute, or points to a file above the current directory,
+ * the file is added to the archive as a top-level entry, using the file name only.
+ * For relative {@code filePath}s below the current directory, the file is added
+ * using the path given and is assumed to be located relative to the current
+ * working directory.
+ * <p>
+ * No checks for file existence are made at this stage.
+ *
+ * @see #entry(String, File)
+ * @deprecated since 0.7.0 use one of the other add methods which makes the strategy explicit */ @Deprecated
+ public ArchiveBuilder add(File file) {
+ checkNotNull(file, "file");
+ String filePath = Os.tidyPath(file.getPath());
+ if (file.isAbsolute() || filePath.startsWith("../")) {
+ return entry(Os.mergePaths(".", file.getName()), file);
+ } else {
+ return entry(Os.mergePaths(".", filePath), file);
+ }
+ }
+
+ /**
+ * Add the file located at the {@code fileSubPath}, relative to the {@code baseDir} on the local system,
+ * to the archive.
+ * <p>
+ * Uses the {@code fileSubPath} as the name of the file in the archive. Note that the
+ * file is found by concatenating the two path components using {@link Os#mergePaths(String...)},
+ * thus {@code fileSubPath} should not be absolute or point to a location above the current directory.
+ * <p>
+ * Use {@link #entry(String, String)} directly or {@link #entries(Map)} for complete
+ * control over file locations and names in the archive.
+ *
+ * @see #entry(String, String)
+ */
+ public ArchiveBuilder addFromLocalBaseDir(File baseDir, String fileSubPath) {
+ checkNotNull(baseDir, "baseDir");
+ checkNotNull(fileSubPath, "filePath");
+ return entry(Os.mergePaths(".", fileSubPath), Os.mergePaths(baseDir.getPath(), fileSubPath));
+ }
+ /** @deprecated since 0.7.0 use {@link #addFromLocalBaseDir(File, String)}, or
+ * one of the other add methods if adding relative to baseDir was not intended */ @Deprecated
+ public ArchiveBuilder addFromLocalBaseDir(String baseDir, String fileSubPath) {
+ return addFromLocalBaseDir(new File(baseDir), fileSubPath);
+ }
+ /** @deprecated since 0.7.0 use {@link #addFromLocalBaseDir(File, String)}, or
+ * one of the other add methods if adding relative to baseDir was not intended */ @Deprecated
+ public ArchiveBuilder add(String baseDir, String fileSubPath) {
+ return addFromLocalBaseDir(baseDir, fileSubPath);
+ }
+
+ /** adds the given file to the archive, preserving its name but putting under the given directory in the archive (may be <code>""</code> or <code>"./"</code>) */
+ public ArchiveBuilder addAt(File file, String archiveParentDir) {
+ checkNotNull(archiveParentDir, "archiveParentDir");
+ checkNotNull(file, "file");
+ return entry(Os.mergePaths(archiveParentDir, file.getName()), file);
+ }
+
+ /**
+ * Add the contents of the directory named {@code dirName} to the archive.
+ *
+ * @see #addDir(File)
+ * @deprecated since 0.7.0 use {@link #addDirContentsAt(File, String) */ @Deprecated
+ public ArchiveBuilder addDir(String dirName) {
+ checkNotNull(dirName, "dirName");
+ return addDir(new File(Os.tidyPath(dirName)));
+ }
+
+ /**
+ * Add the contents of the directory {@code dir} to the archive.
+ * The directory's name is not included; use {@link #addAtRoot(File)} if you want that behaviour.
+ * <p>
+ * Uses {@literal .} as the parent directory name for the contents.
+ *
+ * @see #entry(String, File)
+ */
+ public ArchiveBuilder addDirContentsAt(File dir, String archiveParentDir) {
+ checkNotNull(dir, "dir");
+ if (!dir.isDirectory()) throw new IllegalArgumentException(dir+" is not a directory; cannot add contents to archive");
+ return entry(archiveParentDir, dir);
+ }
+ /**
+ * As {@link #addDirContentsAt(File, String)},
+ * using {@literal .} as the parent directory name for the contents.
+ *
+ * @deprecated since 0.7.0 use {@link #addDirContentsAt(File, String)
+ * to clarify API, argument types, and be explicit about where it should be installed,
+ * because JARs seem to require <code>""<code> whereas ZIPs might want <code>"./"</code>. */ @Deprecated
+ public ArchiveBuilder addDir(File dir) {
+ return addDirContentsAt(dir, ".");
+ }
+
+ /**
+ * Add the collection of {@code files} to the archive.
+ *
+ * @see #add(String)
+ * @deprecated since 0.7.0 use one of the other add methods if keeping this file's path was not intended */ @Deprecated
+ public ArchiveBuilder add(Iterable<String> files) {
+ checkNotNull(files, "files");
+ for (String filePath : files) {
+ add(filePath);
+ }
+ return this;
+ }
+
+ /**
+ * Add the collection of {@code files}, relative to the {@code baseDir}, to
+ * the archive.
+ *
+ * @see #add(String, String)
+ * @deprecated since 0.7.0 use one of the other add methods if keeping this file's path was not intended */ @Deprecated
+ public ArchiveBuilder add(String baseDir, Iterable<String> files) {
+ checkNotNull(baseDir, "baseDir");
+ checkNotNull(files, "files");
+ for (String filePath : files) {
+ add(baseDir, filePath);
+ }
+ return this;
+ }
+
+ /**
+ * Add the {@code file} to the archive with the path {@code entryPath}.
+ *
+ * @see #entry(String, File)
+ */
+ public ArchiveBuilder entry(String entryPath, String filePath) {
+ checkNotNull(entryPath, "entryPath");
+ checkNotNull(filePath, "filePath");
+ return entry(entryPath, new File(filePath));
+ }
+
+ /**
+ * Add the {@code file} to the archive with the path {@code entryPath}.
+ */
+ public ArchiveBuilder entry(String entryPath, File file) {
+ checkNotNull(entryPath, "entryPath");
+ checkNotNull(file, "file");
+ this.entries.put(entryPath, file);
+ return this;
+ }
+
+ /**
+ * Add a {@link Map} of entries to the archive.
+ * <p>
+ * The keys should be the names of the file entries to be added to the archive and
+ * the value should point to the actual {@link File} to be added.
+ * <p>
+ * This allows complete control over the directory structure of the eventual archive,
+ * as the entry names do not need to bear any relationship to the name or location
+ * of the files on the filesystem.
+ */
+ public ArchiveBuilder entries(Map<String, File> entries) {
+ checkNotNull(entries, "entries");
+ for (Map.Entry<String, File> entry: entries.entrySet())
+ this.entries.put(entry.getKey(), entry.getValue());
+ return this;
+ }
+
+ /**
+ * Generates the archive and outputs it to the given stream, ignoring any file name.
+ * <p>
+ * This will add a manifest file if the type is a Jar archive.
+ */
+ public void stream(OutputStream output) {
+ try {
+ ZipOutputStream target;
+ if (type == ArchiveType.ZIP) {
+ target = new ZipOutputStream(output);
+ } else {
+ manifest(Attributes.Name.MANIFEST_VERSION, "1.0");
+ target = new JarOutputStream(output, manifest);
+ }
+ for (String entry : entries.keySet()) {
+ addToArchive(entry, entries.get(entry), target);
+ }
+ target.close();
+ } catch (IOException ioe) {
+ throw Exceptions.propagate(ioe);
+ }
+ }
+
+ /**
+ * Generates the archive, saving it with the given name.
+ */
+ public File create(String archiveFile) {
+ return named(archiveFile).create();
+ }
+
+ /**
+ * Generates the archive.
+ * <p>
+ * If no name has been specified, the archive will be created as a temporary file with
+ * a unique name, that is deleted on exit. Otherwise, the given name will be used.
+ */
+ public File create() {
+ if (archive == null) {
+ File temp = Os.newTempFile("brooklyn-archive", type.toString());
+ temp.deleteOnExit();
+ named(temp);
+ }
+ try {
+ OutputStream output = new FileOutputStream(archive);
+ stream(output);
+ output.close();
+ } catch (IOException ioe) {
+ throw Exceptions.propagate(ioe);
+ }
+ return archive;
+ }
+
+ /**
+ * Recursively add files to the archive.
+ * <p>
+ * Code adapted from this <a href="http://stackoverflow.com/questions/1281229/how-to-use-jaroutputstream-to-create-a-jar-file">example</a>
+ * <p>
+ * <strong>Note</strong> {@link File} provides no support for symbolic links, and as such there is
+ * no way to ensure that a symbolic link to a directory is not followed when traversing the
+ * tree. In this case, iterables created by this traverser could contain files that are
+ * outside of the given directory or even be infinite if there is a symbolic link loop.
+ */
+ private void addToArchive(String path, Iterable<File> sources, ZipOutputStream target) throws IOException {
+ int size = Iterables.size(sources);
+ if (size==0) return;
+ boolean isDirectory;
+ if (size>1) {
+ // it must be directories if we are putting multiple things here
+ isDirectory = true;
+ } else {
+ isDirectory = Iterables.getOnlyElement(sources).isDirectory();
+ }
+
+ String name = path.replace("\\", "/");
+ if (isDirectory) {
+ name += "/";
+ JarEntry entry = new JarEntry(name);
+
+ long lastModified=-1;
+ for (File source: sources)
+ if (source.lastModified()>lastModified)
+ lastModified = source.lastModified();
+
+ entry.setTime(lastModified);
+ target.putNextEntry(entry);
+ target.closeEntry();
+
+ for (File source: sources) {
+ if (!source.isDirectory()) {
+ throw new IllegalStateException("Cannot add multiple items at a path in archive unless they are directories: "+sources+" at "+path+" is not valid.");
+ }
+ Iterable<File> children = Files.fileTreeTraverser().children(source);
+ for (File child : children) {
+ addToArchive(Os.mergePaths(path, child.getName()), Collections.singleton(child), target);
+ }
+ }
+ return;
+ }
+
+ File source = Iterables.getOnlyElement(sources);
+ JarEntry entry = new JarEntry(name);
+ entry.setTime(source.lastModified());
+ target.putNextEntry(entry);
+ Files.asByteSource(source).copyTo(target);
+ target.closeEntry();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/file/ArchiveTasks.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/file/ArchiveTasks.java b/core/src/main/java/org/apache/brooklyn/core/util/file/ArchiveTasks.java
new file mode 100644
index 0000000..b58359a
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/file/ArchiveTasks.java
@@ -0,0 +1,58 @@
+/*
+ * 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.util.file;
+
+import java.util.Map;
+
+import org.apache.brooklyn.api.management.TaskAdaptable;
+import org.apache.brooklyn.api.management.TaskFactory;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.location.basic.SshMachineLocation;
+
+import brooklyn.util.net.Urls;
+
+public class ArchiveTasks {
+
+ /** as {@link #deploy(ResourceUtils, Map, String, SshMachineLocation, String, String, String)} with the most common parameters */
+ public static TaskFactory<?> deploy(final ResourceUtils optionalResolver, final String archiveUrl, final SshMachineLocation machine, final String destDir) {
+ return deploy(optionalResolver, null, archiveUrl, machine, destDir, false, null, null);
+ }
+
+ /** returns a task which installs and unpacks the given archive, as per {@link ArchiveUtils#deploy(ResourceUtils, Map, String, SshMachineLocation, String, String, String)};
+ * if allowNonarchivesOrKeepArchiveAfterDeploy is false, this task will fail if the item is not an archive;
+ * in cases where the download type is not clear in the URL but is known by the caller, supply a optionalDestFile including the appropriate file extension */
+ public static TaskFactory<?> deploy(final ResourceUtils resolver, final Map<String, ?> props, final String archiveUrl, final SshMachineLocation machine, final String destDir, final boolean allowNonarchivesOrKeepArchiveAfterDeploy, final String optionalTmpDir, final String optionalDestFile) {
+ return new TaskFactory<TaskAdaptable<?>>() {
+ @Override
+ public TaskAdaptable<?> newTask() {
+ return Tasks.<Void>builder().name("deploying "+Urls.getBasename(archiveUrl)).description("installing "+archiveUrl+" and unpacking to "+destDir).body(new Runnable() {
+ @Override
+ public void run() {
+ boolean unpacked = ArchiveUtils.deploy(resolver, props, archiveUrl, machine, destDir, allowNonarchivesOrKeepArchiveAfterDeploy, optionalTmpDir, optionalDestFile);
+ if (!unpacked && !allowNonarchivesOrKeepArchiveAfterDeploy) {
+ throw new IllegalStateException("Unable to unpack archive from "+archiveUrl+"; not able to infer archive type");
+ }
+ }
+ }).build();
+ }
+ };
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/file/ArchiveUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/file/ArchiveUtils.java b/core/src/main/java/org/apache/brooklyn/core/util/file/ArchiveUtils.java
new file mode 100644
index 0000000..8277a0d
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/file/ArchiveUtils.java
@@ -0,0 +1,351 @@
+/*
+ * 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.util.file;
+
+import static java.lang.String.format;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.EnumSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.core.util.task.ssh.SshTasks;
+import org.apache.brooklyn.location.basic.SshMachineLocation;
+
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.javalang.StackTraceSimplifier;
+import brooklyn.util.net.Urls;
+import brooklyn.util.os.Os;
+import brooklyn.util.ssh.BashCommands;
+import brooklyn.util.text.Strings;
+
+import com.google.common.base.Charsets;
+import com.google.common.base.Preconditions;
+import com.google.common.io.Files;
+
+public class ArchiveUtils {
+
+ private static final Logger log = LoggerFactory.getLogger(ArchiveUtils.class);
+
+ // TODO Make this a ConfigKey on the machine location
+ /** Number of attempts when copying a file to a remote server. */
+ public static final int NUM_RETRIES_FOR_COPYING = 5;
+
+ /**
+ * The types of archive that are supported by Brooklyn.
+ */
+ public static enum ArchiveType {
+ TAR,
+ TGZ,
+ TBZ,
+ ZIP,
+ JAR,
+ WAR,
+ EAR,
+ UNKNOWN;
+
+ /**
+ * Zip format archives used by Java.
+ */
+ public static Set<ArchiveType> ZIP_ARCHIVES = EnumSet.of(ArchiveType.ZIP, ArchiveType.JAR, ArchiveType.WAR, ArchiveType.EAR);
+
+ public static ArchiveUtils.ArchiveType of(String filename) {
+ if (filename == null) return null;
+ String ext = Files.getFileExtension(filename);
+ try {
+ return valueOf(ext.toUpperCase());
+ } catch (IllegalArgumentException iae) {
+ if (filename.toLowerCase().endsWith(".tar.gz")) {
+ return TGZ;
+ } else if (filename.toLowerCase().endsWith(".tar.bz") ||
+ filename.toLowerCase().endsWith(".tar.bz2") ||
+ filename.toLowerCase().endsWith(".tar.xz")) {
+ return TBZ;
+ } else {
+ return UNKNOWN;
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ if (UNKNOWN.equals(this)) {
+ return "";
+ } else {
+ return name().toLowerCase();
+ }
+ }
+ }
+
+ /**
+ * Returns the list of commands used to install support for an archive with the given name.
+ */
+ public static List<String> installCommands(String fileName) {
+ List<String> commands = new LinkedList<String>();
+ switch (ArchiveType.of(fileName)) {
+ case TAR:
+ case TGZ:
+ case TBZ:
+ commands.add(BashCommands.INSTALL_TAR);
+ break;
+ case ZIP:
+ commands.add(BashCommands.INSTALL_UNZIP);
+ break;
+ case JAR:
+ case WAR:
+ case EAR:
+ case UNKNOWN:
+ break;
+ }
+ return commands;
+ }
+
+ /**
+ * Returns the list of commands used to extract the contents of the archive with the given name.
+ * <p>
+ * Optionally, Java archives of type
+ *
+ * @see #extractCommands(String, String)
+ */
+ public static List<String> extractCommands(String fileName, String sourceDir, String targetDir, boolean extractJar) {
+ return extractCommands(fileName, sourceDir, targetDir, extractJar, true);
+ }
+
+ /** as {@link #extractCommands(String, String, String, boolean)}, but also with option to keep the original */
+ public static List<String> extractCommands(String fileName, String sourceDir, String targetDir, boolean extractJar, boolean keepOriginal) {
+ List<String> commands = new LinkedList<String>();
+ commands.add("cd " + targetDir);
+ String sourcePath = Os.mergePathsUnix(sourceDir, fileName);
+ switch (ArchiveType.of(fileName)) {
+ case TAR:
+ commands.add("tar xvf " + sourcePath);
+ break;
+ case TGZ:
+ commands.add("tar xvfz " + sourcePath);
+ break;
+ case TBZ:
+ commands.add("tar xvfj " + sourcePath);
+ break;
+ case ZIP:
+ commands.add("unzip " + sourcePath);
+ break;
+ case JAR:
+ case WAR:
+ case EAR:
+ if (extractJar) {
+ commands.add("jar -xvf " + sourcePath);
+ break;
+ }
+ case UNKNOWN:
+ if (!sourcePath.equals(Urls.mergePaths(targetDir, fileName))) {
+ commands.add("cp " + sourcePath + " " + targetDir);
+ } else {
+ keepOriginal = true;
+ // else we'd just end up deleting it!
+ // this branch will often lead to errors in any case, see the allowNonarchivesOrKeepArchiveAfterDeploy parameter
+ // in ArchiveTasks which calls through to here and then fails in the case corresponding to this code branch
+ }
+ break;
+ }
+ if (!keepOriginal && !commands.isEmpty())
+ commands.add("rm "+sourcePath);
+ return commands;
+ }
+
+ /**
+ * Returns the list of commands used to extract the contents of the archive with the given name.
+ * <p>
+ * The archive will be extracted in its current directory unless it is a Java archive of type {@code .jar},
+ * {@code .war} or {@code .ear}, which will be left as is.
+ *
+ * @see #extractCommands(String, String, String, boolean)
+ */
+ public static List<String> extractCommands(String fileName, String sourceDir) {
+ return extractCommands(fileName, sourceDir, ".", false);
+ }
+
+ /**
+ * Deploys an archive file to a remote machine and extracts the contents.
+ */
+ public static void deploy(String archiveUrl, SshMachineLocation machine, String destDir) {
+ deploy(MutableMap.<String, Object>of(), archiveUrl, machine, destDir);
+ }
+
+ /**
+ * Deploys an archive file to a remote machine and extracts the contents.
+ * <p>
+ * Copies the archive file from the given URL to the destination directory and extracts
+ * the contents. If the URL is a local directory, the contents are packaged as a Zip archive first.
+ *
+ * @see #deploy(String, SshMachineLocation, String, String)
+ * @see #deploy(Map, String, SshMachineLocation, String, String, String)
+ */
+ public static void deploy(Map<String, ?> props, String archiveUrl, SshMachineLocation machine, String destDir) {
+ if (Urls.isDirectory(archiveUrl)) {
+ File zipFile = ArchiveBuilder.zip().entry(".", Urls.toFile(archiveUrl)).create();
+ archiveUrl = zipFile.getAbsolutePath();
+ }
+
+ // Determine filename
+ String destFile = archiveUrl.contains("?") ? archiveUrl.substring(0, archiveUrl.indexOf('?')) : archiveUrl;
+ destFile = destFile.substring(destFile.lastIndexOf('/') + 1);
+
+ deploy(props, archiveUrl, machine, destDir, destFile);
+ }
+
+ /**
+ * Deploys an archive file to a remote machine and extracts the contents.
+ * <p>
+ * Copies the archive file from the given URL to a file in the destination directory and extracts
+ * the contents.
+ *
+ * @see #deploy(String, SshMachineLocation, String)
+ * @see #deploy(Map, String, SshMachineLocation, String, String, String)
+ */
+ public static void deploy(String archiveUrl, SshMachineLocation machine, String destDir, String destFile) {
+ deploy(MutableMap.<String, Object>of(), archiveUrl, machine, destDir, destDir, destFile);
+ }
+ public static void deploy(Map<String, ?> props, String archiveUrl, SshMachineLocation machine, String destDir, String destFile) {
+ deploy(props, archiveUrl, machine, destDir, destDir, destFile);
+ }
+ public static void deploy(Map<String, ?> props, String archiveUrl, SshMachineLocation machine, String tmpDir, String destDir, String destFile) {
+ deploy(null, props, archiveUrl, machine, destDir, true, tmpDir, destFile);
+ }
+
+ /**
+ * Deploys an archive file to a remote machine and extracts the contents.
+ * <p>
+ * Copies the archive file from the given URL to a file in a temporary directory and extracts
+ * the contents in the destination directory. For Java archives of type {@code .jar},
+ * {@code .war} or {@code .ear} the file is simply copied.
+ *
+ * @return true if the archive is downloaded AND unpacked; false if it is downloaded but not unpacked;
+ * throws if there was an error downloading or, for known archive types, unpacking.
+ *
+ * @see #deploy(String, SshMachineLocation, String)
+ * @see #deploy(Map, String, SshMachineLocation, String, String, String)
+ * @see #install(SshMachineLocation, String, String, int)
+ */
+ public static boolean deploy(ResourceUtils resolver, Map<String, ?> props, String archiveUrl, SshMachineLocation machine, String destDir, boolean keepArchiveAfterUnpacking, String optionalTmpDir, String optionalDestFile) {
+ String destFile = optionalDestFile;
+ if (destFile==null) destFile = Urls.getBasename(Preconditions.checkNotNull(archiveUrl, "archiveUrl"));
+ if (Strings.isBlank(destFile))
+ throw new IllegalStateException("Not given filename and cannot infer archive type from '"+archiveUrl+"'");
+
+ String tmpDir = optionalTmpDir;
+ if (tmpDir==null) tmpDir=Preconditions.checkNotNull(destDir, "destDir");
+ if (props==null) props = MutableMap.of();
+ String destPath = Os.mergePaths(tmpDir, destFile);
+
+ // Use the location mutex to prevent package manager locking issues
+ machine.acquireMutex("installing", "installing archive");
+ try {
+ int result = install(resolver, props, machine, archiveUrl, destPath, NUM_RETRIES_FOR_COPYING);
+ if (result != 0) {
+ throw new IllegalStateException(format("Unable to install archive %s to %s", archiveUrl, machine));
+ }
+
+ // extract, now using task if available
+ MutableList<String> commands = MutableList.copyOf(installCommands(destFile))
+ .appendAll(extractCommands(destFile, tmpDir, destDir, false, keepArchiveAfterUnpacking));
+ if (DynamicTasks.getTaskQueuingContext()!=null) {
+ result = DynamicTasks.queue(SshTasks.newSshExecTaskFactory(machine, commands.toArray(new String[0])).summary("extracting archive").requiringExitCodeZero()).get();
+ } else {
+ result = machine.execCommands(props, "extracting content", commands);
+ }
+ if (result != 0) {
+ throw new IllegalStateException(format("Failed to expand archive %s on %s", archiveUrl, machine));
+ }
+ return ArchiveType.of(destFile)!=ArchiveType.UNKNOWN;
+ } finally {
+ machine.releaseMutex("installing");
+ }
+ }
+
+ /**
+ * Installs a URL onto a remote machine.
+ *
+ * @see #install(Map, SshMachineLocation, String, String, int)
+ */
+ public static int install(SshMachineLocation machine, String urlToInstall, String target) {
+ return install(MutableMap.<String, Object>of(), machine, urlToInstall, target, NUM_RETRIES_FOR_COPYING);
+ }
+
+ /**
+ * Installs a URL onto a remote machine.
+ *
+ * @see #install(SshMachineLocation, String, String)
+ * @see SshMachineLocation#installTo(Map, String, String)
+ */
+ public static int install(Map<String, ?> props, SshMachineLocation machine, String urlToInstall, String target, int numAttempts) {
+ return install(null, props, machine, urlToInstall, target, numAttempts);
+ }
+
+ public static int install(ResourceUtils resolver, Map<String, ?> props, SshMachineLocation machine, String urlToInstall, String target, int numAttempts) {
+ if (resolver==null) resolver = ResourceUtils.create(machine);
+ Exception lastError = null;
+ int retriesRemaining = numAttempts;
+ int attemptNum = 0;
+ do {
+ attemptNum++;
+ try {
+ Tasks.setBlockingDetails("Installing "+urlToInstall+" at "+machine);
+ // TODO would be nice to have this in a task (and the things within it!)
+ return machine.installTo(resolver, props, urlToInstall, target);
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ lastError = e;
+ String stack = StackTraceSimplifier.toString(e);
+ if (stack.contains("net.schmizz.sshj.sftp.RemoteFile.write")) {
+ log.warn("Failed to transfer "+urlToInstall+" to "+machine+", retryable error, attempt "+attemptNum+"/"+numAttempts+": "+e);
+ continue;
+ }
+ log.warn("Failed to transfer "+urlToInstall+" to "+machine+", not a retryable error so failing: "+e);
+ throw Exceptions.propagate(e);
+ } finally {
+ Tasks.resetBlockingDetails();
+ }
+ } while (retriesRemaining --> 0);
+ throw Exceptions.propagate(lastError);
+ }
+
+ /**
+ * Copies the entire contents of a file to a String.
+ *
+ * @see com.google.common.io.Files#toString(File, java.nio.charset.Charset)
+ */
+ public static String readFullyString(File sourceFile) {
+ try {
+ return Files.toString(sourceFile, Charsets.UTF_8);
+ } catch (IOException ioe) {
+ throw Exceptions.propagate(ioe);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/flags/ClassCoercionException.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/flags/ClassCoercionException.java b/core/src/main/java/org/apache/brooklyn/core/util/flags/ClassCoercionException.java
new file mode 100644
index 0000000..72c8698
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/flags/ClassCoercionException.java
@@ -0,0 +1,39 @@
+/*
+ * 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.util.flags;
+
+/**
+ * Thrown to indicate that {@link TypeCoercions} could not cast an object from one
+ * class to another.
+ */
+public class ClassCoercionException extends ClassCastException {
+ public ClassCoercionException() {
+ super();
+ }
+
+ /**
+ * Constructs a <code>ClassCoercionException</code> with the specified
+ * detail message.
+ *
+ * @param s the detail message.
+ */
+ public ClassCoercionException(String s) {
+ super(s);
+ }
+}
[14/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/task/system/SystemTasksTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/task/system/SystemTasksTest.java b/core/src/test/java/brooklyn/util/task/system/SystemTasksTest.java
deleted file mode 100644
index e60310d..0000000
--- a/core/src/test/java/brooklyn/util/task/system/SystemTasksTest.java
+++ /dev/null
@@ -1,134 +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 brooklyn.util.task.system;
-
-import java.io.File;
-
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.core.management.internal.LocalManagementContext;
-import org.testng.Assert;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.entity.basic.Entities;
-import brooklyn.util.os.Os;
-import brooklyn.util.task.ssh.SshTasks;
-
-/**
- * Some tests for {@link SystemTasks}. See {@link SshTasks}.
- */
-public class SystemTasksTest {
-
- ManagementContext mgmt;
- File tempDir;
-
- boolean failureExpected;
-
- @BeforeMethod(alwaysRun=true)
- public void setup() throws Exception {
- mgmt = new LocalManagementContext();
-
- clearExpectedFailure();
- tempDir = Os.newTempDir(getClass());
- }
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws Exception {
- if (mgmt != null) Entities.destroyAll(mgmt);
- mgmt = null;
- tempDir = Os.deleteRecursively(tempDir).asNullOrThrowing();
- checkExpectedFailure();
- }
-
- protected void checkExpectedFailure() {
- if (failureExpected) {
- clearExpectedFailure();
- Assert.fail("Test should have thrown an exception but it did not.");
- }
- }
-
- protected void clearExpectedFailure() {
- failureExpected = false;
- }
-
- protected void setExpectingFailure() {
- failureExpected = true;
- }
-
-
- protected <T> ProcessTaskWrapper<T> submit(final ProcessTaskFactory<T> tf) {
- ProcessTaskWrapper<T> t = tf.newTask();
- mgmt.getExecutionManager().submit(t);
- return t;
- }
-
- @Test(groups="Integration")
- public void testExecEchoHello() {
- ProcessTaskWrapper<Integer> t = submit(SystemTasks.exec("sleep 1 ; echo hello world"));
- Assert.assertFalse(t.isDone());
- Assert.assertEquals(t.get(), (Integer)0);
- Assert.assertEquals(t.getTask().getUnchecked(), (Integer)0);
- Assert.assertEquals(t.getStdout().trim(), "hello world");
- }
-
- // FIXME Behaviour of Bash shell changes from 3.x to 4.x so test is disabled
- @Test(groups="Integration", enabled=false)
- public void testSubshellExitScriptDoesNotExit() {
- checkSubshellExitDoesNotExit(taskSubshellExit().runAsScript());
- }
-
- @Test(groups="Integration")
- public void testSubshellExitCommandDoesNotExit() {
- checkSubshellExitDoesNotExit(taskSubshellExit().runAsCommand());
- }
-
- public ProcessTaskFactory<Integer> taskSubshellExit() {
- return SystemTasks.exec("echo hello", "( exit 1 )", "echo bye code $?");
- }
-
- public void checkSubshellExitDoesNotExit(ProcessTaskFactory<Integer> task) {
- ProcessTaskWrapper<Integer> t = submit(task);
- t.block();
- Assert.assertEquals(t.get(), (Integer)0);
- Assert.assertTrue(t.getStdout().contains("bye code 1"), "stdout is: "+t.getStdout());
- }
-
- @Test(groups="Integration")
- public void testGroupExitScriptDoesNotExit() {
- checkGroupExitDoesExit(taskGroupExit().runAsScript());
- }
-
- @Test(groups="Integration")
- public void testGroupExitCommandDoesNotExit() {
- checkGroupExitDoesExit(taskGroupExit().runAsCommand());
- }
-
- public ProcessTaskFactory<Integer> taskGroupExit() {
- return SystemTasks.exec("echo hello", "{ exit 1 ; }", "echo bye code $?");
- }
-
- public void checkGroupExitDoesExit(ProcessTaskFactory<Integer> task) {
- ProcessTaskWrapper<Integer> t = submit(task);
- t.block();
- Assert.assertEquals(t.get(), (Integer)1);
- Assert.assertFalse(t.getStdout().contains("bye"), "stdout is: "+t.getStdout());
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/text/DataUriSchemeParserTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/text/DataUriSchemeParserTest.java b/core/src/test/java/brooklyn/util/text/DataUriSchemeParserTest.java
deleted file mode 100644
index ff2dc9b..0000000
--- a/core/src/test/java/brooklyn/util/text/DataUriSchemeParserTest.java
+++ /dev/null
@@ -1,52 +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 brooklyn.util.text;
-
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-
-import org.bouncycastle.util.encoders.Base64;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-public class DataUriSchemeParserTest {
-
- @Test
- public void testSimple() {
- Assert.assertEquals(new DataUriSchemeParser("data:,hello").parse().getDataAsString(), "hello");
- Assert.assertEquals(DataUriSchemeParser.toString("data:,hello"), "hello");
- }
-
- @Test
- public void testMimeType() throws UnsupportedEncodingException {
- DataUriSchemeParser p = new DataUriSchemeParser("data:application/json,"+URLEncoder.encode("{ }", "US-ASCII")).parse();
- Assert.assertEquals(p.getMimeType(), "application/json");
- Assert.assertEquals(p.getData(), "{ }".getBytes());
- }
-
- @Test
- public void testBase64() {
- Assert.assertEquals(DataUriSchemeParser.toString(
- "data:;base64,"+new String(Base64.encode("hello".getBytes()))),
- "hello");
- }
-
- // TODO test pictures, etc
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/text/TemplateProcessorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/text/TemplateProcessorTest.java b/core/src/test/java/brooklyn/util/text/TemplateProcessorTest.java
deleted file mode 100644
index bd8ef87..0000000
--- a/core/src/test/java/brooklyn/util/text/TemplateProcessorTest.java
+++ /dev/null
@@ -1,179 +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 brooklyn.util.text;
-
-import static org.testng.Assert.assertEquals;
-
-import org.apache.brooklyn.api.entity.proxying.EntitySpec;
-import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
-import org.apache.brooklyn.test.entity.TestApplication;
-import org.apache.brooklyn.test.entity.TestEntity;
-import org.testng.Assert;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.entity.BrooklynAppUnitTestSupport;
-import brooklyn.event.basic.DependentConfiguration;
-import brooklyn.test.FixedLocaleTest;
-
-import com.google.common.collect.ImmutableMap;
-
-public class TemplateProcessorTest extends BrooklynAppUnitTestSupport {
- private FixedLocaleTest localeFix = new FixedLocaleTest();
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() throws Exception {
- super.setUp();
- localeFix.setUp();
- }
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws Exception {
- super.tearDown();
- localeFix.tearDown();
- }
-
- @Test
- public void testAdditionalArgs() {
- String templateContents = "${mykey}";
- String result = TemplateProcessor.processTemplateContents(templateContents, app, ImmutableMap.of("mykey", "myval"));
- assertEquals(result, "myval");
- }
-
- @Test
- public void testEntityConfig() {
- TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class)
- .configure(TestEntity.CONF_NAME, "myval"));
- String templateContents = "${config['"+TestEntity.CONF_NAME.getName()+"']}";
- String result = TemplateProcessor.processTemplateContents(templateContents, entity, ImmutableMap.<String,Object>of());
- assertEquals(result, "myval");
- }
-
- @Test
- public void testEntityConfigNumber() {
- TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class)
- .configure(TestEntity.CONF_OBJECT, 123456));
- String templateContents = "${config['"+TestEntity.CONF_OBJECT.getName()+"']}";
- String result = TemplateProcessor.processTemplateContents(templateContents, entity, ImmutableMap.<String,Object>of());
- assertEquals(result, "123,456");
- }
-
- @Test
- public void testEntityConfigNumberUnadorned() {
- // ?c is needed to avoid commas (i always forget this!)
- TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class)
- .configure(TestEntity.CONF_OBJECT, 123456));
- String templateContents = "${config['"+TestEntity.CONF_OBJECT.getName()+"']?c}";
- String result = TemplateProcessor.processTemplateContents(templateContents, entity, ImmutableMap.<String,Object>of());
- assertEquals(result, "123456");
- }
-
- @Test
- public void testGetSysProp() {
- System.setProperty("testGetSysProp", "myval");
-
- String templateContents = "${javaSysProps['testGetSysProp']}";
- String result = TemplateProcessor.processTemplateContents(templateContents, app, ImmutableMap.<String,Object>of());
- assertEquals(result, "myval");
- }
-
- @Test
- public void testEntityGetterMethod() {
- String templateContents = "${entity.id}";
- String result = TemplateProcessor.processTemplateContents(templateContents, app, ImmutableMap.<String,Object>of());
- assertEquals(result, app.getId());
- }
-
- @Test
- public void testManagementContextConfig() {
- mgmt.getBrooklynProperties().put("globalmykey", "myval");
- String templateContents = "${mgmt.globalmykey}";
- String result = TemplateProcessor.processTemplateContents(templateContents, app, ImmutableMap.<String,Object>of());
- assertEquals(result, "myval");
- }
-
- @Test
- public void testManagementContextDefaultValue() {
- String templateContents = "${(missing)!\"defval\"}";
- Object result = TemplateProcessor.processTemplateContents(templateContents, app, ImmutableMap.<String,Object>of());
- assertEquals(result, "defval");
- }
-
- @Test
- public void testManagementContextDefaultValueInDotMissingValue() {
- String templateContents = "${(mgmt.missing.more_missing)!\"defval\"}";
- Object result = TemplateProcessor.processTemplateContents(templateContents, app, ImmutableMap.<String,Object>of());
- assertEquals(result, "defval");
- }
-
- @Test
- public void testManagementContextConfigWithDot() {
- mgmt.getBrooklynProperties().put("global.mykey", "myval");
- String templateContents = "${mgmt['global.mykey']}";
- String result = TemplateProcessor.processTemplateContents(templateContents, app, ImmutableMap.<String,Object>of());
- assertEquals(result, "myval");
- }
-
- @Test
- public void testManagementContextErrors() {
- try {
- // NB: dot has special meaning so this should fail; must be accessed using bracket notation as above
- mgmt.getBrooklynProperties().put("global.mykey", "myval");
- String templateContents = "${mgmt.global.mykey}";
- TemplateProcessor.processTemplateContents(templateContents, app, ImmutableMap.<String,Object>of());
- Assert.fail("Should not have found value with intermediate dot");
- } catch (Exception e) {
- Assert.assertTrue(e.toString().contains("global"), "Should have mentioned missing key 'global' in error");
- }
- }
-
- @Test
- public void testApplyTemplatedConfigWithAttributeWhenReady() {
- app.setAttribute(TestApplication.MY_ATTRIBUTE, "myval");
-
- TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class)
- .configure(TestEntity.CONF_NAME, DependentConfiguration.attributeWhenReady(app, TestApplication.MY_ATTRIBUTE)));
-
- String templateContents = "${config['"+TestEntity.CONF_NAME.getName()+"']}";
- String result = TemplateProcessor.processTemplateContents(templateContents, entity, ImmutableMap.<String,Object>of());
- assertEquals(result, "myval");
- }
-
- @Test
- public void testDotSeparatedKey() {
- String templateContents = "${a.b}";
- String result = TemplateProcessor.processTemplateContents(templateContents, (ManagementContextInternal)null,
- ImmutableMap.<String,Object>of("a.b", "myval"));
- assertEquals(result, "myval");
- }
-
- @Test
- public void testDotSeparatedKeyCollisionFailure() {
- String templateContents = "${aaa.bbb}";
- try {
- TemplateProcessor.processTemplateContents(templateContents, (ManagementContextInternal)null,
- ImmutableMap.<String,Object>of("aaa.bbb", "myval", "aaa", "blocker"));
- Assert.fail("Should not have found value with intermediate dot where prefix is overridden");
- } catch (Exception e) {
- Assert.assertTrue(e.toString().contains("aaa"), "Should have mentioned missing key 'aaa' in error");
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/xstream/CompilerCompatibilityTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/xstream/CompilerCompatibilityTest.java b/core/src/test/java/brooklyn/util/xstream/CompilerCompatibilityTest.java
deleted file mode 100644
index 5a1f844..0000000
--- a/core/src/test/java/brooklyn/util/xstream/CompilerCompatibilityTest.java
+++ /dev/null
@@ -1,154 +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 brooklyn.util.xstream;
-
-import static org.testng.Assert.assertTrue;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.reflect.Field;
-
-import org.testng.annotations.Test;
-
-import brooklyn.util.xstream.CompilerCompatibilityTest.EnclosingClass.DynamicClass;
-import brooklyn.util.xstream.CompilerCompatibilityTest.EnclosingClass.DynamicExtendingClass;
-import brooklyn.util.xstream.CompilerCompatibilityTest.EnclosingClass.EnclosingDynamicClass;
-import brooklyn.util.xstream.CompilerCompatibilityTest.EnclosingClass.EnclosingDynamicClass.NestedDynamicClass;
-
-import com.thoughtworks.xstream.XStream;
-import com.thoughtworks.xstream.mapper.MapperWrapper;
-
-// To get the generated synthetic fields use the command:
-/*
- find core/target/test-classes -name CompilerCompatibilityTest\$EnclosingClass\$* | \
- sed s@core/target/test-classes/@@ | sed 's@.class$@@' | sed s@/@.@g | \
- xargs javap -classpath core/target/test-classes/ | grep -B1 this
-*/
-@SuppressWarnings("unused")
-public class CompilerCompatibilityTest {
- private EnclosingClass enclosingClass = new EnclosingClass();
- private DynamicClass dynamicClass = enclosingClass.new DynamicClass();
- private DynamicExtendingClass dynamicExtendingClass = enclosingClass.new DynamicExtendingClass();
- private EnclosingDynamicClass enclosingDynamicClass = enclosingClass.new EnclosingDynamicClass();
- private NestedDynamicClass nestedDynamicClass = enclosingDynamicClass.new NestedDynamicClass();
-// NOT SUPPORTED
-// private DynamicExtendingClassWithDifferentScope dynamicExtendingClassWithDifferentScope =
-// enclosingClass.new DynamicExtendingClassWithDifferentScope(enclosingDynamicClass);
-
- public static class EnclosingClass {
- public class DynamicClass {
- //Oracle/OpenJDK/IBM generates
- //final EnclosingClass this$0;
-
- //eclipse-[groovy-]compiler generates
- //final EnclosingClass this$1;
- }
-
- public class DynamicExtendingClass extends DynamicClass {
- //The field here masks the parent field
-
- //Oracle/OpenJDK/IBM generates
- //final EnclosingClass this$0;
-
- //eclipse-[groovy-]compiler generates
- //final EnclosingClass this$1;
- }
-
- public class EnclosingDynamicClass {
- //Oracle/OpenJDK/IBM generates
- //final EnclosingClass this$0;
-
- //eclipse-[groovy-]compiler generates
- //final EnclosingClass this$1;
-
- public class NestedDynamicClass {
- //Oracle/OpenJDK/IBM generates
- //final EnclosingClass this$1;
-
- //eclipse-[groovy-]compiler generates
- //final EnclosingClass this$2;
- }
- }
-
-// WARNING: Combination NOT SUPPORTED. Not enough information in XML to deserialize reliably,
-// having in mind that different compilers could be used for parent/child classes.
-// If we really need to, we can extend the heuristic to check for field types or assume that
-// only one compiler was used for the whole class hierarchy covering some more cases.
-//
-// The problem is that we have two fields with different names, without relation between the
-// indexes in each one. Changing compilers (or combination of compilers) could change the
-// indexes independently in each field. This makes it impossible to infer which field in the xml
-// maps to which field in the object.
-// When having identical field names with parent classes XStream will put a defined-in attribute
-// which makes it possible to deserialize, but it can't be forced to put it in each element.
-//
- public class DynamicExtendingClassWithDifferentScope extends NestedDynamicClass {
- //Oracle/OpenJDK/IBM generates
- //final EnclosingClass this$0;
-
- //eclipse-[groovy-]compiler generates
- //final EnclosingClass this$1;
-
- //constructor required to compile
- public DynamicExtendingClassWithDifferentScope(EnclosingDynamicClass superEnclosingScope) {
- superEnclosingScope.super();
- }
- }
- }
-
- @Test
- public void testXStreamDeserialize() throws Exception {
- deserialize("/brooklyn/entity/rebind/compiler_compatibility_eclipse.xml");
- deserialize("/brooklyn/entity/rebind/compiler_compatibility_oracle.xml");
- }
-
- private void deserialize(String inputUrl) throws Exception {
- XStream xstream = new XStream() {
- @Override
- protected MapperWrapper wrapMapper(MapperWrapper next) {
- return new CompilerIndependentOuterClassFieldMapper(super.wrapMapper(next));
- }
- };
-
- InputStream in = this.getClass().getResourceAsStream(inputUrl);
- try {
- Object obj = xstream.fromXML(in);
- assertNonNullOuterFields(obj);
- } finally {
- in.close();
- }
- }
-
- private void assertNonNullOuterFields(Object obj) throws Exception {
- Field[] testInstances = obj.getClass().getDeclaredFields();
- for (Field instanceField : testInstances) {
- Object instance = instanceField.get(obj);
- Class<?> type = instance.getClass();
- do {
- for (Field field : type.getDeclaredFields()) {
- if (field.getName().startsWith("this$")) {
- Object value = field.get(instance);
- assertTrue(value != null, field + " should not be null");
- }
- }
- type = type.getSuperclass();
- } while (type != null);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/xstream/ConverterTestFixture.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/xstream/ConverterTestFixture.java b/core/src/test/java/brooklyn/util/xstream/ConverterTestFixture.java
deleted file mode 100644
index bf566ba..0000000
--- a/core/src/test/java/brooklyn/util/xstream/ConverterTestFixture.java
+++ /dev/null
@@ -1,40 +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 brooklyn.util.xstream;
-
-import org.testng.Assert;
-
-import com.thoughtworks.xstream.XStream;
-
-public class ConverterTestFixture {
-
- protected Object assertX(Object obj, String fmt) {
- XStream xstream = new XStream();
- registerConverters(xstream);
- String s1 = xstream.toXML(obj);
- Assert.assertEquals(s1, fmt);
- Object out = xstream.fromXML(s1);
- Assert.assertEquals(out, obj);
- return out;
- }
-
- protected void registerConverters(XStream xstream) {
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/xstream/EnumCaseForgivingConverterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/xstream/EnumCaseForgivingConverterTest.java b/core/src/test/java/brooklyn/util/xstream/EnumCaseForgivingConverterTest.java
deleted file mode 100644
index f22f91b..0000000
--- a/core/src/test/java/brooklyn/util/xstream/EnumCaseForgivingConverterTest.java
+++ /dev/null
@@ -1,52 +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 brooklyn.util.xstream;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.fail;
-
-import org.testng.annotations.Test;
-
-public class EnumCaseForgivingConverterTest {
-
- public enum MyEnum {
- FOO,
- BaR;
- }
-
- @Test
- public void testFindsCaseInsensitive() throws Exception {
- assertEquals(EnumCaseForgivingConverter.resolve(MyEnum.class, "FOO"), MyEnum.FOO);
- assertEquals(EnumCaseForgivingConverter.resolve(MyEnum.class, "foo"), MyEnum.FOO);
- assertEquals(EnumCaseForgivingConverter.resolve(MyEnum.class, "Foo"), MyEnum.FOO);
- assertEquals(EnumCaseForgivingConverter.resolve(MyEnum.class, "BAR"), MyEnum.BaR);
- assertEquals(EnumCaseForgivingConverter.resolve(MyEnum.class, "bar"), MyEnum.BaR);
- assertEquals(EnumCaseForgivingConverter.resolve(MyEnum.class, "Bar"), MyEnum.BaR);
- }
-
- @Test
- public void testFailsIfNoMatch() throws Exception {
- try {
- assertEquals(EnumCaseForgivingConverter.resolve(MyEnum.class, "DoesNotExist"), MyEnum.BaR);
- fail();
- } catch (IllegalArgumentException e) {
- if (!e.toString().matches(".*No enum.*MyEnum.DOESNOTEXIST")) throw e;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/xstream/ImmutableListConverterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/xstream/ImmutableListConverterTest.java b/core/src/test/java/brooklyn/util/xstream/ImmutableListConverterTest.java
deleted file mode 100644
index f8d8855..0000000
--- a/core/src/test/java/brooklyn/util/xstream/ImmutableListConverterTest.java
+++ /dev/null
@@ -1,59 +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 brooklyn.util.xstream;
-
-import java.net.UnknownHostException;
-
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableList;
-import com.thoughtworks.xstream.XStream;
-
-@Test
-public class ImmutableListConverterTest extends ConverterTestFixture {
-
- protected void registerConverters(XStream xstream) {
- super.registerConverters(xstream);
- xstream.aliasType("ImmutableList", ImmutableList.class);
- xstream.registerConverter(new ImmutableListConverter(xstream.getMapper()));
- }
-
- @Test
- public void testImmutableEmptyList() throws UnknownHostException {
- assertX(ImmutableList.of(), "<ImmutableList/>");
- }
-
- @Test
- public void testImmutableSingletonDoubleList() throws UnknownHostException {
- assertX(ImmutableList.of(1.2d), "<ImmutableList>\n <double>1.2</double>\n</ImmutableList>");
- }
-
- @Test
- public void testImmutableTwoValStringList() throws UnknownHostException {
- assertX(ImmutableList.of("a","b"), "<ImmutableList>\n <string>a</string>\n <string>b</string>\n</ImmutableList>");
- }
-
- @Test
- public void testImmutableEmptyListStaysImmutable() throws UnknownHostException {
- Object x = assertX(ImmutableList.of(), "<ImmutableList/>");
- Assert.assertTrue(x instanceof ImmutableList);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/xstream/InetAddressConverterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/xstream/InetAddressConverterTest.java b/core/src/test/java/brooklyn/util/xstream/InetAddressConverterTest.java
deleted file mode 100644
index 237c670..0000000
--- a/core/src/test/java/brooklyn/util/xstream/InetAddressConverterTest.java
+++ /dev/null
@@ -1,41 +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 brooklyn.util.xstream;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
-import org.testng.annotations.Test;
-
-import com.thoughtworks.xstream.XStream;
-
-@Test
-public class InetAddressConverterTest extends ConverterTestFixture {
-
- protected void registerConverters(XStream xstream) {
- super.registerConverters(xstream);
- xstream.registerConverter(new Inet4AddressConverter());
- }
-
- public void testFoo1234() throws UnknownHostException {
- assertX(InetAddress.getByAddress("foo", new byte[] { 1, 2, 3, 4 }),
- "<java.net.Inet4Address>foo/1.2.3.4</java.net.Inet4Address>");
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/xstream/StringKeyMapConverterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/xstream/StringKeyMapConverterTest.java b/core/src/test/java/brooklyn/util/xstream/StringKeyMapConverterTest.java
deleted file mode 100644
index 7d30bc2..0000000
--- a/core/src/test/java/brooklyn/util/xstream/StringKeyMapConverterTest.java
+++ /dev/null
@@ -1,77 +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 brooklyn.util.xstream;
-
-import java.net.UnknownHostException;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-import org.testng.annotations.Test;
-
-import brooklyn.util.collections.MutableMap;
-
-import com.google.common.collect.Maps;
-import com.thoughtworks.xstream.XStream;
-
-@SuppressWarnings({ "rawtypes", "unchecked" })
-@Test
-public class StringKeyMapConverterTest extends ConverterTestFixture {
-
- protected void registerConverters(XStream xstream) {
- super.registerConverters(xstream);
- xstream.alias("map", Map.class, LinkedHashMap.class);
- xstream.alias("MutableMap", MutableMap.class);
- xstream.registerConverter(new StringKeyMapConverter(xstream.getMapper()), /* priority */ 10);
- }
-
- @Test
- public void testSimple() throws UnknownHostException {
- Map m = Maps.newLinkedHashMap();
- m.put("a", "v");
- assertX(m, "<map>\n <a>v</a>\n</map>");
- }
-
- @Test
- public void testDouble() throws UnknownHostException {
- Map m = Maps.newLinkedHashMap();
- m.put("a", "v");
- m.put("x", 1.0d);
- assertX(m, "<map>\n <a>v</a>\n <x type=\"double\">1.0</x>\n</map>");
- }
-
- @Test
- public void testEmpty() throws UnknownHostException {
- Map m = Maps.newLinkedHashMap();
- assertX(m, "<map/>");
- }
-
- @Test
- public void testBigSpacedKeyInMutableMap() throws UnknownHostException {
- Map m = MutableMap.of("a b", "x");
- assertX(m, "<MutableMap>\n <entry key=\"a b\">x</entry>\n</MutableMap>");
- }
-
- @Test
- public void testWithNumericKey() throws UnknownHostException {
- Map m = Maps.newLinkedHashMap();
- m.put("123", "v");
- m.put("a", "v2");
- assertX(m, "<map>\n <entry key=\"123\">v</entry>\n <a>v2</a>\n</map>");
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/xstream/XmlUtilTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/xstream/XmlUtilTest.java b/core/src/test/java/brooklyn/util/xstream/XmlUtilTest.java
deleted file mode 100644
index a81e299..0000000
--- a/core/src/test/java/brooklyn/util/xstream/XmlUtilTest.java
+++ /dev/null
@@ -1,33 +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 brooklyn.util.xstream;
-
-import static org.testng.Assert.assertEquals;
-
-import org.testng.annotations.Test;
-
-
-public class XmlUtilTest {
-
- @Test
- public void testXpath() throws Exception {
- String xml = "<a><b>myb</b></a>";
- assertEquals(XmlUtil.xpath(xml, "/a/b[text()]"), "myb");
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogDtoTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogDtoTest.java b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogDtoTest.java
index 90e039d..3229aac 100644
--- a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogDtoTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogDtoTest.java
@@ -39,12 +39,12 @@ import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.catalog.internal.CatalogXmlSerializer;
import org.apache.brooklyn.core.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.util.BrooklynMavenArtifacts;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestEntity;
import brooklyn.entity.basic.Entities;
-import brooklyn.util.BrooklynMavenArtifacts;
import brooklyn.util.maven.MavenRetriever;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogLoadTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogLoadTest.java b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogLoadTest.java
index eea4933..fb28780 100644
--- a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogLoadTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogLoadTest.java
@@ -28,8 +28,7 @@ import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
import org.apache.brooklyn.core.catalog.internal.CatalogDto;
import org.apache.brooklyn.core.catalog.internal.CatalogItemDtoAbstract;
import org.apache.brooklyn.core.catalog.internal.CatalogXmlSerializer;
-
-import brooklyn.util.ResourceUtils;
+import org.apache.brooklyn.core.util.ResourceUtils;
import com.google.common.base.Joiner;
import com.google.common.collect.Iterables;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogScanTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogScanTest.java b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogScanTest.java
index 2d5abad..0ccb709 100644
--- a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogScanTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogScanTest.java
@@ -34,11 +34,11 @@ import org.apache.brooklyn.core.catalog.CatalogPredicates;
import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
import org.apache.brooklyn.core.catalog.internal.MyCatalogItems.MySillyAppTemplate;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.util.ResourceUtils;
import brooklyn.config.BrooklynProperties;
import brooklyn.config.BrooklynServerConfig;
import brooklyn.entity.basic.Entities;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.net.Urls;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/management/entitlement/AcmeEntitlementManagerTestFixture.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/entitlement/AcmeEntitlementManagerTestFixture.java b/core/src/test/java/org/apache/brooklyn/core/management/entitlement/AcmeEntitlementManagerTestFixture.java
index 5689da2..24b1a1d 100644
--- a/core/src/test/java/org/apache/brooklyn/core/management/entitlement/AcmeEntitlementManagerTestFixture.java
+++ b/core/src/test/java/org/apache/brooklyn/core/management/entitlement/AcmeEntitlementManagerTestFixture.java
@@ -30,6 +30,7 @@ import org.apache.brooklyn.core.management.entitlement.NotEntitledException;
import org.apache.brooklyn.core.management.entitlement.WebEntitlementContext;
import org.apache.brooklyn.core.management.entitlement.Entitlements.EntityAndItem;
import org.apache.brooklyn.core.management.entitlement.Entitlements.StringAndArgument;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
@@ -42,7 +43,6 @@ import brooklyn.config.BrooklynProperties;
import brooklyn.entity.basic.ApplicationBuilder;
import brooklyn.entity.basic.BasicApplication;
import brooklyn.entity.basic.Entities;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
public abstract class AcmeEntitlementManagerTestFixture {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/management/entitlement/EntityEntitlementTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/entitlement/EntityEntitlementTest.java b/core/src/test/java/org/apache/brooklyn/core/management/entitlement/EntityEntitlementTest.java
index bb25740..7181c99 100644
--- a/core/src/test/java/org/apache/brooklyn/core/management/entitlement/EntityEntitlementTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/management/entitlement/EntityEntitlementTest.java
@@ -27,6 +27,7 @@ import org.apache.brooklyn.core.management.entitlement.NotEntitledException;
import org.apache.brooklyn.core.management.entitlement.Entitlements.EntityAndItem;
import org.apache.brooklyn.core.management.entitlement.Entitlements.StringAndArgument;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -40,7 +41,6 @@ import brooklyn.config.BrooklynProperties;
import brooklyn.entity.basic.ApplicationBuilder;
import brooklyn.entity.basic.BasicApplication;
import brooklyn.entity.basic.Entities;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
public class EntityEntitlementTest {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/management/internal/EntityExecutionManagerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/internal/EntityExecutionManagerTest.java b/core/src/test/java/org/apache/brooklyn/core/management/internal/EntityExecutionManagerTest.java
index 7f35bba..721057d 100644
--- a/core/src/test/java/org/apache/brooklyn/core/management/internal/EntityExecutionManagerTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/management/internal/EntityExecutionManagerTest.java
@@ -37,6 +37,10 @@ import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.core.management.internal.BrooklynGarbageCollector;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.util.task.BasicExecutionManager;
+import org.apache.brooklyn.core.util.task.ExecutionListener;
+import org.apache.brooklyn.core.util.task.TaskBuilder;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestEntity;
@@ -58,10 +62,6 @@ import brooklyn.test.Asserts;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.javalang.JavaClassNames;
import brooklyn.util.repeat.Repeater;
-import brooklyn.util.task.BasicExecutionManager;
-import brooklyn.util.task.ExecutionListener;
-import brooklyn.util.task.TaskBuilder;
-import brooklyn.util.task.Tasks;
import brooklyn.util.time.Duration;
import brooklyn.util.time.Time;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiStandaloneTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiStandaloneTest.java b/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiStandaloneTest.java
index 7f1cc48..7180b1b 100644
--- a/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiStandaloneTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiStandaloneTest.java
@@ -27,6 +27,9 @@ import java.util.List;
import java.util.jar.JarInputStream;
import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.osgi.Osgis;
+import org.apache.brooklyn.core.util.osgi.Osgis.ManifestHelper;
import org.apache.brooklyn.test.TestResourceUnavailableException;
import brooklyn.util.exceptions.Exceptions;
@@ -43,14 +46,11 @@ import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableSet;
import brooklyn.util.maven.MavenArtifact;
import brooklyn.util.maven.MavenRetriever;
import brooklyn.util.net.Urls;
import brooklyn.util.os.Os;
-import brooklyn.util.osgi.Osgis;
-import brooklyn.util.osgi.Osgis.ManifestHelper;
import brooklyn.util.stream.Streams;
/**
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiVersionMoreEntityTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiVersionMoreEntityTest.java b/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiVersionMoreEntityTest.java
index 7220e47..edc73d6 100644
--- a/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiVersionMoreEntityTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiVersionMoreEntityTest.java
@@ -45,6 +45,7 @@ import org.apache.brooklyn.core.catalog.internal.CatalogTestUtils;
import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.util.osgi.Osgis;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.effector.Effectors;
@@ -57,7 +58,6 @@ import org.apache.brooklyn.test.entity.TestApplication;
import brooklyn.util.guava.Maybe;
import brooklyn.util.os.Os;
-import brooklyn.util.osgi.Osgis;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/BrooklynMavenArtifactsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/BrooklynMavenArtifactsTest.java b/core/src/test/java/org/apache/brooklyn/core/util/BrooklynMavenArtifactsTest.java
new file mode 100644
index 0000000..a86d1e0
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/BrooklynMavenArtifactsTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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.util;
+
+import org.apache.brooklyn.core.util.BrooklynMavenArtifacts;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import brooklyn.test.Asserts;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.maven.MavenArtifact;
+import brooklyn.util.maven.MavenRetriever;
+import brooklyn.util.stream.Streams;
+import brooklyn.util.text.Strings;
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Time;
+
+@Test
+public class BrooklynMavenArtifactsTest {
+
+ private static final Logger log = LoggerFactory.getLogger(BrooklynMavenArtifactsTest.class);
+
+ @Test(groups="Integration")
+ public void testUtilsCommon() {
+ ResourceUtils.create(this).checkUrlExists(BrooklynMavenArtifacts.localUrlForJar("brooklyn-utils-common"));
+ }
+
+ @Test(groups="Integration")
+ public void testExampleWar() {
+ String url = BrooklynMavenArtifacts.localUrl("example", "brooklyn-example-hello-world-sql-webapp", "war");
+ ResourceUtils.create(this).checkUrlExists(url);
+ log.info("found example war at: "+url);
+ }
+
+ @Test(groups="Integration")
+ // runs without internet but doesn't assert what it should, and can take a long time, so integration
+ public void testBadExampleWar() {
+ String url = BrooklynMavenArtifacts.localUrl("example", "brooklyn-example-GOODBYE-world-sql-webapp", "war");
+ Assert.assertFalse(ResourceUtils.create(this).doesUrlExist(url), "should not exist: "+url);
+ }
+
+ public void testHostedIsHttp() {
+ String common = BrooklynMavenArtifacts.hostedUrlForJar("brooklyn-utils-common");
+ log.info("online should be at: "+common);
+ Assert.assertTrue(common.startsWith("http"));
+ }
+
+ @Test(groups="Integration")
+ public void testHistoricHosted() {
+ // NB: this should be a version known to be up at sonatype or maven central, NOT necessarily the current version!
+ String snapshot = MavenRetriever.hostedUrl(MavenArtifact.fromCoordinate("org.apache.brooklyn:brooklyn-utils-common:jar:0.7.0-SNAPSHOT"));
+ log.info("Sample snapshot URL is: "+snapshot);
+ checkValidArchive(snapshot);
+ ResourceUtils.create(this).checkUrlExists(snapshot);
+
+ // NB: this should be a version known to be up at sonatype or maven central, NOT necessarily the current version!
+ String release = MavenRetriever.hostedUrl(MavenArtifact.fromCoordinate("io.brooklyn:brooklyn-utils-common:jar:0.6.0"));
+ log.info("Sample release URL is: "+release);
+ checkValidArchive(release);
+ }
+
+ private void checkValidArchive(final String url) {
+ // Note have seen response code 500 from repository.apache.org, for
+ // https://repository.apache.org/service/local/artifact/maven/redirect?r=snapshots&v=0.7.0-SNAPSHOT&g=org.apache.brooklyn&a=brooklyn-utils-common&e=jar
+ // Therefore willing to retry, rather than failing immediately.
+ Asserts.succeedsEventually(new Runnable() {
+ @Override public void run() {
+ try {
+ byte[] bytes = Streams.readFully(ResourceUtils.create(this).getResourceFromUrl(url));
+ // confirm this follow redirects!
+ Assert.assertTrue(bytes.length > 100*1000, "download of "+url+" is suspect ("+Strings.makeSizeString(bytes.length)+")");
+ // (could also check it is a zip etc)
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
+ }});
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/ResourceUtilsHttpTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/ResourceUtilsHttpTest.java b/core/src/test/java/org/apache/brooklyn/core/util/ResourceUtilsHttpTest.java
new file mode 100644
index 0000000..6ea434d
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/ResourceUtilsHttpTest.java
@@ -0,0 +1,197 @@
+/*
+ * 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.util;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.http.HttpException;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.localserver.RequestBasicAuth;
+import org.apache.http.localserver.ResponseBasicUnauthorized;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.protocol.HttpRequestHandler;
+import org.apache.http.protocol.ResponseServer;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import brooklyn.test.TestHttpRequestHandler;
+import brooklyn.test.TestHttpServer;
+import brooklyn.util.stream.Streams;
+import brooklyn.util.text.Strings;
+
+public class ResourceUtilsHttpTest {
+ private ResourceUtils utils;
+ private TestHttpServer server;
+ private String baseUrl;
+
+ @BeforeClass(alwaysRun=true)
+ public void setUp() throws Exception {
+ utils = ResourceUtils.create(this, "mycontext");
+ server = new TestHttpServer()
+ .interceptor(new ResponseServer())
+ .interceptor(new ResponseBasicUnauthorized())
+ .interceptor(new RequestBasicAuth())
+ .handler("/simple", new TestHttpRequestHandler().response("OK"))
+ .handler("/empty", new TestHttpRequestHandler().code(HttpStatus.SC_NO_CONTENT))
+ .handler("/missing", new TestHttpRequestHandler().code(HttpStatus.SC_NOT_FOUND).response("Missing"))
+ .handler("/redirect", new TestHttpRequestHandler().code(HttpStatus.SC_MOVED_TEMPORARILY).response("Redirect").header("Location", "/simple"))
+ .handler("/cycle", new TestHttpRequestHandler().code(HttpStatus.SC_MOVED_TEMPORARILY).response("Redirect").header("Location", "/cycle"))
+ .handler("/secure", new TestHttpRequestHandler().code(HttpStatus.SC_MOVED_TEMPORARILY).response("Redirect").header("Location", "https://0.0.0.0/"))
+ .handler("/auth", new AuthHandler("test", "test", "OK"))
+ .handler("/auth_escape", new AuthHandler("test@me:/", "test", "OK"))
+ .handler("/auth_escape2", new AuthHandler("test@me:test", "", "OK"))
+ .handler("/no_credentials", new CheckNoCredentials())
+ .start();
+ baseUrl = server.getUrl();
+ }
+
+ @AfterClass(alwaysRun=true)
+ public void tearDown() throws Exception {
+ server.stop();
+ }
+
+ @Test
+ public void testGet() throws Exception {
+ InputStream stream = utils.getResourceFromUrl(baseUrl + "/simple");
+ assertEquals(Streams.readFullyString(stream), "OK");
+ }
+
+ @Test
+ public void testGetEmpty() throws Exception {
+ InputStream stream = utils.getResourceFromUrl(baseUrl + "/empty");
+ assertEquals(Streams.readFullyString(stream), "");
+ }
+
+ @Test
+ public void testGetProtected() throws Exception {
+ String url = baseUrl.replace("http://", "http://test:test@") + "/auth";
+ InputStream stream = utils.getResourceFromUrl(url);
+ assertEquals(Streams.readFullyString(stream), "OK");
+ }
+
+ @Test
+ public void testGetProtectedEscape() throws Exception {
+ String url = baseUrl.replace("http://", "http://test%40me%3A%2F:test@") + "/auth_escape";
+ InputStream stream = utils.getResourceFromUrl(url);
+ assertEquals(Streams.readFullyString(stream), "OK");
+ }
+
+ @Test
+ public void testGetProtectedEscape2() throws Exception {
+ String url = baseUrl.replace("http://", "http://test%40me%3Atest@") + "/auth_escape2";
+ InputStream stream = utils.getResourceFromUrl(url);
+ assertEquals(Streams.readFullyString(stream), "OK");
+ }
+
+ @Test(expectedExceptions = RuntimeException.class)
+ public void testProtectedFailsWithoutCredentials() throws Exception {
+ utils.getResourceFromUrl(baseUrl + "/auth");
+ }
+
+ @Test
+ public void testInvalidCredentialsNotPassed() throws Exception {
+ String url = baseUrl + "/no_credentials?no:auth@needed";
+ InputStream stream = utils.getResourceFromUrl(url);
+ assertEquals(Streams.readFullyString(stream), "OK");
+ }
+
+ @Test
+ public void testRedirect() throws Exception {
+ InputStream stream = utils.getResourceFromUrl(baseUrl + "/redirect");
+ assertEquals(Streams.readFullyString(stream), "OK");
+ }
+
+ @Test(expectedExceptions = RuntimeException.class)
+ public void testCycleRedirect() throws Exception {
+ InputStream stream = utils.getResourceFromUrl(baseUrl + "/cycle");
+ assertEquals(Streams.readFullyString(stream), "OK");
+ }
+
+ @Test(expectedExceptions = RuntimeException.class)
+ public void testGetMissing() throws Exception {
+ utils.getResourceFromUrl(baseUrl + "/missing");
+ }
+
+ @Test(expectedExceptions = RuntimeException.class)
+ public void testFollowsProtoChange() throws Exception {
+ utils.getResourceFromUrl(baseUrl + "/secure");
+ }
+
+ // See https://github.com/brooklyncentral/brooklyn/issues/1338
+ @Test(groups={"Integration"})
+ public void testResourceFromUrlFollowsRedirect() throws Exception {
+ String contents = new ResourceUtils(this).getResourceAsString("http://bit.ly/brooklyn-visitors-creation-script");
+ assertFalse(contents.contains("bit.ly"), "contents="+contents);
+ }
+
+ private static class AuthHandler implements HttpRequestHandler {
+ private String username;
+ private String password;
+ private String responseBody;
+
+ public AuthHandler(String username, String password, String response) {
+ this.username = username;
+ this.password = password;
+ this.responseBody = response;
+ }
+
+ @Override
+ public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException {
+ String creds = (String) context.getAttribute("creds");
+ if (creds == null || !creds.equals(getExpectedCredentials())) {
+ response.setStatusCode(HttpStatus.SC_UNAUTHORIZED);
+ } else {
+ response.setEntity(new StringEntity(responseBody));
+ }
+ }
+
+ private String getExpectedCredentials() {
+ if (Strings.isEmpty(password)) {
+ return username;
+ } else {
+ return username + ":" + password;
+ }
+ }
+
+ }
+
+ private static class CheckNoCredentials implements HttpRequestHandler {
+
+ @Override
+ public void handle(HttpRequest request, HttpResponse response,
+ HttpContext context) throws HttpException, IOException {
+ String creds = (String) context.getAttribute("creds");
+ if (creds == null) {
+ response.setEntity(new StringEntity("OK"));
+ } else {
+ response.setStatusCode(HttpStatus.SC_BAD_REQUEST);
+ }
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/ResourceUtilsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/ResourceUtilsTest.java b/core/src/test/java/org/apache/brooklyn/core/util/ResourceUtilsTest.java
new file mode 100644
index 0000000..10cf455
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/ResourceUtilsTest.java
@@ -0,0 +1,190 @@
+/*
+ * 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.util;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Properties;
+
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import brooklyn.util.net.Urls;
+import brooklyn.util.os.Os;
+import brooklyn.util.stream.Streams;
+import brooklyn.util.text.Identifiers;
+
+import com.google.common.base.Charsets;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.io.Files;
+
+public class ResourceUtilsTest {
+
+ private static final Logger log = LoggerFactory.getLogger(ResourceUtilsTest.class);
+
+ private String tempFileContents = "abc";
+ private ResourceUtils utils;
+ private File tempFile;
+
+ @BeforeClass(alwaysRun=true)
+ public void setUp() throws Exception {
+ utils = ResourceUtils.create(this, "mycontext");
+ tempFile = Os.writeToTempFile(new ByteArrayInputStream(tempFileContents.getBytes()), "resourceutils-test", ".txt");
+ }
+
+ @AfterClass(alwaysRun=true)
+ public void tearDown() throws Exception {
+ if (tempFile != null) tempFile.delete();
+ }
+
+ @Test
+ public void testWriteStreamToTempFile() throws Exception {
+ File tempFileLocal = Os.writeToTempFile(new ByteArrayInputStream("mycontents".getBytes()), "resourceutils-test", ".txt");
+ try {
+ List<String> lines = Files.readLines(tempFileLocal, Charsets.UTF_8);
+ assertEquals(lines, ImmutableList.of("mycontents"));
+ } finally {
+ tempFileLocal.delete();
+ }
+ }
+
+ @Test
+ public void testPropertiesStreamToTempFile() throws Exception {
+ Properties props = new Properties();
+ props.setProperty("mykey", "myval");
+ File tempFileLocal = Os.writePropertiesToTempFile(props, "resourceutils-test", ".txt");
+ FileInputStream fis = null;
+ try {
+ fis = new FileInputStream(tempFileLocal);
+ Properties props2 = new Properties();
+ props2.load(fis);
+ assertEquals(props2.getProperty("mykey"), "myval");
+ } finally {
+ Streams.closeQuietly(fis);
+ tempFileLocal.delete();
+ }
+ }
+
+ @Test
+ public void testGetResourceViaClasspathWithPrefix() throws Exception {
+ InputStream stream = utils.getResourceFromUrl("classpath://brooklyn/config/sample.properties");
+ assertNotNull(stream);
+ }
+
+ @Test
+ public void testGetResourceViaClasspathWithoutPrefix() throws Exception {
+ InputStream stream = utils.getResourceFromUrl("/brooklyn/config/sample.properties");
+ assertNotNull(stream);
+ }
+
+ @Test
+ public void testGetResourceViaFileWithPrefix() throws Exception {
+ // The correct format for file URLs is file:///<absolute path>.
+ // On UNIX file:///tmp.
+ // On Windows both file:/C:/temp and file:///C:/temp are supported by Java,
+ // while Windows itself supports the latter only.
+ // Note that file://C:/temp is *wrong*, because C: is interpreted as the host
+ InputStream stream = utils.getResourceFromUrl(tempFile.toURI().toURL().toString());
+ assertEquals(Streams.readFullyString(stream), tempFileContents);
+ }
+
+ @Test
+ public void testGetResourceViaFileWithoutPrefix() throws Exception {
+ InputStream stream = utils.getResourceFromUrl(tempFile.getAbsolutePath());
+ assertEquals(Streams.readFullyString(stream), tempFileContents);
+ }
+
+ @Test
+ public void testClassLoaderDir() throws Exception {
+ String d = utils.getClassLoaderDir();
+ log.info("Found resource "+this+" in: "+d);
+ assertTrue(new File(d, "brooklyn/util/").exists());
+ }
+
+ @Test
+ public void testClassLoaderDirFromJar() throws Exception {
+ String d = utils.getClassLoaderDir("java/lang/Object.class");
+ log.info("Found Object in: "+d);
+ assertTrue(d.toLowerCase().endsWith(".jar"));
+ }
+
+ @Test
+ public void testClassLoaderDirFromJarWithSlash() throws Exception {
+ String d = utils.getClassLoaderDir("/java/lang/Object.class");
+ log.info("Found Object in: "+d);
+ assertTrue(d.toLowerCase().endsWith(".jar"));
+ }
+
+ @Test(expectedExceptions={NoSuchElementException.class})
+ public void testClassLoaderDirNotFound() throws Exception {
+ String d = utils.getClassLoaderDir("/somewhere/not/found/XXX.xxx");
+ // above should fail
+ log.warn("Uh oh found imaginary resource in: "+d);
+ }
+
+ @Test(groups="Integration")
+ public void testGetResourceViaSftp() throws Exception {
+ InputStream stream = utils.getResourceFromUrl("sftp://localhost:"+tempFile.getAbsolutePath());
+ assertEquals(Streams.readFullyString(stream), tempFileContents);
+ }
+
+ @Test(groups="Integration")
+ public void testGetResourceViaSftpWithUsername() throws Exception {
+ String user = System.getProperty("user.name");
+ InputStream stream = utils.getResourceFromUrl("sftp://"+user+"@localhost:"+tempFile.getAbsolutePath());
+ assertEquals(Streams.readFullyString(stream), tempFileContents);
+ }
+
+ @Test
+ public void testDataUrl() throws Exception {
+ assertEquals(utils.getResourceAsString("data:,hello"), "hello");
+ assertEquals(utils.getResourceAsString("data:,hello%20world"), "hello world");
+ // above is correct. below are not valid ... but we accept them anyway
+ assertEquals(utils.getResourceAsString("data:hello"), "hello");
+ assertEquals(utils.getResourceAsString("data://hello"), "hello");
+ assertEquals(utils.getResourceAsString("data:hello world"), "hello world");
+ assertEquals(utils.getResourceAsString(Urls.asDataUrlBase64("hello world")), "hello world");
+
+ String longString = Identifiers.makeRandomId(256);
+ for (int a=32; a<128; a++) longString += (char)a;
+ assertEquals(utils.getResourceAsString(Urls.asDataUrlBase64(longString)), longString);
+ }
+
+ @Test
+ public void testGetResources() {
+ Iterable<URL> manifests = ResourceUtils.create().getResources("META-INF/MANIFEST.MF");
+ assertFalse(Iterables.isEmpty(manifests));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/config/ConfigBagTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/config/ConfigBagTest.java b/core/src/test/java/org/apache/brooklyn/core/util/config/ConfigBagTest.java
new file mode 100644
index 0000000..f4db6c2
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/config/ConfigBagTest.java
@@ -0,0 +1,193 @@
+/*
+ * 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.util.config;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.config.ConfigBagTest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.time.Duration;
+
+public class ConfigBagTest {
+
+ @SuppressWarnings("unused")
+ private static final Logger log = LoggerFactory.getLogger(ConfigBagTest.class);
+
+ private static final ConfigKey<String> K1 = ConfigKeys.newStringConfigKey("k1");
+ private static final ConfigKey<String> K2 = ConfigKeys.newStringConfigKey("k2");
+ private static final ConfigKey<String> K3 = ConfigKeys.newStringConfigKey("k3");
+
+ @Test
+ public void testPutAndGet() {
+ ConfigBag bag = ConfigBag.newInstance();
+ bag.put(K1, "v1");
+ assertEquals(bag.get(K1), "v1");
+ }
+
+ @Test
+ public void testPutStringAndGet() {
+ ConfigBag bag = ConfigBag.newInstance();
+ bag.putAsStringKey(K1.getName(), "v1");
+ assertEquals(bag.get(K1), "v1");
+ }
+
+ @Test
+ public void testUnused() {
+ ConfigBag bag = ConfigBag.newInstance();
+ bag.put(K1, "v1");
+ bag.put(K2, "v2a");
+ assertEquals(bag.get(K1), "v1");
+ assertEquals(bag.getUnusedConfig().size(), 1);
+ assertEquals(bag.peek(K2), "v2a");
+ assertEquals(bag.getUnusedConfig().size(), 1);
+ assertEquals(bag.get(K2), "v2a");
+ Assert.assertTrue(bag.getUnusedConfig().isEmpty());
+ }
+
+ @Test
+ public void testOrder() {
+ ConfigBag bag = ConfigBag.newInstance();
+ bag.put(K1, "v1");
+ bag.put(K2, "v2");
+ bag.put(K3, "v3");
+ Assert.assertEquals(MutableList.copyOf(bag.getAllConfig().keySet()), MutableList.of(K1.getName(), K2.getName(), K3.getName()));
+ Assert.assertEquals(MutableList.copyOf(bag.getAllConfig().values()), MutableList.of("v1", "v2", "v3"));
+ }
+
+ @Test
+ public void testCopyOverwriteAndGet() {
+ ConfigBag bag1 = ConfigBag.newInstance();
+ bag1.put(K1, "v1");
+ bag1.put(K2, "v2a");
+ bag1.put(K3, "v3");
+ assertEquals(bag1.get(K1), "v1");
+
+ ConfigBag bag2 = ConfigBag.newInstanceCopying(bag1).putAll(MutableMap.of(K2, "v2b"));
+ assertEquals(bag1.getUnusedConfig().size(), 2);
+ assertEquals(bag2.getUnusedConfig().size(), 2);
+
+ assertEquals(bag2.get(K1), "v1");
+ assertEquals(bag1.get(K2), "v2a");
+ assertEquals(bag1.getUnusedConfig().size(), 1);
+ assertEquals(bag2.getUnusedConfig().size(), 2);
+
+ assertEquals(bag2.get(K2), "v2b");
+ assertEquals(bag2.getUnusedConfig().size(), 1);
+
+ assertEquals(bag2.get(K3), "v3");
+ assertEquals(bag2.getUnusedConfig().size(), 0);
+ assertEquals(bag1.getUnusedConfig().size(), 1);
+ }
+
+ @Test
+ public void testCopyExtendingAndGet() {
+ ConfigBag bag1 = ConfigBag.newInstance();
+ bag1.put(K1, "v1");
+ bag1.put(K2, "v2a");
+ bag1.put(K3, "v3");
+ assertEquals(bag1.get(K1), "v1");
+
+ ConfigBag bag2 = ConfigBag.newInstanceExtending(bag1, null).putAll(MutableMap.of(K2, "v2b"));
+ assertEquals(bag1.getUnusedConfig().size(), 2);
+ assertEquals(bag2.getUnusedConfig().size(), 2, "unused are: "+bag2.getUnusedConfig());
+
+ assertEquals(bag2.get(K1), "v1");
+ assertEquals(bag1.get(K2), "v2a");
+ assertEquals(bag1.getUnusedConfig().size(), 1);
+ assertEquals(bag2.getUnusedConfig().size(), 2);
+
+ assertEquals(bag2.get(K2), "v2b");
+ assertEquals(bag2.getUnusedConfig().size(), 1);
+
+ assertEquals(bag2.get(K3), "v3");
+ assertEquals(bag2.getUnusedConfig().size(), 0);
+ // when extended, the difference is that parent is also marked
+ assertEquals(bag1.getUnusedConfig().size(), 0);
+ }
+
+ @Test
+ public void testConcurrent() throws InterruptedException {
+ ConfigBag bag = ConfigBag.newInstance();
+ bag.put(K1, "v1");
+ bag.put(K2, "v2");
+ bag.put(K3, "v3");
+ runConcurrentTest(bag, 10, Duration.millis(50));
+ }
+
+ @Test(groups="Integration")
+ public void testConcurrentBig() throws InterruptedException {
+ ConfigBag bag = ConfigBag.newInstance();
+ bag.put(K1, "v1");
+ bag.put(K2, "v2");
+ bag.put(K3, "v3");
+ runConcurrentTest(bag, 20, Duration.seconds(5));
+ }
+
+ private void runConcurrentTest(final ConfigBag bag, int numThreads, Duration time) throws InterruptedException {
+ List<Thread> threads = MutableList.of();
+ final Map<Thread,Exception> exceptions = new ConcurrentHashMap<Thread,Exception>();
+ final AtomicInteger successes = new AtomicInteger();
+ for (int i=0; i<numThreads; i++) {
+ Thread t = new Thread() {
+ @Override
+ public void run() {
+ try {
+ while (!interrupted()) {
+ if (Math.random()<0.9)
+ bag.put(ConfigKeys.newStringConfigKey("k"+((int)(10*Math.random()))), "v"+((int)(10*Math.random())));
+ if (Math.random()<0.8)
+ bag.get(ConfigKeys.newStringConfigKey("k"+((int)(10*Math.random()))));
+ if (Math.random()<0.2)
+ bag.copy(bag);
+ if (Math.random()<0.6)
+ bag.remove(ConfigKeys.newStringConfigKey("k"+((int)(10*Math.random()))));
+ successes.incrementAndGet();
+ }
+ } catch (Exception e) {
+ exceptions.put(Thread.currentThread(), e);
+ Exceptions.propagateIfFatal(e);
+ }
+ }
+ };
+ t.setName("ConfigBagTest-concurrent-thread-"+i);
+ threads.add(t);
+ }
+ for (Thread t: threads) t.start();
+ time.countdownTimer().waitForExpiry();
+ for (Thread t: threads) t.interrupt();
+ for (Thread t: threads) t.join();
+ Assert.assertTrue(exceptions.isEmpty(), "Got "+exceptions.size()+"/"+numThreads+" exceptions ("+successes.get()+" successful): "+exceptions);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/crypto/SecureKeysAndSignerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/crypto/SecureKeysAndSignerTest.java b/core/src/test/java/org/apache/brooklyn/core/util/crypto/SecureKeysAndSignerTest.java
new file mode 100644
index 0000000..d681b0f
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/crypto/SecureKeysAndSignerTest.java
@@ -0,0 +1,169 @@
+/*
+ * 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.util.crypto;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.nio.charset.Charset;
+import java.security.KeyPair;
+import java.security.PublicKey;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.crypto.FluentKeySigner;
+import org.apache.brooklyn.core.util.crypto.SecureKeys;
+import org.apache.brooklyn.core.util.crypto.SecureKeys.PassphraseProblem;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import brooklyn.util.crypto.AuthorizedKeysParser;
+import brooklyn.util.os.Os;
+
+import com.google.common.io.Files;
+
+public class SecureKeysAndSignerTest {
+
+ // a bit slow, so marked as integration (but possibly due to leftover rebind-cleanup, benign failures writing to /tmp/xx)
+ @Test(groups="Integration")
+ public void testGenerateSignedKeys() throws Exception {
+ FluentKeySigner signer = new FluentKeySigner("the-root").
+ validForYears(2).
+ selfsign();
+ X509Certificate signerCert = signer.getAuthorityCertificate();
+
+ KeyPair aKey = SecureKeys.newKeyPair();
+ X509Certificate aCert = signer.newCertificateFor("A", aKey);
+
+ KeyPair bKey = SecureKeys.newKeyPair();
+ X509Certificate bCert = signer.newCertificateFor("B", bKey);
+
+ FluentKeySigner selfSigner1 = new FluentKeySigner("self1").selfsign();
+ X509Certificate selfCert1 = selfSigner1.getAuthorityCertificate();
+
+ SecureKeys.getTrustManager(aCert).checkClientTrusted(new X509Certificate[] { aCert }, "RSA");
+ SecureKeys.getTrustManager(signerCert).checkClientTrusted(new X509Certificate[] { signerCert }, "RSA");
+
+ try {
+ SecureKeys.getTrustManager(aCert).checkClientTrusted(new X509Certificate[] { bCert }, "RSA");
+ Assert.fail("Trust manager for A should not accept B");
+ } catch (CertificateException e) { /* expected */ }
+
+// SecureKeys.getTrustManager(signerCert).checkClientTrusted(new X509Certificate[] { aCert }, "RSA");
+ // NB, the above failes; we have to convert to a canonical implementation, handled by the following
+
+ Assert.assertTrue(SecureKeys.isCertificateAuthorizedBy(signerCert, signerCert));
+ Assert.assertTrue(SecureKeys.isCertificateAuthorizedBy(aCert, signerCert));
+ Assert.assertTrue(SecureKeys.isCertificateAuthorizedBy(bCert, signerCert));
+ Assert.assertFalse(SecureKeys.isCertificateAuthorizedBy(signerCert, aCert));
+ Assert.assertFalse(SecureKeys.isCertificateAuthorizedBy(bCert, aCert));
+
+ Assert.assertTrue(SecureKeys.isCertificateAuthorizedBy(selfCert1, selfCert1));
+ Assert.assertFalse(SecureKeys.isCertificateAuthorizedBy(selfCert1, signerCert));
+ }
+
+ @Test
+ public void testInjectCertificateAuthority() throws Exception {
+ KeyPair caKey = SecureKeys.newKeyPair();
+ X509Certificate caCert = new FluentKeySigner("the-root", caKey).selfsign().getAuthorityCertificate();
+
+ FluentKeySigner signer = new FluentKeySigner(caCert, caKey);
+ Assert.assertEquals("the-root", signer.getCommonName());
+
+ KeyPair aKey = SecureKeys.newKeyPair();
+ X509Certificate aCert = signer.newCertificateFor("A", aKey);
+
+ Assert.assertTrue(SecureKeys.isCertificateAuthorizedBy(aCert, caCert));
+ }
+
+ @Test
+ public void testReadRsaKey() throws Exception {
+ KeyPair key = SecureKeys.readPem(ResourceUtils.create(this).getResourceFromUrl("classpath://brooklyn/util/crypto/sample_rsa.pem"), null);
+ checkNonTrivial(key);
+ }
+
+ @Test(expectedExceptions=IllegalStateException.class)
+ public void testReadRsaPublicKeyAsPemFails() throws Exception {
+ // should fail; see next test
+ SecureKeys.readPem(ResourceUtils.create(this).getResourceFromUrl("classpath://brooklyn/util/crypto/sample_rsa.pem.pub"), null);
+ }
+
+ @Test
+ public void testReadRsaPublicKeyAsAuthKeysWorks() throws Exception {
+ PublicKey key = AuthorizedKeysParser.decodePublicKey(
+ ResourceUtils.create(this).getResourceAsString("classpath://brooklyn/util/crypto/sample_rsa.pem.pub"));
+ KeyPair fromPem = SecureKeys.readPem(ResourceUtils.create(this).getResourceFromUrl("classpath://brooklyn/util/crypto/sample_rsa.pem"), null);
+ Assert.assertEquals(key, fromPem.getPublic());
+ }
+
+ @Test
+ public void testEncodeDecodeRsaPublicKey() throws Exception {
+ String data = ResourceUtils.create(this).getResourceAsString("classpath://brooklyn/util/crypto/sample_rsa.pem.pub");
+ PublicKey key = AuthorizedKeysParser.decodePublicKey(data);
+ String data2 = AuthorizedKeysParser.encodePublicKey(key);
+ Assert.assertTrue(data.contains(data2), "Expected to find '"+data2+"' in '"+data+"'");
+ PublicKey key2 = AuthorizedKeysParser.decodePublicKey(data2);
+ Assert.assertEquals(key2, key);
+ }
+
+ @Test
+ public void testEncodeDecodeDsaPublicKey() throws Exception {
+ String data = ResourceUtils.create(this).getResourceAsString("classpath://brooklyn/util/crypto/sample_dsa.pem.pub");
+ PublicKey key = AuthorizedKeysParser.decodePublicKey(data);
+ String data2 = AuthorizedKeysParser.encodePublicKey(key);
+ Assert.assertTrue(data.contains(data2), "Expected to find '"+data2+"' in '"+data+"'");
+ PublicKey key2 = AuthorizedKeysParser.decodePublicKey(data2);
+ Assert.assertEquals(key2, key);
+ }
+
+ @Test
+ public void testReadDsaKey() throws Exception {
+ KeyPair key = SecureKeys.readPem(ResourceUtils.create(this).getResourceFromUrl("classpath://brooklyn/util/crypto/sample_dsa.pem"), null);
+ checkNonTrivial(key);
+ }
+
+ @Test(expectedExceptions=Exception.class)
+ public void testCantReadRsaPassphraseKeyWithoutPassphrase() throws Exception {
+ KeyPair key = SecureKeys.readPem(ResourceUtils.create(this).getResourceFromUrl("classpath://brooklyn/util/crypto/sample_rsa_passphrase.pem"), null);
+ checkNonTrivial(key);
+ }
+
+ @Test(expectedExceptions=PassphraseProblem.class)
+ public void testReadRsaPassphraseWithoutKeyFails() throws Exception {
+ SecureKeys.readPem(ResourceUtils.create(this).getResourceFromUrl("classpath://brooklyn/util/crypto/sample_rsa_passphrase.pem"), null);
+ }
+
+ @Test
+ public void testReadRsaPassphraseKeyAndWriteWithoutPassphrase() throws Exception {
+ KeyPair key = SecureKeys.readPem(ResourceUtils.create(this).getResourceFromUrl("classpath://brooklyn/util/crypto/sample_rsa_passphrase.pem"), "passphrase");
+ checkNonTrivial(key);
+ File f = Os.newTempFile(getClass(), "brooklyn-sample_rsa_passphrase_without_passphrase.pem");
+ Files.write(SecureKeys.stringPem(key), f, Charset.defaultCharset());
+ KeyPair key2 = SecureKeys.readPem(new FileInputStream(f), null);
+ checkNonTrivial(key2);
+ Assert.assertEquals(key2.getPrivate().getEncoded(), key.getPrivate().getEncoded());
+ Assert.assertEquals(key2.getPublic().getEncoded(), key.getPublic().getEncoded());
+ }
+
+ private void checkNonTrivial(KeyPair key) {
+ Assert.assertNotEquals(key.getPrivate().getEncoded().length, 0);
+ Assert.assertNotEquals(key.getPublic().getEncoded().length, 0);
+ }
+
+}
[10/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/task/DynamicSequentialTaskTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/task/DynamicSequentialTaskTest.java b/core/src/test/java/org/apache/brooklyn/core/util/task/DynamicSequentialTaskTest.java
new file mode 100644
index 0000000..c4f8d4c
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/task/DynamicSequentialTaskTest.java
@@ -0,0 +1,371 @@
+/*
+ * 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.util.task;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.brooklyn.api.management.HasTaskChildren;
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.task.BasicExecutionContext;
+import org.apache.brooklyn.core.util.task.BasicExecutionManager;
+import org.apache.brooklyn.core.util.task.DynamicSequentialTask;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.TaskTags;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.test.Asserts;
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.time.CountdownTimer;
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Time;
+
+import com.google.common.base.Stopwatch;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+public class DynamicSequentialTaskTest {
+
+ private static final Logger log = LoggerFactory.getLogger(DynamicSequentialTaskTest.class);
+
+ public static final Duration TIMEOUT = Duration.TEN_SECONDS;
+ public static final Duration TINY_TIME = Duration.millis(20);
+
+ BasicExecutionManager em;
+ BasicExecutionContext ec;
+ List<String> messages;
+ Semaphore cancellations;
+ Stopwatch stopwatch;
+ Map<String,Semaphore> monitorableJobSemaphoreMap;
+ Map<String,Task<String>> monitorableTasksMap;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() {
+ em = new BasicExecutionManager("mycontext");
+ ec = new BasicExecutionContext(em);
+ cancellations = new Semaphore(0);
+ messages = new ArrayList<String>();
+ monitorableJobSemaphoreMap = MutableMap.of();
+ monitorableTasksMap = MutableMap.of();
+ monitorableTasksMap.clear();
+ stopwatch = Stopwatch.createStarted();
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ if (em != null) em.shutdownNow();
+ }
+
+ @Test
+ public void testSimple() throws InterruptedException, ExecutionException {
+ Callable<String> mainJob = new Callable<String>() {
+ public String call() {
+ log.info("main job - "+Tasks.current());
+ messages.add("main");
+ DynamicTasks.queue( sayTask("world") );
+ return "bye";
+ }
+ };
+ DynamicSequentialTask<String> t = new DynamicSequentialTask<String>(mainJob);
+ // this should be added before anything added when the task is invoked
+ t.queue(sayTask("hello"));
+
+ Assert.assertEquals(messages, Lists.newArrayList());
+ Assert.assertEquals(t.isBegun(), false);
+ Assert.assertEquals(Iterables.size(t.getChildren()), 1);
+
+ ec.submit(t);
+ Assert.assertEquals(t.isSubmitted(), true);
+ Assert.assertEquals(t.getUnchecked(Duration.ONE_SECOND), "bye");
+ long elapsed = t.getEndTimeUtc() - t.getSubmitTimeUtc();
+ Assert.assertTrue(elapsed < 1000, "elapsed time should have been less than 1s but was "+
+ Time.makeTimeString(elapsed, true));
+ Assert.assertEquals(Iterables.size(t.getChildren()), 2);
+ Assert.assertEquals(messages.size(), 3, "expected 3 entries, but had "+messages);
+ // either main or hello can be first, but world should be last
+ Assert.assertEquals(messages.get(2), "world");
+ }
+
+ public Callable<String> sayCallable(final String message, final Duration duration, final String message2) {
+ return new Callable<String>() {
+ public String call() {
+ try {
+ if (message != null) {
+ log.info("saying: "+message+ " - "+Tasks.current());
+ synchronized (messages) {
+ messages.add(message);
+ messages.notifyAll();
+ }
+ }
+ if (message2 != null) {
+ log.info("will say "+message2+" after "+duration);
+ }
+ if (duration != null && duration.toMilliseconds() > 0) {
+ Thread.sleep(duration.toMillisecondsRoundingUp());
+ }
+ } catch (InterruptedException e) {
+ cancellations.release();
+ throw Exceptions.propagate(e);
+ }
+ if (message2 != null) {
+ log.info("saying: "+message2+ " - "+Tasks.current());
+ synchronized (messages) {
+ messages.add(message2);
+ messages.notifyAll();
+ }
+ }
+ return message;
+ }
+ };
+ }
+
+ public Task<String> sayTask(String message) {
+ return sayTask(message, null, null);
+ }
+
+ public Task<String> sayTask(String message, Duration duration, String message2) {
+ return Tasks.<String>builder().body(sayCallable(message, duration, message2)).build();
+ }
+
+ @Test
+ public void testComplex() throws InterruptedException, ExecutionException {
+ Task<List<?>> t = Tasks.sequential(
+ sayTask("1"),
+ sayTask("2"),
+ Tasks.parallel(sayTask("4"), sayTask("3")),
+ sayTask("5")
+ );
+ ec.submit(t);
+ Assert.assertEquals(t.get().size(), 4);
+ Asserts.assertEqualsIgnoringOrder((List<?>)t.get().get(2), ImmutableSet.of("3", "4"));
+ Assert.assertTrue(messages.equals(Arrays.asList("1", "2", "3", "4", "5")) || messages.equals(Arrays.asList("1", "2", "4", "3", "5")), "messages="+messages);
+ }
+
+ @Test
+ public void testCancelled() throws InterruptedException, ExecutionException {
+ Task<List<?>> t = Tasks.sequential(
+ sayTask("1"),
+ sayTask("2a", Duration.THIRTY_SECONDS, "2b"),
+ sayTask("3"));
+ ec.submit(t);
+ synchronized (messages) {
+ while (messages.size() <= 1)
+ messages.wait();
+ }
+ Assert.assertEquals(messages, Arrays.asList("1", "2a"));
+ Time.sleep(Duration.millis(50));
+ t.cancel(true);
+ Assert.assertTrue(t.isDone());
+ // 2 should get cancelled, and invoke the cancellation semaphore
+ // 3 should get cancelled and not run at all
+ Assert.assertEquals(messages, Arrays.asList("1", "2a"));
+
+ // Need to ensure that 2 has been started; race where we might cancel it before its run method
+ // is even begun. Hence doing "2a; pause; 2b" where nothing is interruptable before pause.
+ Assert.assertTrue(cancellations.tryAcquire(10, TimeUnit.SECONDS));
+
+ Iterator<Task<?>> ci = ((HasTaskChildren)t).getChildren().iterator();
+ Assert.assertEquals(ci.next().get(), "1");
+ Task<?> task2 = ci.next();
+ Assert.assertTrue(task2.isBegun());
+ Assert.assertTrue(task2.isDone());
+ Assert.assertTrue(task2.isCancelled());
+
+ Task<?> task3 = ci.next();
+ Assert.assertFalse(task3.isBegun());
+ Assert.assertTrue(task2.isDone());
+ Assert.assertTrue(task2.isCancelled());
+
+ // but we do _not_ get a mutex from task3 as it does not run (is not interrupted)
+ Assert.assertEquals(cancellations.availablePermits(), 0);
+ }
+
+ protected Task<String> monitorableTask(final String id) {
+ return monitorableTask(null, id, null);
+ }
+ protected Task<String> monitorableTask(final Runnable pre, final String id, final Callable<String> post) {
+ Task<String> t = Tasks.<String>builder().body(monitorableJob(pre, id, post)).build();
+ monitorableTasksMap.put(id, t);
+ return t;
+ }
+ protected Callable<String> monitorableJob(final String id) {
+ return monitorableJob(null, id, null);
+ }
+ protected Callable<String> monitorableJob(final Runnable pre, final String id, final Callable<String> post) {
+ monitorableJobSemaphoreMap.put(id, new Semaphore(0));
+ return new Callable<String>() {
+ @Override
+ public String call() throws Exception {
+ if (pre!=null) pre.run();
+ // wait for semaphore
+ if (!monitorableJobSemaphoreMap.get(id).tryAcquire(1, TIMEOUT.toMilliseconds(), TimeUnit.MILLISECONDS))
+ throw new IllegalStateException("timeout for "+id);
+ synchronized (messages) {
+ messages.add(id);
+ messages.notifyAll();
+ }
+ if (post!=null) return post.call();
+ return id;
+ }
+ };
+ }
+ protected void releaseMonitorableJob(final String id) {
+ monitorableJobSemaphoreMap.get(id).release();
+ }
+ protected void waitForMessage(final String id) {
+ CountdownTimer timer = CountdownTimer.newInstanceStarted(TIMEOUT);
+ synchronized (messages) {
+ while (!timer.isExpired()) {
+ if (messages.contains(id)) return;
+ timer.waitOnForExpiryUnchecked(messages);
+ }
+ }
+ Assert.fail("Did not see message "+id);
+ }
+ protected void releaseAndWaitForMonitorableJob(final String id) {
+ releaseMonitorableJob(id);
+ waitForMessage(id);
+ }
+
+ @Test
+ public void testChildrenRunConcurrentlyWithPrimary() {
+ Task<String> t = Tasks.<String>builder().dynamic(true)
+ .body(monitorableJob("main"))
+ .add(monitorableTask("1")).add(monitorableTask("2")).build();
+ ec.submit(t);
+ releaseAndWaitForMonitorableJob("1");
+ releaseAndWaitForMonitorableJob("main");
+ Assert.assertFalse(t.blockUntilEnded(TINY_TIME));
+ releaseMonitorableJob("2");
+
+ Assert.assertTrue(t.blockUntilEnded(TIMEOUT));
+ Assert.assertEquals(messages, MutableList.of("1", "main", "2"));
+ Assert.assertTrue(stopwatch.elapsed(TimeUnit.MILLISECONDS) < TIMEOUT.toMilliseconds(), "took too long: "+stopwatch);
+ Assert.assertFalse(t.isError());
+ }
+
+ protected static class FailRunnable implements Runnable {
+ @Override public void run() { throw new RuntimeException("Planned exception for test"); }
+ }
+ protected static class FailCallable implements Callable<String> {
+ @Override public String call() { throw new RuntimeException("Planned exception for test"); }
+ }
+
+ @Test
+ public void testByDefaultChildrenFailureAbortsSecondaryFailsPrimaryButNotAbortsPrimary() {
+ Task<String> t1 = monitorableTask(null, "1", new FailCallable());
+ Task<String> t = Tasks.<String>builder().dynamic(true)
+ .body(monitorableJob("main"))
+ .add(t1).add(monitorableTask("2")).build();
+ ec.submit(t);
+ releaseAndWaitForMonitorableJob("1");
+ Assert.assertFalse(t.blockUntilEnded(TINY_TIME));
+ releaseMonitorableJob("main");
+
+ Assert.assertTrue(t.blockUntilEnded(TIMEOUT));
+ Assert.assertEquals(messages, MutableList.of("1", "main"));
+ Assert.assertTrue(stopwatch.elapsed(TimeUnit.MILLISECONDS) < TIMEOUT.toMilliseconds(), "took too long: "+stopwatch);
+ Assert.assertTrue(t.isError());
+ Assert.assertTrue(t1.isError());
+ }
+
+ @Test
+ public void testWhenSwallowingChildrenFailureDoesNotAbortSecondaryOrFailPrimary() {
+ Task<String> t1 = monitorableTask(null, "1", new FailCallable());
+ Task<String> t = Tasks.<String>builder().dynamic(true)
+ .body(monitorableJob("main"))
+ .add(t1).add(monitorableTask("2")).swallowChildrenFailures(true).build();
+ ec.submit(t);
+ releaseAndWaitForMonitorableJob("1");
+ Assert.assertFalse(t.blockUntilEnded(TINY_TIME));
+ releaseAndWaitForMonitorableJob("2");
+ Assert.assertFalse(t.blockUntilEnded(TINY_TIME));
+ releaseMonitorableJob("main");
+ Assert.assertTrue(t.blockUntilEnded(TIMEOUT));
+ Assert.assertEquals(messages, MutableList.of("1", "2", "main"));
+ Assert.assertTrue(stopwatch.elapsed(TimeUnit.MILLISECONDS) < TIMEOUT.toMilliseconds(), "took too long: "+stopwatch);
+ Assert.assertFalse(t.isError());
+ Assert.assertTrue(t1.isError());
+ }
+
+ @Test
+ public void testInessentialChildrenFailureDoesNotAbortSecondaryOrFailPrimary() {
+ Task<String> t1 = monitorableTask(null, "1", new FailCallable());
+ TaskTags.markInessential(t1);
+ Task<String> t = Tasks.<String>builder().dynamic(true)
+ .body(monitorableJob("main"))
+ .add(t1).add(monitorableTask("2")).build();
+ ec.submit(t);
+ releaseAndWaitForMonitorableJob("1");
+ Assert.assertFalse(t.blockUntilEnded(TINY_TIME));
+ releaseAndWaitForMonitorableJob("2");
+ Assert.assertFalse(t.blockUntilEnded(TINY_TIME));
+ releaseMonitorableJob("main");
+ Assert.assertTrue(t.blockUntilEnded(TIMEOUT));
+ Assert.assertEquals(messages, MutableList.of("1", "2", "main"));
+ Assert.assertTrue(stopwatch.elapsed(TimeUnit.MILLISECONDS) < TIMEOUT.toMilliseconds(), "took too long: "+stopwatch);
+ Assert.assertFalse(t.isError());
+ Assert.assertTrue(t1.isError());
+ }
+
+ @Test
+ public void testTaskBuilderUsingAddVarargChildren() {
+ Task<String> t = Tasks.<String>builder().dynamic(true)
+ .body(monitorableJob("main"))
+ .add(monitorableTask("1"), monitorableTask("2"))
+ .build();
+ ec.submit(t);
+ releaseAndWaitForMonitorableJob("1");
+ releaseAndWaitForMonitorableJob("2");
+ releaseAndWaitForMonitorableJob("main");
+
+ Assert.assertEquals(messages, MutableList.of("1", "2", "main"));
+ }
+
+ @Test
+ public void testTaskBuilderUsingAddAllChildren() {
+ Task<String> t = Tasks.<String>builder().dynamic(true)
+ .body(monitorableJob("main"))
+ .addAll(ImmutableList.of(monitorableTask("1"), monitorableTask("2")))
+ .build();
+ ec.submit(t);
+ releaseAndWaitForMonitorableJob("1");
+ releaseAndWaitForMonitorableJob("2");
+ releaseAndWaitForMonitorableJob("main");
+
+ Assert.assertEquals(messages, MutableList.of("1", "2", "main"));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/task/NonBasicTaskExecutionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/task/NonBasicTaskExecutionTest.java b/core/src/test/java/org/apache/brooklyn/core/util/task/NonBasicTaskExecutionTest.java
new file mode 100644
index 0000000..980a701
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/task/NonBasicTaskExecutionTest.java
@@ -0,0 +1,130 @@
+/*
+ * 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.util.task;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.task.BasicExecutionManager;
+import org.apache.brooklyn.core.util.task.BasicTask;
+import org.apache.brooklyn.core.util.task.ForwardingTask;
+import org.apache.brooklyn.core.util.task.TaskInternal;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.test.Asserts;
+import brooklyn.util.collections.MutableMap;
+
+/**
+ * Test the operation of the {@link BasicTask} class.
+ *
+ * TODO clarify test purpose
+ */
+public class NonBasicTaskExecutionTest {
+ private static final Logger log = LoggerFactory.getLogger(NonBasicTaskExecutionTest.class);
+
+ private static final int TIMEOUT_MS = 10*1000;
+
+ public static class ConcreteForwardingTask<T> extends ForwardingTask<T> {
+ private final TaskInternal<T> delegate;
+
+ ConcreteForwardingTask(TaskInternal<T> delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ protected TaskInternal<T> delegate() {
+ return delegate;
+ }
+ }
+
+ private BasicExecutionManager em;
+ private Map<Integer,String> data;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ em = new BasicExecutionManager("mycontext");
+ data = Collections.synchronizedMap(new HashMap<Integer,String>());
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ if (em != null) em.shutdownNow();
+ }
+
+ @Test
+ public void runSimpleTask() throws Exception {
+ TaskInternal<Object> t = new ConcreteForwardingTask<Object>(new BasicTask<Object>(new Callable<Object>() {
+ @Override public Object call() {
+ return data.put(1, "b");
+ }}));
+ data.put(1, "a");
+ Task<?> t2 = em.submit(MutableMap.of("tag", "A"), t);
+ assertEquals("a", t.get());
+ assertEquals("a", t2.get());
+ assertSame(t, t2, "t="+t+"; t2="+t2);
+ assertEquals("b", data.get(1));
+ }
+
+ @Test
+ public void runBasicTaskWithWaits() throws Exception {
+ final CountDownLatch signalStarted = new CountDownLatch(1);
+ final CountDownLatch allowCompletion = new CountDownLatch(1);
+ final TaskInternal<Object> t = new ConcreteForwardingTask<Object>(new BasicTask<Object>(new Callable<Object>() {
+ @Override public Object call() throws Exception {
+ Object result = data.put(1, "b");
+ signalStarted.countDown();
+ assertTrue(allowCompletion.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ return result;
+ }}));
+ data.put(1, "a");
+
+ Task<?> t2 = em.submit(MutableMap.of("tag", "A"), t);
+ assertEquals(t, t2);
+ assertFalse(t.isDone());
+
+ assertTrue(signalStarted.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertEquals("b", data.get(1));
+ assertFalse(t.isDone());
+
+ log.debug("runBasicTaskWithWaits, BasicTask status: {}", t.getStatusDetail(false));
+
+ Asserts.succeedsEventually(new Runnable() {
+ @Override public void run() {
+ t.getStatusDetail(false).toLowerCase().contains("waiting");
+ }});
+ // "details="+t.getStatusDetail(false))
+
+ allowCompletion.countDown();
+ assertEquals("a", t.get());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/task/ScheduledExecutionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/task/ScheduledExecutionTest.java b/core/src/test/java/org/apache/brooklyn/core/util/task/ScheduledExecutionTest.java
new file mode 100644
index 0000000..3b338da
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/task/ScheduledExecutionTest.java
@@ -0,0 +1,291 @@
+/*
+ * 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.util.task;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.task.BasicExecutionManager;
+import org.apache.brooklyn.core.util.task.BasicTask;
+import org.apache.brooklyn.core.util.task.ScheduledTask;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import brooklyn.test.Asserts;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.exceptions.RuntimeInterruptedException;
+import brooklyn.util.javalang.JavaClassNames;
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Time;
+
+import com.google.common.base.Stopwatch;
+import com.google.common.collect.Lists;
+
+@SuppressWarnings({"unchecked","rawtypes"})
+public class ScheduledExecutionTest {
+
+ public static final Logger log = LoggerFactory.getLogger(ScheduledExecutionTest.class);
+
+ @Test
+ public void testScheduledTask() throws Exception {
+ int PERIOD = 20;
+ BasicExecutionManager m = new BasicExecutionManager("mycontextid");
+ final AtomicInteger i = new AtomicInteger(0);
+ ScheduledTask t = new ScheduledTask(MutableMap.of("delay", 2*PERIOD, "period", PERIOD, "maxIterations", 5), new Callable<Task<?>>() {
+ public Task<?> call() throws Exception {
+ return new BasicTask<Integer>(new Callable<Integer>() {
+ public Integer call() {
+ log.debug("task running: "+Tasks.current()+" "+Tasks.current().getStatusDetail(false));
+ return i.incrementAndGet();
+ }});
+ }});
+
+ log.info("submitting {} {}", t, t.getStatusDetail(false));
+ m.submit(t);
+ log.info("submitted {} {}", t, t.getStatusDetail(false));
+ Integer interimResult = (Integer) t.get();
+ log.info("done one ({}) {} {}", new Object[] {interimResult, t, t.getStatusDetail(false)});
+ assertTrue(i.get() > 0, "i="+i);
+ t.blockUntilEnded();
+ Integer finalResult = (Integer) t.get();
+ log.info("ended ({}) {} {}", new Object[] {finalResult, t, t.getStatusDetail(false)});
+ assertEquals(finalResult, (Integer)5);
+ assertEquals(i.get(), 5);
+ }
+
+ /** like testScheduledTask but the loop is terminated by the task itself adjusting the period */
+ @Test
+ public void testScheduledTaskSelfEnding() throws Exception {
+ int PERIOD = 20;
+ BasicExecutionManager m = new BasicExecutionManager("mycontextid");
+ final AtomicInteger i = new AtomicInteger(0);
+ ScheduledTask t = new ScheduledTask(MutableMap.of("delay", 2*PERIOD, "period", PERIOD), new Callable<Task<?>>() {
+ public Task<?> call() throws Exception {
+ return new BasicTask<Integer>(new Callable<Integer>() {
+ public Integer call() {
+ ScheduledTask submitter = (ScheduledTask) ((BasicTask)Tasks.current()).getSubmittedByTask();
+ if (i.get() >= 4) submitter.period = null;
+ log.info("task running ("+i+"): "+Tasks.current()+" "+Tasks.current().getStatusDetail(false));
+ return i.incrementAndGet();
+ }});
+ }});
+
+ log.info("submitting {} {}", t, t.getStatusDetail(false));
+ m.submit(t);
+ log.info("submitted {} {}", t, t.getStatusDetail(false));
+ Integer interimResult = (Integer) t.get();
+ log.info("done one ({}) {} {}", new Object[] {interimResult, t, t.getStatusDetail(false)});
+ assertTrue(i.get() > 0);
+ t.blockUntilEnded();
+ Integer finalResult = (Integer) t.get();
+ log.info("ended ({}) {} {}", new Object[] {finalResult, t, t.getStatusDetail(false)});
+ assertEquals(finalResult, (Integer)5);
+ assertEquals(i.get(), 5);
+ }
+
+ @Test
+ public void testScheduledTaskCancelEnding() throws Exception {
+ Duration PERIOD = Duration.millis(20);
+ BasicExecutionManager m = new BasicExecutionManager("mycontextid");
+ final AtomicInteger i = new AtomicInteger();
+ ScheduledTask t = new ScheduledTask(MutableMap.of("delay", PERIOD.times(2), "period", PERIOD), new Callable<Task<?>>() {
+ public Task<?> call() throws Exception {
+ return new BasicTask<Integer>(new Callable<Integer>() {
+ public Integer call() {
+ log.info("task running ("+i+"): "+Tasks.current()+" "+Tasks.current().getStatusDetail(false));
+ ScheduledTask submitter = (ScheduledTask) ((BasicTask)Tasks.current()).getSubmittedByTask();
+ i.incrementAndGet();
+ if (i.get() >= 5) submitter.cancel();
+ return i.get();
+ }});
+ }});
+
+ log.info(JavaClassNames.niceClassAndMethod()+" - submitting {} {}", t, t.getStatusDetail(false));
+ m.submit(t);
+ log.info("submitted {} {}", t, t.getStatusDetail(false));
+ Integer interimResult = (Integer) t.get();
+ log.info("done one ({}) {} {}", new Object[] {interimResult, t, t.getStatusDetail(false)});
+ assertTrue(i.get() > 0);
+ t.blockUntilEnded();
+// int finalResult = t.get()
+ log.info("ended ({}) {} {}", new Object[] {i, t, t.getStatusDetail(false)});
+// assertEquals(finalResult, 5)
+ assertEquals(i.get(), 5);
+ }
+
+ @Test(groups="Integration")
+ public void testScheduledTaskCancelOuter() throws Exception {
+ final Duration PERIOD = Duration.millis(20);
+ final Duration CYCLE_DELAY = Duration.ONE_SECOND;
+ // this should be enough to start the next cycle, but not so much that the cycle ends;
+ // and enough that when a task is interrupted it terminates within this period
+ final Duration SMALL_FRACTION_OF_CYCLE_DELAY = PERIOD.add(CYCLE_DELAY.multiply(0.1));
+
+ BasicExecutionManager m = new BasicExecutionManager("mycontextid");
+ final AtomicInteger i = new AtomicInteger();
+ ScheduledTask t = new ScheduledTask(MutableMap.of("delay", PERIOD.times(2), "period", PERIOD), new Callable<Task<?>>() {
+ public Task<?> call() throws Exception {
+ return new BasicTask<Integer>(new Callable<Integer>() {
+ public Integer call() {
+ log.info("task running ("+i+"): "+Tasks.current()+" "+Tasks.current().getStatusDetail(false));
+ Time.sleep(CYCLE_DELAY);
+ i.incrementAndGet();
+ return i.get();
+ }});
+ }});
+
+ log.info(JavaClassNames.niceClassAndMethod()+" - submitting {} {}", t, t.getStatusDetail(false));
+ m.submit(t);
+ log.info("submitted {} {}", t, t.getStatusDetail(false));
+ Integer interimResult = (Integer) t.get();
+ log.info("done one ({}) {} {}", new Object[] {interimResult, t, t.getStatusDetail(false)});
+ assertEquals(i.get(), 1);
+
+ Time.sleep(SMALL_FRACTION_OF_CYCLE_DELAY);
+ assertEquals(t.get(), 2);
+
+ Time.sleep(SMALL_FRACTION_OF_CYCLE_DELAY);
+ Stopwatch timer = Stopwatch.createUnstarted();
+ t.cancel(true);
+ t.blockUntilEnded();
+// int finalResult = t.get()
+ log.info("blocked until ended ({}) {} {}, in {}", new Object[] {i, t, t.getStatusDetail(false), Duration.of(timer)});
+ try {
+ t.get();
+ Assert.fail("Should have failed getting result of cancelled "+t);
+ } catch (Exception e) {
+ /* expected */
+ }
+ assertEquals(i.get(), 2);
+ log.info("ended ({}) {} {}, in {}", new Object[] {i, t, t.getStatusDetail(false), Duration.of(timer)});
+ Assert.assertTrue(Duration.of(timer).isShorterThan(SMALL_FRACTION_OF_CYCLE_DELAY));
+ }
+
+ @Test(groups="Integration")
+ public void testScheduledTaskCancelInterrupts() throws Exception {
+ final Duration PERIOD = Duration.millis(20);
+ final Duration CYCLE_DELAY = Duration.ONE_SECOND;
+ // this should be enough to start the next cycle, but not so much that the cycle ends;
+ // and enough that when a task is interrupted it terminates within this period
+ final Duration SMALL_FRACTION_OF_CYCLE_DELAY = PERIOD.add(CYCLE_DELAY.multiply(0.1));
+
+ BasicExecutionManager m = new BasicExecutionManager("mycontextid");
+ final Semaphore interruptedSemaphore = new Semaphore(0);
+ final AtomicInteger i = new AtomicInteger();
+ ScheduledTask t = new ScheduledTask(MutableMap.of("delay", PERIOD.times(2), "period", PERIOD), new Callable<Task<?>>() {
+ public Task<?> call() throws Exception {
+ return new BasicTask<Integer>(new Callable<Integer>() {
+ public Integer call() {
+ try {
+ log.info("task running ("+i+"): "+Tasks.current()+" "+Tasks.current().getStatusDetail(false));
+ Time.sleep(CYCLE_DELAY);
+ i.incrementAndGet();
+ return i.get();
+ } catch (RuntimeInterruptedException e) {
+ interruptedSemaphore.release();
+ throw Exceptions.propagate(e);
+ }
+ }});
+ }});
+
+ log.info(JavaClassNames.niceClassAndMethod()+" - submitting {} {}", t, t.getStatusDetail(false));
+ m.submit(t);
+ log.info("submitted {} {}", t, t.getStatusDetail(false));
+ Integer interimResult = (Integer) t.get();
+ log.info("done one ({}) {} {}", new Object[] {interimResult, t, t.getStatusDetail(false)});
+ assertEquals(i.get(), 1);
+
+ Time.sleep(SMALL_FRACTION_OF_CYCLE_DELAY);
+ assertEquals(t.get(), 2);
+
+ Time.sleep(SMALL_FRACTION_OF_CYCLE_DELAY);
+ Stopwatch timer = Stopwatch.createUnstarted();
+ t.cancel(true);
+ t.blockUntilEnded();
+// int finalResult = t.get()
+ log.info("blocked until ended ({}) {} {}, in {}", new Object[] {i, t, t.getStatusDetail(false), Duration.of(timer)});
+ try {
+ t.get();
+ Assert.fail("Should have failed getting result of cancelled "+t);
+ } catch (Exception e) {
+ /* expected */
+ }
+ assertEquals(i.get(), 2);
+ Assert.assertTrue(interruptedSemaphore.tryAcquire(1, SMALL_FRACTION_OF_CYCLE_DELAY.toMilliseconds(), TimeUnit.MILLISECONDS), "child thread was not interrupted");
+ log.info("ended ({}) {} {}, in {}", new Object[] {i, t, t.getStatusDetail(false), Duration.of(timer)});
+ Assert.assertTrue(Duration.of(timer).isShorterThan(SMALL_FRACTION_OF_CYCLE_DELAY));
+ }
+
+ @Test(groups="Integration")
+ public void testScheduledTaskTakesLongerThanPeriod() throws Exception {
+ final int PERIOD = 1;
+ final int SLEEP_TIME = 100;
+ final int EARLY_RETURN_GRACE = 10;
+ BasicExecutionManager m = new BasicExecutionManager("mycontextid");
+ final List<Long> execTimes = new CopyOnWriteArrayList<Long>();
+
+ ScheduledTask t = new ScheduledTask(MutableMap.of("delay", PERIOD, "period", PERIOD), new Callable<Task<?>>() {
+ public Task<?> call() throws Exception {
+ return new BasicTask<Void>(new Runnable() {
+ public void run() {
+ execTimes.add(System.currentTimeMillis());
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ throw Exceptions.propagate(e);
+ }
+ }});
+ }});
+
+ m.submit(t);
+
+ Asserts.succeedsEventually(new Runnable() {
+ public void run() {
+ assertTrue(execTimes.size() > 3, "size="+execTimes.size());
+ }});
+
+ List<Long> timeDiffs = Lists.newArrayList();
+ long prevExecTime = -1;
+ for (Long execTime : execTimes) {
+ if (prevExecTime == -1) {
+ prevExecTime = execTime;
+ } else {
+ timeDiffs.add(execTime - prevExecTime);
+ prevExecTime = execTime;
+ }
+ }
+
+ for (Long timeDiff : timeDiffs) {
+ if (timeDiff < (SLEEP_TIME - EARLY_RETURN_GRACE)) fail("timeDiffs="+timeDiffs+"; execTimes="+execTimes);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/task/SingleThreadedSchedulerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/task/SingleThreadedSchedulerTest.java b/core/src/test/java/org/apache/brooklyn/core/util/task/SingleThreadedSchedulerTest.java
new file mode 100644
index 0000000..e3420c8
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/task/SingleThreadedSchedulerTest.java
@@ -0,0 +1,195 @@
+/*
+ * 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.util.task;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.fail;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.brooklyn.core.util.task.BasicExecutionManager;
+import org.apache.brooklyn.core.util.task.BasicTask;
+import org.apache.brooklyn.core.util.task.SingleThreadedScheduler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.test.Asserts;
+import brooklyn.util.collections.MutableMap;
+
+import com.google.common.util.concurrent.Callables;
+
+public class SingleThreadedSchedulerTest {
+
+ private static final Logger log = LoggerFactory.getLogger(SingleThreadedSchedulerTest.class);
+
+ private BasicExecutionManager em;
+
+ @BeforeMethod
+ public void setUp() {
+ em = new BasicExecutionManager("mycontextid");
+ em.setTaskSchedulerForTag("category1", SingleThreadedScheduler.class);
+ }
+
+ @AfterMethod
+ public void tearDown() {
+ if (em != null) em.shutdownNow();
+ }
+
+ @Test
+ public void testExecutesInOrder() throws Exception {
+ final int NUM_TIMES = 1000;
+ final List<Integer> result = new CopyOnWriteArrayList<Integer>();
+ for (int i = 0; i < NUM_TIMES; i++) {
+ final int counter = i;
+ em.submit(MutableMap.of("tag", "category1"), new Runnable() {
+ public void run() {
+ result.add(counter);
+ }});
+ }
+
+ Asserts.succeedsEventually(new Runnable() {
+ @Override public void run() {
+ assertEquals(result.size(), NUM_TIMES);
+ }});
+
+ for (int i = 0; i < NUM_TIMES; i++) {
+ assertEquals(result.get(i), (Integer)i);
+ }
+ }
+
+ @Test
+ public void testLargeQueueDoesNotConsumeTooManyThreads() throws Exception {
+ final int NUM_TIMES = 3000;
+ final CountDownLatch latch = new CountDownLatch(1);
+ BasicTask<Void> blockingTask = new BasicTask<Void>(newLatchAwaiter(latch));
+ em.submit(MutableMap.of("tag", "category1"), blockingTask);
+
+ final AtomicInteger counter = new AtomicInteger(0);
+ for (int i = 0; i < NUM_TIMES; i++) {
+ BasicTask<Void> t = new BasicTask<Void>(new Runnable() {
+ public void run() {
+ counter.incrementAndGet();
+ }});
+ em.submit(MutableMap.of("tag", "category1"), t);
+ if (i % 500 == 0) log.info("Submitted "+i+" jobs...");
+ }
+
+ Thread.sleep(100); // give it more of a chance to create the threads before we let them execute
+ latch.countDown();
+
+ Asserts.succeedsEventually(new Runnable() {
+ @Override public void run() {
+ assertEquals(counter.get(), NUM_TIMES);
+ }});
+ }
+
+ @Test
+ public void testGetResultOfQueuedTaskBeforeItExecutes() throws Exception {
+ final CountDownLatch latch = new CountDownLatch(1);
+ em.submit(MutableMap.of("tag", "category1"), newLatchAwaiter(latch));
+
+ BasicTask<Integer> t = new BasicTask<Integer>(Callables.returning(123));
+ Future<Integer> future = em.submit(MutableMap.of("tag", "category1"), t);
+
+ Thread thread = new Thread(new Runnable() {
+ public void run() {
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ latch.countDown();
+ }});
+ thread.start();
+ assertEquals(future.get(), (Integer)123);
+ }
+
+ @Test
+ public void testGetResultOfQueuedTaskBeforeItExecutesWithTimeout() throws Exception {
+ final CountDownLatch latch = new CountDownLatch(1);
+ em.submit(MutableMap.of("tag", "category1"), newLatchAwaiter(latch));
+
+ BasicTask<Integer> t = new BasicTask<Integer>(Callables.returning(123));
+ Future<Integer> future = em.submit(MutableMap.of("tag", "category1"), t);
+
+ try {
+ assertEquals(future.get(10, TimeUnit.MILLISECONDS), (Integer)123);
+ fail();
+ } catch (TimeoutException e) {
+ // success
+ }
+ }
+
+ @Test
+ public void testCancelQueuedTaskBeforeItExecutes() throws Exception {
+ final CountDownLatch latch = new CountDownLatch(1);
+ em.submit(MutableMap.of("tag", "category1"), newLatchAwaiter(latch));
+
+ final AtomicBoolean executed = new AtomicBoolean();
+ BasicTask<?> t = new BasicTask<Void>(new Runnable() {
+ public void run() {
+ executed.set(true);
+ }});
+ Future<?> future = em.submit(MutableMap.of("tag", "category1"), t);
+
+ future.cancel(true);
+ latch.countDown();
+ Thread.sleep(10);
+ try {
+ future.get();
+ } catch (CancellationException e) {
+ // success
+ }
+ assertFalse(executed.get());
+ }
+
+ @Test
+ public void testGetResultOfQueuedTaskAfterItExecutes() throws Exception {
+ final CountDownLatch latch = new CountDownLatch(1);
+ em.submit(MutableMap.of("tag", "category1"), newLatchAwaiter(latch));
+
+ BasicTask<Integer> t = new BasicTask<Integer>(Callables.returning(123));
+ Future<Integer> future = em.submit(MutableMap.of("tag", "category1"), t);
+
+ latch.countDown();
+ assertEquals(future.get(), (Integer)123);
+ }
+
+ private Callable<Void> newLatchAwaiter(final CountDownLatch latch) {
+ return new Callable<Void>() {
+ public Void call() throws Exception {
+ latch.await();
+ return null;
+ }
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/task/TaskFinalizationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/task/TaskFinalizationTest.java b/core/src/test/java/org/apache/brooklyn/core/util/task/TaskFinalizationTest.java
new file mode 100644
index 0000000..1ff181b
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/task/TaskFinalizationTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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.util.task;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.task.BasicTask;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import brooklyn.util.time.Time;
+
+import com.google.common.base.Stopwatch;
+
+public class TaskFinalizationTest {
+
+ private static final Logger log = LoggerFactory.getLogger(TaskFinalizationTest.class);
+
+ // integration because it can take a while (and finalizers aren't even guaranteed)
+ @Test(groups="Integration")
+ public void testFinalizerInvoked() throws InterruptedException {
+ BasicTask<?> t = new BasicTask<Void>(new Runnable() { public void run() { /* no op */ }});
+ final Semaphore x = new Semaphore(0);
+ t.setFinalizer(new BasicTask.TaskFinalizer() {
+ public void onTaskFinalization(Task<?> t) {
+ synchronized (x) {
+ x.release();
+ }
+ }
+ });
+ t = null;
+ Stopwatch watch = Stopwatch.createStarted();
+ for (int i=0; i<30; i++) {
+ System.gc(); System.gc();
+ if (x.tryAcquire(1, TimeUnit.SECONDS)) {
+ log.info("finalizer ran after "+Time.makeTimeStringRounded(watch));
+ return;
+ }
+ }
+ Assert.fail("finalizer did not run in time");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/task/TasksTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/task/TasksTest.java b/core/src/test/java/org/apache/brooklyn/core/util/task/TasksTest.java
new file mode 100644
index 0000000..0800984
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/task/TasksTest.java
@@ -0,0 +1,184 @@
+/*
+ * 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.util.task;
+
+import static brooklyn.event.basic.DependentConfiguration.attributeWhenReady;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+
+import org.apache.brooklyn.api.management.ExecutionContext;
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.task.TaskInternal;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.core.util.task.ValueResolver;
+import org.apache.brooklyn.test.entity.TestApplication;
+import org.apache.brooklyn.test.entity.TestEntity;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.BrooklynAppUnitTestSupport;
+import brooklyn.entity.basic.EntityFunctions;
+import brooklyn.util.guava.Functionals;
+import brooklyn.util.repeat.Repeater;
+import brooklyn.util.time.Duration;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.util.concurrent.Callables;
+
+
+public class TasksTest extends BrooklynAppUnitTestSupport {
+
+ private ExecutionContext executionContext;
+
+ @BeforeMethod(alwaysRun=true)
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ executionContext = app.getExecutionContext();
+ }
+
+ @Test
+ public void testResolveNull() throws Exception {
+ assertResolvesValue(null, String.class, null);
+ }
+
+ @Test
+ public void testResolveValueCastsToType() throws Exception {
+ assertResolvesValue(123, String.class, "123");
+ }
+
+ @Test
+ public void testResolvesAttributeWhenReady() throws Exception {
+ app.setAttribute(TestApplication.MY_ATTRIBUTE, "myval");
+ assertResolvesValue(attributeWhenReady(app, TestApplication.MY_ATTRIBUTE), String.class, "myval");
+ }
+
+ @Test
+ public void testResolvesMapWithAttributeWhenReady() throws Exception {
+ app.setAttribute(TestApplication.MY_ATTRIBUTE, "myval");
+ Map<?,?> orig = ImmutableMap.of("mykey", attributeWhenReady(app, TestApplication.MY_ATTRIBUTE));
+ Map<?,?> expected = ImmutableMap.of("mykey", "myval");
+ assertResolvesValue(orig, String.class, expected);
+ }
+
+ @Test
+ public void testResolvesSetWithAttributeWhenReady() throws Exception {
+ app.setAttribute(TestApplication.MY_ATTRIBUTE, "myval");
+ Set<?> orig = ImmutableSet.of(attributeWhenReady(app, TestApplication.MY_ATTRIBUTE));
+ Set<?> expected = ImmutableSet.of("myval");
+ assertResolvesValue(orig, String.class, expected);
+ }
+
+ @Test
+ public void testResolvesMapOfMapsWithAttributeWhenReady() throws Exception {
+ app.setAttribute(TestApplication.MY_ATTRIBUTE, "myval");
+ Map<?,?> orig = ImmutableMap.of("mykey", ImmutableMap.of("mysubkey", attributeWhenReady(app, TestApplication.MY_ATTRIBUTE)));
+ Map<?,?> expected = ImmutableMap.of("mykey", ImmutableMap.of("mysubkey", "myval"));
+ assertResolvesValue(orig, String.class, expected);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testResolvesIterableOfMapsWithAttributeWhenReady() throws Exception {
+ app.setAttribute(TestApplication.MY_ATTRIBUTE, "myval");
+ // using Iterables.concat so that orig is of type FluentIterable rather than List etc
+ Iterable<?> orig = Iterables.concat(ImmutableList.of(ImmutableMap.of("mykey", attributeWhenReady(app, TestApplication.MY_ATTRIBUTE))));
+ Iterable<Map<?,?>> expected = ImmutableList.<Map<?,?>>of(ImmutableMap.of("mykey", "myval"));
+ assertResolvesValue(orig, String.class, expected);
+ }
+
+ private void assertResolvesValue(Object actual, Class<?> type, Object expected) throws Exception {
+ Object result = Tasks.resolveValue(actual, type, executionContext);
+ assertEquals(result, expected);
+ }
+
+ @Test
+ public void testErrorsResolvingPropagatesOrSwallowedAllCorrectly() throws Exception {
+ app.setConfig(TestEntity.CONF_OBJECT, ValueResolverTest.newThrowTask(Duration.ZERO));
+ Task<Object> t = Tasks.builder().body(Functionals.callable(EntityFunctions.config(TestEntity.CONF_OBJECT), app)).build();
+ ValueResolver<Object> v = Tasks.resolving(t).as(Object.class).context(app.getExecutionContext());
+
+ ValueResolverTest.assertThrowsOnMaybe(v);
+ ValueResolverTest.assertThrowsOnGet(v);
+
+ v.swallowExceptions();
+ ValueResolverTest.assertMaybeIsAbsent(v);
+ ValueResolverTest.assertThrowsOnGet(v);
+
+ v.defaultValue("foo");
+ ValueResolverTest.assertMaybeIsAbsent(v);
+ assertEquals(v.clone().get(), "foo");
+ assertResolvesValue(v, Object.class, "foo");
+ }
+
+ @Test
+ public void testRepeater() throws Exception {
+ Task<?> t;
+
+ t = Tasks.requiring(Repeater.create().until(Callables.returning(true)).every(Duration.millis(1))).build();
+ app.getExecutionContext().submit(t);
+ t.get(Duration.TEN_SECONDS);
+
+ t = Tasks.testing(Repeater.create().until(Callables.returning(true)).every(Duration.millis(1))).build();
+ app.getExecutionContext().submit(t);
+ Assert.assertEquals(t.get(Duration.TEN_SECONDS), true);
+
+ t = Tasks.requiring(Repeater.create().until(Callables.returning(false)).limitIterationsTo(2).every(Duration.millis(1))).build();
+ app.getExecutionContext().submit(t);
+ try {
+ t.get(Duration.TEN_SECONDS);
+ Assert.fail("Should have failed");
+ } catch (Exception e) {
+ // expected
+ }
+
+ t = Tasks.testing(Repeater.create().until(Callables.returning(false)).limitIterationsTo(2).every(Duration.millis(1))).build();
+ app.getExecutionContext().submit(t);
+ Assert.assertEquals(t.get(Duration.TEN_SECONDS), false);
+ }
+
+ @Test
+ public void testRepeaterDescription() throws Exception{
+ final String description = "task description";
+ Repeater repeater = Repeater.create(description)
+ .repeat(Callables.returning(null))
+ .every(Duration.ONE_MILLISECOND)
+ .limitIterationsTo(1)
+ .until(new Callable<Boolean>() {
+ @Override
+ public Boolean call() {
+ TaskInternal<?> current = (TaskInternal<?>)Tasks.current();
+ assertEquals(current.getBlockingDetails(), description);
+ return true;
+ }
+ });
+ Task<Boolean> t = Tasks.testing(repeater).build();
+ app.getExecutionContext().submit(t);
+ assertTrue(t.get(Duration.TEN_SECONDS));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/task/ValueResolverTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/task/ValueResolverTest.java b/core/src/test/java/org/apache/brooklyn/core/util/task/ValueResolverTest.java
new file mode 100644
index 0000000..9f65bc4
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/task/ValueResolverTest.java
@@ -0,0 +1,134 @@
+/*
+ * 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.util.task;
+
+import java.util.concurrent.Callable;
+
+import org.apache.brooklyn.api.management.ExecutionContext;
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.core.util.task.ValueResolver;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.BrooklynAppUnitTestSupport;
+import brooklyn.util.guava.Maybe;
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Time;
+
+/**
+ * see also {@link TasksTest} for more tests
+ */
+@Test
+public class ValueResolverTest extends BrooklynAppUnitTestSupport {
+
+ private ExecutionContext executionContext;
+
+ @BeforeMethod(alwaysRun=true)
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ executionContext = app.getExecutionContext();
+ }
+
+ public static final Task<String> newSleepTask(final Duration timeout, final String result) {
+ return Tasks.<String>builder().body(new Callable<String>() {
+ public String call() {
+ Time.sleep(timeout);
+ return result;
+ }}
+ ).build();
+ }
+
+ public static final Task<String> newThrowTask(final Duration timeout) {
+ return Tasks.<String>builder().body(new Callable<String>() {
+ public String call() {
+ Time.sleep(timeout);
+ throw new IllegalStateException("intended, during tests");
+ }}
+ ).build();
+ }
+
+ public void testTimeoutZero() {
+ Maybe<String> result = Tasks.resolving(newSleepTask(Duration.TEN_SECONDS, "foo")).as(String.class).context(executionContext).timeout(Duration.ZERO).getMaybe();
+ Assert.assertFalse(result.isPresent());
+ }
+
+ public void testTimeoutBig() {
+ Maybe<String> result = Tasks.resolving(newSleepTask(Duration.ZERO, "foo")).as(String.class).context(executionContext).timeout(Duration.TEN_SECONDS).getMaybe();
+ Assert.assertEquals(result.get(), "foo");
+ }
+
+ public void testNoExecutionContextOnCompleted() {
+ Task<String> t = newSleepTask(Duration.ZERO, "foo");
+ executionContext.submit(t).getUnchecked();
+ Maybe<String> result = Tasks.resolving(t).as(String.class).timeout(Duration.ZERO).getMaybe();
+ Assert.assertEquals(result.get(), "foo");
+ }
+
+ public static Throwable assertThrowsOnMaybe(ValueResolver<?> result) {
+ try {
+ result = result.clone();
+ result.getMaybe();
+ Assert.fail("should have thrown");
+ return null;
+ } catch (Exception e) { return e; }
+ }
+ public static Throwable assertThrowsOnGet(ValueResolver<?> result) {
+ result = result.clone();
+ try {
+ result.get();
+ Assert.fail("should have thrown");
+ return null;
+ } catch (Exception e) { return e; }
+ }
+ public static <T> Maybe<T> assertMaybeIsAbsent(ValueResolver<T> result) {
+ result = result.clone();
+ Maybe<T> maybe = result.getMaybe();
+ Assert.assertFalse(maybe.isPresent());
+ return maybe;
+ }
+
+ public void testSwallowError() {
+ ValueResolver<String> result = Tasks.resolving(newThrowTask(Duration.ZERO)).as(String.class).context(executionContext).swallowExceptions();
+ assertMaybeIsAbsent(result);
+ assertThrowsOnGet(result);
+ }
+
+
+ public void testDontSwallowError() {
+ ValueResolver<String> result = Tasks.resolving(newThrowTask(Duration.ZERO)).as(String.class).context(executionContext);
+ assertThrowsOnMaybe(result);
+ assertThrowsOnGet(result);
+ }
+
+ public void testDefaultWhenSwallowError() {
+ ValueResolver<String> result = Tasks.resolving(newThrowTask(Duration.ZERO)).as(String.class).context(executionContext).swallowExceptions().defaultValue("foo");
+ assertMaybeIsAbsent(result);
+ Assert.assertEquals(result.get(), "foo");
+ }
+
+ public void testDefaultBeforeDelayAndError() {
+ ValueResolver<String> result = Tasks.resolving(newThrowTask(Duration.TEN_SECONDS)).as(String.class).context(executionContext).timeout(Duration.ZERO).defaultValue("foo");
+ assertMaybeIsAbsent(result);
+ Assert.assertEquals(result.get(), "foo");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/task/ssh/SshTasksTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/task/ssh/SshTasksTest.java b/core/src/test/java/org/apache/brooklyn/core/util/task/ssh/SshTasksTest.java
new file mode 100644
index 0000000..94fe3e6
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/task/ssh/SshTasksTest.java
@@ -0,0 +1,213 @@
+/*
+ * 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.util.task.ssh;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.util.ssh.BashCommandsIntegrationTest;
+import org.apache.brooklyn.core.util.task.ssh.SshFetchTaskFactory;
+import org.apache.brooklyn.core.util.task.ssh.SshFetchTaskWrapper;
+import org.apache.brooklyn.core.util.task.ssh.SshPutTaskFactory;
+import org.apache.brooklyn.core.util.task.ssh.SshPutTaskWrapper;
+import org.apache.brooklyn.core.util.task.ssh.SshTasks;
+import org.apache.brooklyn.core.util.task.ssh.SshTasksTest;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskFactory;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
+import org.apache.commons.io.FileUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.basic.BrooklynConfigKeys;
+import brooklyn.entity.basic.Entities;
+
+import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
+import org.apache.brooklyn.location.basic.SshMachineLocation;
+
+import brooklyn.util.net.Urls;
+import brooklyn.util.os.Os;
+
+/**
+ * Some tests for {@link SshTasks}. Note more tests in {@link BashCommandsIntegrationTest},
+ * {@link SshEffectorTasksTest}, and {@link SoftwareEffectorTest}.
+ */
+public class SshTasksTest {
+
+ private static final Logger log = LoggerFactory.getLogger(SshTasksTest.class);
+
+ ManagementContext mgmt;
+ SshMachineLocation host;
+ File tempDir;
+
+ boolean failureExpected;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setup() throws Exception {
+ mgmt = new LocalManagementContext();
+
+ LocalhostMachineProvisioningLocation lhc = mgmt.getLocationManager().createLocation(LocationSpec.create(LocalhostMachineProvisioningLocation.class));
+ host = lhc.obtain();
+ clearExpectedFailure();
+ tempDir = Os.newTempDir(getClass());
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ if (mgmt != null) Entities.destroyAll(mgmt);
+ mgmt = null;
+ tempDir = Os.deleteRecursively(tempDir).asNullOrThrowing();
+ checkExpectedFailure();
+ }
+
+ protected void checkExpectedFailure() {
+ if (failureExpected) {
+ clearExpectedFailure();
+ Assert.fail("Test should have thrown an exception but it did not.");
+ }
+ }
+
+ protected void clearExpectedFailure() {
+ failureExpected = false;
+ }
+
+ protected void setExpectingFailure() {
+ failureExpected = true;
+ }
+
+
+ protected <T> ProcessTaskWrapper<T> submit(final ProcessTaskFactory<T> tf) {
+ tf.machine(host);
+ ProcessTaskWrapper<T> t = tf.newTask();
+ mgmt.getExecutionManager().submit(t);
+ return t;
+ }
+
+ protected SshPutTaskWrapper submit(final SshPutTaskFactory tf) {
+ SshPutTaskWrapper t = tf.newTask();
+ mgmt.getExecutionManager().submit(t);
+ return t;
+ }
+
+ @Test(groups="Integration")
+ public void testSshEchoHello() {
+ ProcessTaskWrapper<Integer> t = submit(SshTasks.newSshExecTaskFactory(host, "sleep 1 ; echo hello world"));
+ Assert.assertFalse(t.isDone());
+ Assert.assertEquals(t.get(), (Integer)0);
+ Assert.assertEquals(t.getTask().getUnchecked(), (Integer)0);
+ Assert.assertEquals(t.getStdout().trim(), "hello world");
+ }
+
+ @Test(groups="Integration")
+ public void testCopyTo() throws IOException {
+ String fn = Urls.mergePaths(tempDir.getPath(), "f1");
+ SshPutTaskWrapper t = submit(SshTasks.newSshPutTaskFactory(host, fn).contents("hello world"));
+ t.block();
+ Assert.assertEquals(FileUtils.readFileToString(new File(fn)), "hello world");
+ // and make sure this doesn't throw
+ Assert.assertTrue(t.isDone());
+ Assert.assertTrue(t.isSuccessful());
+ Assert.assertEquals(t.get(), null);
+ Assert.assertEquals(t.getExitCode(), (Integer)0);
+ }
+
+ @Test(groups="Integration")
+ public void testCopyToFailBadSubdir() throws IOException {
+ String fn = Urls.mergePaths(tempDir.getPath(), "non-existent-subdir/file");
+ SshPutTaskWrapper t = submit(SshTasks.newSshPutTaskFactory(host, fn).contents("hello world"));
+ //this doesn't fail
+ t.block();
+ Assert.assertTrue(t.isDone());
+ setExpectingFailure();
+ try {
+ // but this does
+ t.get();
+ } catch (Exception e) {
+ log.info("The error if file cannot be written is: "+e);
+ clearExpectedFailure();
+ }
+ checkExpectedFailure();
+ // and the results indicate failure
+ Assert.assertFalse(t.isSuccessful());
+ Assert.assertNotNull(t.getException());
+ Assert.assertNotEquals(t.getExitCode(), (Integer)0);
+ }
+
+ @Test(groups="Integration")
+ public void testCopyToFailBadSubdirAllow() throws IOException {
+ String fn = Urls.mergePaths(tempDir.getPath(), "non-existent-subdir/file");
+ SshPutTaskWrapper t = submit(SshTasks.newSshPutTaskFactory(host, fn).contents("hello world").allowFailure());
+ //this doesn't fail
+ t.block();
+ Assert.assertTrue(t.isDone());
+ // and this doesn't fail either
+ Assert.assertEquals(t.get(), null);
+ // but it's not successful
+ Assert.assertNotNull(t.getException());
+ Assert.assertFalse(t.isSuccessful());
+ // exit code probably null, but won't be zero
+ Assert.assertNotEquals(t.getExitCode(), (Integer)0);
+ }
+
+ @Test(groups="Integration")
+ public void testCopyToFailBadSubdirCreate() throws IOException {
+ String fn = Urls.mergePaths(tempDir.getPath(), "non-existent-subdir-to-create/file");
+ SshPutTaskWrapper t = submit(SshTasks.newSshPutTaskFactory(host, fn).contents("hello world").createDirectory());
+ t.block();
+ // directory should be created, and file readable now
+ Assert.assertEquals(FileUtils.readFileToString(new File(fn)), "hello world");
+ Assert.assertEquals(t.getExitCode(), (Integer)0);
+ }
+
+ @Test(groups="Integration")
+ public void testSshFetch() throws IOException {
+ String fn = Urls.mergePaths(tempDir.getPath(), "f2");
+ FileUtils.write(new File(fn), "hello fetched world");
+
+ SshFetchTaskFactory tf = SshTasks.newSshFetchTaskFactory(host, fn);
+ SshFetchTaskWrapper t = tf.newTask();
+ mgmt.getExecutionManager().submit(t);
+
+ t.block();
+ Assert.assertTrue(t.isDone());
+ Assert.assertEquals(t.get(), "hello fetched world");
+ Assert.assertEquals(t.getBytes(), "hello fetched world".getBytes());
+ }
+
+ @Test(groups="Integration")
+ public void testSshWithHeaderProperty() {
+ host.setConfig(BrooklynConfigKeys.SSH_CONFIG_SCRIPT_HEADER, "#!/bin/bash -e\necho foo\n");
+ ProcessTaskWrapper<Integer> t = submit(SshTasks.newSshExecTaskFactory(host, "echo bar"));
+ Assert.assertTrue(t.block().getStdout().trim().matches("foo\\s+bar"), "mismatched output was: "+t.getStdout());
+ }
+
+ @Test(groups="Integration")
+ public void testSshIgnoringHeaderProperty() {
+ host.setConfig(BrooklynConfigKeys.SSH_CONFIG_SCRIPT_HEADER, "#!/bin/bash -e\necho foo\n");
+ ProcessTaskWrapper<Integer> t = submit(SshTasks.newSshExecTaskFactory(host, false, "echo bar"));
+ Assert.assertTrue(t.block().getStdout().trim().matches("bar"), "mismatched output was: "+t.getStdout());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/task/system/SystemTasksTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/task/system/SystemTasksTest.java b/core/src/test/java/org/apache/brooklyn/core/util/task/system/SystemTasksTest.java
new file mode 100644
index 0000000..b673056
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/task/system/SystemTasksTest.java
@@ -0,0 +1,137 @@
+/*
+ * 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.util.task.system;
+
+import java.io.File;
+
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.util.task.ssh.SshTasks;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskFactory;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
+import org.apache.brooklyn.core.util.task.system.SystemTasks;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.basic.Entities;
+import brooklyn.util.os.Os;
+
+/**
+ * Some tests for {@link SystemTasks}. See {@link SshTasks}.
+ */
+public class SystemTasksTest {
+
+ ManagementContext mgmt;
+ File tempDir;
+
+ boolean failureExpected;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setup() throws Exception {
+ mgmt = new LocalManagementContext();
+
+ clearExpectedFailure();
+ tempDir = Os.newTempDir(getClass());
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ if (mgmt != null) Entities.destroyAll(mgmt);
+ mgmt = null;
+ tempDir = Os.deleteRecursively(tempDir).asNullOrThrowing();
+ checkExpectedFailure();
+ }
+
+ protected void checkExpectedFailure() {
+ if (failureExpected) {
+ clearExpectedFailure();
+ Assert.fail("Test should have thrown an exception but it did not.");
+ }
+ }
+
+ protected void clearExpectedFailure() {
+ failureExpected = false;
+ }
+
+ protected void setExpectingFailure() {
+ failureExpected = true;
+ }
+
+
+ protected <T> ProcessTaskWrapper<T> submit(final ProcessTaskFactory<T> tf) {
+ ProcessTaskWrapper<T> t = tf.newTask();
+ mgmt.getExecutionManager().submit(t);
+ return t;
+ }
+
+ @Test(groups="Integration")
+ public void testExecEchoHello() {
+ ProcessTaskWrapper<Integer> t = submit(SystemTasks.exec("sleep 1 ; echo hello world"));
+ Assert.assertFalse(t.isDone());
+ Assert.assertEquals(t.get(), (Integer)0);
+ Assert.assertEquals(t.getTask().getUnchecked(), (Integer)0);
+ Assert.assertEquals(t.getStdout().trim(), "hello world");
+ }
+
+ // FIXME Behaviour of Bash shell changes from 3.x to 4.x so test is disabled
+ @Test(groups="Integration", enabled=false)
+ public void testSubshellExitScriptDoesNotExit() {
+ checkSubshellExitDoesNotExit(taskSubshellExit().runAsScript());
+ }
+
+ @Test(groups="Integration")
+ public void testSubshellExitCommandDoesNotExit() {
+ checkSubshellExitDoesNotExit(taskSubshellExit().runAsCommand());
+ }
+
+ public ProcessTaskFactory<Integer> taskSubshellExit() {
+ return SystemTasks.exec("echo hello", "( exit 1 )", "echo bye code $?");
+ }
+
+ public void checkSubshellExitDoesNotExit(ProcessTaskFactory<Integer> task) {
+ ProcessTaskWrapper<Integer> t = submit(task);
+ t.block();
+ Assert.assertEquals(t.get(), (Integer)0);
+ Assert.assertTrue(t.getStdout().contains("bye code 1"), "stdout is: "+t.getStdout());
+ }
+
+ @Test(groups="Integration")
+ public void testGroupExitScriptDoesNotExit() {
+ checkGroupExitDoesExit(taskGroupExit().runAsScript());
+ }
+
+ @Test(groups="Integration")
+ public void testGroupExitCommandDoesNotExit() {
+ checkGroupExitDoesExit(taskGroupExit().runAsCommand());
+ }
+
+ public ProcessTaskFactory<Integer> taskGroupExit() {
+ return SystemTasks.exec("echo hello", "{ exit 1 ; }", "echo bye code $?");
+ }
+
+ public void checkGroupExitDoesExit(ProcessTaskFactory<Integer> task) {
+ ProcessTaskWrapper<Integer> t = submit(task);
+ t.block();
+ Assert.assertEquals(t.get(), (Integer)1);
+ Assert.assertFalse(t.getStdout().contains("bye"), "stdout is: "+t.getStdout());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/text/DataUriSchemeParserTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/text/DataUriSchemeParserTest.java b/core/src/test/java/org/apache/brooklyn/core/util/text/DataUriSchemeParserTest.java
new file mode 100644
index 0000000..73794a3
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/text/DataUriSchemeParserTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.util.text;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+
+import org.apache.brooklyn.core.util.text.DataUriSchemeParser;
+import org.bouncycastle.util.encoders.Base64;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class DataUriSchemeParserTest {
+
+ @Test
+ public void testSimple() {
+ Assert.assertEquals(new DataUriSchemeParser("data:,hello").parse().getDataAsString(), "hello");
+ Assert.assertEquals(DataUriSchemeParser.toString("data:,hello"), "hello");
+ }
+
+ @Test
+ public void testMimeType() throws UnsupportedEncodingException {
+ DataUriSchemeParser p = new DataUriSchemeParser("data:application/json,"+URLEncoder.encode("{ }", "US-ASCII")).parse();
+ Assert.assertEquals(p.getMimeType(), "application/json");
+ Assert.assertEquals(p.getData(), "{ }".getBytes());
+ }
+
+ @Test
+ public void testBase64() {
+ Assert.assertEquals(DataUriSchemeParser.toString(
+ "data:;base64,"+new String(Base64.encode("hello".getBytes()))),
+ "hello");
+ }
+
+ // TODO test pictures, etc
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/org/apache/brooklyn/core/util/text/TemplateProcessorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/util/text/TemplateProcessorTest.java b/core/src/test/java/org/apache/brooklyn/core/util/text/TemplateProcessorTest.java
new file mode 100644
index 0000000..05f4fde
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/util/text/TemplateProcessorTest.java
@@ -0,0 +1,180 @@
+/*
+ * 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.util.text;
+
+import static org.testng.Assert.assertEquals;
+
+import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.util.text.TemplateProcessor;
+import org.apache.brooklyn.test.entity.TestApplication;
+import org.apache.brooklyn.test.entity.TestEntity;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.BrooklynAppUnitTestSupport;
+import brooklyn.event.basic.DependentConfiguration;
+import brooklyn.test.FixedLocaleTest;
+
+import com.google.common.collect.ImmutableMap;
+
+public class TemplateProcessorTest extends BrooklynAppUnitTestSupport {
+ private FixedLocaleTest localeFix = new FixedLocaleTest();
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ super.setUp();
+ localeFix.setUp();
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ super.tearDown();
+ localeFix.tearDown();
+ }
+
+ @Test
+ public void testAdditionalArgs() {
+ String templateContents = "${mykey}";
+ String result = TemplateProcessor.processTemplateContents(templateContents, app, ImmutableMap.of("mykey", "myval"));
+ assertEquals(result, "myval");
+ }
+
+ @Test
+ public void testEntityConfig() {
+ TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class)
+ .configure(TestEntity.CONF_NAME, "myval"));
+ String templateContents = "${config['"+TestEntity.CONF_NAME.getName()+"']}";
+ String result = TemplateProcessor.processTemplateContents(templateContents, entity, ImmutableMap.<String,Object>of());
+ assertEquals(result, "myval");
+ }
+
+ @Test
+ public void testEntityConfigNumber() {
+ TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class)
+ .configure(TestEntity.CONF_OBJECT, 123456));
+ String templateContents = "${config['"+TestEntity.CONF_OBJECT.getName()+"']}";
+ String result = TemplateProcessor.processTemplateContents(templateContents, entity, ImmutableMap.<String,Object>of());
+ assertEquals(result, "123,456");
+ }
+
+ @Test
+ public void testEntityConfigNumberUnadorned() {
+ // ?c is needed to avoid commas (i always forget this!)
+ TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class)
+ .configure(TestEntity.CONF_OBJECT, 123456));
+ String templateContents = "${config['"+TestEntity.CONF_OBJECT.getName()+"']?c}";
+ String result = TemplateProcessor.processTemplateContents(templateContents, entity, ImmutableMap.<String,Object>of());
+ assertEquals(result, "123456");
+ }
+
+ @Test
+ public void testGetSysProp() {
+ System.setProperty("testGetSysProp", "myval");
+
+ String templateContents = "${javaSysProps['testGetSysProp']}";
+ String result = TemplateProcessor.processTemplateContents(templateContents, app, ImmutableMap.<String,Object>of());
+ assertEquals(result, "myval");
+ }
+
+ @Test
+ public void testEntityGetterMethod() {
+ String templateContents = "${entity.id}";
+ String result = TemplateProcessor.processTemplateContents(templateContents, app, ImmutableMap.<String,Object>of());
+ assertEquals(result, app.getId());
+ }
+
+ @Test
+ public void testManagementContextConfig() {
+ mgmt.getBrooklynProperties().put("globalmykey", "myval");
+ String templateContents = "${mgmt.globalmykey}";
+ String result = TemplateProcessor.processTemplateContents(templateContents, app, ImmutableMap.<String,Object>of());
+ assertEquals(result, "myval");
+ }
+
+ @Test
+ public void testManagementContextDefaultValue() {
+ String templateContents = "${(missing)!\"defval\"}";
+ Object result = TemplateProcessor.processTemplateContents(templateContents, app, ImmutableMap.<String,Object>of());
+ assertEquals(result, "defval");
+ }
+
+ @Test
+ public void testManagementContextDefaultValueInDotMissingValue() {
+ String templateContents = "${(mgmt.missing.more_missing)!\"defval\"}";
+ Object result = TemplateProcessor.processTemplateContents(templateContents, app, ImmutableMap.<String,Object>of());
+ assertEquals(result, "defval");
+ }
+
+ @Test
+ public void testManagementContextConfigWithDot() {
+ mgmt.getBrooklynProperties().put("global.mykey", "myval");
+ String templateContents = "${mgmt['global.mykey']}";
+ String result = TemplateProcessor.processTemplateContents(templateContents, app, ImmutableMap.<String,Object>of());
+ assertEquals(result, "myval");
+ }
+
+ @Test
+ public void testManagementContextErrors() {
+ try {
+ // NB: dot has special meaning so this should fail; must be accessed using bracket notation as above
+ mgmt.getBrooklynProperties().put("global.mykey", "myval");
+ String templateContents = "${mgmt.global.mykey}";
+ TemplateProcessor.processTemplateContents(templateContents, app, ImmutableMap.<String,Object>of());
+ Assert.fail("Should not have found value with intermediate dot");
+ } catch (Exception e) {
+ Assert.assertTrue(e.toString().contains("global"), "Should have mentioned missing key 'global' in error");
+ }
+ }
+
+ @Test
+ public void testApplyTemplatedConfigWithAttributeWhenReady() {
+ app.setAttribute(TestApplication.MY_ATTRIBUTE, "myval");
+
+ TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class)
+ .configure(TestEntity.CONF_NAME, DependentConfiguration.attributeWhenReady(app, TestApplication.MY_ATTRIBUTE)));
+
+ String templateContents = "${config['"+TestEntity.CONF_NAME.getName()+"']}";
+ String result = TemplateProcessor.processTemplateContents(templateContents, entity, ImmutableMap.<String,Object>of());
+ assertEquals(result, "myval");
+ }
+
+ @Test
+ public void testDotSeparatedKey() {
+ String templateContents = "${a.b}";
+ String result = TemplateProcessor.processTemplateContents(templateContents, (ManagementContextInternal)null,
+ ImmutableMap.<String,Object>of("a.b", "myval"));
+ assertEquals(result, "myval");
+ }
+
+ @Test
+ public void testDotSeparatedKeyCollisionFailure() {
+ String templateContents = "${aaa.bbb}";
+ try {
+ TemplateProcessor.processTemplateContents(templateContents, (ManagementContextInternal)null,
+ ImmutableMap.<String,Object>of("aaa.bbb", "myval", "aaa", "blocker"));
+ Assert.fail("Should not have found value with intermediate dot where prefix is overridden");
+ } catch (Exception e) {
+ Assert.assertTrue(e.toString().contains("aaa"), "Should have mentioned missing key 'aaa' in error");
+ }
+ }
+
+}
[08/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/policy/src/main/java/brooklyn/enricher/TimeFractionDeltaEnricher.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/enricher/TimeFractionDeltaEnricher.java b/policy/src/main/java/brooklyn/enricher/TimeFractionDeltaEnricher.java
index e1fce23..d86aec0 100644
--- a/policy/src/main/java/brooklyn/enricher/TimeFractionDeltaEnricher.java
+++ b/policy/src/main/java/brooklyn/enricher/TimeFractionDeltaEnricher.java
@@ -27,9 +27,9 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.event.SensorEvent;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.enricher.basic.AbstractTypeTransformingEnricher;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.javalang.JavaClassNames;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/policy/src/main/java/brooklyn/enricher/TimeWeightedDeltaEnricher.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/enricher/TimeWeightedDeltaEnricher.java b/policy/src/main/java/brooklyn/enricher/TimeWeightedDeltaEnricher.java
index 3f7357d..0d5e066 100644
--- a/policy/src/main/java/brooklyn/enricher/TimeWeightedDeltaEnricher.java
+++ b/policy/src/main/java/brooklyn/enricher/TimeWeightedDeltaEnricher.java
@@ -24,13 +24,13 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.event.SensorEvent;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.enricher.basic.AbstractTypeTransformingEnricher;
import brooklyn.enricher.basic.YamlTimeWeightedDeltaEnricher;
import brooklyn.util.GroovyJavaMethods;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.javalang.JavaClassNames;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/policy/src/main/java/brooklyn/entity/brooklyn/BrooklynMetrics.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/entity/brooklyn/BrooklynMetrics.java b/policy/src/main/java/brooklyn/entity/brooklyn/BrooklynMetrics.java
index e927c1e..f717812 100644
--- a/policy/src/main/java/brooklyn/entity/brooklyn/BrooklynMetrics.java
+++ b/policy/src/main/java/brooklyn/entity/brooklyn/BrooklynMetrics.java
@@ -21,10 +21,10 @@ package brooklyn.entity.brooklyn;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.event.basic.BasicAttributeSensor;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
-import brooklyn.util.flags.SetFromFlag;
@ImplementedBy(BrooklynMetricsImpl.class)
public interface BrooklynMetrics extends Entity {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/policy/src/main/java/brooklyn/entity/brooklyn/BrooklynMetricsImpl.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/entity/brooklyn/BrooklynMetricsImpl.java b/policy/src/main/java/brooklyn/entity/brooklyn/BrooklynMetricsImpl.java
index 93ece4a..caf1120 100644
--- a/policy/src/main/java/brooklyn/entity/brooklyn/BrooklynMetricsImpl.java
+++ b/policy/src/main/java/brooklyn/entity/brooklyn/BrooklynMetricsImpl.java
@@ -26,9 +26,9 @@ import java.util.concurrent.TimeUnit;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.core.management.internal.LocalSubscriptionManager;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.util.task.BasicExecutionManager;
import brooklyn.entity.basic.AbstractEntity;
-import brooklyn.util.task.BasicExecutionManager;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/policy/src/main/java/brooklyn/policy/autoscaling/AutoScalerPolicy.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/policy/autoscaling/AutoScalerPolicy.java b/policy/src/main/java/brooklyn/policy/autoscaling/AutoScalerPolicy.java
index 28c2123..9da5e12 100644
--- a/policy/src/main/java/brooklyn/policy/autoscaling/AutoScalerPolicy.java
+++ b/policy/src/main/java/brooklyn/policy/autoscaling/AutoScalerPolicy.java
@@ -40,6 +40,9 @@ import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
+import org.apache.brooklyn.core.util.task.Tasks;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.BrooklynTaskTags;
@@ -52,9 +55,6 @@ import brooklyn.policy.autoscaling.SizeHistory.WindowSummary;
import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.policy.loadbalancing.LoadBalancingPolicy;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.flags.SetFromFlag;
-import brooklyn.util.flags.TypeCoercions;
-import brooklyn.util.task.Tasks;
import brooklyn.util.time.Duration;
import com.google.common.base.Function;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/policy/src/main/java/brooklyn/policy/followthesun/FollowTheSunPolicy.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/policy/followthesun/FollowTheSunPolicy.java b/policy/src/main/java/brooklyn/policy/followthesun/FollowTheSunPolicy.java
index 1747424..dde1609 100644
--- a/policy/src/main/java/brooklyn/policy/followthesun/FollowTheSunPolicy.java
+++ b/policy/src/main/java/brooklyn/policy/followthesun/FollowTheSunPolicy.java
@@ -38,6 +38,7 @@ import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -46,7 +47,6 @@ import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.policy.followthesun.FollowTheSunPool.ContainerItemPair;
import brooklyn.policy.loadbalancing.Movable;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/policy/src/main/java/brooklyn/policy/ha/AbstractFailureDetector.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/policy/ha/AbstractFailureDetector.java b/policy/src/main/java/brooklyn/policy/ha/AbstractFailureDetector.java
index f88dc60..0c2f4d2 100644
--- a/policy/src/main/java/brooklyn/policy/ha/AbstractFailureDetector.java
+++ b/policy/src/main/java/brooklyn/policy/ha/AbstractFailureDetector.java
@@ -28,6 +28,9 @@ import java.util.concurrent.atomic.AtomicReference;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
+import org.apache.brooklyn.core.util.task.BasicTask;
+import org.apache.brooklyn.core.util.task.ScheduledTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -39,9 +42,6 @@ import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.policy.ha.HASensors.FailureDescriptor;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.SetFromFlag;
-import brooklyn.util.task.BasicTask;
-import brooklyn.util.task.ScheduledTask;
import brooklyn.util.time.Duration;
import brooklyn.util.time.Time;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/policy/src/main/java/brooklyn/policy/ha/ConditionalSuspendPolicy.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/policy/ha/ConditionalSuspendPolicy.java b/policy/src/main/java/brooklyn/policy/ha/ConditionalSuspendPolicy.java
index 9be8256..9a869ae 100644
--- a/policy/src/main/java/brooklyn/policy/ha/ConditionalSuspendPolicy.java
+++ b/policy/src/main/java/brooklyn/policy/ha/ConditionalSuspendPolicy.java
@@ -23,13 +23,13 @@ import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.policy.basic.AbstractPolicy;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.javalang.JavaClassNames;
import com.google.common.base.Preconditions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/policy/src/main/java/brooklyn/policy/ha/ConnectionFailureDetector.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/policy/ha/ConnectionFailureDetector.java b/policy/src/main/java/brooklyn/policy/ha/ConnectionFailureDetector.java
index a1a59a4..ff5d60e 100644
--- a/policy/src/main/java/brooklyn/policy/ha/ConnectionFailureDetector.java
+++ b/policy/src/main/java/brooklyn/policy/ha/ConnectionFailureDetector.java
@@ -20,13 +20,13 @@ package brooklyn.policy.ha;
import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.event.Sensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.event.basic.BasicConfigKey;
import brooklyn.event.basic.BasicNotificationSensor;
import brooklyn.policy.ha.HASensors.FailureDescriptor;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.guava.Maybe;
import brooklyn.util.net.Networking;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/policy/src/main/java/brooklyn/policy/ha/ServiceFailureDetector.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/policy/ha/ServiceFailureDetector.java b/policy/src/main/java/brooklyn/policy/ha/ServiceFailureDetector.java
index 7ae6f33..2e4b719 100644
--- a/policy/src/main/java/brooklyn/policy/ha/ServiceFailureDetector.java
+++ b/policy/src/main/java/brooklyn/policy/ha/ServiceFailureDetector.java
@@ -24,6 +24,10 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.brooklyn.api.event.SensorEvent;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
+import org.apache.brooklyn.core.util.task.BasicTask;
+import org.apache.brooklyn.core.util.task.ScheduledTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -38,11 +42,7 @@ import brooklyn.event.basic.BasicConfigKey;
import brooklyn.event.basic.BasicNotificationSensor;
import brooklyn.policy.ha.HASensors.FailureDescriptor;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.SetFromFlag;
-import brooklyn.util.task.BasicTask;
-import brooklyn.util.task.ScheduledTask;
import brooklyn.util.time.Duration;
import brooklyn.util.time.Time;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/policy/src/main/java/brooklyn/policy/ha/ServiceReplacer.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/policy/ha/ServiceReplacer.java b/policy/src/main/java/brooklyn/policy/ha/ServiceReplacer.java
index 459c13e..884f2df 100644
--- a/policy/src/main/java/brooklyn/policy/ha/ServiceReplacer.java
+++ b/policy/src/main/java/brooklyn/policy/ha/ServiceReplacer.java
@@ -35,6 +35,8 @@ import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
@@ -48,9 +50,7 @@ import brooklyn.event.basic.BasicNotificationSensor;
import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.policy.ha.HASensors.FailureDescriptor;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.base.Ticker;
import com.google.common.collect.Lists;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/policy/src/main/java/brooklyn/policy/ha/ServiceRestarter.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/policy/ha/ServiceRestarter.java b/policy/src/main/java/brooklyn/policy/ha/ServiceRestarter.java
index 3a3f0b4..d53434e 100644
--- a/policy/src/main/java/brooklyn/policy/ha/ServiceRestarter.java
+++ b/policy/src/main/java/brooklyn/policy/ha/ServiceRestarter.java
@@ -28,6 +28,8 @@ import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
@@ -40,8 +42,6 @@ import brooklyn.event.basic.BasicNotificationSensor;
import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.policy.ha.HASensors.FailureDescriptor;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.javalang.JavaClassNames;
import brooklyn.util.time.Duration;
import brooklyn.util.time.Time;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/policy/src/main/java/brooklyn/policy/ha/SshMachineFailureDetector.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/policy/ha/SshMachineFailureDetector.java b/policy/src/main/java/brooklyn/policy/ha/SshMachineFailureDetector.java
index 7d31cf7..1fa9982 100644
--- a/policy/src/main/java/brooklyn/policy/ha/SshMachineFailureDetector.java
+++ b/policy/src/main/java/brooklyn/policy/ha/SshMachineFailureDetector.java
@@ -23,16 +23,18 @@ import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.brooklyn.api.catalog.Catalog;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.event.basic.BasicNotificationSensor;
+
import org.apache.brooklyn.location.basic.Machines;
import org.apache.brooklyn.location.basic.SshMachineLocation;
+
import brooklyn.policy.ha.HASensors.FailureDescriptor;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.guava.Maybe;
-import brooklyn.util.internal.ssh.SshTool;
import brooklyn.util.time.Duration;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/policy/src/main/java/brooklyn/policy/loadbalancing/ItemsInContainersGroup.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/policy/loadbalancing/ItemsInContainersGroup.java b/policy/src/main/java/brooklyn/policy/loadbalancing/ItemsInContainersGroup.java
index ac93639..efd41d8 100644
--- a/policy/src/main/java/brooklyn/policy/loadbalancing/ItemsInContainersGroup.java
+++ b/policy/src/main/java/brooklyn/policy/loadbalancing/ItemsInContainersGroup.java
@@ -21,11 +21,11 @@ package brooklyn.policy.loadbalancing;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.Group;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.DynamicGroup;
import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/policy/src/main/java/brooklyn/policy/loadbalancing/LoadBalancingPolicy.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/policy/loadbalancing/LoadBalancingPolicy.java b/policy/src/main/java/brooklyn/policy/loadbalancing/LoadBalancingPolicy.java
index f5ae09c..2c50883 100644
--- a/policy/src/main/java/brooklyn/policy/loadbalancing/LoadBalancingPolicy.java
+++ b/policy/src/main/java/brooklyn/policy/loadbalancing/LoadBalancingPolicy.java
@@ -35,6 +35,7 @@ import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -44,7 +45,6 @@ import brooklyn.policy.autoscaling.AutoScalerPolicy;
import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.policy.loadbalancing.BalanceableWorkerPool.ContainerItemPair;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/policy/src/main/java/brooklyn/policy/loadbalancing/Movable.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/policy/loadbalancing/Movable.java b/policy/src/main/java/brooklyn/policy/loadbalancing/Movable.java
index f95ba4f..b0f1658 100644
--- a/policy/src/main/java/brooklyn/policy/loadbalancing/Movable.java
+++ b/policy/src/main/java/brooklyn/policy/loadbalancing/Movable.java
@@ -19,6 +19,7 @@
package brooklyn.policy.loadbalancing;
import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.annotation.Effector;
@@ -26,7 +27,6 @@ import brooklyn.entity.annotation.EffectorParam;
import brooklyn.entity.basic.MethodEffector;
import brooklyn.event.basic.BasicAttributeSensor;
import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.util.flags.SetFromFlag;
/**
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/policy/src/test/java/brooklyn/enricher/HttpLatencyDetectorTest.java
----------------------------------------------------------------------
diff --git a/policy/src/test/java/brooklyn/enricher/HttpLatencyDetectorTest.java b/policy/src/test/java/brooklyn/enricher/HttpLatencyDetectorTest.java
index 9777e03..7c7a9f3 100644
--- a/policy/src/test/java/brooklyn/enricher/HttpLatencyDetectorTest.java
+++ b/policy/src/test/java/brooklyn/enricher/HttpLatencyDetectorTest.java
@@ -24,6 +24,7 @@ import java.util.concurrent.TimeUnit;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.http.BetterMockWebServer;
import org.apache.brooklyn.test.EntityTestUtils;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestEntity;
@@ -35,9 +36,10 @@ import org.testng.annotations.Test;
import brooklyn.entity.basic.Entities;
import brooklyn.event.basic.Sensors;
+
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
+
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.http.BetterMockWebServer;
import com.google.common.collect.ImmutableList;
import com.google.mockwebserver.MockResponse;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/policy/src/test/java/brooklyn/enricher/RebindEnricherTest.java
----------------------------------------------------------------------
diff --git a/policy/src/test/java/brooklyn/enricher/RebindEnricherTest.java b/policy/src/test/java/brooklyn/enricher/RebindEnricherTest.java
index ac1b5c1..a01fd17 100644
--- a/policy/src/test/java/brooklyn/enricher/RebindEnricherTest.java
+++ b/policy/src/test/java/brooklyn/enricher/RebindEnricherTest.java
@@ -24,6 +24,7 @@ import java.net.URL;
import java.util.concurrent.TimeUnit;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.http.BetterMockWebServer;
import org.apache.brooklyn.test.EntityTestUtils;
import org.apache.brooklyn.test.entity.TestApplication;
import org.testng.annotations.AfterMethod;
@@ -33,7 +34,6 @@ import brooklyn.entity.basic.Attributes;
import brooklyn.entity.rebind.RebindTestFixtureWithApp;
import brooklyn.event.basic.Sensors;
import brooklyn.test.Asserts;
-import brooklyn.util.http.BetterMockWebServer;
import brooklyn.util.time.Duration;
import brooklyn.util.time.Time;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/policy/src/test/java/brooklyn/policy/ha/ServiceReplacerTest.java
----------------------------------------------------------------------
diff --git a/policy/src/test/java/brooklyn/policy/ha/ServiceReplacerTest.java b/policy/src/test/java/brooklyn/policy/ha/ServiceReplacerTest.java
index 5a88649..c679224 100644
--- a/policy/src/test/java/brooklyn/policy/ha/ServiceReplacerTest.java
+++ b/policy/src/test/java/brooklyn/policy/ha/ServiceReplacerTest.java
@@ -35,6 +35,7 @@ import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.test.EntityTestUtils;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.test.entity.TestApplication;
@@ -60,7 +61,6 @@ import org.apache.brooklyn.location.basic.SimulatedLocation;
import brooklyn.policy.ha.HASensors.FailureDescriptor;
import brooklyn.test.Asserts;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.javalang.JavaClassNames;
import com.google.common.base.Predicate;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/policy/src/test/java/brooklyn/policy/ha/ServiceRestarterTest.java
----------------------------------------------------------------------
diff --git a/policy/src/test/java/brooklyn/policy/ha/ServiceRestarterTest.java b/policy/src/test/java/brooklyn/policy/ha/ServiceRestarterTest.java
index ce0fbf1..81cff78 100644
--- a/policy/src/test/java/brooklyn/policy/ha/ServiceRestarterTest.java
+++ b/policy/src/test/java/brooklyn/policy/ha/ServiceRestarterTest.java
@@ -31,6 +31,7 @@ import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestEntity;
@@ -45,7 +46,6 @@ import brooklyn.entity.basic.Lifecycle;
import brooklyn.entity.trait.FailingEntity;
import brooklyn.policy.ha.HASensors.FailureDescriptor;
import brooklyn.test.Asserts;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
import com.google.common.base.Function;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/policy/src/test/java/brooklyn/policy/loadbalancing/MockContainerEntity.java
----------------------------------------------------------------------
diff --git a/policy/src/test/java/brooklyn/policy/loadbalancing/MockContainerEntity.java b/policy/src/test/java/brooklyn/policy/loadbalancing/MockContainerEntity.java
index da4472e..70d4b57 100644
--- a/policy/src/test/java/brooklyn/policy/loadbalancing/MockContainerEntity.java
+++ b/policy/src/test/java/brooklyn/policy/loadbalancing/MockContainerEntity.java
@@ -23,6 +23,7 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.Effector;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.annotation.EffectorParam;
@@ -30,7 +31,6 @@ import brooklyn.entity.basic.AbstractGroup;
import brooklyn.entity.basic.MethodEffector;
import brooklyn.entity.trait.Startable;
import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.util.flags.SetFromFlag;
@ImplementedBy(MockContainerEntityImpl.class)
public interface MockContainerEntity extends AbstractGroup, BalanceableContainer<Movable>, Startable {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/basic/AbstractSoftwareProcessDriver.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/basic/AbstractSoftwareProcessDriver.java b/software/base/src/main/java/brooklyn/entity/basic/AbstractSoftwareProcessDriver.java
index bf7454d..a1b4ea8 100644
--- a/software/base/src/main/java/brooklyn/entity/basic/AbstractSoftwareProcessDriver.java
+++ b/software/base/src/main/java/brooklyn/entity/basic/AbstractSoftwareProcessDriver.java
@@ -29,19 +29,19 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.core.util.text.TemplateProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.config.ConfigKey;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.os.Os;
import brooklyn.util.stream.ReaderInputStream;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.Tasks;
import brooklyn.util.text.Strings;
-import brooklyn.util.text.TemplateProcessor;
import com.google.common.annotations.Beta;
import com.google.common.base.Optional;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/basic/AbstractSoftwareProcessSshDriver.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/basic/AbstractSoftwareProcessSshDriver.java b/software/base/src/main/java/brooklyn/entity/basic/AbstractSoftwareProcessSshDriver.java
index c8efbb9..31ee4be 100644
--- a/software/base/src/main/java/brooklyn/entity/basic/AbstractSoftwareProcessSshDriver.java
+++ b/software/base/src/main/java/brooklyn/entity/basic/AbstractSoftwareProcessSshDriver.java
@@ -29,6 +29,11 @@ import java.util.Set;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.entity.drivers.downloads.DownloadResolver;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
+import org.apache.brooklyn.core.util.internal.ssh.sshj.SshjTool;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -45,18 +50,15 @@ import brooklyn.entity.basic.lifecycle.ScriptHelper;
import brooklyn.entity.effector.EffectorTasks;
import brooklyn.entity.software.SshEffectorTasks;
import brooklyn.event.feed.ConfigToAttributes;
+
import org.apache.brooklyn.location.basic.SshMachineLocation;
+
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.guava.Maybe;
-import brooklyn.util.internal.ssh.SshTool;
-import brooklyn.util.internal.ssh.sshj.SshjTool;
import brooklyn.util.os.Os;
import brooklyn.util.ssh.BashCommands;
import brooklyn.util.stream.KnownSizeInputStream;
import brooklyn.util.stream.Streams;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.task.system.ProcessTaskWrapper;
import brooklyn.util.text.StringPredicates;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/basic/SameServerDriverLifecycleEffectorTasks.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/basic/SameServerDriverLifecycleEffectorTasks.java b/software/base/src/main/java/brooklyn/entity/basic/SameServerDriverLifecycleEffectorTasks.java
index 1a926a5..c7d19c1 100644
--- a/software/base/src/main/java/brooklyn/entity/basic/SameServerDriverLifecycleEffectorTasks.java
+++ b/software/base/src/main/java/brooklyn/entity/basic/SameServerDriverLifecycleEffectorTasks.java
@@ -27,6 +27,8 @@ import org.apache.brooklyn.api.location.MachineLocation;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
import org.apache.brooklyn.api.location.PortRange;
import org.apache.brooklyn.api.management.TaskAdaptable;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -43,9 +45,7 @@ import brooklyn.entity.trait.StartableMethods;
import org.apache.brooklyn.location.basic.LocationConfigKeys;
import brooklyn.util.collections.MutableSet;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.guava.Maybe;
-import brooklyn.util.task.DynamicTasks;
public class SameServerDriverLifecycleEffectorTasks extends MachineLifecycleEffectorTasks {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/basic/SameServerEntity.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/basic/SameServerEntity.java b/software/base/src/main/java/brooklyn/entity/basic/SameServerEntity.java
index 080cb87..374402a 100644
--- a/software/base/src/main/java/brooklyn/entity/basic/SameServerEntity.java
+++ b/software/base/src/main/java/brooklyn/entity/basic/SameServerEntity.java
@@ -24,6 +24,7 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ServiceStateLogic.ComputeServiceIndicatorsFromChildrenAndMembers;
@@ -31,7 +32,6 @@ import brooklyn.entity.trait.Startable;
import brooklyn.event.basic.BasicAttributeSensor;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.QuorumCheck;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.reflect.TypeToken;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/basic/SameServerEntityImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/basic/SameServerEntityImpl.java b/software/base/src/main/java/brooklyn/entity/basic/SameServerEntityImpl.java
index 32050fd..ff58d89 100644
--- a/software/base/src/main/java/brooklyn/entity/basic/SameServerEntityImpl.java
+++ b/software/base/src/main/java/brooklyn/entity/basic/SameServerEntityImpl.java
@@ -24,13 +24,13 @@ import java.util.Collection;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.Tasks;
import brooklyn.entity.basic.ServiceStateLogic.ComputeServiceIndicatorsFromChildrenAndMembers;
import brooklyn.entity.software.MachineLifecycleEffectorTasks;
import brooklyn.util.collections.QuorumCheck;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.Tasks;
public class SameServerEntityImpl extends AbstractEntity implements SameServerEntity {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcess.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcess.java b/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcess.java
index cf0dd6b..e80013f 100644
--- a/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcess.java
+++ b/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcess.java
@@ -24,6 +24,7 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.Lifecycle.Transition;
@@ -33,7 +34,6 @@ import brooklyn.event.basic.AttributeSensorAndConfigKey;
import brooklyn.event.basic.MapConfigKey;
import brooklyn.event.basic.Sensors;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.time.Duration;
import com.google.common.annotations.Beta;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcessDriverLifecycleEffectorTasks.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcessDriverLifecycleEffectorTasks.java b/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcessDriverLifecycleEffectorTasks.java
index 1067333..457bb12 100644
--- a/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcessDriverLifecycleEffectorTasks.java
+++ b/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcessDriverLifecycleEffectorTasks.java
@@ -23,6 +23,8 @@ import java.util.Map;
import org.apache.brooklyn.api.location.MachineLocation;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
import org.apache.brooklyn.api.management.TaskAdaptable;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -31,8 +33,6 @@ import brooklyn.entity.basic.SoftwareProcess.RestartSoftwareParameters;
import brooklyn.entity.basic.SoftwareProcess.RestartSoftwareParameters.RestartMachineMode;
import brooklyn.entity.software.MachineLifecycleEffectorTasks;
import brooklyn.entity.trait.StartableMethods;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.task.DynamicTasks;
import brooklyn.util.text.Strings;
import com.google.common.annotations.Beta;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcessImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcessImpl.java b/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcessImpl.java
index dffe783..0ae6339 100644
--- a/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcessImpl.java
+++ b/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcessImpl.java
@@ -18,7 +18,6 @@
*/
package brooklyn.entity.basic;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.guava.Maybe;
import groovy.time.TimeDuration;
@@ -42,6 +41,10 @@ import org.apache.brooklyn.api.location.MachineProvisioningLocation;
import org.apache.brooklyn.api.location.PortRange;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.policy.EnricherSpec;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -58,10 +61,7 @@ import org.apache.brooklyn.location.cloud.CloudLocationConfig;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.Tasks;
import brooklyn.util.time.CountdownTimer;
import brooklyn.util.time.Duration;
import brooklyn.util.time.Time;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/basic/VanillaSoftwareProcessSshDriver.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/basic/VanillaSoftwareProcessSshDriver.java b/software/base/src/main/java/brooklyn/entity/basic/VanillaSoftwareProcessSshDriver.java
index b66bd62..29ef57f 100644
--- a/software/base/src/main/java/brooklyn/entity/basic/VanillaSoftwareProcessSshDriver.java
+++ b/software/base/src/main/java/brooklyn/entity/basic/VanillaSoftwareProcessSshDriver.java
@@ -24,11 +24,13 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.entity.drivers.downloads.DownloadResolver;
+import org.apache.brooklyn.core.util.file.ArchiveUtils;
import brooklyn.entity.basic.lifecycle.ScriptHelper;
+
import org.apache.brooklyn.location.basic.SshMachineLocation;
+
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.file.ArchiveUtils;
import brooklyn.util.guava.Maybe;
import brooklyn.util.net.Urls;
import brooklyn.util.os.Os;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/basic/lifecycle/NaiveScriptRunner.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/basic/lifecycle/NaiveScriptRunner.java b/software/base/src/main/java/brooklyn/entity/basic/lifecycle/NaiveScriptRunner.java
index 670b1df..7d51e22 100644
--- a/software/base/src/main/java/brooklyn/entity/basic/lifecycle/NaiveScriptRunner.java
+++ b/software/base/src/main/java/brooklyn/entity/basic/lifecycle/NaiveScriptRunner.java
@@ -21,7 +21,7 @@ package brooklyn.entity.basic.lifecycle;
import java.util.List;
import java.util.Map;
-import brooklyn.util.task.ssh.SshTasks;
+import org.apache.brooklyn.core.util.task.ssh.SshTasks;
/** Marks something which can run scripts. Called "Naive" because it hides too much of the complexity,
* about script execution and other ssh-related tasks (put, etc). The {@link SshTasks} approach seems better.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/basic/lifecycle/ScriptHelper.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/basic/lifecycle/ScriptHelper.java b/software/base/src/main/java/brooklyn/entity/basic/lifecycle/ScriptHelper.java
index 07532f8..da9e0a1 100644
--- a/software/base/src/main/java/brooklyn/entity/basic/lifecycle/ScriptHelper.java
+++ b/software/base/src/main/java/brooklyn/entity/basic/lifecycle/ScriptHelper.java
@@ -19,7 +19,6 @@
package brooklyn.entity.basic.lifecycle;
import static java.lang.String.format;
-import brooklyn.util.internal.ssh.ShellTool;
import groovy.lang.Closure;
import java.io.ByteArrayOutputStream;
@@ -35,20 +34,23 @@ import javax.annotation.Nullable;
import org.apache.brooklyn.api.management.ExecutionContext;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.management.TaskQueueingContext;
+import org.apache.brooklyn.core.util.internal.ssh.ShellTool;
+import org.apache.brooklyn.core.util.mutex.WithMutexes;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.TaskBuilder;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.BrooklynTaskTags;
+
import org.apache.brooklyn.location.basic.SshMachineLocation;
+
import brooklyn.util.GroovyJavaMethods;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.RuntimeInterruptedException;
-import brooklyn.util.mutex.WithMutexes;
import brooklyn.util.stream.Streams;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.TaskBuilder;
-import brooklyn.util.task.Tasks;
import brooklyn.util.text.Identifiers;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynEntityMirrorImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynEntityMirrorImpl.java b/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynEntityMirrorImpl.java
index 7cbae99..22dae74 100644
--- a/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynEntityMirrorImpl.java
+++ b/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynEntityMirrorImpl.java
@@ -25,6 +25,10 @@ import java.util.concurrent.Callable;
import javax.annotation.Nullable;
import org.apache.brooklyn.api.entity.Effector;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.apache.http.HttpStatus;
import brooklyn.entity.basic.AbstractEntity;
@@ -39,11 +43,7 @@ import brooklyn.event.feed.http.HttpFeed;
import brooklyn.event.feed.http.HttpPollConfig;
import brooklyn.util.collections.Jsonya;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.http.HttpToolResponse;
import brooklyn.util.net.Urls;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.Tasks;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynNode.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynNode.java b/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynNode.java
index da6016b..83314db 100644
--- a/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynNode.java
+++ b/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynNode.java
@@ -31,6 +31,7 @@ import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
import org.apache.brooklyn.api.management.ha.ManagementNodeState;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.BrooklynConfigKeys;
@@ -45,7 +46,6 @@ import brooklyn.event.basic.BasicAttributeSensorAndConfigKey.StringAttributeSens
import brooklyn.event.basic.MapConfigKey;
import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.net.Networking;
import brooklyn.util.ssh.BashCommands;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynNodeImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynNodeImpl.java b/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynNodeImpl.java
index 4250b74..4f1c2d5 100644
--- a/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynNodeImpl.java
+++ b/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynNodeImpl.java
@@ -31,6 +31,11 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.management.TaskAdaptable;
import org.apache.brooklyn.api.management.ha.ManagementNodeState;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.TaskTags;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.apache.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -59,21 +64,18 @@ import brooklyn.event.feed.http.HttpFeed;
import brooklyn.event.feed.http.HttpPollConfig;
import brooklyn.event.feed.http.HttpValueFunctions;
import brooklyn.event.feed.http.JsonFunctions;
+
import org.apache.brooklyn.location.access.BrooklynAccessUtils;
import org.apache.brooklyn.location.basic.Locations;
+
import brooklyn.util.collections.Jsonya;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.exceptions.PropagatedRuntimeException;
import brooklyn.util.guava.Functionals;
-import brooklyn.util.http.HttpToolResponse;
import brooklyn.util.javalang.Enums;
import brooklyn.util.javalang.JavaClassNames;
import brooklyn.util.repeat.Repeater;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.TaskTags;
-import brooklyn.util.task.Tasks;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Duration;
import brooklyn.util.time.Time;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynNodeSshDriver.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynNodeSshDriver.java b/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynNodeSshDriver.java
index ab4ffb2..55c544e 100644
--- a/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynNodeSshDriver.java
+++ b/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynNodeSshDriver.java
@@ -34,16 +34,18 @@ import brooklyn.entity.brooklynnode.BrooklynNode.ExistingFileBehaviour;
import brooklyn.entity.drivers.downloads.DownloadSubstituters;
import brooklyn.entity.java.JavaSoftwareProcessSshDriver;
import brooklyn.entity.software.SshEffectorTasks;
+
+import org.apache.brooklyn.core.util.file.ArchiveBuilder;
+import org.apache.brooklyn.core.util.file.ArchiveUtils;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
import org.apache.brooklyn.location.basic.SshMachineLocation;
+
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.file.ArchiveBuilder;
-import brooklyn.util.file.ArchiveUtils;
-import brooklyn.util.internal.ssh.SshTool;
import brooklyn.util.net.Networking;
import brooklyn.util.net.Urls;
import brooklyn.util.os.Os;
import brooklyn.util.ssh.BashCommands;
-import brooklyn.util.task.DynamicTasks;
import brooklyn.util.text.Identifiers;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/brooklynnode/EntityHttpClient.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/brooklynnode/EntityHttpClient.java b/software/base/src/main/java/brooklyn/entity/brooklynnode/EntityHttpClient.java
index 25df319..58d1229 100644
--- a/software/base/src/main/java/brooklyn/entity/brooklynnode/EntityHttpClient.java
+++ b/software/base/src/main/java/brooklyn/entity/brooklynnode/EntityHttpClient.java
@@ -20,8 +20,8 @@ package brooklyn.entity.brooklynnode;
import java.util.Map;
-import brooklyn.util.http.HttpTool;
-import brooklyn.util.http.HttpToolResponse;
+import org.apache.brooklyn.core.util.http.HttpTool;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/brooklynnode/EntityHttpClientImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/brooklynnode/EntityHttpClientImpl.java b/software/base/src/main/java/brooklyn/entity/brooklynnode/EntityHttpClientImpl.java
index 2403380..59449a2 100644
--- a/software/base/src/main/java/brooklyn/entity/brooklynnode/EntityHttpClientImpl.java
+++ b/software/base/src/main/java/brooklyn/entity/brooklynnode/EntityHttpClientImpl.java
@@ -25,6 +25,9 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.http.HttpTool;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.HttpClient;
import org.slf4j.Logger;
@@ -37,11 +40,8 @@ import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.http.HttpTool;
-import brooklyn.util.http.HttpToolResponse;
import brooklyn.util.net.Urls;
import brooklyn.util.stream.Streams;
-import brooklyn.util.task.Tasks;
public class EntityHttpClientImpl implements EntityHttpClient {
private static final Logger LOG = LoggerFactory.getLogger(EntityHttpClientImpl.class);
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/brooklynnode/RemoteEffectorBuilder.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/brooklynnode/RemoteEffectorBuilder.java b/software/base/src/main/java/brooklyn/entity/brooklynnode/RemoteEffectorBuilder.java
index 0cb944e..05b28eb 100644
--- a/software/base/src/main/java/brooklyn/entity/brooklynnode/RemoteEffectorBuilder.java
+++ b/software/base/src/main/java/brooklyn/entity/brooklynnode/RemoteEffectorBuilder.java
@@ -23,11 +23,11 @@ import java.util.Collection;
import java.util.Map;
import org.apache.brooklyn.api.entity.Effector;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
import brooklyn.entity.brooklynnode.BrooklynEntityMirrorImpl.RemoteEffector;
import brooklyn.entity.effector.Effectors;
import brooklyn.entity.effector.Effectors.EffectorBuilder;
-import brooklyn.util.http.HttpToolResponse;
import com.google.common.base.Function;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/brooklynnode/effector/BrooklynClusterUpgradeEffectorBody.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/brooklynnode/effector/BrooklynClusterUpgradeEffectorBody.java b/software/base/src/main/java/brooklyn/entity/brooklynnode/effector/BrooklynClusterUpgradeEffectorBody.java
index 798f9b5..df902b1 100644
--- a/software/base/src/main/java/brooklyn/entity/brooklynnode/effector/BrooklynClusterUpgradeEffectorBody.java
+++ b/software/base/src/main/java/brooklyn/entity/brooklynnode/effector/BrooklynClusterUpgradeEffectorBody.java
@@ -31,6 +31,9 @@ import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.TaskAdaptable;
import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
import org.apache.brooklyn.api.management.ha.ManagementNodeState;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -47,10 +50,7 @@ import brooklyn.entity.effector.EffectorBody;
import brooklyn.entity.effector.Effectors;
import brooklyn.entity.group.DynamicCluster;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.net.Urls;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.Tasks;
import brooklyn.util.time.Duration;
import com.google.common.base.Preconditions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/brooklynnode/effector/BrooklynNodeUpgradeEffectorBody.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/brooklynnode/effector/BrooklynNodeUpgradeEffectorBody.java b/software/base/src/main/java/brooklyn/entity/brooklynnode/effector/BrooklynNodeUpgradeEffectorBody.java
index 9c3a17b..1706a93 100644
--- a/software/base/src/main/java/brooklyn/entity/brooklynnode/effector/BrooklynNodeUpgradeEffectorBody.java
+++ b/software/base/src/main/java/brooklyn/entity/brooklynnode/effector/BrooklynNodeUpgradeEffectorBody.java
@@ -26,6 +26,9 @@ import org.apache.brooklyn.api.entity.drivers.DriverDependentEntity;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
import org.apache.brooklyn.api.management.ha.ManagementNodeState;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -44,10 +47,7 @@ import brooklyn.entity.effector.EffectorBody;
import brooklyn.entity.effector.Effectors;
import brooklyn.entity.software.SshEffectorTasks;
import brooklyn.event.basic.MapConfigKey;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.net.Urls;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.Tasks;
import brooklyn.util.text.Identifiers;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/brooklynnode/effector/SelectMasterEffectorBody.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/brooklynnode/effector/SelectMasterEffectorBody.java b/software/base/src/main/java/brooklyn/entity/brooklynnode/effector/SelectMasterEffectorBody.java
index 3817b6b..d5a5555 100644
--- a/software/base/src/main/java/brooklyn/entity/brooklynnode/effector/SelectMasterEffectorBody.java
+++ b/software/base/src/main/java/brooklyn/entity/brooklynnode/effector/SelectMasterEffectorBody.java
@@ -27,6 +27,8 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.Group;
import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
import org.apache.brooklyn.api.management.ha.ManagementNodeState;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -39,9 +41,7 @@ import brooklyn.entity.brooklynnode.BrooklynNode.SetHighAvailabilityPriorityEffe
import brooklyn.entity.effector.EffectorBody;
import brooklyn.entity.effector.Effectors;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.repeat.Repeater;
-import brooklyn.util.task.DynamicTasks;
import brooklyn.util.time.Duration;
import com.google.common.base.Preconditions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/brooklynnode/effector/SetHighAvailabilityModeEffectorBody.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/brooklynnode/effector/SetHighAvailabilityModeEffectorBody.java b/software/base/src/main/java/brooklyn/entity/brooklynnode/effector/SetHighAvailabilityModeEffectorBody.java
index 2edf67d..89387d5 100644
--- a/software/base/src/main/java/brooklyn/entity/brooklynnode/effector/SetHighAvailabilityModeEffectorBody.java
+++ b/software/base/src/main/java/brooklyn/entity/brooklynnode/effector/SetHighAvailabilityModeEffectorBody.java
@@ -21,6 +21,8 @@ package brooklyn.entity.brooklynnode.effector;
import org.apache.brooklyn.api.entity.Effector;
import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
import org.apache.brooklyn.api.management.ha.ManagementNodeState;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
import org.apache.http.HttpStatus;
import brooklyn.entity.brooklynnode.BrooklynNode;
@@ -30,9 +32,7 @@ import brooklyn.entity.effector.EffectorBody;
import brooklyn.entity.effector.Effectors;
import brooklyn.event.feed.http.HttpValueFunctions;
import brooklyn.event.feed.http.JsonFunctions;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.guava.Functionals;
-import brooklyn.util.http.HttpToolResponse;
import brooklyn.util.javalang.Enums;
import com.google.common.base.Preconditions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/brooklynnode/effector/SetHighAvailabilityPriorityEffectorBody.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/brooklynnode/effector/SetHighAvailabilityPriorityEffectorBody.java b/software/base/src/main/java/brooklyn/entity/brooklynnode/effector/SetHighAvailabilityPriorityEffectorBody.java
index 884d7ba..b9496d5 100644
--- a/software/base/src/main/java/brooklyn/entity/brooklynnode/effector/SetHighAvailabilityPriorityEffectorBody.java
+++ b/software/base/src/main/java/brooklyn/entity/brooklynnode/effector/SetHighAvailabilityPriorityEffectorBody.java
@@ -19,6 +19,8 @@
package brooklyn.entity.brooklynnode.effector;
import org.apache.brooklyn.api.entity.Effector;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
import org.apache.http.HttpStatus;
import brooklyn.entity.brooklynnode.BrooklynNode;
@@ -26,8 +28,6 @@ import brooklyn.entity.brooklynnode.BrooklynNode.SetHighAvailabilityPriorityEffe
import brooklyn.entity.brooklynnode.EntityHttpClient;
import brooklyn.entity.effector.EffectorBody;
import brooklyn.entity.effector.Effectors;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.http.HttpToolResponse;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/chef/ChefAttributeFeed.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/chef/ChefAttributeFeed.java b/software/base/src/main/java/brooklyn/entity/chef/ChefAttributeFeed.java
index fde4f51..8d3a1ef 100644
--- a/software/base/src/main/java/brooklyn/entity/chef/ChefAttributeFeed.java
+++ b/software/base/src/main/java/brooklyn/entity/chef/ChefAttributeFeed.java
@@ -31,6 +31,8 @@ import java.util.concurrent.TimeUnit;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.management.ExecutionContext;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -41,8 +43,6 @@ import brooklyn.event.feed.AbstractFeed;
import brooklyn.event.feed.PollHandler;
import brooklyn.event.feed.Poller;
import brooklyn.event.feed.ssh.SshPollValue;
-import brooklyn.util.flags.TypeCoercions;
-import brooklyn.util.task.system.ProcessTaskWrapper;
import brooklyn.util.time.Duration;
import com.google.common.base.Joiner;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/chef/ChefConfig.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/chef/ChefConfig.java b/software/base/src/main/java/brooklyn/entity/chef/ChefConfig.java
index 769d8d0..e768280 100644
--- a/software/base/src/main/java/brooklyn/entity/chef/ChefConfig.java
+++ b/software/base/src/main/java/brooklyn/entity/chef/ChefConfig.java
@@ -18,11 +18,12 @@
*/
package brooklyn.entity.chef;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
+
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.event.basic.MapConfigKey;
import brooklyn.event.basic.SetConfigKey;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.annotations.Beta;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/chef/ChefLifecycleEffectorTasks.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/chef/ChefLifecycleEffectorTasks.java b/software/base/src/main/java/brooklyn/entity/chef/ChefLifecycleEffectorTasks.java
index 9f6bf82..402d8d3 100644
--- a/software/base/src/main/java/brooklyn/entity/chef/ChefLifecycleEffectorTasks.java
+++ b/software/base/src/main/java/brooklyn/entity/chef/ChefLifecycleEffectorTasks.java
@@ -23,6 +23,11 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.location.MachineLocation;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.TaskTags;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -37,14 +42,9 @@ import org.apache.brooklyn.location.basic.Machines;
import brooklyn.util.collections.Jsonya;
import brooklyn.util.collections.Jsonya.Navigator;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.net.Urls;
import brooklyn.util.ssh.BashCommands;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.TaskTags;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.task.system.ProcessTaskWrapper;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Duration;
import brooklyn.util.time.Time;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/chef/ChefServerTasks.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/chef/ChefServerTasks.java b/software/base/src/main/java/brooklyn/entity/chef/ChefServerTasks.java
index 743e335..b192f0b 100644
--- a/software/base/src/main/java/brooklyn/entity/chef/ChefServerTasks.java
+++ b/software/base/src/main/java/brooklyn/entity/chef/ChefServerTasks.java
@@ -24,8 +24,8 @@ import java.io.IOException;
import java.nio.charset.Charset;
import java.security.KeyPair;
+import org.apache.brooklyn.core.util.crypto.SecureKeys;
import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.crypto.SecureKeys;
import com.google.common.base.Throwables;
import com.google.common.io.Files;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/chef/ChefSoloDriver.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/chef/ChefSoloDriver.java b/software/base/src/main/java/brooklyn/entity/chef/ChefSoloDriver.java
index 0d9935c..ce727af 100644
--- a/software/base/src/main/java/brooklyn/entity/chef/ChefSoloDriver.java
+++ b/software/base/src/main/java/brooklyn/entity/chef/ChefSoloDriver.java
@@ -21,12 +21,13 @@ package brooklyn.entity.chef;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.management.TaskAdaptable;
import org.apache.brooklyn.api.management.TaskFactory;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.AbstractSoftwareProcessSshDriver;
import brooklyn.entity.basic.ConfigKeys;
+
import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.task.DynamicTasks;
import com.google.common.annotations.Beta;
import com.google.common.reflect.TypeToken;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/chef/ChefTasks.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/chef/ChefTasks.java b/software/base/src/main/java/brooklyn/entity/chef/ChefTasks.java
index 369df99..31f99a5 100644
--- a/software/base/src/main/java/brooklyn/entity/chef/ChefTasks.java
+++ b/software/base/src/main/java/brooklyn/entity/chef/ChefTasks.java
@@ -23,19 +23,19 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.management.TaskAdaptable;
import org.apache.brooklyn.api.management.TaskFactory;
+import org.apache.brooklyn.core.util.file.ArchiveTasks;
+import org.apache.brooklyn.core.util.file.ArchiveUtils.ArchiveType;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.TaskBuilder;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.entity.effector.EffectorTasks;
import brooklyn.entity.software.SshEffectorTasks;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.file.ArchiveTasks;
-import brooklyn.util.file.ArchiveUtils.ArchiveType;
import brooklyn.util.net.Urls;
import brooklyn.util.ssh.BashCommands;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.TaskBuilder;
-import brooklyn.util.task.Tasks;
import brooklyn.util.text.Identifiers;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/chef/KnifeConvergeTaskFactory.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/chef/KnifeConvergeTaskFactory.java b/software/base/src/main/java/brooklyn/entity/chef/KnifeConvergeTaskFactory.java
index f9ec730..b32cad7 100644
--- a/software/base/src/main/java/brooklyn/entity/chef/KnifeConvergeTaskFactory.java
+++ b/software/base/src/main/java/brooklyn/entity/chef/KnifeConvergeTaskFactory.java
@@ -29,16 +29,18 @@ import com.google.common.base.Strings;
import com.google.common.net.HostAndPort;
import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.entity.effector.EffectorTasks;
+
import org.apache.brooklyn.location.basic.SshMachineLocation;
+
import brooklyn.util.collections.Jsonya;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.ssh.BashCommands;
-import brooklyn.util.task.system.ProcessTaskWrapper;
import com.google.common.base.Function;
import com.google.common.base.Functions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/chef/KnifeTaskFactory.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/chef/KnifeTaskFactory.java b/software/base/src/main/java/brooklyn/entity/chef/KnifeTaskFactory.java
index f3b748f..52abcc2 100644
--- a/software/base/src/main/java/brooklyn/entity/chef/KnifeTaskFactory.java
+++ b/software/base/src/main/java/brooklyn/entity/chef/KnifeTaskFactory.java
@@ -24,15 +24,15 @@ import java.util.List;
import javax.annotation.Nullable;
import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.core.util.internal.ssh.process.ProcessTool;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskFactory;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
+import org.apache.brooklyn.core.util.task.system.internal.SystemProcessTaskFactory;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.util.collections.MutableList;
-import brooklyn.util.internal.ssh.process.ProcessTool;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.task.system.ProcessTaskFactory;
-import brooklyn.util.task.system.ProcessTaskWrapper;
-import brooklyn.util.task.system.internal.SystemProcessTaskFactory;
import brooklyn.util.text.StringEscapes.BashStringEscapes;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/java/JavaSoftwareProcessSshDriver.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/java/JavaSoftwareProcessSshDriver.java b/software/base/src/main/java/brooklyn/entity/java/JavaSoftwareProcessSshDriver.java
index 1853259..e6b3245 100644
--- a/software/base/src/main/java/brooklyn/entity/java/JavaSoftwareProcessSshDriver.java
+++ b/software/base/src/main/java/brooklyn/entity/java/JavaSoftwareProcessSshDriver.java
@@ -28,6 +28,13 @@ import java.util.Map;
import java.util.Set;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
+import org.apache.brooklyn.core.util.internal.ssh.ShellTool;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.core.util.task.ssh.SshTasks;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskFactory;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -48,18 +55,13 @@ import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.effector.EffectorTasks;
import brooklyn.entity.software.SshEffectorTasks;
+
import org.apache.brooklyn.location.basic.SshMachineLocation;
+
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.TypeCoercions;
-import brooklyn.util.internal.ssh.ShellTool;
import brooklyn.util.ssh.BashCommands;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.task.ssh.SshTasks;
-import brooklyn.util.task.system.ProcessTaskFactory;
-import brooklyn.util.task.system.ProcessTaskWrapper;
import brooklyn.util.text.StringEscapes.BashStringEscapes;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/java/JmxSupport.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/java/JmxSupport.java b/software/base/src/main/java/brooklyn/entity/java/JmxSupport.java
index 2f88ff8..7e7c4c6 100644
--- a/software/base/src/main/java/brooklyn/entity/java/JmxSupport.java
+++ b/software/base/src/main/java/brooklyn/entity/java/JmxSupport.java
@@ -26,6 +26,9 @@ import javax.annotation.Nullable;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
+import org.apache.brooklyn.core.util.BrooklynMavenArtifacts;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,11 +36,11 @@ import brooklyn.config.ConfigKey;
import brooklyn.config.ConfigKey.HasConfigKey;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.event.feed.jmx.JmxHelper;
+
import org.apache.brooklyn.location.access.BrooklynAccessUtils;
import org.apache.brooklyn.location.basic.Locations;
import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.BrooklynMavenArtifacts;
-import brooklyn.util.ResourceUtils;
+
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.guava.Maybe;
@@ -46,7 +49,6 @@ import brooklyn.util.jmx.jmxrmi.JmxRmiAgent;
import brooklyn.util.maven.MavenArtifact;
import brooklyn.util.maven.MavenRetriever;
import brooklyn.util.net.Urls;
-import brooklyn.util.task.Tasks;
import brooklyn.util.text.Strings;
import com.google.common.base.Preconditions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/java/JmxmpSslSupport.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/java/JmxmpSslSupport.java b/software/base/src/main/java/brooklyn/entity/java/JmxmpSslSupport.java
index 2c91999..dc57a3d 100644
--- a/software/base/src/main/java/brooklyn/entity/java/JmxmpSslSupport.java
+++ b/software/base/src/main/java/brooklyn/entity/java/JmxmpSslSupport.java
@@ -26,13 +26,14 @@ import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
+import org.apache.brooklyn.core.util.crypto.FluentKeySigner;
+import org.apache.brooklyn.core.util.crypto.SecureKeys;
+import org.apache.brooklyn.core.util.task.Tasks;
+
import brooklyn.util.collections.MutableMap.Builder;
-import brooklyn.util.crypto.FluentKeySigner;
-import brooklyn.util.crypto.SecureKeys;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.jmx.jmxmp.JmxmpAgent;
import brooklyn.util.net.Urls;
-import brooklyn.util.task.Tasks;
import com.google.common.base.Preconditions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/java/UsesJava.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/java/UsesJava.java b/software/base/src/main/java/brooklyn/entity/java/UsesJava.java
index 1f824a1..a1afb97 100644
--- a/software/base/src/main/java/brooklyn/entity/java/UsesJava.java
+++ b/software/base/src/main/java/brooklyn/entity/java/UsesJava.java
@@ -18,6 +18,8 @@
*/
package brooklyn.entity.java;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
+
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
@@ -25,7 +27,6 @@ import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.event.basic.MapConfigKey;
import brooklyn.event.basic.SetConfigKey;
-import brooklyn.util.flags.SetFromFlag;
public interface UsesJava {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/java/UsesJavaMXBeans.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/java/UsesJavaMXBeans.java b/software/base/src/main/java/brooklyn/entity/java/UsesJavaMXBeans.java
index f15e217..a556811 100644
--- a/software/base/src/main/java/brooklyn/entity/java/UsesJavaMXBeans.java
+++ b/software/base/src/main/java/brooklyn/entity/java/UsesJavaMXBeans.java
@@ -21,12 +21,12 @@ package brooklyn.entity.java;
import java.util.Map;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.event.basic.BasicAttributeSensor;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
public interface UsesJavaMXBeans {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/java/UsesJmx.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/java/UsesJmx.java b/software/base/src/main/java/brooklyn/entity/java/UsesJmx.java
index 141c5e5..2bb5bf0 100644
--- a/software/base/src/main/java/brooklyn/entity/java/UsesJmx.java
+++ b/software/base/src/main/java/brooklyn/entity/java/UsesJmx.java
@@ -24,6 +24,7 @@ import java.security.cert.Certificate;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.location.PortRange;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
@@ -34,8 +35,6 @@ import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
import org.apache.brooklyn.location.basic.PortRanges;
-import brooklyn.util.flags.SetFromFlag;
-
public interface UsesJmx extends UsesJava {
public static final int DEFAULT_JMX_PORT = 1099; // RMI port?
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/java/VanillaJavaApp.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/java/VanillaJavaApp.java b/software/base/src/main/java/brooklyn/entity/java/VanillaJavaApp.java
index 42e3090..6ae48e8 100644
--- a/software/base/src/main/java/brooklyn/entity/java/VanillaJavaApp.java
+++ b/software/base/src/main/java/brooklyn/entity/java/VanillaJavaApp.java
@@ -23,13 +23,13 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.SoftwareProcess;
import brooklyn.event.basic.Sensors;
import brooklyn.util.collections.MutableList;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/java/VanillaJavaAppImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/java/VanillaJavaAppImpl.java b/software/base/src/main/java/brooklyn/entity/java/VanillaJavaAppImpl.java
index 719a0ba..bbee991 100644
--- a/software/base/src/main/java/brooklyn/entity/java/VanillaJavaAppImpl.java
+++ b/software/base/src/main/java/brooklyn/entity/java/VanillaJavaAppImpl.java
@@ -24,12 +24,12 @@ import java.util.List;
import java.util.Map;
import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.entity.basic.SoftwareProcessImpl;
import brooklyn.event.feed.jmx.JmxFeed;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.annotations.VisibleForTesting;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/java/VanillaJavaAppSshDriver.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/java/VanillaJavaAppSshDriver.java b/software/base/src/main/java/brooklyn/entity/java/VanillaJavaAppSshDriver.java
index 104dd7d..db1bb63 100644
--- a/software/base/src/main/java/brooklyn/entity/java/VanillaJavaAppSshDriver.java
+++ b/software/base/src/main/java/brooklyn/entity/java/VanillaJavaAppSshDriver.java
@@ -28,16 +28,18 @@ import java.util.Map;
import javax.annotation.Nullable;
import brooklyn.entity.basic.lifecycle.ScriptHelper;
+
+import org.apache.brooklyn.core.util.file.ArchiveBuilder;
+import org.apache.brooklyn.core.util.file.ArchiveUtils;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.apache.brooklyn.location.basic.SshMachineLocation;
+
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.file.ArchiveBuilder;
-import brooklyn.util.file.ArchiveUtils;
-import brooklyn.util.internal.ssh.SshTool;
import brooklyn.util.net.Urls;
import brooklyn.util.os.Os;
-import brooklyn.util.task.Tasks;
import brooklyn.util.text.StringEscapes.BashStringEscapes;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/machine/MachineEntityImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/machine/MachineEntityImpl.java b/software/base/src/main/java/brooklyn/entity/machine/MachineEntityImpl.java
index f101e66..7459c19 100644
--- a/software/base/src/main/java/brooklyn/entity/machine/MachineEntityImpl.java
+++ b/software/base/src/main/java/brooklyn/entity/machine/MachineEntityImpl.java
@@ -31,11 +31,13 @@ import brooklyn.entity.software.SshEffectorTasks;
import brooklyn.event.feed.ssh.SshFeed;
import brooklyn.event.feed.ssh.SshPollConfig;
import brooklyn.event.feed.ssh.SshPollValue;
+
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
import org.apache.brooklyn.location.basic.Machines;
import org.apache.brooklyn.location.basic.SshMachineLocation;
+
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.system.ProcessTaskWrapper;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/pool/ServerPoolImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/pool/ServerPoolImpl.java b/software/base/src/main/java/brooklyn/entity/pool/ServerPoolImpl.java
index c35e287..e5066f2 100644
--- a/software/base/src/main/java/brooklyn/entity/pool/ServerPoolImpl.java
+++ b/software/base/src/main/java/brooklyn/entity/pool/ServerPoolImpl.java
@@ -31,6 +31,7 @@ import org.apache.brooklyn.api.location.NoMachinesAvailableException;
import org.apache.brooklyn.api.management.LocationManager;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -51,7 +52,6 @@ import org.apache.brooklyn.location.dynamic.DynamicLocation;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.guava.Maybe;
-import brooklyn.util.task.DynamicTasks;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/pool/ServerPoolLocation.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/pool/ServerPoolLocation.java b/software/base/src/main/java/brooklyn/entity/pool/ServerPoolLocation.java
index 704459b..df0a76c 100644
--- a/software/base/src/main/java/brooklyn/entity/pool/ServerPoolLocation.java
+++ b/software/base/src/main/java/brooklyn/entity/pool/ServerPoolLocation.java
@@ -34,11 +34,10 @@ import brooklyn.entity.basic.ConfigKeys;
import org.apache.brooklyn.api.location.MachineLocation;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
import org.apache.brooklyn.api.location.NoMachinesAvailableException;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.location.basic.AbstractLocation;
import org.apache.brooklyn.location.dynamic.DynamicLocation;
-import brooklyn.util.flags.SetFromFlag;
-
public class ServerPoolLocation extends AbstractLocation implements MachineProvisioningLocation<MachineLocation>,
DynamicLocation<ServerPool, ServerPoolLocation> {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/base/src/main/java/brooklyn/entity/service/EntityLaunchListener.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/service/EntityLaunchListener.java b/software/base/src/main/java/brooklyn/entity/service/EntityLaunchListener.java
index 354653d..e263d0d 100644
--- a/software/base/src/main/java/brooklyn/entity/service/EntityLaunchListener.java
+++ b/software/base/src/main/java/brooklyn/entity/service/EntityLaunchListener.java
@@ -28,11 +28,11 @@ import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
import org.apache.brooklyn.api.management.ExecutionManager;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.task.Tasks;
import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.entity.basic.BrooklynTaskTags.EffectorCallTag;
import brooklyn.entity.basic.Lifecycle;
-import brooklyn.util.task.Tasks;
public class EntityLaunchListener implements Runnable, SensorEventListener<Lifecycle> {
private static final String SSH_LAUNCH_TASK_PREFIX = "ssh: launching";
[26/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/SshTool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/SshTool.java b/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/SshTool.java
new file mode 100644
index 0000000..4361f46
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/SshTool.java
@@ -0,0 +1,174 @@
+/*
+ * 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.util.internal.ssh;
+
+import static brooklyn.entity.basic.ConfigKeys.newConfigKey;
+import static brooklyn.entity.basic.ConfigKeys.newStringConfigKey;
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.util.stream.KnownSizeInputStream;
+import brooklyn.util.time.Duration;
+
+/**
+ * Defines the methods available on the various different implementations of SSH,
+ * and configuration options which are also generally available.
+ * <p>
+ * The config keys in this class can be supplied (or their string equivalents, where the flags/props take {@code Map<String,?>})
+ * to influence configuration, either for the tool/session itself or for individual commands.
+ * <p>
+ * To specify some of these properties on a global basis, use the variants of the keys here
+ * contained in {@link ConfigKeys}
+ * (which are generally {@value #BROOKLYN_CONFIG_KEY_PREFIX} prefixed to the names of keys here).
+ */
+public interface SshTool extends ShellTool {
+
+ /** Public-facing global config keys for Brooklyn are defined in ConfigKeys,
+ * and have this prefix pre-prended to the config keys in this class.
+ * These keys are detected from entity/global config and automatically applied to ssh executions. */
+ public static final String BROOKLYN_CONFIG_KEY_PREFIX = "brooklyn.ssh.config.";
+
+ public static final ConfigKey<String> PROP_TOOL_CLASS = newStringConfigKey("tool.class", "SshTool implementation to use", null);
+
+ public static final ConfigKey<String> PROP_HOST = newStringConfigKey("host", "Host to connect to (required)", null);
+ public static final ConfigKey<Integer> PROP_PORT = newConfigKey("port", "Port on host to connect to", 22);
+ public static final ConfigKey<String> PROP_USER = newConfigKey("user", "User to connect as", System.getProperty("user.name"));
+ public static final ConfigKey<String> PROP_PASSWORD = newStringConfigKey("password", "Password to use to connect", null);
+
+ public static final ConfigKey<String> PROP_PRIVATE_KEY_FILE = newStringConfigKey("privateKeyFile", "the path of an ssh private key file; leave blank to use defaults (i.e. ~/.ssh/id_rsa and id_dsa)", null);
+ public static final ConfigKey<String> PROP_PRIVATE_KEY_DATA = newStringConfigKey("privateKeyData", "the private ssh key (e.g. contents of an id_rsa or id_dsa file)", null);
+ public static final ConfigKey<String> PROP_PRIVATE_KEY_PASSPHRASE = newStringConfigKey("privateKeyPassphrase", "the passphrase for the ssh private key", null);
+ public static final ConfigKey<Boolean> PROP_STRICT_HOST_KEY_CHECKING = newConfigKey("strictHostKeyChecking", "whether to check the remote host's identification; defaults to false", false);
+ public static final ConfigKey<Boolean> PROP_ALLOCATE_PTY = newConfigKey("allocatePTY", "whether to allocate PTY (vt100); if true then stderr is sent to stdout, but sometimes required for sudo'ing due to requiretty", false);
+
+ public static final ConfigKey<Long> PROP_CONNECT_TIMEOUT = newConfigKey("connectTimeout", "Timeout in millis when establishing an SSH connection; if 0 then uses default (usually 30s)", 0L);
+ public static final ConfigKey<Long> PROP_SESSION_TIMEOUT = newConfigKey("sessionTimeout", "Timeout in millis for an ssh session; if 0 then uses default", 0L);
+ public static final ConfigKey<Integer> PROP_SSH_TRIES = newConfigKey("sshTries", "Max number of times to attempt ssh operations", 4);
+ public static final ConfigKey<Long> PROP_SSH_TRIES_TIMEOUT = newConfigKey("sshTriesTimeout", "Time limit for attempting retries; will not interrupt tasks, but stops retrying after a total amount of elapsed time", Duration.TWO_MINUTES.toMilliseconds());
+ public static final ConfigKey<Long> PROP_SSH_RETRY_DELAY = newConfigKey("sshRetryDelay", "Time (in milliseconds) before first ssh-retry, after which it will do exponential backoff", 50L);
+
+ // NB -- items above apply for _session_ (a tool), below apply for a _call_
+ // TODO would be nice to track which arguments are used, so we can indicate whether extras are supplied
+
+ public static final ConfigKey<String> PROP_PERMISSIONS = newConfigKey("permissions", "Default permissions for files copied/created on remote machine; must be four-digit octal string, default '0644'", "0644");
+ public static final ConfigKey<Long> PROP_LAST_MODIFICATION_DATE = newConfigKey("lastModificationDate", "Last-modification-date to be set on files copied/created (should be UTC/1000, ie seconds since 1970; default 0 usually means current)", 0L);
+ public static final ConfigKey<Long> PROP_LAST_ACCESS_DATE = newConfigKey("lastAccessDate", "Last-access-date to be set on files copied/created (should be UTC/1000, ie seconds since 1970; default 0 usually means lastModificationDate)", 0L);
+ public static final ConfigKey<Integer> PROP_OWNER_UID = newConfigKey("ownerUid", "Default owner UID (not username) for files created on remote machine; default is unset", -1);
+
+ // TODO remove unnecessary "public static final" modifiers
+
+ // TODO Could define the following in SshMachineLocation, or some such?
+ //public static ConfigKey<String> PROP_LOG_PREFIX = newStringKey("logPrefix", "???", ???);
+ //public static ConfigKey<Boolean> PROP_NO_STDOUT_LOGGING = newStringKey("noStdoutLogging", "???", ???);
+ //public static ConfigKey<Boolean> PROP_NO_STDOUT_LOGGING = newStringKey("noStdoutLogging", "???", ???);
+
+ /**
+ * @throws SshException
+ */
+ public void connect();
+
+ /**
+ * @deprecated since 0.7.0; (since much earlier) this ignores the argument in favour of {@link #PROP_SSH_TRIES}
+ *
+ * @param maxAttempts
+ * @throws SshException
+ */
+ public void connect(int maxAttempts);
+
+ public void disconnect();
+
+ public boolean isConnected();
+
+ /**
+ * @see super{@link #execScript(Map, List, Map)}
+ * @throws SshException If failed to connect
+ */
+ @Override
+ public int execScript(Map<String,?> props, List<String> commands, Map<String,?> env);
+
+ /**
+ * @see #execScript(Map, List, Map)
+ */
+ @Override
+ public int execScript(Map<String,?> props, List<String> commands);
+
+ /**
+ * @see super{@link #execCommands(Map, List, Map)}
+ * @throws SshException If failed to connect
+ */
+ @Override
+ public int execCommands(Map<String,?> properties, List<String> commands, Map<String,?> env);
+
+ /**
+ * @see #execCommands(Map, List, Map)
+ */
+ @Override
+ public int execCommands(Map<String,?> properties, List<String> commands);
+
+ /**
+ * Copies the file to the server at the given path.
+ * If path is null, empty, '.', '..', or ends with '/' then file name is used.
+ * <p>
+ * The file will not preserve the permission of last _access_ date.
+ *
+ * Optional properties are:
+ * <ul>
+ * <li>'permissions' (e.g. "0644") - see {@link #PROP_PERMISSIONS}
+ * <li>'lastModificationDate' see {@link #PROP_LAST_MODIFICATION_DATE}; not supported by all SshTool implementations
+ * <li>'lastAccessDate' see {@link #PROP_LAST_ACCESS_DATE}; not supported by all SshTool implementations
+ * </ul>
+ *
+ * @return exit code (not supported by all SshTool implementations, usually throwing on error;
+ * sometimes possibly returning 0 even on error (?) )
+ */
+ public int copyToServer(Map<String,?> props, File localFile, String pathAndFileOnRemoteServer);
+
+ /**
+ * Closes the given input stream before returning.
+ * Consider using {@link KnownSizeInputStream} for efficiency when the size of the stream is known.
+ *
+ * @see #copyToServer(Map, File, String)
+ */
+ public int copyToServer(Map<String,?> props, InputStream contents, String pathAndFileOnRemoteServer);
+
+ /**
+ * @see #copyToServer(Map, File, String)
+ */
+ public int copyToServer(Map<String,?> props, byte[] contents, String pathAndFileOnRemoteServer);
+
+ /**
+ * Copies the file from the server at the given path.
+ *
+ * @return exit code (not supported by all SshTool implementations, usually throwing on error;
+ * sometimes possibly returning 0 even on error (?) )
+ */
+ public int copyFromServer(Map<String,?> props, String pathAndFileOnRemoteServer, File local);
+
+ // TODO might be more efficicent than copyFrom by way of temp file
+// /**
+// * Reads from the file at the given path on the remote server.
+// */
+// public InputStream streamFromServer(Map<String,?> props, String pathAndFileOnRemoteServer);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/cli/SshCliTool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/cli/SshCliTool.java b/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/cli/SshCliTool.java
new file mode 100644
index 0000000..5fe0408
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/cli/SshCliTool.java
@@ -0,0 +1,317 @@
+/*
+ * 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.util.internal.ssh.cli;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.brooklyn.core.util.internal.ssh.SshAbstractTool;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
+import org.apache.brooklyn.core.util.internal.ssh.cli.SshCliTool;
+import org.apache.brooklyn.core.util.internal.ssh.process.ProcessTool;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.text.StringEscapes.BashStringEscapes;
+import brooklyn.util.text.Strings;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+
+/**
+ * For ssh and scp commands, delegating to system calls.
+ */
+public class SshCliTool extends SshAbstractTool implements SshTool {
+
+ // TODO No retry support, with backoffLimitedRetryHandler
+
+ private static final Logger LOG = LoggerFactory.getLogger(SshCliTool.class);
+
+ public static final ConfigKey<String> PROP_SSH_EXECUTABLE = ConfigKeys.newStringConfigKey("sshExecutable", "command to execute for ssh (defaults to \"ssh\", but could be overridden to sshg3 for Tectia for example)", "ssh");
+ public static final ConfigKey<String> PROP_SSH_FLAGS = ConfigKeys.newStringConfigKey("sshFlags", "flags to pass to ssh, as a space separated list", "");
+ public static final ConfigKey<String> PROP_SCP_EXECUTABLE = ConfigKeys.newStringConfigKey("scpExecutable", "command to execute for scp (defaults to \"scp\", but could be overridden to scpg3 for Tectia for example)", "scp");
+
+ public static Builder<SshCliTool,?> builder() {
+ return new ConcreteBuilder();
+ }
+
+ private static class ConcreteBuilder extends Builder<SshCliTool, ConcreteBuilder> {
+ }
+
+ public static class Builder<T extends SshCliTool, B extends Builder<T,B>> extends AbstractSshToolBuilder<T,B> {
+ private String sshExecutable;
+ private String sshFlags;
+ private String scpExecutable;
+
+ @Override
+ public B from(Map<String,?> props) {
+ super.from(props);
+ sshExecutable = getOptionalVal(props, PROP_SSH_EXECUTABLE);
+ sshFlags = getOptionalVal(props, PROP_SSH_FLAGS);
+ scpExecutable = getOptionalVal(props, PROP_SCP_EXECUTABLE);
+ return self();
+ }
+ public B sshExecutable(String val) {
+ this.sshExecutable = val; return self();
+ }
+ public B scpExecutable(String val) {
+ this.scpExecutable = val; return self();
+ }
+ @SuppressWarnings("unchecked")
+ public T build() {
+ return (T) new SshCliTool(this);
+ }
+ }
+
+ private final String sshExecutable;
+ private final String sshFlags;
+ private final String scpExecutable;
+
+ public SshCliTool(Map<String,?> map) {
+ this(builder().from(map));
+ }
+
+ private SshCliTool(Builder<?,?> builder) {
+ super(builder);
+ sshExecutable = checkNotNull(builder.sshExecutable);
+ sshFlags = checkNotNull(builder.sshFlags);
+ scpExecutable = checkNotNull(builder.scpExecutable);
+ if (LOG.isTraceEnabled()) LOG.trace("Created SshCliTool {} ({})", this, System.identityHashCode(this));
+ }
+
+ @Override
+ public void connect() {
+ // no-op
+ }
+
+ @Override
+ public void connect(int maxAttempts) {
+ // no-op
+ }
+
+ @Override
+ public void disconnect() {
+ if (LOG.isTraceEnabled()) LOG.trace("Disconnecting SshCliTool {} ({}) - no-op", this, System.identityHashCode(this));
+ // no-op
+ }
+
+ @Override
+ public boolean isConnected() {
+ // TODO Always pretends to be connected
+ return true;
+ }
+
+ @Override
+ public int copyToServer(java.util.Map<String,?> props, byte[] contents, String pathAndFileOnRemoteServer) {
+ return copyTempFileToServer(props, writeTempFile(contents), pathAndFileOnRemoteServer);
+ }
+
+ @Override
+ public int copyToServer(java.util.Map<String,?> props, InputStream contents, String pathAndFileOnRemoteServer) {
+ return copyTempFileToServer(props, writeTempFile(contents), pathAndFileOnRemoteServer);
+ }
+
+ @Override
+ public int copyToServer(Map<String,?> props, File f, String pathAndFileOnRemoteServer) {
+ if (hasVal(props, PROP_LAST_MODIFICATION_DATE)) {
+ LOG.warn("Unsupported ssh feature, setting lastModificationDate for {}:{}", this, pathAndFileOnRemoteServer);
+ }
+ if (hasVal(props, PROP_LAST_ACCESS_DATE)) {
+ LOG.warn("Unsupported ssh feature, setting lastAccessDate for {}:{}", this, pathAndFileOnRemoteServer);
+ }
+ String permissions = getOptionalVal(props, PROP_PERMISSIONS);
+
+ int uid = getOptionalVal(props, PROP_OWNER_UID);
+
+ int result = scpToServer(props, f, pathAndFileOnRemoteServer);
+ if (result == 0) {
+ result = chmodOnServer(props, permissions, pathAndFileOnRemoteServer);
+ if (result == 0) {
+ if (uid != -1) {
+ result = chownOnServer(props, uid, pathAndFileOnRemoteServer);
+ if (result != 0) {
+ LOG.warn("Error setting file owner to {}, after copying file {} to {}:{}; exit code {}", new Object[] { uid, pathAndFileOnRemoteServer, this, f, result });
+ }
+ }
+ } else {
+ LOG.warn("Error setting file permissions to {}, after copying file {} to {}:{}; exit code {}", new Object[] { permissions, pathAndFileOnRemoteServer, this, f, result });
+ }
+ } else {
+ LOG.warn("Error copying file {} to {}:{}; exit code {}", new Object[] {pathAndFileOnRemoteServer, this, f, result});
+ }
+ return result;
+ }
+
+ private int chownOnServer(Map<String,?> props, int uid, String remote) {
+ return sshExec(props, "chown "+uid+" "+remote);
+ }
+
+ private int copyTempFileToServer(Map<String,?> props, File f, String pathAndFileOnRemoteServer) {
+ try {
+ return copyToServer(props, f, pathAndFileOnRemoteServer);
+ } finally {
+ f.delete();
+ }
+ }
+
+ @Override
+ public int copyFromServer(Map<String,?> props, String pathAndFileOnRemoteServer, File localFile) {
+ return scpFromServer(props, pathAndFileOnRemoteServer, localFile);
+ }
+
+ @Override
+ public int execScript(final Map<String,?> props, final List<String> commands, final Map<String,?> env) {
+ return new ToolAbstractExecScript(props) {
+ public int run() {
+ String scriptContents = toScript(props, commands, env);
+ if (LOG.isTraceEnabled()) LOG.trace("Running shell command at {} as script: {}", host, scriptContents);
+ copyTempFileToServer(ImmutableMap.of("permissions", "0700"), writeTempFile(scriptContents), scriptPath);
+
+ String cmd = Strings.join(buildRunScriptCommand(), separator);
+ return asInt(sshExec(props, cmd), -1);
+ }
+ }.run();
+ }
+
+ @Override
+ public int execCommands(Map<String,?> props, List<String> commands, Map<String,?> env) {
+ Map<String,Object> props2 = new MutableMap<String,Object>();
+ if (props!=null) props2.putAll(props);
+ props2.put(SshTool.PROP_NO_EXTRA_OUTPUT.getName(), true);
+ return execScript(props2, commands, env);
+ }
+
+ private int scpToServer(Map<String,?> props, File local, String remote) {
+ String to = (Strings.isEmpty(getUsername()) ? "" : getUsername()+"@")+getHostAddress()+":"+remote;
+ return scpExec(props, local.getAbsolutePath(), to);
+ }
+
+ private int scpFromServer(Map<String,?> props, String remote, File local) {
+ String from = (Strings.isEmpty(getUsername()) ? "" : getUsername()+"@")+getHostAddress()+":"+remote;
+ return scpExec(props, from, local.getAbsolutePath());
+ }
+
+ private int chmodOnServer(Map<String,?> props, String permissions, String remote) {
+ return sshExec(props, "chmod "+permissions+" "+remote);
+ }
+
+ private int scpExec(Map<String,?> props, String from, String to) {
+ File tempFile = null;
+ try {
+ List<String> cmd = Lists.newArrayList();
+ cmd.add(getOptionalVal(props, PROP_SCP_EXECUTABLE, scpExecutable));
+ if (privateKeyFile != null) {
+ cmd.add("-i");
+ cmd.add(privateKeyFile.getAbsolutePath());
+ } else if (privateKeyData != null) {
+ tempFile = writeTempFile(privateKeyData);
+ cmd.add("-i");
+ cmd.add(tempFile.getAbsolutePath());
+ }
+ if (!strictHostKeyChecking) {
+ cmd.add("-o");
+ cmd.add("StrictHostKeyChecking=no");
+ }
+ if (port != 22) {
+ cmd.add("-P");
+ cmd.add(""+port);
+ }
+ cmd.add(from);
+ cmd.add(to);
+
+ if (LOG.isTraceEnabled()) LOG.trace("Executing with command: {}", cmd);
+ int result = execProcess(props, cmd);
+
+ if (LOG.isTraceEnabled()) LOG.trace("Executed command: {}; exit code {}", cmd, result);
+ return result;
+
+ } finally {
+ if (tempFile != null) tempFile.delete();
+ }
+ }
+
+ private int sshExec(Map<String,?> props, String command) {
+ File tempKeyFile = null;
+ try {
+ List<String> cmd = Lists.newArrayList();
+ cmd.add(getOptionalVal(props, PROP_SSH_EXECUTABLE, sshExecutable));
+ String propsFlags = getOptionalVal(props, PROP_SSH_FLAGS, sshFlags);
+ if (propsFlags!=null && propsFlags.trim().length()>0)
+ cmd.addAll(Arrays.asList(propsFlags.trim().split(" ")));
+ if (privateKeyFile != null) {
+ cmd.add("-i");
+ cmd.add(privateKeyFile.getAbsolutePath());
+ } else if (privateKeyData != null) {
+ tempKeyFile = writeTempFile(privateKeyData);
+ cmd.add("-i");
+ cmd.add(tempKeyFile.getAbsolutePath());
+ }
+ if (!strictHostKeyChecking) {
+ cmd.add("-o");
+ cmd.add("StrictHostKeyChecking=no");
+ }
+ if (port != 22) {
+ cmd.add("-P");
+ cmd.add(""+port);
+ }
+ if (allocatePTY) {
+ // have to be careful with double -tt as it can leave a shell session active
+ // when done from bash (ie ssh -tt localhost < /tmp/myscript.sh);
+ // hover that doesn't seem to be a problem the way we use it from brooklyn
+ // (and note single -t doesn't work _programmatically_ since the input isn't a terminal)
+ cmd.add("-tt");
+ }
+ cmd.add((Strings.isEmpty(getUsername()) ? "" : getUsername()+"@")+getHostAddress());
+
+ cmd.add("bash -c "+BashStringEscapes.wrapBash(command));
+ // previously we tried these approaches:
+ //cmd.add("$(<"+tempCmdFile.getAbsolutePath()+")");
+ // only pays attention to the first word; the "; echo Executing ..." get treated as arguments
+ // to the script in the first word, when invoked from java (when invoked from prompt the behaviour is as desired)
+ //cmd.add("\""+command+"\"");
+ // only works if command is a single word
+ //cmd.add(tempCmdFile.getAbsolutePath());
+ // above of course only works if the metafile is copied across
+
+ if (LOG.isTraceEnabled()) LOG.trace("Executing ssh with command: {} (with {})", command, cmd);
+ int result = execProcess(props, cmd);
+
+ if (LOG.isTraceEnabled()) LOG.trace("Executed command: {}; exit code {}", cmd, result);
+ return result;
+
+ } finally {
+ if (tempKeyFile != null) tempKeyFile.delete();
+ }
+ }
+
+ private int execProcess(Map<String,?> props, List<String> cmdWords) {
+ OutputStream out = getOptionalVal(props, PROP_OUT_STREAM);
+ OutputStream err = getOptionalVal(props, PROP_ERR_STREAM);
+ return ProcessTool.execSingleProcess(cmdWords, null, (File)null, out, err, this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/process/ProcessTool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/process/ProcessTool.java b/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/process/ProcessTool.java
new file mode 100644
index 0000000..8f33143
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/process/ProcessTool.java
@@ -0,0 +1,215 @@
+/*
+ * 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.util.internal.ssh.process;
+
+import static brooklyn.entity.basic.ConfigKeys.newConfigKey;
+import static brooklyn.entity.basic.ConfigKeys.newStringConfigKey;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.brooklyn.core.util.internal.ssh.ShellAbstractTool;
+import org.apache.brooklyn.core.util.internal.ssh.ShellTool;
+import org.apache.brooklyn.core.util.internal.ssh.SshException;
+import org.apache.brooklyn.core.util.internal.ssh.process.ProcessTool;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.os.Os;
+import brooklyn.util.stream.StreamGobbler;
+import brooklyn.util.text.Strings;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Throwables;
+import com.google.common.io.ByteSource;
+import com.google.common.io.ByteStreams;
+import com.google.common.io.Files;
+
+/** Implementation of {@link ShellTool} which runs locally. */
+public class ProcessTool extends ShellAbstractTool implements ShellTool {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ProcessTool.class);
+
+ // applies to calls
+
+ public static final ConfigKey<Boolean> PROP_LOGIN_SHELL = newConfigKey("loginShell", "Causes the commands to be invoked with bash arguments to forcea login shell", Boolean.FALSE);
+
+ public static final ConfigKey<String> PROP_DIRECTORY = newStringConfigKey("directory", "the working directory, for executing commands", null);
+
+ public ProcessTool() {
+ this(null);
+ }
+
+ public ProcessTool(Map<String,?> flags) {
+ super(getOptionalVal(flags, PROP_LOCAL_TEMP_DIR));
+ if (flags!=null) {
+ MutableMap<String, Object> flags2 = MutableMap.copyOf(flags);
+ // TODO should remember other flags here? (e.g. NO_EXTRA_OUTPUT, RUN_AS_ROOT, etc)
+ flags2.remove(PROP_LOCAL_TEMP_DIR.getName());
+ if (!flags2.isEmpty())
+ LOG.warn(""+this+" ignoring unsupported constructor flags: "+flags);
+ }
+ }
+
+ @Override
+ public int execScript(final Map<String,?> props, final List<String> commands, final Map<String,?> env) {
+ return new ToolAbstractExecScript(props) {
+ public int run() {
+ try {
+ String directory = getOptionalVal(props, PROP_DIRECTORY);
+ File directoryDir = (directory != null) ? new File(Os.tidyPath(directory)) : null;
+
+ String scriptContents = toScript(props, commands, env);
+
+ if (LOG.isTraceEnabled()) LOG.trace("Running shell process (process) as script:\n{}", scriptContents);
+ File to = new File(scriptPath);
+ Files.createParentDirs(to);
+ ByteSource.wrap(scriptContents.getBytes()).copyTo(Files.asByteSink(to));
+
+ List<String> cmds = buildRunScriptCommand();
+ cmds.add(0, "chmod +x "+scriptPath);
+ return asInt(execProcesses(cmds, null, directoryDir, out, err, separator, getOptionalVal(props, PROP_LOGIN_SHELL), this), -1);
+ } catch (IOException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+ }.run();
+ }
+
+ @Override
+ public int execCommands(Map<String,?> props, List<String> commands, Map<String,?> env) {
+ if (Boolean.FALSE.equals(props.get("blocks"))) {
+ throw new IllegalArgumentException("Cannot exec non-blocking: command="+commands);
+ }
+ OutputStream out = getOptionalVal(props, PROP_OUT_STREAM);
+ OutputStream err = getOptionalVal(props, PROP_ERR_STREAM);
+ String separator = getOptionalVal(props, PROP_SEPARATOR);
+ String directory = getOptionalVal(props, PROP_DIRECTORY);
+ File directoryDir = (directory != null) ? new File(Os.tidyPath(directory)) : null;
+
+ List<String> allcmds = toCommandSequence(commands, null);
+
+ String singlecmd = Joiner.on(separator).join(allcmds);
+ if (Boolean.TRUE.equals(getOptionalVal(props, PROP_RUN_AS_ROOT))) {
+ LOG.warn("Cannot run as root when executing as command; run as a script instead (will run as normal user): "+singlecmd);
+ }
+ if (LOG.isTraceEnabled()) LOG.trace("Running shell command (process): {}", singlecmd);
+
+ return asInt(execProcesses(allcmds, env, directoryDir, out, err, separator, getOptionalVal(props, PROP_LOGIN_SHELL), this), -1);
+ }
+
+ /**
+ * as {@link #execProcesses(List, Map, OutputStream, OutputStream, String, boolean, Object)} but not using a login shell
+ * @deprecated since 0.7; use {@link #execProcesses(List, Map, File, OutputStream, OutputStream, String, boolean, Object)}
+ */
+ @Deprecated
+ public static int execProcesses(List<String> cmds, Map<String,?> env, OutputStream out, OutputStream err, String separator, Object contextForLogging) {
+ return execProcesses(cmds, env, (File)null, out, err, separator, false, contextForLogging);
+ }
+
+ /**
+ * @deprecated since 0.7; use {@link #execProcesses(List, Map, File, OutputStream, OutputStream, String, boolean, Object)}
+ */
+ @Deprecated
+ public static int execProcesses(List<String> cmds, Map<String,?> env, OutputStream out, OutputStream err, String separator, boolean asLoginShell, Object contextForLogging) {
+ return execProcesses(cmds, env, (File)null, out, err, separator, asLoginShell, contextForLogging);
+ }
+
+ /** executes a set of commands by sending them as a single process to `bash -c`
+ * (single command argument of all the commands, joined with separator)
+ * <p>
+ * consequence of this is that you should not normally need to escape things oddly in your commands,
+ * type them just as you would into a bash shell (if you find exceptions please note them here!)
+ */
+ public static int execProcesses(List<String> cmds, Map<String,?> env, File directory, OutputStream out, OutputStream err, String separator, boolean asLoginShell, Object contextForLogging) {
+ MutableList<String> commands = new MutableList<String>().append("bash");
+ if (asLoginShell) commands.append("-l");
+ commands.append("-c", Strings.join(cmds, Preconditions.checkNotNull(separator, "separator")));
+ return execSingleProcess(commands, env, directory, out, err, contextForLogging);
+ }
+
+ /**
+ * @deprecated since 0.7; use {@link #execSingleProcess(List, Map, File, OutputStream, OutputStream, Object)}
+ */
+ @Deprecated
+ public static int execSingleProcess(List<String> cmdWords, Map<String,?> env, OutputStream out, OutputStream err, Object contextForLogging) {
+ return execSingleProcess(cmdWords, env, (File)null, out, err, contextForLogging);
+ }
+
+ /** executes a single process made up of the given command words (*not* bash escaped);
+ * should be portable across OS's */
+ public static int execSingleProcess(List<String> cmdWords, Map<String,?> env, File directory, OutputStream out, OutputStream err, Object contextForLogging) {
+ StreamGobbler errgobbler = null;
+ StreamGobbler outgobbler = null;
+
+ ProcessBuilder pb = new ProcessBuilder(cmdWords);
+ if (env!=null) {
+ for (Map.Entry<String,?> kv: env.entrySet()) pb.environment().put(kv.getKey(), String.valueOf(kv.getValue()));
+ }
+ if (directory != null) {
+ pb.directory(directory);
+ }
+
+ try {
+ Process p = pb.start();
+
+ if (out != null) {
+ InputStream outstream = p.getInputStream();
+ outgobbler = new StreamGobbler(outstream, out, (Logger) null);
+ outgobbler.start();
+ }
+ if (err != null) {
+ InputStream errstream = p.getErrorStream();
+ errgobbler = new StreamGobbler(errstream, err, (Logger) null);
+ errgobbler.start();
+ }
+
+ int result = p.waitFor();
+
+ if (outgobbler != null) outgobbler.blockUntilFinished();
+ if (errgobbler != null) errgobbler.blockUntilFinished();
+
+ if (result==255)
+ // this is not definitive, but tests (and code?) expects throw exception if can't connect;
+ // only return exit code when it is exit code from underlying process;
+ // we have no way to distinguish 255 from ssh failure from 255 from the command run through ssh ...
+ // but probably 255 is from CLI ssh
+ throw new SshException("exit code 255 from CLI ssh; probably failed to connect");
+
+ return result;
+ } catch (InterruptedException e) {
+ throw Exceptions.propagate(e);
+ } catch (IOException e) {
+ throw Exceptions.propagate(e);
+ } finally {
+ closeWhispering(outgobbler, contextForLogging, "execProcess");
+ closeWhispering(errgobbler, contextForLogging, "execProcess");
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/sshj/SshjClientConnection.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/sshj/SshjClientConnection.java b/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/sshj/SshjClientConnection.java
new file mode 100644
index 0000000..c042415
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/internal/ssh/sshj/SshjClientConnection.java
@@ -0,0 +1,282 @@
+/*
+ * 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.util.internal.ssh.sshj;
+
+import static com.google.common.base.Objects.equal;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.File;
+import java.io.IOException;
+
+import net.schmizz.sshj.SSHClient;
+import net.schmizz.sshj.transport.verification.PromiscuousVerifier;
+import net.schmizz.sshj.userauth.keyprovider.OpenSSHKeyFile;
+import net.schmizz.sshj.userauth.password.PasswordUtils;
+
+import org.apache.brooklyn.core.util.internal.ssh.SshAbstractTool.SshAction;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.util.GroovyJavaMethods;
+
+import com.google.common.base.Objects;
+import com.google.common.net.HostAndPort;
+
+/** based on code from jclouds */
+public class SshjClientConnection implements SshAction<SSHClient> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SshjClientConnection.class);
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+
+ protected HostAndPort hostAndPort;
+ protected String username;
+ protected String password;
+ protected String privateKeyPassphrase;
+ protected String privateKeyData;
+ protected File privateKeyFile;
+ protected long connectTimeout;
+ protected long sessionTimeout;
+ protected boolean strictHostKeyChecking;
+
+ public Builder hostAndPort(HostAndPort hostAndPort) {
+ this.hostAndPort = hostAndPort;
+ return this;
+ }
+
+ public Builder username(String username) {
+ this.username = username;
+ return this;
+ }
+
+ public Builder password(String val) {
+ this.password = val;
+ return this;
+ }
+
+ /** @deprecated use privateKeyData */
+ public Builder privateKey(String val) {
+ this.privateKeyData = val;
+ return this;
+ }
+
+ public Builder privateKeyPassphrase(String val) {
+ this.privateKeyPassphrase = val;
+ return this;
+ }
+
+ public Builder privateKeyData(String val) {
+ this.privateKeyData = val;
+ return this;
+ }
+
+ public Builder privateKeyFile(File val) {
+ this.privateKeyFile = val;
+ return this;
+ }
+
+ public Builder strictHostKeyChecking(boolean val) {
+ this.strictHostKeyChecking = val;
+ return this;
+ }
+
+ public Builder connectTimeout(long connectTimeout) {
+ this.connectTimeout = connectTimeout;
+ return this;
+ }
+
+ public Builder sessionTimeout(long sessionTimeout) {
+ this.sessionTimeout = sessionTimeout;
+ return this;
+ }
+
+ public SshjClientConnection build() {
+ return new SshjClientConnection(this);
+ }
+
+ protected static Builder fromSSHClientConnection(SshjClientConnection in) {
+ return new Builder().hostAndPort(in.getHostAndPort()).connectTimeout(in.getConnectTimeout()).sessionTimeout(
+ in.getSessionTimeout()).username(in.username).password(in.password).privateKey(in.privateKeyData).privateKeyFile(in.privateKeyFile);
+ }
+ }
+
+ private final HostAndPort hostAndPort;
+ private final String username;
+ private final String password;
+ private final String privateKeyPassphrase;
+ private final String privateKeyData;
+ private final File privateKeyFile;
+ private final boolean strictHostKeyChecking;
+ private final int connectTimeout;
+ private final int sessionTimeout;
+
+ SSHClient ssh;
+
+ private SshjClientConnection(Builder builder) {
+ this.hostAndPort = checkNotNull(builder.hostAndPort);
+ this.username = builder.username;
+ this.password = builder.password;
+ this.privateKeyPassphrase = builder.privateKeyPassphrase;
+ this.privateKeyData = builder.privateKeyData;
+ this.privateKeyFile = builder.privateKeyFile;
+ this.strictHostKeyChecking = builder.strictHostKeyChecking;
+ this.connectTimeout = checkInt("connectTimeout", builder.connectTimeout, Integer.MAX_VALUE);
+ this.sessionTimeout = checkInt("sessionTimeout", builder.sessionTimeout, Integer.MAX_VALUE);
+ }
+
+ static Integer checkInt(String context, long value, Integer ifTooLarge) {
+ if (value > Integer.MAX_VALUE) {
+ LOG.warn("Value '"+value+"' for "+context+" too large in SshjClientConnection; using "+value);
+ return ifTooLarge;
+ }
+ return (int)value;
+ }
+
+ public boolean isConnected() {
+ return ssh != null && ssh.isConnected();
+ }
+
+ public boolean isAuthenticated() {
+ return ssh != null && ssh.isAuthenticated();
+ }
+
+ @Override
+ public void clear() {
+ if (ssh != null && ssh.isConnected()) {
+ try {
+ if (LOG.isTraceEnabled()) LOG.trace("Disconnecting SshjClientConnection {} ({})", this, System.identityHashCode(this));
+ ssh.disconnect();
+ } catch (IOException e) {
+ if (LOG.isDebugEnabled()) LOG.debug("<< exception disconnecting from {}: {}", e, e.getMessage());
+ }
+ }
+ ssh = null;
+ }
+
+ @Override
+ public SSHClient create() throws Exception {
+ if (LOG.isTraceEnabled()) LOG.trace("Connecting SshjClientConnection {} ({})", this, System.identityHashCode(this));
+ ssh = new net.schmizz.sshj.SSHClient();
+ if (!strictHostKeyChecking) {
+ ssh.addHostKeyVerifier(new PromiscuousVerifier());
+ }
+ if (connectTimeout != 0) {
+ ssh.setConnectTimeout(connectTimeout);
+ }
+ if (sessionTimeout != 0) {
+ ssh.setTimeout(sessionTimeout);
+ }
+ ssh.connect(hostAndPort.getHostText(), hostAndPort.getPortOrDefault(22));
+
+ if (password != null) {
+ ssh.authPassword(username, password);
+ } else if (privateKeyData != null) {
+ OpenSSHKeyFile key = new OpenSSHKeyFile();
+ key.init(privateKeyData, null,
+ GroovyJavaMethods.truth(privateKeyPassphrase) ?
+ PasswordUtils.createOneOff(privateKeyPassphrase.toCharArray())
+ : null);
+ ssh.authPublickey(username, key);
+ } else if (privateKeyFile != null) {
+ OpenSSHKeyFile key = new OpenSSHKeyFile();
+ key.init(privateKeyFile,
+ GroovyJavaMethods.truth(privateKeyPassphrase) ?
+ PasswordUtils.createOneOff(privateKeyPassphrase.toCharArray())
+ : null);
+ ssh.authPublickey(username, key);
+ } else {
+ // Accept defaults (in ~/.ssh)
+ ssh.authPublickey(username);
+ }
+
+ return ssh;
+ }
+
+ /**
+ * @return host and port, where port if not present defaults to {@code 22}
+ */
+ public HostAndPort getHostAndPort() {
+ return hostAndPort;
+ }
+
+ /**
+ * @return username used in this ssh
+ */
+ public String getUsername() {
+ return username;
+ }
+
+ /**
+ *
+ * @return how long to wait for the initial connection to be made
+ */
+ public int getConnectTimeout() {
+ return connectTimeout;
+ }
+
+ /**
+ *
+ * @return how long to keep the ssh open, or {@code 0} for indefinitely
+ */
+ public int getSessionTimeout() {
+ return sessionTimeout;
+ }
+
+ /**
+ *
+ * @return the current ssh or {@code null} if not connected
+ */
+ public SSHClient getSSHClient() {
+ return ssh;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+ SshjClientConnection that = SshjClientConnection.class.cast(o);
+ return equal(this.hostAndPort, that.hostAndPort) && equal(this.username, that.username)
+ && equal(this.password, that.password) && equal(this.privateKeyData, that.privateKeyData)
+ && equal(this.privateKeyFile, that.privateKeyFile) && equal(this.ssh, that.ssh);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(hostAndPort, username, password, privateKeyData, ssh);
+ }
+
+ @Override
+ public String toString() {
+ return Objects.toStringHelper("")
+ .add("hostAndPort", hostAndPort)
+ .add("user", username)
+ .add("ssh", ssh != null ? ssh.hashCode() : null)
+ .add("password", (password != null ? "xxxxxx" : null))
+ .add("privateKeyFile", privateKeyFile)
+ .add("privateKey", (privateKeyData != null ? "xxxxxx" : null))
+ .add("connectTimeout", connectTimeout)
+ .add("sessionTimeout", sessionTimeout).toString();
+ }
+}
[32/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/ValueResolver.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/ValueResolver.java b/core/src/main/java/brooklyn/util/task/ValueResolver.java
deleted file mode 100644
index 37f4269..0000000
--- a/core/src/main/java/brooklyn/util/task/ValueResolver.java
+++ /dev/null
@@ -1,426 +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 brooklyn.util.task;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Callable;
-import java.util.concurrent.Future;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.management.ExecutionContext;
-import org.apache.brooklyn.api.management.Task;
-import org.apache.brooklyn.api.management.TaskAdaptable;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.entity.basic.BrooklynTaskTags;
-import brooklyn.entity.basic.EntityInternal;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.TypeCoercions;
-import brooklyn.util.guava.Maybe;
-import brooklyn.util.javalang.JavaClassNames;
-import brooklyn.util.repeat.Repeater;
-import brooklyn.util.time.CountdownTimer;
-import brooklyn.util.time.Duration;
-import brooklyn.util.time.Durations;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import com.google.common.reflect.TypeToken;
-
-/**
- * Resolves a given object, as follows:
- * <li> If it is a {@link Tasks} or a {@link DeferredSupplier} then get its contents
- * <li> If it's a map and {@link #deep(boolean)} is requested, it applies resolution to contents
- * <li> It applies coercion
- * <p>
- * Fluent-style API exposes a number of other options.
- */
-public class ValueResolver<T> implements DeferredSupplier<T> {
-
- /**
- * Period to wait if we're expected to return real quick
- * but we want fast things to have time to finish.
- * <p>
- * Timings are always somewhat arbitrary but this at least
- * allows some intention to be captured in code rather than arbitrary values. */
- public static Duration REAL_QUICK_WAIT = Duration.millis(50);
- /**
- * Period to wait if we're expected to return quickly
- * but we want to be a bit more generous for things to finish,
- * without letting a caller get annoyed.
- * <p>
- * See {@link #REAL_QUICK_WAIT}. */
- public static Duration PRETTY_QUICK_WAIT = Duration.millis(200);
-
- /** Period to wait when we have to poll but want to give the illusion of no wait.
- * See {@link Repeater#DEFAULT_REAL_QUICK_PERIOD} */
- public static Duration REAL_QUICK_PERIOD = Repeater.DEFAULT_REAL_QUICK_PERIOD;
-
- private static final Logger log = LoggerFactory.getLogger(ValueResolver.class);
-
- final Object value;
- final Class<T> type;
- ExecutionContext exec;
- String description;
- boolean forceDeep;
- /** null means do it if you can; true means always, false means never */
- Boolean embedResolutionInTask;
- /** timeout on execution, if possible, or if embedResolutionInTask is true */
- Duration timeout;
- boolean isTransientTask = true;
-
- T defaultValue = null;
- boolean returnDefaultOnGet = false;
- boolean swallowExceptions = false;
-
- // internal fields
- final Object parentOriginalValue;
- final CountdownTimer parentTimer;
- AtomicBoolean started = new AtomicBoolean(false);
- boolean expired;
-
- ValueResolver(Object v, Class<T> type) {
- this.value = v;
- this.type = type;
- checkTypeNotNull();
- parentOriginalValue = null;
- parentTimer = null;
- }
-
- ValueResolver(Object v, Class<T> type, ValueResolver<?> parent) {
- this.value = v;
- this.type = type;
- checkTypeNotNull();
-
- exec = parent.exec;
- description = parent.description;
- forceDeep = parent.forceDeep;
- embedResolutionInTask = parent.embedResolutionInTask;
-
- parentOriginalValue = parent.getOriginalValue();
-
- timeout = parent.timeout;
- parentTimer = parent.parentTimer;
- if (parentTimer!=null && parentTimer.isExpired())
- expired = true;
-
- // default value and swallow exceptions do not need to be nested
- }
-
- public static class ResolverBuilderPretype {
- final Object v;
- public ResolverBuilderPretype(Object v) {
- this.v = v;
- }
- public <T> ValueResolver<T> as(Class<T> type) {
- return new ValueResolver<T>(v, type);
- }
- }
-
- /** returns a copy of this resolver which can be queried, even if the original (single-use instance) has already been copied */
- public ValueResolver<T> clone() {
- ValueResolver<T> result = new ValueResolver<T>(value, type)
- .context(exec).description(description)
- .embedResolutionInTask(embedResolutionInTask)
- .deep(forceDeep)
- .timeout(timeout);
- if (returnDefaultOnGet) result.defaultValue(defaultValue);
- if (swallowExceptions) result.swallowExceptions();
- return result;
- }
-
- /** execution context to use when resolving; required if resolving unsubmitted tasks or running with a time limit */
- public ValueResolver<T> context(ExecutionContext exec) {
- this.exec = exec;
- return this;
- }
- /** as {@link #context(ExecutionContext)} for use from an entity */
- public ValueResolver<T> context(Entity entity) {
- return context(entity!=null ? ((EntityInternal)entity).getExecutionContext() : null);
- }
-
- /** sets a message which will be displayed in status reports while it waits (e.g. the name of the config key being looked up) */
- public ValueResolver<T> description(String description) {
- this.description = description;
- return this;
- }
-
- /** sets a default value which will be returned on a call to {@link #get()} if the task does not complete
- * or completes with an error
- * <p>
- * note that {@link #getMaybe()} returns an absent object even in the presence of
- * a default, so that any error can still be accessed */
- public ValueResolver<T> defaultValue(T defaultValue) {
- this.defaultValue = defaultValue;
- this.returnDefaultOnGet = true;
- return this;
- }
-
- /** indicates that no default value should be returned on a call to {@link #get()}, and instead it should throw
- * (this is the default; this method is provided to undo a call to {@link #defaultValue(Object)}) */
- public ValueResolver<T> noDefaultValue() {
- this.returnDefaultOnGet = false;
- this.defaultValue = null;
- return this;
- }
-
- /** indicates that exceptions in resolution should not be thrown on a call to {@link #getMaybe()},
- * but rather used as part of the {@link Maybe#get()} if it's absent,
- * and swallowed altogether on a call to {@link #get()} in the presence of a {@link #defaultValue(Object)} */
- public ValueResolver<T> swallowExceptions() {
- this.swallowExceptions = true;
- return this;
- }
-
- /** whether the task should be marked as transient; defaults true */
- public ValueResolver<T> transientTask(boolean isTransientTask) {
- this.isTransientTask = isTransientTask;
- return this;
- }
-
- public Maybe<T> getDefault() {
- if (returnDefaultOnGet) return Maybe.of(defaultValue);
- else return Maybe.absent("No default value set");
- }
-
- /** causes nested structures (maps, lists) to be descended and nested unresolved values resolved */
- public ValueResolver<T> deep(boolean forceDeep) {
- this.forceDeep = forceDeep;
- return this;
- }
-
- /** if true, forces execution of a deferred supplier to be run in a task;
- * if false, it prevents it (meaning time limits may not be applied);
- * if null, the default, it runs in a task if a time limit is applied.
- * <p>
- * running inside a task is required for some {@link DeferredSupplier}
- * instances which look up a task {@link ExecutionContext}. */
- public ValueResolver<T> embedResolutionInTask(Boolean embedResolutionInTask) {
- this.embedResolutionInTask = embedResolutionInTask;
- return this;
- }
-
- /** sets a time limit on executions
- * <p>
- * used for {@link Task} and {@link DeferredSupplier} instances.
- * may require an execution context at runtime. */
- public ValueResolver<T> timeout(Duration timeout) {
- this.timeout = timeout;
- return this;
- }
-
- protected void checkTypeNotNull() {
- if (type==null)
- throw new NullPointerException("type must be set to resolve, for '"+value+"'"+(description!=null ? ", "+description : ""));
- }
-
- public T get() {
- Maybe<T> m = getMaybe();
- if (m.isPresent()) return m.get();
- if (returnDefaultOnGet) return defaultValue;
- return m.get();
- }
-
- public Maybe<T> getMaybe() {
- Maybe<T> result = getMaybeInternal();
- if (log.isTraceEnabled()) {
- log.trace(this+" evaluated as "+result);
- }
- return result;
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- protected Maybe<T> getMaybeInternal() {
- if (started.getAndSet(true))
- throw new IllegalStateException("ValueResolver can only be used once");
-
- if (expired) return Maybe.absent("Nested resolution of "+getOriginalValue()+" did not complete within "+timeout);
-
- ExecutionContext exec = this.exec;
- if (exec==null) {
- // if execution context not specified, take it from the current task if present
- exec = BasicExecutionContext.getCurrentExecutionContext();
- }
-
- CountdownTimer timerU = parentTimer;
- if (timerU==null && timeout!=null)
- timerU = timeout.countdownTimer();
- final CountdownTimer timer = timerU;
- if (timer!=null && !timer.isRunning())
- timer.start();
-
- checkTypeNotNull();
- Object v = this.value;
-
- //if the expected type is a closure or map and that's what we have, we're done (or if it's null);
- //but not allowed to return a future or DeferredSupplier as the resolved value
- if (v==null || (!forceDeep && type.isInstance(v) && !Future.class.isInstance(v) && !DeferredSupplier.class.isInstance(v)))
- return Maybe.of((T) v);
-
- try {
- //if it's a task or a future, we wait for the task to complete
- if (v instanceof TaskAdaptable<?>) {
- //if it's a task, we make sure it is submitted
- if (!((TaskAdaptable<?>) v).asTask().isSubmitted() ) {
- if (exec==null)
- return Maybe.absent("Value for unsubmitted task '"+getDescription()+"' requested but no execution context available");
- exec.submit(((TaskAdaptable<?>) v).asTask());
- }
- }
-
- if (v instanceof Future) {
- final Future<?> vfuture = (Future<?>) v;
-
- //including tasks, above
- if (!vfuture.isDone()) {
- Callable<Maybe> callable = new Callable<Maybe>() {
- public Maybe call() throws Exception {
- return Durations.get(vfuture, timer);
- } };
-
- String description = getDescription();
- Maybe vm = Tasks.withBlockingDetails("Waiting for "+description, callable);
- if (vm.isAbsent()) return vm;
- v = vm.get();
-
- } else {
- v = vfuture.get();
-
- }
-
- } else if (v instanceof DeferredSupplier<?>) {
- final Object vf = v;
-
- if ((!Boolean.FALSE.equals(embedResolutionInTask) && (exec!=null || timeout!=null)) || Boolean.TRUE.equals(embedResolutionInTask)) {
- if (exec==null)
- return Maybe.absent("Embedding in task needed for '"+getDescription()+"' but no execution context available");
-
- Callable<Object> callable = new Callable<Object>() {
- public Object call() throws Exception {
- try {
- Tasks.setBlockingDetails("Retrieving "+vf);
- return ((DeferredSupplier<?>) vf).get();
- } finally {
- Tasks.resetBlockingDetails();
- }
- } };
- String description = getDescription();
- TaskBuilder<Object> vb = Tasks.<Object>builder().body(callable).name("Resolving dependent value").description(description);
- if (isTransientTask) vb.tag(BrooklynTaskTags.TRANSIENT_TASK_TAG);
- Task<Object> vt = exec.submit(vb.build());
- // TODO to handle immediate resolution, it would be nice to be able to submit
- // so it executes in the current thread,
- // or put a marker in the target thread or task while it is running that the task
- // should never wait on anything other than another value being resolved
- // (though either could recurse infinitely)
- Maybe<Object> vm = Durations.get(vt, timer);
- vt.cancel(true);
- if (vm.isAbsent()) return (Maybe<T>)vm;
- v = vm.get();
-
- } else {
- try {
- Tasks.setBlockingDetails("Retrieving (non-task) "+vf);
- v = ((DeferredSupplier<?>) vf).get();
- } finally {
- Tasks.resetBlockingDetails();
- }
- }
-
- } else if (v instanceof Map) {
- //and if a map or list we look inside
- Map result = Maps.newLinkedHashMap();
- for (Map.Entry<?,?> entry : ((Map<?,?>)v).entrySet()) {
- Maybe<?> kk = new ValueResolver(entry.getKey(), type, this)
- .description( (description!=null ? description+", " : "") + "map key "+entry.getKey() )
- .getMaybe();
- if (kk.isAbsent()) return (Maybe<T>)kk;
- Maybe<?> vv = new ValueResolver(entry.getValue(), type, this)
- .description( (description!=null ? description+", " : "") + "map value for key "+kk.get() )
- .getMaybe();
- if (vv.isAbsent()) return (Maybe<T>)vv;
- result.put(kk.get(), vv.get());
- }
- return Maybe.of((T) result);
-
- } else if (v instanceof Set) {
- Set result = Sets.newLinkedHashSet();
- int count = 0;
- for (Object it : (Set)v) {
- Maybe<?> vv = new ValueResolver(it, type, this)
- .description( (description!=null ? description+", " : "") + "entry "+count )
- .getMaybe();
- if (vv.isAbsent()) return (Maybe<T>)vv;
- result.add(vv.get());
- count++;
- }
- return Maybe.of((T) result);
-
- } else if (v instanceof Iterable) {
- List result = Lists.newArrayList();
- int count = 0;
- for (Object it : (Iterable)v) {
- Maybe<?> vv = new ValueResolver(it, type, this)
- .description( (description!=null ? description+", " : "") + "entry "+count )
- .getMaybe();
- if (vv.isAbsent()) return (Maybe<T>)vv;
- result.add(vv.get());
- count++;
- }
- return Maybe.of((T) result);
-
- } else {
- return TypeCoercions.tryCoerce(v, TypeToken.of(type));
- }
-
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
-
- IllegalArgumentException problem = new IllegalArgumentException("Error resolving "+(description!=null ? description+", " : "")+v+", in "+exec+": "+e, e);
- if (swallowExceptions) {
- if (log.isDebugEnabled())
- log.debug("Resolution of "+this+" failed, swallowing and returning: "+e);
- return Maybe.absent(problem);
- }
- if (log.isDebugEnabled())
- log.debug("Resolution of "+this+" failed, throwing: "+e);
- throw problem;
- }
-
- return new ValueResolver(v, type, this).getMaybe();
- }
-
- protected String getDescription() {
- return description!=null ? description : ""+value;
- }
- protected Object getOriginalValue() {
- if (parentOriginalValue!=null) return parentOriginalValue;
- return value;
- }
-
- @Override
- public String toString() {
- return JavaClassNames.cleanSimpleClassName(this)+"["+JavaClassNames.cleanSimpleClassName(type)+" "+value+"]";
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/ssh/SshFetchTaskFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/ssh/SshFetchTaskFactory.java b/core/src/main/java/brooklyn/util/task/ssh/SshFetchTaskFactory.java
deleted file mode 100644
index bd9e96e..0000000
--- a/core/src/main/java/brooklyn/util/task/ssh/SshFetchTaskFactory.java
+++ /dev/null
@@ -1,89 +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 brooklyn.util.task.ssh;
-
-import org.apache.brooklyn.api.management.TaskFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.config.ConfigBag;
-
-// cannot be (cleanly) instantiated due to nested generic self-referential type; however trivial subclasses do allow it
-public class SshFetchTaskFactory implements TaskFactory<SshFetchTaskWrapper> {
-
- private static final Logger log = LoggerFactory.getLogger(SshFetchTaskFactory.class);
-
- private boolean dirty = false;
-
- protected SshMachineLocation machine;
- protected String remoteFile;
- protected final ConfigBag config = ConfigBag.newInstance();
-
- /** constructor where machine will be added later */
- public SshFetchTaskFactory(String remoteFile) {
- remoteFile(remoteFile);
- }
-
- /** convenience constructor to supply machine immediately */
- public SshFetchTaskFactory(SshMachineLocation machine, String remoteFile) {
- machine(machine);
- remoteFile(remoteFile);
- }
-
- protected SshFetchTaskFactory self() { return this; }
-
- protected void markDirty() {
- dirty = true;
- }
-
- public SshFetchTaskFactory machine(SshMachineLocation machine) {
- markDirty();
- this.machine = machine;
- return self();
- }
-
- public SshMachineLocation getMachine() {
- return machine;
- }
-
- public SshFetchTaskFactory remoteFile(String remoteFile) {
- this.remoteFile = remoteFile;
- return self();
- }
-
- public ConfigBag getConfig() {
- return config;
- }
-
- @Override
- public SshFetchTaskWrapper newTask() {
- dirty = false;
- return new SshFetchTaskWrapper(this);
- }
-
- @Override
- protected void finalize() throws Throwable {
- // help let people know of API usage error
- if (dirty)
- log.warn("Task "+this+" was modified but modification was never used");
- super.finalize();
- }
-
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/ssh/SshFetchTaskWrapper.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/ssh/SshFetchTaskWrapper.java b/core/src/main/java/brooklyn/util/task/ssh/SshFetchTaskWrapper.java
deleted file mode 100644
index 9553b4f..0000000
--- a/core/src/main/java/brooklyn/util/task/ssh/SshFetchTaskWrapper.java
+++ /dev/null
@@ -1,135 +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 brooklyn.util.task.ssh;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.concurrent.Callable;
-
-import org.apache.brooklyn.api.management.Task;
-import org.apache.brooklyn.api.management.TaskWrapper;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.FilenameUtils;
-
-import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.os.Os;
-import brooklyn.util.task.TaskBuilder;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.task.system.ProcessTaskWrapper;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Preconditions;
-
-/**
- * As {@link ProcessTaskWrapper}, but putting a file on the remote machine
- *
- * @since 0.6.0
- */
-@Beta
-public class SshFetchTaskWrapper implements TaskWrapper<String> {
-
- private final Task<String> task;
-
- private final String remoteFile;
- private final SshMachineLocation machine;
- private File backingFile;
- private final ConfigBag config;
-
-
- // package private as only AbstractSshTaskFactory should invoke
- SshFetchTaskWrapper(SshFetchTaskFactory factory) {
- this.remoteFile = Preconditions.checkNotNull(factory.remoteFile, "remoteFile");
- this.machine = Preconditions.checkNotNull(factory.machine, "machine");
- TaskBuilder<String> tb = TaskBuilder.<String>builder().dynamic(false).name("ssh fetch "+factory.remoteFile);
- task = tb.body(new SshFetchJob()).build();
- config = factory.getConfig();
- }
-
- @Override
- public Task<String> asTask() {
- return getTask();
- }
-
- @Override
- public Task<String> getTask() {
- return task;
- }
-
- public String getRemoteFile() {
- return remoteFile;
- }
-
- public SshMachineLocation getMachine() {
- return machine;
- }
-
- private class SshFetchJob implements Callable<String> {
- @Override
- public String call() throws Exception {
- int result = -1;
- try {
- Preconditions.checkNotNull(getMachine(), "machine");
- backingFile = Os.newTempFile("brooklyn-ssh-fetch-", FilenameUtils.getName(remoteFile));
- backingFile.deleteOnExit();
-
- result = getMachine().copyFrom(config.getAllConfig(), remoteFile, backingFile.getPath());
- } catch (Exception e) {
- throw new IllegalStateException("SSH fetch "+getRemoteFile()+" from "+getMachine()+" returned threw exception, in "+Tasks.current()+": "+e, e);
- }
- if (result!=0) {
- throw new IllegalStateException("SSH fetch "+getRemoteFile()+" from "+getMachine()+" returned non-zero exit code "+result+", in "+Tasks.current());
- }
- return FileUtils.readFileToString(backingFile);
- }
- }
-
- @Override
- public String toString() {
- return super.toString()+"["+task+"]";
- }
-
- /** blocks, returns the fetched file as a string, throwing if there was an exception */
- public String get() {
- return getTask().getUnchecked();
- }
-
- /** blocks, returns the fetched file as bytes, throwing if there was an exception */
- public byte[] getBytes() {
- block();
- try {
- return FileUtils.readFileToByteArray(backingFile);
- } catch (IOException e) {
- throw Exceptions.propagate(e);
- }
- }
-
- /** blocks until the task completes; does not throw */
- public SshFetchTaskWrapper block() {
- getTask().blockUntilEnded();
- return this;
- }
-
- /** true iff the ssh job has completed (with or without failure) */
- public boolean isDone() {
- return getTask().isDone();
- }
-
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/ssh/SshPutTaskFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/ssh/SshPutTaskFactory.java b/core/src/main/java/brooklyn/util/task/ssh/SshPutTaskFactory.java
deleted file mode 100644
index e2c5502..0000000
--- a/core/src/main/java/brooklyn/util/task/ssh/SshPutTaskFactory.java
+++ /dev/null
@@ -1,123 +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 brooklyn.util.task.ssh;
-
-import java.io.InputStream;
-import java.io.Reader;
-
-import org.apache.brooklyn.api.management.TaskFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.stream.KnownSizeInputStream;
-import brooklyn.util.stream.ReaderInputStream;
-
-import com.google.common.base.Suppliers;
-
-// cannot be (cleanly) instantiated due to nested generic self-referential type; however trivial subclasses do allow it
-public class SshPutTaskFactory extends SshPutTaskStub implements TaskFactory<SshPutTaskWrapper> {
-
- private static final Logger log = LoggerFactory.getLogger(SshPutTaskFactory.class);
-
- private boolean dirty = false;
-
- /** constructor where machine will be added later */
- public SshPutTaskFactory(String remoteFile) {
- remoteFile(remoteFile);
- }
-
- /** convenience constructor to supply machine immediately */
- public SshPutTaskFactory(SshMachineLocation machine, String remoteFile) {
- machine(machine);
- remoteFile(remoteFile);
- }
-
- protected SshPutTaskFactory self() { return this; }
-
- protected void markDirty() {
- dirty = true;
- }
-
- public SshPutTaskFactory machine(SshMachineLocation machine) {
- markDirty();
- this.machine = machine;
- return self();
- }
-
- public SshPutTaskFactory remoteFile(String remoteFile) {
- this.remoteFile = remoteFile;
- return self();
- }
-
- public SshPutTaskFactory summary(String summary) {
- markDirty();
- this.summary = summary;
- return self();
- }
-
- public SshPutTaskFactory contents(String contents) {
- markDirty();
- this.contents = Suppliers.ofInstance(KnownSizeInputStream.of(contents));
- return self();
- }
-
- public SshPutTaskFactory contents(byte[] contents) {
- markDirty();
- this.contents = Suppliers.ofInstance(KnownSizeInputStream.of(contents));
- return self();
- }
-
- public SshPutTaskFactory contents(InputStream stream) {
- markDirty();
- this.contents = Suppliers.ofInstance(stream);
- return self();
- }
-
- public SshPutTaskFactory contents(Reader reader) {
- markDirty();
- this.contents = Suppliers.ofInstance(new ReaderInputStream(reader));
- return self();
- }
-
- public SshPutTaskFactory allowFailure() {
- markDirty();
- allowFailure = true;
- return self();
- }
-
- public SshPutTaskFactory createDirectory() {
- markDirty();
- createDirectory = true;
- return self();
- }
-
- public SshPutTaskWrapper newTask() {
- dirty = false;
- return new SshPutTaskWrapper(this);
- }
-
- @Override
- protected void finalize() throws Throwable {
- // help let people know of API usage error
- if (dirty)
- log.warn("Task "+this+" was modified but modification was never used");
- super.finalize();
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/ssh/SshPutTaskStub.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/ssh/SshPutTaskStub.java b/core/src/main/java/brooklyn/util/task/ssh/SshPutTaskStub.java
deleted file mode 100644
index 185e819..0000000
--- a/core/src/main/java/brooklyn/util/task/ssh/SshPutTaskStub.java
+++ /dev/null
@@ -1,69 +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 brooklyn.util.task.ssh;
-
-import java.io.InputStream;
-
-import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.config.ConfigBag;
-
-import com.google.common.base.Supplier;
-
-public class SshPutTaskStub {
-
- protected String remoteFile;
- protected SshMachineLocation machine;
- protected Supplier<? extends InputStream> contents;
- protected String summary;
- protected String permissions;
- protected boolean allowFailure = false;
- protected boolean createDirectory = false;
- protected final ConfigBag config = ConfigBag.newInstance();
-
- protected SshPutTaskStub() {
- }
-
- protected SshPutTaskStub(SshPutTaskStub constructor) {
- this.remoteFile = constructor.remoteFile;
- this.machine = constructor.machine;
- this.contents = constructor.contents;
- this.summary = constructor.summary;
- this.allowFailure = constructor.allowFailure;
- this.createDirectory = constructor.createDirectory;
- this.permissions = constructor.permissions;
- this.config.copy(constructor.config);
- }
-
- public String getRemoteFile() {
- return remoteFile;
- }
-
- public String getSummary() {
- if (summary!=null) return summary;
- return "scp put: "+remoteFile;
- }
-
- public SshMachineLocation getMachine() {
- return machine;
- }
-
- protected ConfigBag getConfig() {
- return config;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/ssh/SshPutTaskWrapper.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/ssh/SshPutTaskWrapper.java b/core/src/main/java/brooklyn/util/task/ssh/SshPutTaskWrapper.java
deleted file mode 100644
index 4f0cd76..0000000
--- a/core/src/main/java/brooklyn/util/task/ssh/SshPutTaskWrapper.java
+++ /dev/null
@@ -1,190 +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 brooklyn.util.task.ssh;
-
-import java.util.Arrays;
-import java.util.concurrent.Callable;
-
-import org.apache.brooklyn.api.management.Task;
-import org.apache.brooklyn.api.management.TaskWrapper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.internal.ssh.SshTool;
-import brooklyn.util.task.TaskBuilder;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.task.system.ProcessTaskWrapper;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Preconditions;
-
-/** As {@link ProcessTaskWrapper}, but putting a file on the remote machine */
-@Beta
-public class SshPutTaskWrapper extends SshPutTaskStub implements TaskWrapper<Void> {
-
- private static final Logger log = LoggerFactory.getLogger(SshPutTaskWrapper.class);
-
- private final Task<Void> task;
-
- protected Integer exitCodeOfCopy = null;
- protected Exception exception = null;
- protected boolean successful = false;
-
- // package private as only AbstractSshTaskFactory should invoke
- SshPutTaskWrapper(SshPutTaskFactory constructor) {
- super(constructor);
- TaskBuilder<Void> tb = TaskBuilder.<Void>builder().dynamic(false).name(getSummary());
- task = tb.body(new SshPutJob()).build();
- }
-
- @Override
- public Task<Void> asTask() {
- return getTask();
- }
-
- @Override
- public Task<Void> getTask() {
- return task;
- }
-
- // TODO:
- // verify
- // copyAsRoot
- // owner
- // lastModificationDate - see {@link #PROP_LAST_MODIFICATION_DATE}; not supported by all SshTool implementations
- // lastAccessDate - see {@link #PROP_LAST_ACCESS_DATE}; not supported by all SshTool implementations
-
- private class SshPutJob implements Callable<Void> {
- @Override
- public Void call() throws Exception {
- try {
- Preconditions.checkNotNull(getMachine(), "machine");
-
- String remoteFile = getRemoteFile();
-
- if (createDirectory) {
- String remoteDir = remoteFile;
- int exitCodeOfCreate = -1;
- try {
- int li = remoteDir.lastIndexOf("/");
- if (li>=0) {
- remoteDir = remoteDir.substring(0, li+1);
- exitCodeOfCreate = getMachine().execCommands("creating directory for "+getSummary(),
- Arrays.asList("mkdir -p "+remoteDir));
- } else {
- // nothing to create
- exitCodeOfCreate = 0;
- }
- } catch (Exception e) {
- if (log.isDebugEnabled())
- log.debug("SSH put "+getRemoteFile()+" (create dir, in task "+getSummary()+") to "+getMachine()+" threw exception: "+e);
- exception = e;
- }
- if (exception!=null || !((Integer)0).equals(exitCodeOfCreate)) {
- if (!allowFailure) {
- if (exception != null) {
- throw new IllegalStateException(getSummary()+" (creating dir "+remoteDir+" for SSH put task) ended with exception, in "+Tasks.current()+": "+exception, exception);
- }
- if (exitCodeOfCreate!=0) {
- exception = new IllegalStateException(getSummary()+" (creating dir "+remoteDir+" SSH put task) ended with exit code "+exitCodeOfCreate+", in "+Tasks.current());
- throw exception;
- }
- }
- // not successful, but allowed
- return null;
- }
- }
-
- ConfigBag config = ConfigBag.newInstanceCopying(getConfig());
- if (permissions!=null) config.put(SshTool.PROP_PERMISSIONS, permissions);
-
- exitCodeOfCopy = getMachine().copyTo(config.getAllConfig(), contents.get(), remoteFile);
-
- if (log.isDebugEnabled())
- log.debug("SSH put "+getRemoteFile()+" (task "+getSummary()+") to "+getMachine()+" completed with exit code "+exitCodeOfCopy);
- } catch (Exception e) {
- if (log.isDebugEnabled())
- log.debug("SSH put "+getRemoteFile()+" (task "+getSummary()+") to "+getMachine()+" threw exception: "+e);
- exception = e;
- }
-
- if (exception!=null || !((Integer)0).equals(exitCodeOfCopy)) {
- if (!allowFailure) {
- if (exception != null) {
- throw new IllegalStateException(getSummary()+" (SSH put task) ended with exception, in "+Tasks.current()+": "+exception, exception);
- }
- if (exitCodeOfCopy!=0) {
- exception = new IllegalStateException(getSummary()+" (SSH put task) ended with exit code "+exitCodeOfCopy+", in "+Tasks.current());
- throw exception;
- }
- }
- // not successful, but allowed
- return null;
- }
-
- // TODO verify
-
- successful = (exception==null && ((Integer)0).equals(exitCodeOfCopy));
- return null;
- }
- }
-
- @Override
- public String toString() {
- return super.toString()+"["+task+"]";
- }
-
- /** blocks, throwing if there was an exception */
- public Void get() {
- return getTask().getUnchecked();
- }
-
- /** returns the exit code from the copy, 0 on success;
- * null if it has not completed or threw exception
- * (not sure if this is ever a non-zero integer or if it is meaningful)
- * <p>
- * most callers will want the simpler {@link #isSuccessful()} */
- public Integer getExitCode() {
- return exitCodeOfCopy;
- }
-
- /** returns any exception encountered in the operation */
- public Exception getException() {
- return exception;
- }
-
- /** blocks until the task completes; does not throw */
- public SshPutTaskWrapper block() {
- getTask().blockUntilEnded();
- return this;
- }
-
- /** true iff the ssh job has completed (with or without failure) */
- public boolean isDone() {
- return getTask().isDone();
- }
-
- /** true iff the scp has completed successfully; guaranteed to be set before {@link #isDone()} or {@link #block()} are satisfied */
- public boolean isSuccessful() {
- return successful;
- }
-
-
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/ssh/SshTasks.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/ssh/SshTasks.java b/core/src/main/java/brooklyn/util/task/ssh/SshTasks.java
deleted file mode 100644
index 9f6fbb9..0000000
--- a/core/src/main/java/brooklyn/util/task/ssh/SshTasks.java
+++ /dev/null
@@ -1,236 +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 brooklyn.util.task.ssh;
-
-import java.util.Map;
-
-import javax.annotation.Nullable;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.api.management.Task;
-import org.apache.brooklyn.api.management.TaskAdaptable;
-import org.apache.brooklyn.api.management.TaskFactory;
-import org.apache.brooklyn.api.management.TaskQueueingContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.config.ConfigUtils;
-import brooklyn.entity.basic.BrooklynTaskTags;
-import brooklyn.entity.basic.ConfigKeys;
-
-import org.apache.brooklyn.location.basic.AbstractLocation;
-import org.apache.brooklyn.location.basic.LocationInternal;
-import org.apache.brooklyn.location.basic.SshMachineLocation;
-
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.internal.ssh.SshTool;
-import brooklyn.util.net.Urls;
-import brooklyn.util.ssh.BashCommands;
-import brooklyn.util.stream.Streams;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.task.ssh.internal.PlainSshExecTaskFactory;
-import brooklyn.util.task.system.ProcessTaskFactory;
-import brooklyn.util.task.system.ProcessTaskWrapper;
-import brooklyn.util.text.Identifiers;
-import brooklyn.util.text.Strings;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Function;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-
-/**
- * Conveniences for generating {@link Task} instances to perform SSH activities on an {@link SshMachineLocation}.
- * <p>
- * To infer the {@link SshMachineLocation} and take properties from entities and global management context the
- * {@link SshEffectorTasks} should be preferred over this class.
- *
- * @see SshEffectorTasks
- * @since 0.6.0
- */
-@Beta
-public class SshTasks {
-
- private static final Logger log = LoggerFactory.getLogger(SshTasks.class);
-
- public static ProcessTaskFactory<Integer> newSshExecTaskFactory(SshMachineLocation machine, String ...commands) {
- return newSshExecTaskFactory(machine, true, commands);
- }
-
- public static ProcessTaskFactory<Integer> newSshExecTaskFactory(SshMachineLocation machine, final boolean useMachineConfig, String ...commands) {
- return new PlainSshExecTaskFactory<Integer>(machine, commands) {
- {
- if (useMachineConfig)
- config.putIfAbsent(getSshFlags(machine));
- }
- };
- }
-
- public static SshPutTaskFactory newSshPutTaskFactory(SshMachineLocation machine, String remoteFile) {
- return newSshPutTaskFactory(machine, true, remoteFile);
- }
-
- public static SshPutTaskFactory newSshPutTaskFactory(SshMachineLocation machine, final boolean useMachineConfig, String remoteFile) {
- return new SshPutTaskFactory(machine, remoteFile) {
- {
- if (useMachineConfig)
- config.putIfAbsent(getSshFlags(machine));
- }
- };
- }
-
- public static SshFetchTaskFactory newSshFetchTaskFactory(SshMachineLocation machine, String remoteFile) {
- return newSshFetchTaskFactory(machine, true, remoteFile);
- }
-
- public static SshFetchTaskFactory newSshFetchTaskFactory(SshMachineLocation machine, final boolean useMachineConfig, String remoteFile) {
- return new SshFetchTaskFactory(machine, remoteFile) {
- {
- if (useMachineConfig)
- config.putIfAbsent(getSshFlags(machine));
- }
- };
- }
-
- private static Map<String, Object> getSshFlags(Location location) {
- ConfigBag allConfig = ConfigBag.newInstance();
-
- if (location instanceof AbstractLocation) {
- ManagementContext mgmt = ((AbstractLocation)location).getManagementContext();
- if (mgmt!=null)
- allConfig.putAll(mgmt.getConfig().getAllConfig());
- }
-
- allConfig.putAll(((LocationInternal)location).config().getBag());
-
- Map<String, Object> result = Maps.newLinkedHashMap();
- for (String keyS : allConfig.getAllConfig().keySet()) {
- ConfigKey<?> key = ConfigKeys.newConfigKey(Object.class, keyS);
- if (key.getName().startsWith(SshTool.BROOKLYN_CONFIG_KEY_PREFIX)) {
- result.put(ConfigUtils.unprefixedKey(SshTool.BROOKLYN_CONFIG_KEY_PREFIX, key).getName(), allConfig.get(key));
- }
- }
- return result;
- }
-
- @Beta
- public static enum OnFailingTask {
- FAIL,
- /** issues a warning, sometimes implemented as marking the task inessential and failing it if it appears
- * we are in a dynamic {@link TaskQueueingContext};
- * useful because this way the warning appears to the user;
- * but note that the check is done against the calling thread so use with some care
- * (and thus this enum is currently here rather then elsewhere) */
- WARN_OR_IF_DYNAMIC_FAIL_MARKING_INESSENTIAL,
- /** issues a warning in the log if the task fails, otherwise swallows it */
- WARN_IN_LOG_ONLY,
- /** not even a warning if the task fails (the caller is expected to handle it as appropriate) */
- IGNORE }
-
- public static ProcessTaskFactory<Boolean> dontRequireTtyForSudo(SshMachineLocation machine, final boolean failIfCantSudo) {
- return dontRequireTtyForSudo(machine, failIfCantSudo ? OnFailingTask.FAIL : OnFailingTask.WARN_IN_LOG_ONLY);
- }
- /** creates a task which returns modifies sudoers to ensure non-tty access is permitted;
- * also gives nice warnings if sudo is not permitted */
- public static ProcessTaskFactory<Boolean> dontRequireTtyForSudo(SshMachineLocation machine, OnFailingTask onFailingTaskRequested) {
- final OnFailingTask onFailingTask;
- if (onFailingTaskRequested==OnFailingTask.WARN_OR_IF_DYNAMIC_FAIL_MARKING_INESSENTIAL) {
- if (DynamicTasks.getTaskQueuingContext()!=null)
- onFailingTask = onFailingTaskRequested;
- else
- onFailingTask = OnFailingTask.WARN_IN_LOG_ONLY;
- } else {
- onFailingTask = onFailingTaskRequested;
- }
-
- final String id = Identifiers.makeRandomId(6);
- return newSshExecTaskFactory(machine,
- BashCommands.dontRequireTtyForSudo(),
- // strange quotes are to ensure we don't match against echoed stdin
- BashCommands.sudo("echo \"sudo\"-is-working-"+id))
- .summary("setting up sudo")
- .configure(SshTool.PROP_ALLOCATE_PTY, true)
- .allowingNonZeroExitCode()
- .returning(new Function<ProcessTaskWrapper<?>,Boolean>() { public Boolean apply(ProcessTaskWrapper<?> task) {
- if (task.getExitCode()==0 && task.getStdout().contains("sudo-is-working-"+id)) return true;
- Entity entity = BrooklynTaskTags.getTargetOrContextEntity(Tasks.current());
-
-
- if (onFailingTask!=OnFailingTask.IGNORE) {
- // TODO if in a queueing context can we mark this task inessential and throw?
- // that way user sees the message...
- String message = "Error setting up sudo for "+task.getMachine().getUser()+"@"+task.getMachine().getAddress().getHostName()+" "+
- " (exit code "+task.getExitCode()+(entity!=null ? ", entity "+entity : "")+")";
- DynamicTasks.queueIfPossible(Tasks.warning(message, null));
- }
- Streams.logStreamTail(log, "STDERR of sudo setup problem", Streams.byteArrayOfString(task.getStderr()), 1024);
-
- if (onFailingTask==OnFailingTask.WARN_OR_IF_DYNAMIC_FAIL_MARKING_INESSENTIAL) {
- Tasks.markInessential();
- }
- if (onFailingTask==OnFailingTask.FAIL || onFailingTask==OnFailingTask.WARN_OR_IF_DYNAMIC_FAIL_MARKING_INESSENTIAL) {
- throw new IllegalStateException("Passwordless sudo is required for "+task.getMachine().getUser()+"@"+task.getMachine().getAddress().getHostName()+
- (entity!=null ? " ("+entity+")" : ""));
- }
- return false;
- } });
- }
-
- /** Function for use in {@link ProcessTaskFactory#returning(Function)} which logs all information, optionally requires zero exit code,
- * and then returns stdout */
- public static Function<ProcessTaskWrapper<?>, String> returningStdoutLoggingInfo(final Logger logger, final boolean requireZero) {
- return new Function<ProcessTaskWrapper<?>, String>() {
- public String apply(@Nullable ProcessTaskWrapper<?> input) {
- if (logger!=null) logger.info(input+" COMMANDS:\n"+Strings.join(input.getCommands(),"\n"));
- if (logger!=null) logger.info(input+" STDOUT:\n"+input.getStdout());
- if (logger!=null) logger.info(input+" STDERR:\n"+input.getStderr());
- if (requireZero && input.getExitCode()!=0)
- throw new IllegalStateException("non-zero exit code in "+input.getSummary()+": see log for more details!");
- return input.getStdout();
- }
- };
- }
-
- /** task to install a file given a url, where the url is resolved remotely first then locally */
- public static TaskFactory<?> installFromUrl(final SshMachineLocation location, final String url, final String destPath) {
- return installFromUrl(ResourceUtils.create(SshTasks.class), ImmutableMap.<String,Object>of(), location, url, destPath);
- }
- /** task to install a file given a url, where the url is resolved remotely first then locally */
- public static TaskFactory<?> installFromUrl(final ResourceUtils utils, final Map<String, ?> props, final SshMachineLocation location, final String url, final String destPath) {
- return new TaskFactory<TaskAdaptable<?>>() {
- @Override
- public TaskAdaptable<?> newTask() {
- return Tasks.<Void>builder().name("installing "+Urls.getBasename(url)).description("installing "+url+" to "+destPath).body(new Runnable() {
- @Override
- public void run() {
- int result = location.installTo(utils, props, url, destPath);
- if (result!=0)
- throw new IllegalStateException("Failed to install '"+url+"' to '"+destPath+"' at "+location+": exit code "+result);
- }
- }).build();
- }
- };
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/ssh/internal/AbstractSshExecTaskFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/ssh/internal/AbstractSshExecTaskFactory.java b/core/src/main/java/brooklyn/util/task/ssh/internal/AbstractSshExecTaskFactory.java
deleted file mode 100644
index 86764f3..0000000
--- a/core/src/main/java/brooklyn/util/task/ssh/internal/AbstractSshExecTaskFactory.java
+++ /dev/null
@@ -1,58 +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 brooklyn.util.task.ssh.internal;
-
-import com.google.common.base.Preconditions;
-
-import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.task.system.ProcessTaskFactory;
-import brooklyn.util.task.system.ProcessTaskWrapper;
-import brooklyn.util.task.system.internal.AbstractProcessTaskFactory;
-
-// cannot be (cleanly) instantiated due to nested generic self-referential type; however trivial subclasses do allow it
-public abstract class AbstractSshExecTaskFactory<T extends AbstractProcessTaskFactory<T,RET>,RET> extends AbstractProcessTaskFactory<T,RET> implements ProcessTaskFactory<RET> {
-
- /** constructor where machine will be added later */
- public AbstractSshExecTaskFactory(String ...commands) {
- super(commands);
- }
-
- /** convenience constructor to supply machine immediately */
- public AbstractSshExecTaskFactory(SshMachineLocation machine, String ...commands) {
- this(commands);
- machine(machine);
- }
-
- @Override
- public ProcessTaskWrapper<RET> newTask() {
- dirty = false;
- return new ProcessTaskWrapper<RET>(this) {
- protected void run(ConfigBag config) {
- Preconditions.checkNotNull(getMachine(), "machine");
- if (Boolean.FALSE.equals(this.runAsScript)) {
- this.exitCode = getMachine().execCommands(config.getAllConfig(), getSummary(), commands, shellEnvironment);
- } else { // runScript = null or TRUE
- this.exitCode = getMachine().execScript(config.getAllConfig(), getSummary(), commands, shellEnvironment);
- }
- }
- protected String taskTypeShortName() { return "SSH"; }
- };
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/ssh/internal/PlainSshExecTaskFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/ssh/internal/PlainSshExecTaskFactory.java b/core/src/main/java/brooklyn/util/task/ssh/internal/PlainSshExecTaskFactory.java
deleted file mode 100644
index efc14db..0000000
--- a/core/src/main/java/brooklyn/util/task/ssh/internal/PlainSshExecTaskFactory.java
+++ /dev/null
@@ -1,71 +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 brooklyn.util.task.ssh.internal;
-
-import java.util.List;
-
-import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.task.system.ProcessTaskWrapper;
-
-import com.google.common.base.Function;
-
-/** the "Plain" class exists purely so we can massage return types for callers' convenience */
-public class PlainSshExecTaskFactory<RET> extends AbstractSshExecTaskFactory<PlainSshExecTaskFactory<RET>,RET> {
- /** constructor where machine will be added later */
- public PlainSshExecTaskFactory(String ...commands) {
- super(commands);
- }
-
- /** convenience constructor to supply machine immediately */
- public PlainSshExecTaskFactory(SshMachineLocation machine, String ...commands) {
- this(commands);
- machine(machine);
- }
-
- /** Constructor where machine will be added later */
- public PlainSshExecTaskFactory(List<String> commands) {
- this(commands.toArray(new String[commands.size()]));
- }
-
- /** Convenience constructor to supply machine immediately */
- public PlainSshExecTaskFactory(SshMachineLocation machine, List<String> commands) {
- this(machine, commands.toArray(new String[commands.size()]));
- }
-
- @Override
- public <T2> PlainSshExecTaskFactory<T2> returning(ScriptReturnType type) {
- return (PlainSshExecTaskFactory<T2>) super.<T2>returning(type);
- }
-
- @Override
- public <RET2> PlainSshExecTaskFactory<RET2> returning(Function<ProcessTaskWrapper<?>, RET2> resultTransformation) {
- return (PlainSshExecTaskFactory<RET2>) super.returning(resultTransformation);
- }
-
- @Override
- public PlainSshExecTaskFactory<Boolean> returningIsExitCodeZero() {
- return (PlainSshExecTaskFactory<Boolean>) super.returningIsExitCodeZero();
- }
-
- @Override
- public PlainSshExecTaskFactory<String> requiringZeroAndReturningStdout() {
- return (PlainSshExecTaskFactory<String>) super.requiringZeroAndReturningStdout();
- }
-
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/system/ProcessTaskFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/system/ProcessTaskFactory.java b/core/src/main/java/brooklyn/util/task/system/ProcessTaskFactory.java
deleted file mode 100644
index 407111c..0000000
--- a/core/src/main/java/brooklyn/util/task/system/ProcessTaskFactory.java
+++ /dev/null
@@ -1,65 +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 brooklyn.util.task.system;
-
-import java.util.Map;
-
-import org.apache.brooklyn.api.management.TaskFactory;
-
-import brooklyn.config.ConfigKey;
-import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.internal.ssh.SshTool;
-import brooklyn.util.task.system.ProcessTaskStub.ScriptReturnType;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Function;
-
-public interface ProcessTaskFactory<T> extends TaskFactory<ProcessTaskWrapper<T>> {
- public ProcessTaskFactory<T> machine(SshMachineLocation machine);
- public ProcessTaskFactory<T> add(String ...commandsToAdd);
- public ProcessTaskFactory<T> add(Iterable<String> commandsToAdd);
- public ProcessTaskFactory<T> requiringExitCodeZero();
- public ProcessTaskFactory<T> requiringExitCodeZero(String extraErrorMessage);
- public ProcessTaskFactory<T> allowingNonZeroExitCode();
- public ProcessTaskFactory<String> requiringZeroAndReturningStdout();
- public ProcessTaskFactory<Boolean> returningIsExitCodeZero();
- public <RET2> ProcessTaskFactory<RET2> returning(ScriptReturnType type);
- public <RET2> ProcessTaskFactory<RET2> returning(Function<ProcessTaskWrapper<?>, RET2> resultTransformation);
- public ProcessTaskFactory<T> runAsCommand();
- public ProcessTaskFactory<T> runAsScript();
- public ProcessTaskFactory<T> runAsRoot();
- public ProcessTaskFactory<T> environmentVariable(String key, String val);
- public ProcessTaskFactory<T> environmentVariables(Map<String,String> vars);
- public ProcessTaskFactory<T> summary(String summary);
-
- /** allows setting config-key based properties for specific underlying tools */
- @Beta
- public <V> ProcessTaskFactory<T> configure(ConfigKey<V> key, V value);
-
- /** allows setting config-key/flag based properties for specific underlying tools;
- * but note that if any are prefixed with {@link SshTool#BROOKLYN_CONFIG_KEY_PREFIX}
- * these should normally be filtered out */
- @Beta
- public ProcessTaskFactory<T> configure(Map<?,?> flags);
-
- /** adds a listener which will be notified of (otherwise) successful completion,
- * typically used to invalidate the result (ie throw exception, to promote a string in the output to an exception);
- * invoked even if return code is zero, so a better error can be thrown */
- public ProcessTaskFactory<T> addCompletionListener(Function<ProcessTaskWrapper<?>, Void> function);
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/system/ProcessTaskStub.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/system/ProcessTaskStub.java b/core/src/main/java/brooklyn/util/task/system/ProcessTaskStub.java
deleted file mode 100644
index df37691..0000000
--- a/core/src/main/java/brooklyn/util/task/system/ProcessTaskStub.java
+++ /dev/null
@@ -1,101 +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 brooklyn.util.task.system;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.text.Strings;
-
-import com.google.common.base.Function;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-
-public class ProcessTaskStub {
-
- protected final List<String> commands = new ArrayList<String>();
- /** null for localhost */
- protected SshMachineLocation machine;
-
- // config data
- protected String summary;
- protected final ConfigBag config = ConfigBag.newInstance();
-
- public static enum ScriptReturnType { CUSTOM, EXIT_CODE, STDOUT_STRING, STDOUT_BYTES, STDERR_STRING, STDERR_BYTES }
- protected Function<ProcessTaskWrapper<?>, ?> returnResultTransformation = null;
- protected ScriptReturnType returnType = ScriptReturnType.EXIT_CODE;
-
- protected Boolean runAsScript = null;
- protected boolean runAsRoot = false;
- protected Boolean requireExitCodeZero = null;
- protected String extraErrorMessage = null;
- protected Map<String,String> shellEnvironment = new MutableMap<String, String>();
- protected final List<Function<ProcessTaskWrapper<?>, Void>> completionListeners = new ArrayList<Function<ProcessTaskWrapper<?>,Void>>();
-
- public ProcessTaskStub() {}
-
- protected ProcessTaskStub(ProcessTaskStub source) {
- commands.addAll(source.getCommands());
- machine = source.getMachine();
- summary = source.getSummary();
- config.copy(source.getConfig());
- returnResultTransformation = source.returnResultTransformation;
- returnType = source.returnType;
- runAsScript = source.runAsScript;
- runAsRoot = source.runAsRoot;
- requireExitCodeZero = source.requireExitCodeZero;
- extraErrorMessage = source.extraErrorMessage;
- shellEnvironment.putAll(source.getShellEnvironment());
- completionListeners.addAll(source.getCompletionListeners());
- }
-
- public String getSummary() {
- if (summary!=null) return summary;
- return Strings.maxlen(Strings.join(commands, " ; "), 160);
- }
-
- /** null for localhost */
- public SshMachineLocation getMachine() {
- return machine;
- }
-
- public Map<String, String> getShellEnvironment() {
- return ImmutableMap.copyOf(shellEnvironment);
- }
-
- @Override
- public String toString() {
- return super.toString()+"["+getSummary()+"]";
- }
-
- public List<String> getCommands() {
- return ImmutableList.copyOf(commands);
- }
-
- public List<Function<ProcessTaskWrapper<?>, Void>> getCompletionListeners() {
- return completionListeners;
- }
-
- protected ConfigBag getConfig() { return config; }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/system/ProcessTaskWrapper.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/system/ProcessTaskWrapper.java b/core/src/main/java/brooklyn/util/task/system/ProcessTaskWrapper.java
deleted file mode 100644
index 5c18fdd..0000000
--- a/core/src/main/java/brooklyn/util/task/system/ProcessTaskWrapper.java
+++ /dev/null
@@ -1,187 +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 brooklyn.util.task.system;
-
-import java.io.ByteArrayOutputStream;
-import java.util.concurrent.Callable;
-
-import org.apache.brooklyn.api.management.Task;
-import org.apache.brooklyn.api.management.TaskWrapper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.entity.basic.BrooklynTaskTags;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.internal.ssh.ShellTool;
-import brooklyn.util.stream.Streams;
-import brooklyn.util.task.TaskBuilder;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.task.system.internal.AbstractProcessTaskFactory;
-import brooklyn.util.text.Strings;
-
-import com.google.common.base.Function;
-
-/** Wraps a fully constructed process task, and allows callers to inspect status.
- * Note that methods in here such as {@link #getStdout()} will return partially completed streams while the task is ongoing
- * (and exit code will be null). You can {@link #block()} or {@link #get()} as conveniences on the underlying {@link #getTask()}. */
-public abstract class ProcessTaskWrapper<RET> extends ProcessTaskStub implements TaskWrapper<RET> {
-
- private static final Logger log = LoggerFactory.getLogger(ProcessTaskWrapper.class);
-
- private final Task<RET> task;
-
- // execution details
- protected ByteArrayOutputStream stdout = new ByteArrayOutputStream();
- protected ByteArrayOutputStream stderr = new ByteArrayOutputStream();
- protected Integer exitCode = null;
-
- @SuppressWarnings("unchecked")
- protected ProcessTaskWrapper(AbstractProcessTaskFactory<?,RET> constructor) {
- super(constructor);
- TaskBuilder<Object> tb = constructor.constructCustomizedTaskBuilder();
- if (stdout!=null) tb.tag(BrooklynTaskTags.tagForStreamSoft(BrooklynTaskTags.STREAM_STDOUT, stdout));
- if (stderr!=null) tb.tag(BrooklynTaskTags.tagForStreamSoft(BrooklynTaskTags.STREAM_STDERR, stderr));
- task = (Task<RET>) tb.body(new ProcessTaskInternalJob()).build();
- }
-
- @Override
- public Task<RET> asTask() {
- return getTask();
- }
-
- @Override
- public Task<RET> getTask() {
- return task;
- }
-
- public Integer getExitCode() {
- return exitCode;
- }
-
- public byte[] getStdoutBytes() {
- if (stdout==null) return null;
- return stdout.toByteArray();
- }
-
- public byte[] getStderrBytes() {
- if (stderr==null) return null;
- return stderr.toByteArray();
- }
-
- public String getStdout() {
- if (stdout==null) return null;
- return stdout.toString();
- }
-
- public String getStderr() {
- if (stderr==null) return null;
- return stderr.toString();
- }
-
- protected class ProcessTaskInternalJob implements Callable<Object> {
- @Override
- public Object call() throws Exception {
- run( getConfigForRunning() );
-
- for (Function<ProcessTaskWrapper<?>, Void> listener: completionListeners) {
- try {
- listener.apply(ProcessTaskWrapper.this);
- } catch (Exception e) {
- logWithDetailsAndThrow("Error in "+taskTypeShortName()+" task "+getSummary()+": "+e, e);
- }
- }
-
- if (exitCode!=0 && !Boolean.FALSE.equals(requireExitCodeZero)) {
- if (Boolean.TRUE.equals(requireExitCodeZero)) {
- logWithDetailsAndThrow(taskTypeShortName()+" task ended with exit code "+exitCode+" when 0 was required, in "+Tasks.current()+": "+getSummary(), null);
- } else {
- // warn, but allow, on non-zero not explicitly allowed
- log.warn(taskTypeShortName()+" task ended with exit code "+exitCode+" when non-zero was not explicitly allowed (error may be thrown in future), in "
- +Tasks.current()+": "+getSummary());
- }
- }
- switch (returnType) {
- case CUSTOM: return returnResultTransformation.apply(ProcessTaskWrapper.this);
- case STDOUT_STRING: return stdout.toString();
- case STDOUT_BYTES: return stdout.toByteArray();
- case STDERR_STRING: return stderr.toString();
- case STDERR_BYTES: return stderr.toByteArray();
- case EXIT_CODE: return exitCode;
- }
-
- throw new IllegalStateException("Unknown return type for "+taskTypeShortName()+" job "+getSummary()+": "+returnType);
- }
-
- protected void logWithDetailsAndThrow(String message, Throwable optionalCause) {
- message = (extraErrorMessage!=null ? extraErrorMessage+": " : "") + message;
- log.warn(message+" (throwing)");
- logProblemDetails("STDERR", stderr, 1024);
- logProblemDetails("STDOUT", stdout, 1024);
- logProblemDetails("STDIN", Streams.byteArrayOfString(Strings.join(commands,"\n")), 4096);
- if (optionalCause!=null) throw new IllegalStateException(message, optionalCause);
- throw new IllegalStateException(message);
- }
-
- protected void logProblemDetails(String streamName, ByteArrayOutputStream stream, int max) {
- Streams.logStreamTail(log, streamName+" for problem in "+Tasks.current(), stream, max);
- }
-
- }
-
- @Override
- public String toString() {
- return super.toString()+"["+task+"]";
- }
-
- /** blocks and gets the result, throwing if there was an exception */
- public RET get() {
- return getTask().getUnchecked();
- }
-
- /** blocks until the task completes; does not throw */
- public ProcessTaskWrapper<RET> block() {
- getTask().blockUntilEnded();
- return this;
- }
-
- /** true iff the process has completed (with or without failure) */
- public boolean isDone() {
- return getTask().isDone();
- }
-
- /** for overriding */
- protected ConfigBag getConfigForRunning() {
- ConfigBag config = ConfigBag.newInstanceCopying(ProcessTaskWrapper.this.config);
- if (stdout!=null) config.put(ShellTool.PROP_OUT_STREAM, stdout);
- if (stderr!=null) config.put(ShellTool.PROP_ERR_STREAM, stderr);
-
- if (!config.containsKey(ShellTool.PROP_NO_EXTRA_OUTPUT))
- // by default no extra output (so things like cat, etc work as expected)
- config.put(ShellTool.PROP_NO_EXTRA_OUTPUT, true);
-
- if (runAsRoot)
- config.put(ShellTool.PROP_RUN_AS_ROOT, true);
- return config;
- }
-
- protected abstract void run(ConfigBag config);
-
- protected abstract String taskTypeShortName();
-
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/system/SystemTasks.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/system/SystemTasks.java b/core/src/main/java/brooklyn/util/task/system/SystemTasks.java
deleted file mode 100644
index 8553935..0000000
--- a/core/src/main/java/brooklyn/util/task/system/SystemTasks.java
+++ /dev/null
@@ -1,29 +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 brooklyn.util.task.system;
-
-import brooklyn.util.task.system.internal.SystemProcessTaskFactory.ConcreteSystemProcessTaskFactory;
-
-public class SystemTasks {
-
- public static ProcessTaskFactory<Integer> exec(String ...commands) {
- return new ConcreteSystemProcessTaskFactory<Integer>(commands);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/task/system/internal/AbstractProcessTaskFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/system/internal/AbstractProcessTaskFactory.java b/core/src/main/java/brooklyn/util/task/system/internal/AbstractProcessTaskFactory.java
deleted file mode 100644
index e41a9a9..0000000
--- a/core/src/main/java/brooklyn/util/task/system/internal/AbstractProcessTaskFactory.java
+++ /dev/null
@@ -1,214 +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 brooklyn.util.task.system.internal;
-
-import java.util.Arrays;
-import java.util.Map;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.entity.basic.BrooklynTaskTags;
-import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.stream.Streams;
-import brooklyn.util.task.TaskBuilder;
-import brooklyn.util.task.system.ProcessTaskFactory;
-import brooklyn.util.task.system.ProcessTaskStub;
-import brooklyn.util.task.system.ProcessTaskWrapper;
-import brooklyn.util.text.Strings;
-
-import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Iterables;
-
-public abstract class AbstractProcessTaskFactory<T extends AbstractProcessTaskFactory<T,RET>,RET> extends ProcessTaskStub implements ProcessTaskFactory<RET> {
-
- private static final Logger log = LoggerFactory.getLogger(AbstractProcessTaskFactory.class);
-
- protected boolean dirty = false;
-
- public AbstractProcessTaskFactory(String ...commands) {
- this.commands.addAll(Arrays.asList(commands));
- }
-
- @SuppressWarnings("unchecked")
- protected T self() { return (T)this; }
-
- protected void markDirty() {
- dirty = true;
- }
-
- @Override
- public T add(String ...commandsToAdd) {
- markDirty();
- for (String commandToAdd: commandsToAdd) this.commands.add(commandToAdd);
- return self();
- }
-
- @Override
- public T add(Iterable<String> commandsToAdd) {
- Iterables.addAll(this.commands, commandsToAdd);
- return self();
- }
-
- @Override
- public T machine(SshMachineLocation machine) {
- markDirty();
- this.machine = machine;
- return self();
- }
-
- @Override
- public T requiringExitCodeZero() {
- markDirty();
- requireExitCodeZero = true;
- return self();
- }
-
- @Override
- public T requiringExitCodeZero(String extraErrorMessage) {
- markDirty();
- requireExitCodeZero = true;
- this.extraErrorMessage = extraErrorMessage;
- return self();
- }
-
- @Override
- public T allowingNonZeroExitCode() {
- markDirty();
- requireExitCodeZero = false;
- return self();
- }
-
- @Override
- public ProcessTaskFactory<Boolean> returningIsExitCodeZero() {
- if (requireExitCodeZero==null) allowingNonZeroExitCode();
- return returning(new Function<ProcessTaskWrapper<?>,Boolean>() {
- public Boolean apply(ProcessTaskWrapper<?> input) {
- return input.getExitCode()==0;
- }
- });
- }
-
- @Override
- public ProcessTaskFactory<String> requiringZeroAndReturningStdout() {
- requiringExitCodeZero();
- return this.<String>returning(ScriptReturnType.STDOUT_STRING);
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public <RET2> ProcessTaskFactory<RET2> returning(ScriptReturnType type) {
- markDirty();
- returnType = Preconditions.checkNotNull(type);
- return (ProcessTaskFactory<RET2>) self();
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public <RET2> ProcessTaskFactory<RET2> returning(Function<ProcessTaskWrapper<?>, RET2> resultTransformation) {
- markDirty();
- returnType = ScriptReturnType.CUSTOM;
- this.returnResultTransformation = resultTransformation;
- return (ProcessTaskFactory<RET2>) self();
- }
-
- @Override
- public T runAsCommand() {
- markDirty();
- runAsScript = false;
- return self();
- }
-
- @Override
- public T runAsScript() {
- markDirty();
- runAsScript = true;
- return self();
- }
-
- @Override
- public T runAsRoot() {
- markDirty();
- runAsRoot = true;
- return self();
- }
-
- @Override
- public T environmentVariable(String key, String val) {
- markDirty();
- shellEnvironment.put(key, val);
- return self();
- }
-
- @Override
- public T environmentVariables(Map<String,String> vars) {
- if (vars!=null) {
- markDirty();
- shellEnvironment.putAll(vars);
- }
- return self();
- }
-
- /** creates the TaskBuilder which can be further customized; typically invoked by the initial {@link #newTask()} */
- public TaskBuilder<Object> constructCustomizedTaskBuilder() {
- TaskBuilder<Object> tb = TaskBuilder.builder().dynamic(false).name("ssh: "+getSummary());
-
- tb.tag(BrooklynTaskTags.tagForStream(BrooklynTaskTags.STREAM_STDIN,
- Streams.byteArrayOfString(Strings.join(commands, "\n"))));
- tb.tag(BrooklynTaskTags.tagForEnvStream(BrooklynTaskTags.STREAM_ENV, shellEnvironment));
-
- return tb;
- }
-
- @Override
- public T summary(String summary) {
- markDirty();
- this.summary = summary;
- return self();
- }
-
- @Override
- public <V> T configure(ConfigKey<V> key, V value) {
- config.configure(key, value);
- return self();
- }
-
- @Override
- public T configure(Map<?, ?> flags) {
- if (flags!=null)
- config.putAll(flags);
- return self();
- }
-
- @Override
- public T addCompletionListener(Function<ProcessTaskWrapper<?>, Void> listener) {
- completionListeners.add(listener);
- return self();
- }
-
- @Override
- protected void finalize() throws Throwable {
- // help let people know of API usage error
- if (dirty)
- log.warn("Task "+this+" was modified but modification was never used");
- super.finalize();
- }
-}
[20/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/system/internal/ExecWithLoggingHelpers.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/system/internal/ExecWithLoggingHelpers.java b/core/src/main/java/org/apache/brooklyn/core/util/task/system/internal/ExecWithLoggingHelpers.java
new file mode 100644
index 0000000..9e96674
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/system/internal/ExecWithLoggingHelpers.java
@@ -0,0 +1,202 @@
+/*
+ * 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.util.task.system.internal;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.util.List;
+import java.util.Map;
+
+import org.slf4j.Logger;
+
+import brooklyn.config.ConfigKey;
+
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
+import org.apache.brooklyn.core.util.internal.ssh.ShellAbstractTool;
+import org.apache.brooklyn.core.util.internal.ssh.ShellTool;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.location.basic.SshMachineLocation;
+
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.stream.StreamGobbler;
+import brooklyn.util.stream.Streams;
+import brooklyn.util.text.Strings;
+
+import com.google.common.base.Function;
+import com.google.common.base.Throwables;
+
+public abstract class ExecWithLoggingHelpers {
+
+ public static final ConfigKey<OutputStream> STDOUT = SshMachineLocation.STDOUT;
+ public static final ConfigKey<OutputStream> STDERR = SshMachineLocation.STDERR;
+ public static final ConfigKey<Boolean> NO_STDOUT_LOGGING = SshMachineLocation.NO_STDOUT_LOGGING;
+ public static final ConfigKey<Boolean> NO_STDERR_LOGGING = SshMachineLocation.NO_STDERR_LOGGING;
+ public static final ConfigKey<String> LOG_PREFIX = SshMachineLocation.LOG_PREFIX;
+
+ protected final String shortName;
+ protected Logger commandLogger = null;
+
+ public interface ExecRunner {
+ public int exec(ShellTool ssh, Map<String,?> flags, List<String> cmds, Map<String,?> env);
+ }
+
+ protected abstract <T> T execWithTool(MutableMap<String, Object> toolCreationAndConnectionProperties, Function<ShellTool, T> runMethodOnTool);
+ protected abstract void preExecChecks();
+ protected abstract String getTargetName();
+ protected abstract String constructDefaultLoggingPrefix(ConfigBag execFlags);
+
+ /** takes a very short name for use in blocking details, e.g. SSH or Process */
+ public ExecWithLoggingHelpers(String shortName) {
+ this.shortName = shortName;
+ }
+
+ public ExecWithLoggingHelpers logger(Logger commandLogger) {
+ this.commandLogger = commandLogger;
+ return this;
+ }
+
+ public int execScript(Map<String,?> props, String summaryForLogging, List<String> commands, Map<String,?> env) {
+ // TODO scriptHeader are the extra commands we expect the SshTool/ShellTool to add.
+ // Would be better if could get this from the ssh-tool, rather than assuming it will behave as
+ // we expect.
+ String scriptHeader = ShellAbstractTool.getOptionalVal(props, ShellTool.PROP_SCRIPT_HEADER);
+
+ return execWithLogging(props, summaryForLogging, commands, env, scriptHeader, new ExecRunner() {
+ @Override public int exec(ShellTool ssh, Map<String, ?> flags, List<String> cmds, Map<String, ?> env) {
+ return ssh.execScript(flags, cmds, env);
+ }});
+ }
+
+ protected static <T> T getOptionalVal(Map<String,?> map, ConfigKey<T> keyC) {
+ if (keyC==null) return null;
+ String key = keyC.getName();
+ if (map!=null && map.containsKey(key)) {
+ return TypeCoercions.coerce(map.get(key), keyC.getTypeToken());
+ } else {
+ return keyC.getDefaultValue();
+ }
+ }
+
+ public int execCommands(Map<String,?> props, String summaryForLogging, List<String> commands, Map<String,?> env) {
+ return execWithLogging(props, summaryForLogging, commands, env, new ExecRunner() {
+ @Override public int exec(ShellTool tool, Map<String,?> flags, List<String> cmds, Map<String,?> env) {
+ return tool.execCommands(flags, cmds, env);
+ }});
+ }
+
+ public int execWithLogging(Map<String,?> props, final String summaryForLogging, final List<String> commands,
+ final Map<String,?> env, final ExecRunner execCommand) {
+ return execWithLogging(props, summaryForLogging, commands, env, null, execCommand);
+ }
+
+ @SuppressWarnings("resource")
+ public int execWithLogging(Map<String,?> props, final String summaryForLogging, final List<String> commands,
+ final Map<String,?> env, String expectedCommandHeaders, final ExecRunner execCommand) {
+ if (commandLogger!=null && commandLogger.isDebugEnabled()) {
+ String allcmds = (Strings.isBlank(expectedCommandHeaders) ? "" : expectedCommandHeaders + " ; ") + Strings.join(commands, " ; ");
+ commandLogger.debug("{}, initiating "+shortName.toLowerCase()+" on machine {}{}: {}",
+ new Object[] {summaryForLogging, getTargetName(),
+ env!=null && !env.isEmpty() ? " (env "+env+")": "", allcmds});
+ }
+
+ if (commands.isEmpty()) {
+ if (commandLogger!=null && commandLogger.isDebugEnabled())
+ commandLogger.debug("{}, on machine {}, ending: no commands to run", summaryForLogging, getTargetName());
+ return 0;
+ }
+
+ final ConfigBag execFlags = new ConfigBag().putAll(props);
+ // some props get overridden in execFlags, so remove them from the tool flags
+ final ConfigBag toolFlags = new ConfigBag().putAll(props).removeAll(
+ LOG_PREFIX, STDOUT, STDERR, ShellTool.PROP_NO_EXTRA_OUTPUT);
+
+ execFlags.configure(ShellTool.PROP_SUMMARY, summaryForLogging);
+
+ PipedOutputStream outO = null;
+ PipedOutputStream outE = null;
+ StreamGobbler gO=null, gE=null;
+ try {
+ preExecChecks();
+
+ String logPrefix = execFlags.get(LOG_PREFIX);
+ if (logPrefix==null) logPrefix = constructDefaultLoggingPrefix(execFlags);
+
+ if (!execFlags.get(NO_STDOUT_LOGGING)) {
+ PipedInputStream insO = new PipedInputStream();
+ outO = new PipedOutputStream(insO);
+
+ String stdoutLogPrefix = "["+(logPrefix != null ? logPrefix+":stdout" : "stdout")+"] ";
+ gO = new StreamGobbler(insO, execFlags.get(STDOUT), commandLogger).setLogPrefix(stdoutLogPrefix);
+ gO.start();
+
+ execFlags.put(STDOUT, outO);
+ }
+
+ if (!execFlags.get(NO_STDERR_LOGGING)) {
+ PipedInputStream insE = new PipedInputStream();
+ outE = new PipedOutputStream(insE);
+
+ String stderrLogPrefix = "["+(logPrefix != null ? logPrefix+":stderr" : "stderr")+"] ";
+ gE = new StreamGobbler(insE, execFlags.get(STDERR), commandLogger).setLogPrefix(stderrLogPrefix);
+ gE.start();
+
+ execFlags.put(STDERR, outE);
+ }
+
+ Tasks.setBlockingDetails(shortName+" executing, "+summaryForLogging);
+ try {
+ return execWithTool(MutableMap.copyOf(toolFlags.getAllConfig()), new Function<ShellTool, Integer>() {
+ public Integer apply(ShellTool tool) {
+ int result = execCommand.exec(tool, MutableMap.copyOf(execFlags.getAllConfig()), commands, env);
+ if (commandLogger!=null && commandLogger.isDebugEnabled())
+ commandLogger.debug("{}, on machine {}, completed: return status {}",
+ new Object[] {summaryForLogging, getTargetName(), result});
+ return result;
+ }});
+
+ } finally {
+ Tasks.setBlockingDetails(null);
+ }
+
+ } catch (IOException e) {
+ if (commandLogger!=null && commandLogger.isDebugEnabled())
+ commandLogger.debug("{}, on machine {}, failed: {}", new Object[] {summaryForLogging, getTargetName(), e});
+ throw Throwables.propagate(e);
+ } finally {
+ // Must close the pipedOutStreams, otherwise input will never read -1 so StreamGobbler thread would never die
+ if (outO!=null) try { outO.flush(); } catch (IOException e) {}
+ if (outE!=null) try { outE.flush(); } catch (IOException e) {}
+ Streams.closeQuietly(outO);
+ Streams.closeQuietly(outE);
+
+ try {
+ if (gE!=null) { gE.join(); }
+ if (gO!=null) { gO.join(); }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ Throwables.propagate(e);
+ }
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/system/internal/SystemProcessTaskFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/system/internal/SystemProcessTaskFactory.java b/core/src/main/java/org/apache/brooklyn/core/util/task/system/internal/SystemProcessTaskFactory.java
new file mode 100644
index 0000000..4a6dacb
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/system/internal/SystemProcessTaskFactory.java
@@ -0,0 +1,131 @@
+/*
+ * 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.util.task.system.internal;
+
+import java.io.File;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.internal.ssh.ShellTool;
+import org.apache.brooklyn.core.util.internal.ssh.process.ProcessTool;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
+import org.apache.brooklyn.location.basic.SshMachineLocation;
+
+import brooklyn.util.collections.MutableMap;
+
+import com.google.common.base.Function;
+
+public class SystemProcessTaskFactory<T extends SystemProcessTaskFactory<T,RET>,RET> extends AbstractProcessTaskFactory<T, RET> {
+
+ private static final Logger log = LoggerFactory.getLogger(SystemProcessTaskFactory.class);
+
+ // FIXME Plum this through?!
+ private File directory;
+ private Boolean loginShell;
+
+ public SystemProcessTaskFactory(String ...commands) {
+ super(commands);
+ }
+
+ public T directory(File directory) {
+ markDirty();
+ this.directory = directory;
+ return self();
+ }
+
+ public T loginShell(boolean loginShell) {
+ markDirty();
+ this.loginShell = loginShell;
+ return self();
+ }
+
+ @Override
+ public T machine(SshMachineLocation machine) {
+ log.warn("Not permitted to set machines on "+this+" (ignoring - "+machine+")");
+ if (log.isDebugEnabled())
+ log.debug("Source of attempt to set machines on "+this+" ("+machine+")",
+ new Throwable("Source of attempt to set machines on "+this+" ("+machine+")"));
+ return self();
+ }
+
+ @Override
+ public ProcessTaskWrapper<RET> newTask() {
+ return new SystemProcessTaskWrapper();
+ }
+
+ protected class SystemProcessTaskWrapper extends ProcessTaskWrapper<RET> {
+ protected final String taskTypeShortName;
+
+ public SystemProcessTaskWrapper() {
+ this("Process");
+ }
+ public SystemProcessTaskWrapper(String taskTypeShortName) {
+ super(SystemProcessTaskFactory.this);
+ this.taskTypeShortName = taskTypeShortName;
+ }
+ @Override
+ protected ConfigBag getConfigForRunning() {
+ ConfigBag result = super.getConfigForRunning();
+ if (directory != null) config.put(ProcessTool.PROP_DIRECTORY, directory.getAbsolutePath());
+ if (loginShell != null) config.put(ProcessTool.PROP_LOGIN_SHELL, loginShell);
+ return result;
+ }
+ @Override
+ protected void run(ConfigBag config) {
+ if (Boolean.FALSE.equals(this.runAsScript)) {
+ this.exitCode = newExecWithLoggingHelpers().execCommands(config.getAllConfig(), getSummary(), getCommands(), getShellEnvironment());
+ } else { // runScript = null or TRUE
+ this.exitCode = newExecWithLoggingHelpers().execScript(config.getAllConfig(), getSummary(), getCommands(), getShellEnvironment());
+ }
+ }
+ @Override
+ protected String taskTypeShortName() { return taskTypeShortName; }
+ }
+
+ protected ExecWithLoggingHelpers newExecWithLoggingHelpers() {
+ return new ExecWithLoggingHelpers("Process") {
+ @Override
+ protected <U> U execWithTool(MutableMap<String, Object> props, Function<ShellTool, U> task) {
+ // properties typically passed to both
+ if (log.isDebugEnabled() && props!=null && !props.isEmpty())
+ log.debug("Ignoring flags "+props+" when running "+this);
+ return task.apply(new ProcessTool());
+ }
+ @Override
+ protected void preExecChecks() {}
+ @Override
+ protected String constructDefaultLoggingPrefix(ConfigBag execFlags) {
+ return "system.exec";
+ }
+ @Override
+ protected String getTargetName() {
+ return "local host";
+ }
+ }.logger(log);
+ }
+
+ /** concrete instance (for generics) */
+ public static class ConcreteSystemProcessTaskFactory<RET> extends SystemProcessTaskFactory<ConcreteSystemProcessTaskFactory<RET>, RET> {
+ public ConcreteSystemProcessTaskFactory(String ...commands) {
+ super(commands);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/text/DataUriSchemeParser.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/text/DataUriSchemeParser.java b/core/src/main/java/org/apache/brooklyn/core/util/text/DataUriSchemeParser.java
new file mode 100644
index 0000000..d4ed26c
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/text/DataUriSchemeParser.java
@@ -0,0 +1,267 @@
+/*
+ * 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.util.text;
+
+import java.io.ByteArrayInputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URLDecoder;
+import java.nio.charset.Charset;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import brooklyn.util.exceptions.Exceptions;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.io.BaseEncoding;
+//import com.sun.jersey.core.util.Base64;
+
+/** implementation (currently hokey) of RFC-2397 data: URI scheme.
+ * see: http://stackoverflow.com/questions/12353552/any-rfc-2397-data-uri-parser-for-java */
+public class DataUriSchemeParser {
+
+ public static final String PROTOCOL_PREFIX = "data:";
+ public static final String DEFAULT_MIME_TYPE = "text/plain";
+ public static final String DEFAULT_CHARSET = "US-ASCII";
+
+ private final String url;
+ private int parseIndex = 0;
+ private boolean isParsed = false;
+ private boolean allowMissingComma = false;
+ private boolean allowSlashesAfterColon = false;
+ private boolean allowOtherLaxities = false;
+
+ private String mimeType;
+ private byte[] data;
+ private Map<String,String> parameters = new LinkedHashMap<String,String>();
+
+ public DataUriSchemeParser(String url) {
+ this.url = Preconditions.checkNotNull(url, "url");
+ }
+
+ // ---- static conveniences -----
+
+ public static String toString(String url) {
+ return new DataUriSchemeParser(url).lax().parse().getDataAsString();
+ }
+
+ public static byte[] toBytes(String url) {
+ return new DataUriSchemeParser(url).lax().parse().getData();
+ }
+
+ // ---- accessors (once it is parsed) -----------
+
+ public String getCharset() {
+ String charset = parameters.get("charset");
+ if (charset!=null) return charset;
+ return DEFAULT_CHARSET;
+ }
+
+ public String getMimeType() {
+ assertParsed();
+ if (mimeType!=null) return mimeType;
+ return DEFAULT_MIME_TYPE;
+ }
+
+ public Map<String, String> getParameters() {
+ return ImmutableMap.<String, String>copyOf(parameters);
+ }
+
+ public byte[] getData() {
+ assertParsed();
+ return data;
+ }
+
+ public ByteArrayInputStream getDataAsInputStream() {
+ return new ByteArrayInputStream(getData());
+ }
+
+ public String getDataAsString() {
+ return new String(getData(), Charset.forName(getCharset()));
+ }
+
+ // ---- config ------------------
+
+ public synchronized DataUriSchemeParser lax() {
+ return allowMissingComma(true).allowSlashesAfterColon(true).allowOtherLaxities(true);
+ }
+
+ public synchronized DataUriSchemeParser allowMissingComma(boolean allowMissingComma) {
+ assertNotParsed();
+ this.allowMissingComma = allowMissingComma;
+ return this;
+ }
+
+ public synchronized DataUriSchemeParser allowSlashesAfterColon(boolean allowSlashesAfterColon) {
+ assertNotParsed();
+ this.allowSlashesAfterColon = allowSlashesAfterColon;
+ return this;
+ }
+
+ private synchronized DataUriSchemeParser allowOtherLaxities(boolean allowOtherLaxities) {
+ assertNotParsed();
+ this.allowOtherLaxities = allowOtherLaxities;
+ return this;
+ }
+
+ private void assertNotParsed() {
+ if (isParsed) throw new IllegalStateException("Operation not permitted after parsing");
+ }
+
+ private void assertParsed() {
+ if (!isParsed) throw new IllegalStateException("Operation not permitted before parsing");
+ }
+
+ public synchronized DataUriSchemeParser parse() {
+ try {
+ return parseChecked();
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ public synchronized DataUriSchemeParser parseChecked() throws UnsupportedEncodingException, MalformedURLException {
+ if (isParsed) return this;
+
+ skipOptional(PROTOCOL_PREFIX);
+ if (allowSlashesAfterColon)
+ while (skipOptional("/")) ;
+
+ if (allowMissingComma && remainder().indexOf(',')==-1) {
+ mimeType = DEFAULT_MIME_TYPE;
+ parameters.put("charset", DEFAULT_CHARSET);
+ } else {
+ parseMediaType();
+ parseParameterOrParameterValues();
+ skipRequired(",");
+ }
+
+ parseData();
+
+ isParsed = true;
+ return this;
+ }
+
+ private void parseMediaType() throws MalformedURLException {
+ if (remainder().startsWith(";") || remainder().startsWith(","))
+ return;
+ int slash = remainder().indexOf("/");
+ if (slash==-1) throw new MalformedURLException("Missing required '/' in MIME type of data: URL");
+ String type = read(slash);
+ skipRequired("/");
+ int next = nextSemiOrComma();
+ String subtype = read(next);
+ mimeType = type+"/"+subtype;
+ }
+
+ private String read(int next) {
+ String result = remainder().substring(0, next);
+ parseIndex += next;
+ return result;
+ }
+
+ private int nextSemiOrComma() throws MalformedURLException {
+ int semi = remainder().indexOf(';');
+ int comma = remainder().indexOf(',');
+ if (semi<0 && comma<0) throw new MalformedURLException("Missing required ',' in data: URL");
+ if (semi<0) return comma;
+ if (comma<0) return semi;
+ return Math.min(semi, comma);
+ }
+
+ private void parseParameterOrParameterValues() throws MalformedURLException {
+ while (true) {
+ if (!remainder().startsWith(";")) return;
+ parseIndex++;
+ int eq = remainder().indexOf('=');
+ String word, value;
+ int nextSemiOrComma = nextSemiOrComma();
+ if (eq==-1 || eq>nextSemiOrComma) {
+ word = read(nextSemiOrComma);
+ value = null;
+ } else {
+ word = read(eq);
+ if (remainder().startsWith("\"")) {
+ // is quoted
+ parseIndex++;
+ int nextUnescapedQuote = nextUnescapedQuote();
+ value = "\"" + read(nextUnescapedQuote);
+ } else {
+ value = read(nextSemiOrComma());
+ }
+ }
+ parameters.put(word, value);
+ }
+ }
+
+ private int nextUnescapedQuote() throws MalformedURLException {
+ int i=0;
+ String r = remainder();
+ boolean escaped = false;
+ while (i<r.length()) {
+ if (escaped) {
+ escaped = false;
+ } else {
+ if (r.charAt(i)=='"') return i;
+ if (r.charAt(i)=='\\') escaped = true;
+ }
+ i++;
+ }
+ throw new MalformedURLException("Unclosed double-quote in data: URL");
+ }
+
+ private void parseData() throws UnsupportedEncodingException, MalformedURLException {
+ if (parameters.containsKey("base64")) {
+ checkNoParamValue("base64");
+ data = BaseEncoding.base64().decode(remainder());
+ } else if (parameters.containsKey("base64url")) {
+ checkNoParamValue("base64url");
+ data = BaseEncoding.base64Url().decode(remainder());
+ } else {
+ data = URLDecoder.decode(remainder(), getCharset()).getBytes(Charset.forName(getCharset()));
+ }
+ }
+
+ private void checkNoParamValue(String param) throws MalformedURLException {
+ if (allowOtherLaxities) return;
+ String value = parameters.get(param);
+ if (value!=null)
+ throw new MalformedURLException(param+" parameter must not take a value ("+value+") in data: URL");
+ }
+
+ private String remainder() {
+ return url.substring(parseIndex);
+ }
+
+ private boolean skipOptional(String word) {
+ if (remainder().startsWith(word)) {
+ parseIndex += word.length();
+ return true;
+ }
+ return false;
+ }
+
+ private void skipRequired(String word) throws MalformedURLException {
+ if (!remainder().startsWith(word))
+ throw new MalformedURLException("Missing required '"+word+"' at position "+parseIndex+" of data: URL");
+ parseIndex += word.length();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/text/TemplateProcessor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/text/TemplateProcessor.java b/core/src/main/java/org/apache/brooklyn/core/util/text/TemplateProcessor.java
new file mode 100644
index 0000000..6fb3c15
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/text/TemplateProcessor.java
@@ -0,0 +1,398 @@
+/*
+ * 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.util.text;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.Map;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.drivers.EntityDriver;
+import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.event.basic.DependentConfiguration;
+import brooklyn.event.basic.Sensors;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.text.Strings;
+
+import com.google.common.base.Charsets;
+import com.google.common.collect.Iterables;
+import com.google.common.io.Files;
+
+import freemarker.cache.StringTemplateLoader;
+import freemarker.template.Configuration;
+import freemarker.template.ObjectWrapper;
+import freemarker.template.Template;
+import freemarker.template.TemplateHashModel;
+import freemarker.template.TemplateModel;
+import freemarker.template.TemplateModelException;
+
+/** A variety of methods to assist in Freemarker template processing,
+ * including passing in maps with keys flattened (dot-separated namespace),
+ * and accessing {@link ManagementContext} brooklyn.properties
+ * and {@link Entity}, {@link EntityDriver}, and {@link Location} methods and config.
+ * <p>
+ * See {@link #processTemplateContents(String, ManagementContextInternal, Map)} for
+ * a description of how management access is done.
+ */
+public class TemplateProcessor {
+
+ private static final Logger log = LoggerFactory.getLogger(TemplateProcessor.class);
+
+ protected static TemplateModel wrapAsTemplateModel(Object o) throws TemplateModelException {
+ if (o instanceof Map) return new DotSplittingTemplateModel((Map<?,?>)o);
+ return ObjectWrapper.DEFAULT_WRAPPER.wrap(o);
+ }
+
+ /** @deprecated since 0.7.0 use {@link #processTemplateFile(String, Map)} */ @Deprecated
+ public static String processTemplate(String templateFileName, Map<String, ? extends Object> substitutions) {
+ return processTemplateFile(templateFileName, substitutions);
+ }
+
+ /** As per {@link #processTemplateContents(String, Map)}, but taking a file. */
+ public static String processTemplateFile(String templateFileName, Map<String, ? extends Object> substitutions) {
+ String templateContents;
+ try {
+ templateContents = Files.toString(new File(templateFileName), Charsets.UTF_8);
+ } catch (IOException e) {
+ log.warn("Error loading file " + templateFileName, e);
+ throw Exceptions.propagate(e);
+ }
+ return processTemplateContents(templateContents, substitutions);
+ }
+
+ /** @deprecated since 0.7.0 use {@link #processTemplateFile(String, EntityDriver, Map)} */ @Deprecated
+ public static String processTemplate(String templateFileName, EntityDriver driver, Map<String, ? extends Object> extraSubstitutions) {
+ return processTemplateFile(templateFileName, driver, extraSubstitutions);
+ }
+
+ /** Processes template contents according to {@link EntityAndMapTemplateModel}. */
+ public static String processTemplateFile(String templateFileName, EntityDriver driver, Map<String, ? extends Object> extraSubstitutions) {
+ String templateContents;
+ try {
+ templateContents = Files.toString(new File(templateFileName), Charsets.UTF_8);
+ } catch (IOException e) {
+ log.warn("Error loading file " + templateFileName, e);
+ throw Exceptions.propagate(e);
+ }
+ return processTemplateContents(templateContents, driver, extraSubstitutions);
+ }
+
+ /** Processes template contents according to {@link EntityAndMapTemplateModel}. */
+ public static String processTemplateContents(String templateContents, EntityDriver driver, Map<String,? extends Object> extraSubstitutions) {
+ return processTemplateContents(templateContents, new EntityAndMapTemplateModel(driver, extraSubstitutions));
+ }
+
+ /** Processes template contents according to {@link EntityAndMapTemplateModel}. */
+ public static String processTemplateContents(String templateContents, ManagementContext managementContext, Map<String,? extends Object> extraSubstitutions) {
+ return processTemplateContents(templateContents, new EntityAndMapTemplateModel(managementContext, extraSubstitutions));
+ }
+
+ /**
+ * A Freemarker {@link TemplateHashModel} which will correctly handle entries of the form "a.b" in this map,
+ * matching against template requests for "${a.b}".
+ * <p>
+ * Freemarker requests "a" in a map when given such a request, and expects that to point to a map
+ * with a key "b". This model provides such maps even for "a.b" in a map.
+ * <p>
+ * However if "a" <b>and</b> "a.b" are in the map, this will <b>not</b> currently do the deep mapping.
+ * (It does not have enough contextual information from Freemarker to handle this case.) */
+ public static final class DotSplittingTemplateModel implements TemplateHashModel {
+ protected final Map<?,?> map;
+
+ protected DotSplittingTemplateModel(Map<?,?> map) {
+ this.map = map;
+ }
+
+ @Override
+ public boolean isEmpty() { return map!=null && map.isEmpty(); }
+
+ public boolean contains(String key) {
+ if (map==null) return false;
+ if (map.containsKey(key)) return true;
+ for (Map.Entry<?,?> entry: map.entrySet()) {
+ String k = Strings.toString(entry.getKey());
+ if (k.startsWith(key+".")) {
+ // contains this prefix
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public TemplateModel get(String key) throws TemplateModelException {
+ if (map==null) return null;
+ try {
+ if (map.containsKey(key))
+ return wrapAsTemplateModel( map.get(key) );
+
+ Map<String,Object> result = MutableMap.of();
+ for (Map.Entry<?,?> entry: map.entrySet()) {
+ String k = Strings.toString(entry.getKey());
+ if (k.startsWith(key+".")) {
+ String k2 = Strings.removeFromStart(k, key+".");
+ result.put(k2, entry.getValue());
+ }
+ }
+ if (!result.isEmpty())
+ return wrapAsTemplateModel( result );
+
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ throw new IllegalStateException("Error accessing config '"+key+"'"+": "+e, e);
+ }
+
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getName()+"["+map+"]";
+ }
+ }
+
+ /** FreeMarker {@link TemplateHashModel} which resolves keys inside the given entity or management context.
+ * Callers are required to include dots for dot-separated keys.
+ * Freemarker will only due this when in inside bracket notation in an outer map, as in <code>${outer['a.b.']}</code>;
+ * as a result this is intended only for use by {@link EntityAndMapTemplateModel} where
+ * a caller has used bracked notation, as in <code>${mgmt['key.subkey']}</code>. */
+ protected static final class EntityConfigTemplateModel implements TemplateHashModel {
+ protected final EntityInternal entity;
+ protected final ManagementContext mgmt;
+
+ protected EntityConfigTemplateModel(EntityInternal entity) {
+ this.entity = entity;
+ this.mgmt = entity.getManagementContext();
+ }
+
+ protected EntityConfigTemplateModel(ManagementContext mgmt) {
+ this.entity = null;
+ this.mgmt = mgmt;
+ }
+
+ @Override
+ public boolean isEmpty() { return false; }
+
+ @Override
+ public TemplateModel get(String key) throws TemplateModelException {
+ try {
+ Object result = null;
+
+ if (entity!=null)
+ result = entity.getConfig(ConfigKeys.builder(Object.class).name(key).build());
+ if (result==null && mgmt!=null)
+ result = mgmt.getConfig().getConfig(ConfigKeys.builder(Object.class).name(key).build());
+
+ if (result!=null)
+ return wrapAsTemplateModel( result );
+
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ throw new IllegalStateException("Error accessing config '"+key+"'"
+ + (entity!=null ? " on "+entity : "")+": "+e, e);
+ }
+
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getName()+"["+entity+"]";
+ }
+ }
+
+ protected final static class EntityAttributeTemplateModel implements TemplateHashModel {
+ protected final EntityInternal entity;
+
+ protected EntityAttributeTemplateModel(EntityInternal entity) {
+ this.entity = entity;
+ }
+
+ @Override
+ public boolean isEmpty() throws TemplateModelException {
+ return false;
+ }
+
+ @Override
+ public TemplateModel get(String key) throws TemplateModelException {
+ Object result;
+ try {
+ result = Entities.submit(entity, DependentConfiguration.attributeWhenReady(entity,
+ Sensors.builder(Object.class, key).persistence(AttributeSensor.SensorPersistenceMode.NONE).build())).get();
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
+ if (result == null) {
+ return null;
+ } else {
+ return wrapAsTemplateModel(result);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getName()+"["+entity+"]";
+ }
+ }
+
+ /**
+ * Provides access to config on an entity or management context, using
+ * <code>${config['entity.config.key']}</code> or <code>${mgmt['brooklyn.properties.key']}</code> notation,
+ * and also allowing access to <code>getX()</code> methods on entity (interface) or driver
+ * using <code>${entity.x}</code> or <code><${driver.x}</code>.
+ * Optional extra properties can be supplied, treated as per {@link DotSplittingTemplateModel}.
+ */
+ protected static final class EntityAndMapTemplateModel implements TemplateHashModel {
+ protected final EntityInternal entity;
+ protected final EntityDriver driver;
+ protected final ManagementContext mgmt;
+ protected final DotSplittingTemplateModel extraSubstitutionsModel;
+
+ protected EntityAndMapTemplateModel(ManagementContext mgmt, Map<String,? extends Object> extraSubstitutions) {
+ this.entity = null;
+ this.driver = null;
+ this.mgmt = mgmt;
+ this.extraSubstitutionsModel = new DotSplittingTemplateModel(extraSubstitutions);
+ }
+
+ protected EntityAndMapTemplateModel(EntityDriver driver, Map<String,? extends Object> extraSubstitutions) {
+ this.driver = driver;
+ this.entity = (EntityInternal) driver.getEntity();
+ this.mgmt = entity.getManagementContext();
+ this.extraSubstitutionsModel = new DotSplittingTemplateModel(extraSubstitutions);
+ }
+
+ protected EntityAndMapTemplateModel(EntityInternal entity, Map<String,? extends Object> extraSubstitutions) {
+ this.entity = entity;
+ this.driver = null;
+ this.mgmt = entity.getManagementContext();
+ this.extraSubstitutionsModel = new DotSplittingTemplateModel(extraSubstitutions);
+ }
+
+ @Override
+ public boolean isEmpty() { return false; }
+
+ @Override
+ public TemplateModel get(String key) throws TemplateModelException {
+ if (extraSubstitutionsModel.contains(key))
+ return wrapAsTemplateModel( extraSubstitutionsModel.get(key) );
+
+ if ("entity".equals(key) && entity!=null)
+ return wrapAsTemplateModel( entity );
+ if ("config".equals(key)) {
+ if (entity!=null)
+ return new EntityConfigTemplateModel(entity);
+ else
+ return new EntityConfigTemplateModel(mgmt);
+ }
+ if ("mgmt".equals(key)) {
+ return new EntityConfigTemplateModel(mgmt);
+ }
+
+ if ("driver".equals(key) && driver!=null)
+ return wrapAsTemplateModel( driver );
+ if ("location".equals(key)) {
+ if (driver!=null && driver.getLocation()!=null)
+ return wrapAsTemplateModel( driver.getLocation() );
+ if (entity!=null)
+ return wrapAsTemplateModel( Iterables.getOnlyElement( entity.getLocations() ) );
+ }
+ if ("attribute".equals(key)) {
+ return new EntityAttributeTemplateModel(entity);
+ }
+
+ if (mgmt!=null) {
+ // TODO deprecated in 0.7.0, remove after next version
+ // ie not supported to access global props without qualification
+ Object result = mgmt.getConfig().getConfig(ConfigKeys.builder(Object.class).name(key).build());
+ if (result!=null) {
+ log.warn("Deprecated access of global brooklyn.properties value for "+key+"; should be qualified with 'mgmt.'");
+ return wrapAsTemplateModel( result );
+ }
+ }
+
+ if ("javaSysProps".equals(key))
+ return wrapAsTemplateModel( System.getProperties() );
+
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getName()+"["+(entity!=null ? entity : mgmt)+"]";
+ }
+ }
+
+ /** Processes template contents with the given items in scope as per {@link EntityAndMapTemplateModel}. */
+ public static String processTemplateContents(String templateContents, final EntityInternal entity, Map<String,? extends Object> extraSubstitutions) {
+ return processTemplateContents(templateContents, new EntityAndMapTemplateModel(entity, extraSubstitutions));
+ }
+
+ /** Processes template contents using the given map, passed to freemarker,
+ * with dot handling as per {@link DotSplittingTemplateModel}. */
+ public static String processTemplateContents(String templateContents, final Map<String, ? extends Object> substitutions) {
+ TemplateHashModel root;
+ try {
+ root = substitutions != null
+ ? (TemplateHashModel)wrapAsTemplateModel(substitutions)
+ : null;
+ } catch (TemplateModelException e) {
+ throw new IllegalStateException("Unable to set up TemplateHashModel to parse template, given "+substitutions+": "+e, e);
+ }
+
+ return processTemplateContents(templateContents, root);
+ }
+
+ /** Processes template contents against the given {@link TemplateHashModel}. */
+ public static String processTemplateContents(String templateContents, final TemplateHashModel substitutions) {
+ try {
+ Configuration cfg = new Configuration();
+ StringTemplateLoader templateLoader = new StringTemplateLoader();
+ templateLoader.putTemplate("config", templateContents);
+ cfg.setTemplateLoader(templateLoader);
+ Template template = cfg.getTemplate("config");
+
+ // TODO could expose CAMP '$brooklyn:' style dsl, based on template.createProcessingEnvironment
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ Writer out = new OutputStreamWriter(baos);
+ template.process(substitutions, out);
+ out.flush();
+
+ return new String(baos.toByteArray());
+ } catch (Exception e) {
+ log.warn("Error processing template (propagating): "+e, e);
+ log.debug("Template which could not be parsed (causing "+e+") is:"
+ + (Strings.isMultiLine(templateContents) ? "\n"+templateContents : templateContents));
+ throw Exceptions.propagate(e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/xstream/CompilerIndependentOuterClassFieldMapper.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/xstream/CompilerIndependentOuterClassFieldMapper.java b/core/src/main/java/org/apache/brooklyn/core/util/xstream/CompilerIndependentOuterClassFieldMapper.java
new file mode 100644
index 0000000..68c7382
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/xstream/CompilerIndependentOuterClassFieldMapper.java
@@ -0,0 +1,166 @@
+/*
+ * 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.util.xstream;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.thoughtworks.xstream.core.Caching;
+import com.thoughtworks.xstream.mapper.Mapper;
+import com.thoughtworks.xstream.mapper.MapperWrapper;
+
+/**
+ * <p>Compiler independent outer class field mapper.</p>
+ * <p>Different compilers generate different indexes for the names of outer class reference
+ * field (this$N) leading to deserialization errors.</p>
+ * <ul>
+ * <li> eclipse-[groovy-]compiler counts all outer static classes
+ * <li> OpenJDK/Oracle/IBM compiler starts at 0, regardless of the nesting level
+ * </ul>
+ * <p>The mapper will be able to update field names for instances with a single this$N
+ * field only (including those from parent classes).</p>
+ * <p>For difference between generated field names compare
+ * {@code src/test/java/brooklyn/util/xstream/compiler_compatibility_eclipse.xml} and
+ * {@code src/test/java/brooklyn/util/xstream/compiler_compatibility_oracle.xml},
+ * generated from {@code org.apache.brooklyn.core.util.xstream.CompilerCompatibilityTest}</p>
+ * <p>JLS 1.1 relevant section, copied verbatim for a lack of reliable URL:</p>
+ * <blockquote>
+ * <p>Java 1.1 compilers are strongly encouraged, though not required, to use the
+ * following naming conventions when implementing inner classes. Compilers may
+ * not use synthetic names of the forms defined here for any other purposes.</p>
+ * <p>A synthetic field pointing to the outermost enclosing instance is named this$0.
+ * The next-outermost enclosing instance is this$1, and so forth. (At most one such
+ * field is necessary in any given inner class.) A synthetic field containing a copy
+ * of a constant v is named val$v. These fields are final.</p>
+ * </blockquote>
+ * <p>Currently available at
+ * http://web.archive.org/web/20000830111107/http://java.sun.com/products/jdk/1.1/docs/guide/innerclasses/spec/innerclasses.doc10.html</p>
+ */
+public class CompilerIndependentOuterClassFieldMapper extends MapperWrapper implements Caching {
+ public static final Logger LOG = LoggerFactory.getLogger(CompilerIndependentOuterClassFieldMapper.class);
+
+ private static final String OUTER_CLASS_FIELD_PREFIX = "this$";
+
+ private final Map<String, Collection<String>> classOuterFields = new ConcurrentHashMap<String, Collection<String>>();
+
+ public CompilerIndependentOuterClassFieldMapper(Mapper wrapped) {
+ super(wrapped);
+ classOuterFields.put(Object.class.getName(), Collections.<String>emptyList());
+ }
+
+ @Override
+ public String realMember(@SuppressWarnings("rawtypes") Class type, String serialized) {
+ // Let com.thoughtworks.xstream.mapper.OuterClassMapper also run on the input.
+ String serializedFieldName = super.realMember(type, serialized);
+
+ if (serializedFieldName.startsWith(OUTER_CLASS_FIELD_PREFIX)) {
+ Collection<String> compiledFieldNames = findOuterClassFieldNames(type);
+ if (compiledFieldNames.size() == 0) {
+ throw new IllegalStateException("Unable to find any outer class fields in " + type + ", searching specifically for " + serializedFieldName);
+ }
+
+ Set<String> uniqueFieldNames = new HashSet<String>(compiledFieldNames);
+ String deserializeFieldName;
+ if (!compiledFieldNames.contains(serializedFieldName)) {
+ String msg =
+ "Unable to find outer class field " + serializedFieldName + " in class " + type + ". " +
+ "This could be caused by " +
+ "1) changing the class (or one of its parents) to a static or " +
+ "2) moving the class to a different lexical level (enclosing classes) or " +
+ "3) using a different compiler (i.e eclipse vs oracle) at the time the object was serialized. ";
+ if (uniqueFieldNames.size() == 1) {
+ // Try to fix the field naming only for the case with a single field or
+ // multiple fields with the same name, in which case XStream puts defined-in
+ // for the field declared in super.
+ //
+ // We don't have access to the XML elements from here to check for same name
+ // so we check the target class instead. This should work most of the time, but
+ // if code is recompiled in such a way that the new instance has fields with
+ // different names, where only the field of the extending class is renamed and
+ // the super field is not, then the instance will be deserialized incorrectly -
+ // the super field will be assigned both times. If the field type is incompatible
+ // then a casting exception will be thrown, if it's the same then only the warning
+ // below will indicate of a possible problem down the line - most probably NPE on
+ // the this$N field.
+ deserializeFieldName = compiledFieldNames.iterator().next();
+ LOG.warn(msg + "Will use the field " + deserializeFieldName + " instead.");
+ } else {
+ // Multiple fields with differing names case - don't try to fix it.
+ // Better fail with an explicit error, and have someone fix it manually,
+ // than try to fix it here non-reliably and have it fail down the line
+ // with some unrelated error.
+ // XStream will fail later with a field not found exception.
+ LOG.error(msg + "Will fail with a field not found exception. " +
+ "Edit the persistence state manually and update the field names. "+
+ "Existing field names are " + uniqueFieldNames);
+ deserializeFieldName = serializedFieldName;
+ }
+ } else {
+ if (uniqueFieldNames.size() > 1) {
+ // Log at debug level as the actual problem would occur in very specific cases. Only
+ // useful when the compiler is changed, otherwise leads to false positives.
+ LOG.debug("Deserializing the non-static class " + type + " with multiple outer class fields " + uniqueFieldNames + ". " +
+ "When changing compilers it's possible that the instance won't be able to be deserialized due to changed outer class field names. " +
+ "In those cases deserialization could fail with field not found exception or class cast exception following this log line.");
+ }
+ deserializeFieldName = serializedFieldName;
+ }
+
+ return deserializeFieldName;
+ } else {
+ return serializedFieldName;
+ }
+ }
+
+ private Collection<String> findOuterClassFieldNames(Class<?> type) {
+ Collection<String> fields = classOuterFields.get(type.getName());
+ if (fields == null) {
+ fields = new ArrayList<String>();
+ addOuterClassFields(type, fields);
+ classOuterFields.put(type.getName(), fields);
+ }
+ return fields;
+ }
+
+ private void addOuterClassFields(Class<?> type, Collection<String> fields) {
+ for (Field field : type.getDeclaredFields()) {
+ if (field.isSynthetic()) {
+ fields.add(field.getName());
+ }
+ }
+ if (type.getSuperclass() != null) {
+ addOuterClassFields(type.getSuperclass(), fields);
+ }
+ }
+
+ @Override
+ public void flushCache() {
+ classOuterFields.keySet().retainAll(Collections.singletonList(Object.class.getName()));
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/xstream/EnumCaseForgivingConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/xstream/EnumCaseForgivingConverter.java b/core/src/main/java/org/apache/brooklyn/core/util/xstream/EnumCaseForgivingConverter.java
new file mode 100644
index 0000000..7d95568
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/xstream/EnumCaseForgivingConverter.java
@@ -0,0 +1,60 @@
+/*
+ * 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.util.xstream;
+
+import brooklyn.util.exceptions.Exceptions;
+
+import com.thoughtworks.xstream.converters.UnmarshallingContext;
+import com.thoughtworks.xstream.converters.enums.EnumConverter;
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+
+/** ... except this doesn't seem to get applied when we think it should
+ * (normal xstream.resgisterConverter doesn't apply to enums) */
+public class EnumCaseForgivingConverter extends EnumConverter {
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
+ Class type = context.getRequiredType();
+ if (type.getSuperclass() != Enum.class) {
+ type = type.getSuperclass(); // polymorphic enums
+ }
+ String token = reader.getValue();
+ // this is the new bit (overriding superclass to accept case-insensitive)
+ return resolve(type, token);
+ }
+
+ public static <T extends Enum<T>> T resolve(Class<T> type, String token) {
+ try {
+ return Enum.valueOf(type, token.toUpperCase());
+ } catch (Exception e) {
+
+ // new stuff here: try reading case insensitive
+
+ Exceptions.propagateIfFatal(e);
+ try {
+ for (T v: type.getEnumConstants())
+ if (v.name().equalsIgnoreCase(token)) return v;
+ throw e;
+ } catch (Exception e2) {
+ throw Exceptions.propagate(e2);
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/xstream/EnumCaseForgivingSingleValueConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/xstream/EnumCaseForgivingSingleValueConverter.java b/core/src/main/java/org/apache/brooklyn/core/util/xstream/EnumCaseForgivingSingleValueConverter.java
new file mode 100644
index 0000000..4bc507c
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/xstream/EnumCaseForgivingSingleValueConverter.java
@@ -0,0 +1,35 @@
+/*
+ * 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.util.xstream;
+
+import com.thoughtworks.xstream.converters.enums.EnumSingleValueConverter;
+
+public class EnumCaseForgivingSingleValueConverter extends EnumSingleValueConverter {
+
+ private final Class enumType;
+
+ public EnumCaseForgivingSingleValueConverter(Class type) {
+ super(type);
+ enumType = type;
+ }
+
+ public Object fromString(String str) {
+ return EnumCaseForgivingConverter.resolve(enumType, str);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/xstream/ImmutableListConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/xstream/ImmutableListConverter.java b/core/src/main/java/org/apache/brooklyn/core/util/xstream/ImmutableListConverter.java
new file mode 100644
index 0000000..a59cfa8
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/xstream/ImmutableListConverter.java
@@ -0,0 +1,54 @@
+/*
+ * 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.util.xstream;
+
+import java.util.Collection;
+
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.thoughtworks.xstream.converters.UnmarshallingContext;
+import com.thoughtworks.xstream.converters.collections.CollectionConverter;
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+import com.thoughtworks.xstream.mapper.Mapper;
+
+public class ImmutableListConverter extends CollectionConverter {
+
+ public ImmutableListConverter(Mapper mapper) {
+ super(mapper);
+ }
+
+ @Override
+ public boolean canConvert(@SuppressWarnings("rawtypes") Class type) {
+ return ImmutableList.class.isAssignableFrom(type);
+ }
+
+ // marshalling is the same
+ // so is unmarshalling the entries
+
+ // only differences are creating the overarching collection, which we do after the fact
+ // (optimizing format on disk as opposed to in-memory), and we discard null values
+ // to avoid failing entirely.
+ public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
+ Collection<?> collection = Lists.newArrayList();
+ populateCollection(reader, context, collection);
+ return ImmutableList.copyOf(Iterables.filter(collection, Predicates.notNull()));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/xstream/ImmutableMapConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/xstream/ImmutableMapConverter.java b/core/src/main/java/org/apache/brooklyn/core/util/xstream/ImmutableMapConverter.java
new file mode 100644
index 0000000..00e44dd
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/xstream/ImmutableMapConverter.java
@@ -0,0 +1,56 @@
+/*
+ * 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.util.xstream;
+
+import java.util.Map;
+import java.util.Map.Entry;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import com.thoughtworks.xstream.converters.UnmarshallingContext;
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+import com.thoughtworks.xstream.mapper.Mapper;
+
+public class ImmutableMapConverter extends MapConverter {
+
+ public ImmutableMapConverter(Mapper mapper) {
+ super(mapper);
+ }
+
+ @Override
+ public boolean canConvert(@SuppressWarnings("rawtypes") Class type) {
+ return ImmutableMap.class.isAssignableFrom(type);
+ }
+
+ // marshalling is the same
+ // so is unmarshalling the entries
+
+ // only differences are creating the overarching collection, which we do after the fact
+ // (optimizing format on disk as opposed to in-memory), and we discard null key/values
+ // to avoid failing entirely.
+ public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
+ Map<?, ?> map = Maps.newLinkedHashMap();
+ populateMap(reader, context, map);
+ return ImmutableMap.copyOf(Maps.filterEntries(map, new Predicate<Map.Entry<?,?>>() {
+ @Override public boolean apply(Entry<?, ?> input) {
+ return input != null && input.getKey() != null && input.getValue() != null;
+ }}));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/xstream/ImmutableSetConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/xstream/ImmutableSetConverter.java b/core/src/main/java/org/apache/brooklyn/core/util/xstream/ImmutableSetConverter.java
new file mode 100644
index 0000000..76975ff
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/xstream/ImmutableSetConverter.java
@@ -0,0 +1,54 @@
+/*
+ * 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.util.xstream;
+
+import java.util.Collection;
+
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.thoughtworks.xstream.converters.UnmarshallingContext;
+import com.thoughtworks.xstream.converters.collections.CollectionConverter;
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+import com.thoughtworks.xstream.mapper.Mapper;
+
+public class ImmutableSetConverter extends CollectionConverter {
+
+ public ImmutableSetConverter(Mapper mapper) {
+ super(mapper);
+ }
+
+ @Override
+ public boolean canConvert(@SuppressWarnings("rawtypes") Class type) {
+ return ImmutableSet.class.isAssignableFrom(type);
+ }
+
+ // marshalling is the same
+ // so is unmarshalling the entries
+
+ // only differences are creating the overarching collection, which we do after the fact
+ // (optimizing format on disk as opposed to in-memory), and we discard null values
+ // to avoid failing entirely.
+ public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
+ Collection<?> collection = Lists.newArrayList();
+ populateCollection(reader, context, collection);
+ return ImmutableSet.copyOf(Iterables.filter(collection, Predicates.notNull()));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/xstream/Inet4AddressConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/xstream/Inet4AddressConverter.java b/core/src/main/java/org/apache/brooklyn/core/util/xstream/Inet4AddressConverter.java
new file mode 100644
index 0000000..53133c1
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/xstream/Inet4AddressConverter.java
@@ -0,0 +1,65 @@
+/*
+ * 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.util.xstream;
+
+import java.net.Inet4Address;
+import java.net.UnknownHostException;
+
+import brooklyn.util.exceptions.Exceptions;
+
+import com.thoughtworks.xstream.converters.Converter;
+import com.thoughtworks.xstream.converters.MarshallingContext;
+import com.thoughtworks.xstream.converters.UnmarshallingContext;
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+
+public class Inet4AddressConverter implements Converter {
+
+ @Override
+ public boolean canConvert(@SuppressWarnings("rawtypes") Class type) {
+ return type.equals(Inet4Address.class);
+ }
+
+ @Override
+ public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
+ Inet4Address addr = (Inet4Address) source;
+ writer.setValue(addr.getHostName()+"/"+addr.getHostAddress());
+ }
+
+ @Override
+ public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
+ String hostSlashAddress = reader.getValue();
+ int i = hostSlashAddress.indexOf('/');
+ try {
+ if (i==-1) {
+ return Inet4Address.getByName(hostSlashAddress);
+ } else {
+ String host = hostSlashAddress.substring(0, i);
+ String addrS = hostSlashAddress.substring(i+1);
+ byte[] addr = new byte[4];
+ String[] addrSI = addrS.split("\\.");
+ for (int k=0; k<4; k++) addr[k] = (byte)(int)Integer.valueOf(addrSI[k]);
+ return Inet4Address.getByAddress(host, addr);
+ }
+ } catch (UnknownHostException e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/xstream/MapConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/xstream/MapConverter.java b/core/src/main/java/org/apache/brooklyn/core/util/xstream/MapConverter.java
new file mode 100644
index 0000000..752ef70
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/xstream/MapConverter.java
@@ -0,0 +1,104 @@
+/*
+ * 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.util.xstream;
+
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.thoughtworks.xstream.converters.MarshallingContext;
+import com.thoughtworks.xstream.converters.UnmarshallingContext;
+import com.thoughtworks.xstream.core.ReferencingMarshallingContext;
+import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+import com.thoughtworks.xstream.mapper.Mapper;
+
+/** equivalent to super, but cleaner methods, overridable, logging, and some retries */
+public class MapConverter extends com.thoughtworks.xstream.converters.collections.MapConverter {
+
+ private static final Logger log = LoggerFactory.getLogger(MapConverter.class);
+
+ public MapConverter(Mapper mapper) {
+ super(mapper);
+ }
+
+ @SuppressWarnings({ "rawtypes" })
+ public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
+ Map map = (Map) source;
+ try {
+ for (Iterator iterator = map.entrySet().iterator(); iterator.hasNext();) {
+ Map.Entry entry = (Map.Entry) iterator.next();
+ marshalEntry(writer, context, entry);
+ }
+ } catch (ConcurrentModificationException e) {
+ log.debug("Map "
+ // seems there is no non-deprecated way to get the path...
+ + (context instanceof ReferencingMarshallingContext ? "at "+((ReferencingMarshallingContext)context).currentPath() : "")
+ + "["+source+"] modified while serializing; will fail, and retry may be attempted");
+ throw e;
+ // would be nice to attempt to re-serialize being slightly more defensive, as code below;
+ // but the code above may have written partial data so that is dangerous, we could have corrupted output.
+ // if we could mark and restore in the output stream then we could do this below (but we don't have that in our stream),
+ // or we could try this copying code in the first instance (but that's slow);
+ // error is rare most of the time (e.g. attribute being updated) so we bail on this whole attempt
+ // and simply try serializing the map-owner (e.g. an entity) again.
+// ImmutableList entries = ImmutableList.copyOf(map.entrySet());
+// for (Iterator iterator = entries.iterator(); iterator.hasNext();) {
+// Map.Entry entry = (Map.Entry) iterator.next();
+// marshalEntry(writer, context, entry);
+// }
+ }
+ }
+
+ protected String getEntryNodeName() { return mapper().serializedClass(Map.Entry.class); }
+
+ protected void marshalEntry(HierarchicalStreamWriter writer, MarshallingContext context, Map.Entry entry) {
+ ExtendedHierarchicalStreamWriterHelper.startNode(writer, getEntryNodeName(), Map.Entry.class);
+
+ writeItem(entry.getKey(), context, writer);
+ writeItem(entry.getValue(), context, writer);
+
+ writer.endNode();
+ }
+
+ protected void populateMap(HierarchicalStreamReader reader, UnmarshallingContext context, Map map) {
+ while (reader.hasMoreChildren()) {
+ reader.moveDown();
+ unmarshalEntry(reader, context, map);
+ reader.moveUp();
+ }
+ }
+
+ protected void unmarshalEntry(HierarchicalStreamReader reader, UnmarshallingContext context, Map map) {
+ reader.moveDown();
+ Object key = readItem(reader, context, map);
+ reader.moveUp();
+
+ reader.moveDown();
+ Object value = readItem(reader, context, map);
+ reader.moveUp();
+
+ map.put(key, value);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/xstream/MutableSetConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/xstream/MutableSetConverter.java b/core/src/main/java/org/apache/brooklyn/core/util/xstream/MutableSetConverter.java
new file mode 100644
index 0000000..4b7bcbc
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/xstream/MutableSetConverter.java
@@ -0,0 +1,44 @@
+/*
+ * 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.util.xstream;
+
+import brooklyn.util.collections.MutableSet;
+
+import com.thoughtworks.xstream.converters.collections.CollectionConverter;
+import com.thoughtworks.xstream.mapper.Mapper;
+
+public class MutableSetConverter extends CollectionConverter {
+
+ // Although this class seems pointless (!), without registering an explicit converter for MutableSet then the
+ // declaration for Set interferes, causing MutableSet.map field to be null on deserialization.
+
+ public MutableSetConverter(Mapper mapper) {
+ super(mapper);
+ }
+
+ @Override
+ public boolean canConvert(@SuppressWarnings("rawtypes") Class type) {
+ return MutableSet.class.isAssignableFrom(type);
+ }
+
+ @Override
+ protected Object createCollection(Class type) {
+ return new MutableSet<Object>();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/xstream/StringKeyMapConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/xstream/StringKeyMapConverter.java b/core/src/main/java/org/apache/brooklyn/core/util/xstream/StringKeyMapConverter.java
new file mode 100644
index 0000000..86a4cd0
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/xstream/StringKeyMapConverter.java
@@ -0,0 +1,134 @@
+/*
+ * 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.util.xstream;
+
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.text.Identifiers;
+
+import com.thoughtworks.xstream.converters.MarshallingContext;
+import com.thoughtworks.xstream.converters.UnmarshallingContext;
+import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+import com.thoughtworks.xstream.mapper.Mapper;
+
+/** converter which simplifies representation of a map for string-based keys,
+ * to <key>value</key>, or <entry key="key" type="string">value</entry>
+ * @author alex
+ *
+ */
+public class StringKeyMapConverter extends MapConverter {
+
+ private static final Logger log = LoggerFactory.getLogger(StringKeyMapConverter.class);
+
+ // full stop is technically allowed ... goes against "best practice" ...
+ // but simplifies property maps, and is used elsewhere in xstream's repn
+ final static String VALID_XML_NODE_NAME_CHARS = Identifiers.JAVA_GOOD_NONSTART_CHARS + ".";
+
+ final static String VALID_XML_NODE_NAME_START_CHARS = Identifiers.JAVA_GOOD_START_CHARS + ".";
+
+ public StringKeyMapConverter(Mapper mapper) {
+ super(mapper);
+ }
+
+ protected boolean isKeyValidForNodeName(String key) {
+ // return false to always write as <entry key="key" ...; otherwise only use that when key is not valid xml
+ return Identifiers.isValidToken(key, VALID_XML_NODE_NAME_START_CHARS, VALID_XML_NODE_NAME_CHARS);
+ }
+
+ public boolean canConvert(Class type) {
+ return super.canConvert(type) || type.getName().equals(MutableMap.class.getName());
+ }
+
+ @Override
+ protected void marshalEntry(HierarchicalStreamWriter writer, MarshallingContext context, Entry entry) {
+ if (entry.getKey() instanceof String) {
+ marshalStringKey(writer, context, entry);
+ } else {
+ super.marshalEntry(writer, context, entry);
+ }
+ }
+
+ protected void marshalStringKey(HierarchicalStreamWriter writer, MarshallingContext context, Entry entry) {
+ String key = (String)entry.getKey();
+ String entryNodeName = getEntryNodeName();
+ boolean useKeyAsNodeName = (!key.equals(entryNodeName) && isKeyValidForNodeName(key));
+ if (useKeyAsNodeName) entryNodeName = key;
+ ExtendedHierarchicalStreamWriterHelper.startNode(writer, entryNodeName, Map.Entry.class);
+ if (!useKeyAsNodeName)
+ writer.addAttribute("key", key);
+
+ Object value = entry.getValue();
+ if (entry.getValue()!=null && isInlineableType(value.getClass())) {
+ if (!(value instanceof String))
+ writer.addAttribute("type", mapper().serializedClass(entry.getValue().getClass()));
+ if (entry.getValue().getClass().isEnum())
+ writer.setValue(((Enum)entry.getValue()).name());
+ else
+ writer.setValue(""+entry.getValue());
+ } else {
+ writeItem(entry.getValue(), context, writer);
+ }
+
+ writer.endNode();
+ }
+
+ protected boolean isInlineableType(Class<?> type) {
+ return TypeCoercions.isPrimitiveOrBoxer(type) || String.class.equals(type) || type.isEnum();
+ }
+
+ @Override
+ protected void unmarshalEntry(HierarchicalStreamReader reader, UnmarshallingContext context, Map map) {
+ String key = reader.getNodeName();
+ if (key.equals(getEntryNodeName())) key = reader.getAttribute("key");
+ if (key==null) {
+ super.unmarshalEntry(reader, context, map);
+ } else {
+ unmarshalStringKey(reader, context, map, key);
+ }
+ }
+
+ protected void unmarshalStringKey(HierarchicalStreamReader reader, UnmarshallingContext context, Map map, String key) {
+ String type = reader.getAttribute("type");
+ Object value;
+ if (type==null && reader.hasMoreChildren()) {
+ reader.moveDown();
+ value = readItem(reader, context, map);
+ reader.moveUp();
+ } else {
+ Class typeC = type!=null ? mapper().realClass(type) : String.class;
+ try {
+ value = TypeCoercions.coerce(reader.getValue(), typeC);
+ } catch (Exception e) {
+ log.warn("FAILED to coerce "+reader.getValue()+" to "+typeC+": "+e);
+ throw Exceptions.propagate(e);
+ }
+ }
+ map.put(key, value);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/xstream/XmlSerializer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/xstream/XmlSerializer.java b/core/src/main/java/org/apache/brooklyn/core/util/xstream/XmlSerializer.java
new file mode 100644
index 0000000..3b3b582
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/xstream/XmlSerializer.java
@@ -0,0 +1,97 @@
+/*
+ * 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.util.xstream;
+
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.collections.MutableSet;
+
+import com.google.common.collect.ImmutableList;
+import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.mapper.MapperWrapper;
+
+public class XmlSerializer<T> {
+
+ protected final XStream xstream;
+
+ public XmlSerializer() {
+ xstream = new XStream() {
+ @Override
+ protected MapperWrapper wrapMapper(MapperWrapper next) {
+ MapperWrapper result = super.wrapMapper(next);
+ return XmlSerializer.this.wrapMapper(result);
+ }
+ };
+
+ // list as array list is default
+ xstream.alias("map", Map.class, LinkedHashMap.class);
+ xstream.alias("set", Set.class, LinkedHashSet.class);
+
+ xstream.registerConverter(new StringKeyMapConverter(xstream.getMapper()), /* priority */ 10);
+ xstream.alias("MutableMap", MutableMap.class);
+ xstream.alias("MutableSet", MutableSet.class);
+ xstream.alias("MutableList", MutableList.class);
+
+ // Needs an explicit MutableSet converter!
+ // Without it, the alias for "set" seems to interfere with the MutableSet.map field, so it gets
+ // a null field on deserialization.
+ xstream.registerConverter(new MutableSetConverter(xstream.getMapper()));
+
+ xstream.aliasType("ImmutableList", ImmutableList.class);
+ xstream.registerConverter(new ImmutableListConverter(xstream.getMapper()));
+ xstream.registerConverter(new ImmutableSetConverter(xstream.getMapper()));
+ xstream.registerConverter(new ImmutableMapConverter(xstream.getMapper()));
+
+ xstream.registerConverter(new EnumCaseForgivingConverter());
+ xstream.registerConverter(new Inet4AddressConverter());
+ }
+
+ protected MapperWrapper wrapMapper(MapperWrapper next) {
+ return new CompilerIndependentOuterClassFieldMapper(next);
+ }
+
+ public void serialize(Object object, Writer writer) {
+ xstream.toXML(object, writer);
+ }
+
+ @SuppressWarnings("unchecked")
+ public T deserialize(Reader xml) {
+ return (T) xstream.fromXML(xml);
+ }
+
+ public String toString(T memento) {
+ Writer writer = new StringWriter();
+ serialize(memento, writer);
+ return writer.toString();
+ }
+
+ public T fromString(String xml) {
+ return deserialize(new StringReader(xml));
+ }
+
+}
[22/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/ForwardingTask.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/ForwardingTask.java b/core/src/main/java/org/apache/brooklyn/core/util/task/ForwardingTask.java
new file mode 100644
index 0000000..794dea9
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/ForwardingTask.java
@@ -0,0 +1,325 @@
+/*
+ * 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.util.task;
+
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.brooklyn.api.management.Task;
+
+import brooklyn.util.time.Duration;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ForwardingObject;
+import com.google.common.util.concurrent.ExecutionList;
+import com.google.common.util.concurrent.ListenableFuture;
+
+public abstract class ForwardingTask<T> extends ForwardingObject implements TaskInternal<T> {
+
+ /** Constructor for use by subclasses. */
+ protected ForwardingTask() {}
+
+ @Override
+ protected abstract TaskInternal<T> delegate();
+
+ @Override
+ public void addListener(Runnable listener, Executor executor) {
+ delegate().addListener(listener, executor);
+ }
+
+ @Override
+ public boolean cancel(boolean arg0) {
+ return delegate().cancel(arg0);
+ }
+
+ @Override
+ public T get() throws InterruptedException, ExecutionException {
+ return delegate().get();
+ }
+
+ @Override
+ public T get(long arg0, TimeUnit arg1) throws InterruptedException, ExecutionException, TimeoutException {
+ return delegate().get(arg0, arg1);
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return delegate().isCancelled();
+ }
+
+ @Override
+ public boolean isDone() {
+ return delegate().isDone();
+ }
+
+ @Override
+ public Task<T> asTask() {
+ return delegate().asTask();
+ }
+
+ @Override
+ public String getId() {
+ return delegate().getId();
+ }
+
+ @Override
+ public Set<Object> getTags() {
+ return delegate().getTags();
+ }
+
+ @Override
+ public long getSubmitTimeUtc() {
+ return delegate().getSubmitTimeUtc();
+ }
+
+ @Override
+ public long getStartTimeUtc() {
+ return delegate().getStartTimeUtc();
+ }
+
+ @Override
+ public long getEndTimeUtc() {
+ return delegate().getEndTimeUtc();
+ }
+
+ @Override
+ public String getDisplayName() {
+ return delegate().getDisplayName();
+ }
+
+ @Override
+ public String getDescription() {
+ return delegate().getDescription();
+ }
+
+ @Override
+ public Task<?> getSubmittedByTask() {
+ return delegate().getSubmittedByTask();
+ }
+
+ @Override
+ public Thread getThread() {
+ return delegate().getThread();
+ }
+
+ @Override
+ public boolean isSubmitted() {
+ return delegate().isSubmitted();
+ }
+
+ @Override
+ public boolean isBegun() {
+ return delegate().isBegun();
+ }
+
+ @Override
+ public boolean isError() {
+ return delegate().isError();
+ }
+
+ @Override
+ public void blockUntilStarted() {
+ delegate().blockUntilStarted();
+ }
+
+ @Override
+ public void blockUntilEnded() {
+ delegate().blockUntilEnded();
+ }
+
+ @Override
+ public boolean blockUntilEnded(Duration timeout) {
+ return delegate().blockUntilEnded(timeout);
+ }
+
+ @Override
+ public String getStatusSummary() {
+ return delegate().getStatusSummary();
+ }
+
+ @Override
+ public String getStatusDetail(boolean multiline) {
+ return delegate().getStatusDetail(multiline);
+ }
+
+ @Override
+ public T get(Duration duration) throws InterruptedException, ExecutionException, TimeoutException {
+ return delegate().get(duration);
+ }
+
+ @Override
+ public T getUnchecked() {
+ return delegate().getUnchecked();
+ }
+
+ @Override
+ public T getUnchecked(Duration duration) {
+ return delegate().getUnchecked(duration);
+ }
+
+ @Override
+ public void initInternalFuture(ListenableFuture<T> result) {
+ delegate().initInternalFuture(result);
+ }
+
+ @Override
+ public long getQueuedTimeUtc() {
+ return delegate().getQueuedTimeUtc();
+ }
+
+ @Override
+ public Future<T> getInternalFuture() {
+ return delegate().getInternalFuture();
+ }
+
+ @Override
+ public boolean isQueued() {
+ return delegate().isQueued();
+ }
+
+ @Override
+ public boolean isQueuedOrSubmitted() {
+ return delegate().isQueuedOrSubmitted();
+ }
+
+ @Override
+ public boolean isQueuedAndNotSubmitted() {
+ return delegate().isQueuedAndNotSubmitted();
+ }
+
+ @Override
+ public void markQueued() {
+ delegate().markQueued();
+ }
+
+ @Override
+ public boolean cancel() {
+ return delegate().cancel();
+ }
+
+ @Override
+ public boolean blockUntilStarted(Duration timeout) {
+ return delegate().blockUntilStarted(timeout);
+ }
+
+ @Override
+ public String setBlockingDetails(String blockingDetails) {
+ return delegate().setBlockingDetails(blockingDetails);
+ }
+
+ @Override
+ public Task<?> setBlockingTask(Task<?> blockingTask) {
+ return delegate().setBlockingTask(blockingTask);
+ }
+
+ @Override
+ public void resetBlockingDetails() {
+ delegate().resetBlockingDetails();
+ }
+
+ @Override
+ public void resetBlockingTask() {
+ delegate().resetBlockingTask();
+ }
+
+ @Override
+ public String getBlockingDetails() {
+ return delegate().getBlockingDetails();
+ }
+
+ @Override
+ public Task<?> getBlockingTask() {
+ return delegate().getBlockingTask();
+ }
+
+ @Override
+ public void setExtraStatusText(Object extraStatus) {
+ delegate().setExtraStatusText(extraStatus);
+ }
+
+ @Override
+ public Object getExtraStatusText() {
+ return delegate().getExtraStatusText();
+ }
+
+ @Override
+ public void runListeners() {
+ delegate().runListeners();
+ }
+
+ @Override
+ public void setEndTimeUtc(long val) {
+ delegate().setEndTimeUtc(val);
+ }
+
+ @Override
+ public void setThread(Thread thread) {
+ delegate().setThread(thread);
+ }
+
+ @Override
+ public Callable<T> getJob() {
+ return delegate().getJob();
+ }
+
+ @Override
+ public void setJob(Callable<T> job) {
+ delegate().setJob(job);
+ }
+
+ @Override
+ public ExecutionList getListeners() {
+ return delegate().getListeners();
+ }
+
+ @Override
+ public void setSubmitTimeUtc(long currentTimeMillis) {
+ delegate().setSubmitTimeUtc(currentTimeMillis);
+ }
+
+ @Override
+ public void setSubmittedByTask(Task<?> task) {
+ delegate().setSubmittedByTask(task);
+ }
+
+ @Override
+ public Set<Object> getMutableTags() {
+ return delegate().getMutableTags();
+ }
+
+ @Override
+ public void setStartTimeUtc(long currentTimeMillis) {
+ delegate().setStartTimeUtc(currentTimeMillis);
+ }
+
+ @Override
+ public void applyTagModifier(Function<Set<Object>, Void> modifier) {
+ delegate().applyTagModifier(modifier);
+ }
+
+ @Override
+ public Task<?> getProxyTarget() {
+ return delegate().getProxyTarget();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/ListenableForwardingFuture.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/ListenableForwardingFuture.java b/core/src/main/java/org/apache/brooklyn/core/util/task/ListenableForwardingFuture.java
new file mode 100644
index 0000000..bfe88b0
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/ListenableForwardingFuture.java
@@ -0,0 +1,50 @@
+/*
+ * 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.util.task;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Future;
+
+import com.google.common.util.concurrent.ExecutionList;
+import com.google.common.util.concurrent.ForwardingFuture.SimpleForwardingFuture;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/** Wraps a Future, making it a ListenableForwardingFuture, but with the caller having the resposibility to:
+ * <li> invoke the listeners on job completion (success or error)
+ * <li> invoke the listeners on cancel */
+public abstract class ListenableForwardingFuture<T> extends SimpleForwardingFuture<T> implements ListenableFuture<T> {
+
+ final ExecutionList listeners;
+
+ protected ListenableForwardingFuture(Future<T> delegate) {
+ super(delegate);
+ this.listeners = new ExecutionList();
+ }
+
+ protected ListenableForwardingFuture(Future<T> delegate, ExecutionList list) {
+ super(delegate);
+ this.listeners = list;
+ }
+
+ @Override
+ public void addListener(Runnable listener, Executor executor) {
+ listeners.add(listener, executor);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/ParallelTask.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/ParallelTask.java b/core/src/main/java/org/apache/brooklyn/core/util/task/ParallelTask.java
new file mode 100644
index 0000000..10da414
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/ParallelTask.java
@@ -0,0 +1,85 @@
+/*
+ * 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.util.task;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+
+import org.apache.brooklyn.api.management.Task;
+
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.text.Strings;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
+/**
+ * Runs {@link Task}s in parallel.
+ *
+ * No guarantees of order of starting the tasks, but the return value is a
+ * {@link List} of the return values of supplied tasks in the same
+ * order they were passed as arguments.
+ */
+public class ParallelTask<T> extends CompoundTask<T> {
+ public ParallelTask(Object... tasks) { super(tasks); }
+
+ public ParallelTask(Map<String,?> flags, Collection<? extends Object> tasks) { super(flags, tasks); }
+ public ParallelTask(Collection<? extends Object> tasks) { super(tasks); }
+
+ public ParallelTask(Map<String,?> flags, Iterable<? extends Object> tasks) { super(flags, ImmutableList.copyOf(tasks)); }
+ public ParallelTask(Iterable<? extends Object> tasks) { super(ImmutableList.copyOf(tasks)); }
+
+ @Override
+ protected List<T> runJobs() throws InterruptedException, ExecutionException {
+ setBlockingDetails("Executing "+
+ (children.size()==1 ? "1 child task" :
+ children.size()+" children tasks in parallel") );
+ for (Task<? extends T> task : children) {
+ submitIfNecessary(task);
+ }
+
+ List<T> result = Lists.newArrayList();
+ List<Exception> exceptions = Lists.newArrayList();
+ for (Task<? extends T> task : children) {
+ T x;
+ try {
+ x = task.get();
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ if (TaskTags.isInessential(task)) {
+ // ignore exception as it's inessential
+ } else {
+ exceptions.add(e);
+ }
+ x = null;
+ }
+ result.add(x);
+ }
+
+ if (exceptions.isEmpty()) {
+ return result;
+ } else {
+ if (result.size()==1 && exceptions.size()==1)
+ throw Exceptions.propagate( exceptions.get(0) );
+ throw Exceptions.propagate(exceptions.size()+" of "+result.size()+" parallel child task"+Strings.s(result.size())+" failed", exceptions);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/ScheduledTask.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/ScheduledTask.java b/core/src/main/java/org/apache/brooklyn/core/util/task/ScheduledTask.java
new file mode 100644
index 0000000..5c4b208
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/ScheduledTask.java
@@ -0,0 +1,185 @@
+/*
+ * 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.util.task;
+
+import static brooklyn.util.GroovyJavaMethods.elvis;
+import static brooklyn.util.GroovyJavaMethods.truth;
+
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.brooklyn.api.management.Task;
+
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.time.Duration;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Throwables;
+
+/**
+ * A task which runs with a fixed period.
+ * <p>
+ * Note that some termination logic, including {@link #addListener(Runnable, java.util.concurrent.Executor)},
+ * is not precisely defined.
+ */
+// TODO ScheduledTask is a very pragmatic implementation; would be nice to tighten,
+// reduce external assumptions about internal structure, and clarify "done" semantics
+public class ScheduledTask extends BasicTask {
+
+ final Callable<Task<?>> taskFactory;
+ /** initial delay before running, set as flag in constructor; defaults to 0 */
+ protected Duration delay;
+ /** time to wait between executions, or null if not to repeat (default), set as flag to constructor;
+ * this may be modified for subsequent submissions by a running task generated by the factory
+ * using getSubmittedByTask().setPeriod(Duration) */
+ protected Duration period = null;
+ /** optional, set as flag in constructor; defaults to null meaning no limit */
+ protected Integer maxIterations = null;
+
+ protected int runCount=0;
+ protected Task<?> recentRun, nextRun;
+
+ public int getRunCount() { return runCount; }
+ public ScheduledFuture<?> getNextScheduled() { return (ScheduledFuture<?>)internalFuture; }
+
+ public ScheduledTask(Callable<Task<?>> taskFactory) {
+ this(MutableMap.of(), taskFactory);
+ }
+
+ public ScheduledTask(final Task<?> task) {
+ this(MutableMap.of(), task);
+ }
+
+ public ScheduledTask(Map flags, final Task<?> task){
+ this(flags, new Callable<Task<?>>(){
+ @Override
+ public Task<?> call() throws Exception {
+ return task;
+ }});
+ }
+
+ public ScheduledTask(Map flags, Callable<Task<?>> taskFactory) {
+ super(flags);
+ this.taskFactory = taskFactory;
+
+ delay = Duration.of(elvis(flags.remove("delay"), 0));
+ period = Duration.of(elvis(flags.remove("period"), null));
+ maxIterations = elvis(flags.remove("maxIterations"), null);
+ }
+
+ public ScheduledTask delay(Duration d) {
+ this.delay = d;
+ return this;
+ }
+ public ScheduledTask delay(long val) {
+ return delay(Duration.millis(val));
+ }
+
+ public ScheduledTask period(Duration d) {
+ this.period = d;
+ return this;
+ }
+ public ScheduledTask period(long val) {
+ return period(Duration.millis(val));
+ }
+
+ public ScheduledTask maxIterations(int val) {
+ this.maxIterations = val;
+ return this;
+ }
+
+ public Callable<Task<?>> getTaskFactory() {
+ return taskFactory;
+ }
+
+ public Task<?> newTask() {
+ try {
+ return taskFactory.call();
+ } catch (Exception e) {
+ throw Throwables.propagate(e);
+ }
+ }
+
+ protected String getActiveTaskStatusString(int verbosity) {
+ StringBuilder rv = new StringBuilder("Scheduler");
+ if (runCount>0) rv.append(", iteration "+(runCount+1));
+ if (recentRun!=null) rv.append(", last run "+
+ Duration.sinceUtc(recentRun.getStartTimeUtc())+" ms ago");
+ if (truth(getNextScheduled())) {
+ Duration untilNext = Duration.millis(getNextScheduled().getDelay(TimeUnit.MILLISECONDS));
+ if (untilNext.isPositive())
+ rv.append(", next in "+untilNext);
+ else
+ rv.append(", next imminent");
+ }
+ return rv.toString();
+ }
+
+ @Override
+ public boolean isDone() {
+ return isCancelled() || (maxIterations!=null && maxIterations <= runCount) || (period==null && nextRun!=null && nextRun.isDone());
+ }
+
+ public synchronized void blockUntilFirstScheduleStarted() {
+ // TODO Assumes that maxIterations is not negative!
+ while (true) {
+ if (isCancelled()) throw new CancellationException();
+ if (recentRun==null)
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ Throwables.propagate(e);
+ }
+ if (recentRun!=null) return;
+ }
+ }
+
+ public void blockUntilEnded() {
+ while (!isDone()) super.blockUntilEnded();
+ }
+
+ /** gets the value of the most recently run task */
+ public Object get() throws InterruptedException, ExecutionException {
+ blockUntilStarted();
+ blockUntilFirstScheduleStarted();
+ return (truth(recentRun)) ? recentRun.get() : internalFuture.get();
+ }
+
+ @Override
+ public synchronized boolean cancel(boolean mayInterrupt) {
+ boolean result = super.cancel(mayInterrupt);
+ if (nextRun!=null) {
+ nextRun.cancel(mayInterrupt);
+ notifyAll();
+ }
+ return result;
+ }
+
+ /** internal method used to allow callers to wait for underlying tasks to finished in the case of cancellation
+ * @param duration */
+ @Beta
+ public boolean blockUntilNextRunFinished(Duration timeout) {
+ return Tasks.blockUntilInternalTasksEnded(nextRun, timeout);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/SequentialTask.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/SequentialTask.java b/core/src/main/java/org/apache/brooklyn/core/util/task/SequentialTask.java
new file mode 100644
index 0000000..93ecdf6
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/SequentialTask.java
@@ -0,0 +1,58 @@
+/*
+ * 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.util.task;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+
+import org.apache.brooklyn.api.management.Task;
+
+import com.google.common.collect.ImmutableList;
+
+
+/** runs tasks in order, waiting for one to finish before starting the next; return value here is TBD;
+ * (currently is all the return values of individual tasks, but we
+ * might want some pipeline support and eventually only to return final value...) */
+public class SequentialTask<T> extends CompoundTask<T> {
+
+ public SequentialTask(Object... tasks) { super(tasks); }
+
+ public SequentialTask(Map<String,?> flags, Collection<? extends Object> tasks) { super(flags, tasks); }
+ public SequentialTask(Collection<? extends Object> tasks) { super(tasks); }
+
+ public SequentialTask(Map<String,?> flags, Iterable<? extends Object> tasks) { super(flags, ImmutableList.copyOf(tasks)); }
+ public SequentialTask(Iterable<? extends Object> tasks) { super(ImmutableList.copyOf(tasks)); }
+
+ protected List<T> runJobs() throws InterruptedException, ExecutionException {
+ setBlockingDetails("Executing "+
+ (children.size()==1 ? "1 child task" :
+ children.size()+" children tasks sequentially") );
+
+ List<T> result = new ArrayList<T>();
+ for (Task<? extends T> task : children) {
+ submitIfNecessary(task);
+ // throw exception (and cancel subsequent tasks) on error
+ result.add(task.get());
+ }
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/SingleThreadedScheduler.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/SingleThreadedScheduler.java b/core/src/main/java/org/apache/brooklyn/core/util/task/SingleThreadedScheduler.java
new file mode 100644
index 0000000..2a5b51d
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/SingleThreadedScheduler.java
@@ -0,0 +1,216 @@
+/*
+ * 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.util.task;
+
+import java.util.Queue;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.brooklyn.api.management.Task;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Instances of this class ensures that {@link Task}s execute with in-order
+ * single-threaded semantics.
+ *
+ * Tasks can be presented through {@link #submit(Callable)}. The order of execution is the
+ * sumbission order.
+ * <p>
+ * This implementation does so by blocking on a {@link ConcurrentLinkedQueue}, <em>after</em>
+ * the task is started in a thread (and {@link Task#isBegun()} returns true), but (of course)
+ * <em>before</em> the {@link TaskInternal#getJob()} actually gets invoked.
+ */
+public class SingleThreadedScheduler implements TaskScheduler, CanSetName {
+ private static final Logger LOG = LoggerFactory.getLogger(SingleThreadedScheduler.class);
+
+ private final Queue<QueuedSubmission<?>> order = new ConcurrentLinkedQueue<QueuedSubmission<?>>();
+ private int queueSize = 0;
+ private final AtomicBoolean running = new AtomicBoolean(false);
+
+ private ExecutorService executor;
+
+ private String name;
+
+ @Override
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ return name!=null ? "SingleThreadedScheduler["+name+"]" : super.toString();
+ }
+
+ @Override
+ public void injectExecutor(ExecutorService executor) {
+ this.executor = executor;
+ }
+
+ @Override
+ public synchronized <T> Future<T> submit(Callable<T> c) {
+ if (running.compareAndSet(false, true)) {
+ return executeNow(c);
+ } else {
+ WrappingFuture<T> f = new WrappingFuture<T>();
+ order.add(new QueuedSubmission<T>(c, f));
+ queueSize++;
+ if (queueSize>0 && (queueSize == 50 || (queueSize<=500 && (queueSize%100)==0) || (queueSize%1000)==0) && queueSize!=lastSizeWarn) {
+ LOG.warn("{} is backing up, {} tasks queued", this, queueSize);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Task queue backing up detail, queue "+this+"; task context is "+Tasks.current()+"; latest task is "+c+"; first task is "+order.peek());
+ }
+ lastSizeWarn = queueSize;
+ }
+ return f;
+ }
+ }
+ int lastSizeWarn = 0;
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ private synchronized void onEnd() {
+ boolean done = false;
+ while (!done) {
+ if (order.isEmpty()) {
+ running.set(false);
+ done = true;
+ } else {
+ QueuedSubmission<?> qs = order.remove();
+ queueSize--;
+ if (!qs.f.isCancelled()) {
+ Future future = executeNow(qs.c);
+ qs.f.setDelegate(future);
+ done = true;
+ }
+ }
+ }
+ }
+
+ private synchronized <T> Future<T> executeNow(final Callable<T> c) {
+ return executor.submit(new Callable<T>() {
+ @Override public T call() throws Exception {
+ try {
+ return c.call();
+ } finally {
+ onEnd();
+ }
+ }});
+ }
+
+
+ private static class QueuedSubmission<T> {
+ final Callable<T> c;
+ final WrappingFuture<T> f;
+
+ QueuedSubmission(Callable<T> c, WrappingFuture<T> f) {
+ this.c = c;
+ this.f = f;
+ }
+
+ @Override
+ public String toString() {
+ return "QueuedSubmission["+c+"]@"+Integer.toHexString(System.identityHashCode(this));
+ }
+ }
+
+ /**
+ * A future, where the task may not yet have been submitted to the real executor.
+ * It delegates to the real future if present, and otherwise waits for that to appear
+ */
+ private static class WrappingFuture<T> implements Future<T> {
+ private volatile Future<T> delegate;
+ private boolean cancelled;
+
+ void setDelegate(Future<T> delegate) {
+ synchronized (this) {
+ this.delegate = delegate;
+ notifyAll();
+ }
+ }
+
+ @Override public boolean cancel(boolean mayInterruptIfRunning) {
+ if (delegate != null) {
+ return delegate.cancel(mayInterruptIfRunning);
+ } else {
+ cancelled = true;
+ synchronized (this) {
+ notifyAll();
+ }
+ return true;
+ }
+ }
+
+ @Override public boolean isCancelled() {
+ if (delegate != null) {
+ return delegate.isCancelled();
+ } else {
+ return cancelled;
+ }
+ }
+
+ @Override public boolean isDone() {
+ return (delegate != null) ? delegate.isDone() : cancelled;
+ }
+
+ @Override public T get() throws CancellationException, ExecutionException, InterruptedException {
+ if (cancelled) {
+ throw new CancellationException();
+ } else if (delegate != null) {
+ return delegate.get();
+ } else {
+ synchronized (this) {
+ while (delegate == null && !cancelled) {
+ wait();
+ }
+ }
+ return get();
+ }
+ }
+
+ @Override public T get(long timeout, TimeUnit unit) throws CancellationException, ExecutionException, InterruptedException, TimeoutException {
+ long endtime = System.currentTimeMillis()+unit.toMillis(timeout);
+
+ if (cancelled) {
+ throw new CancellationException();
+ } else if (delegate != null) {
+ return delegate.get(timeout, unit);
+ } else if (System.currentTimeMillis() >= endtime) {
+ throw new TimeoutException();
+ } else {
+ synchronized (this) {
+ while (delegate == null && !cancelled && System.currentTimeMillis() < endtime) {
+ long remaining = endtime - System.currentTimeMillis();
+ if (remaining > 0) {
+ wait(remaining);
+ }
+ }
+ }
+ long remaining = endtime - System.currentTimeMillis();
+ return get(remaining, TimeUnit.MILLISECONDS);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/TaskBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/TaskBuilder.java b/core/src/main/java/org/apache/brooklyn/core/util/task/TaskBuilder.java
new file mode 100644
index 0000000..b105a00
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/TaskBuilder.java
@@ -0,0 +1,184 @@
+/*
+ * 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.util.task;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.api.management.TaskAdaptable;
+import org.apache.brooklyn.api.management.TaskFactory;
+import org.apache.brooklyn.api.management.TaskQueueingContext;
+
+import brooklyn.util.JavaGroovyEquivalents;
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.collections.MutableSet;
+
+import com.google.common.collect.Iterables;
+
+/** Convenience for creating tasks; note that DynamicSequentialTask is the default */
+public class TaskBuilder<T> {
+
+ String name = null;
+ String description = null;
+ Callable<T> body = null;
+ Boolean swallowChildrenFailures = null;
+ List<TaskAdaptable<?>> children = MutableList.of();
+ Set<Object> tags = MutableSet.of();
+ Map<String,Object> flags = MutableMap.of();
+ Boolean dynamic = null;
+ boolean parallel = false;
+
+ public static <T> TaskBuilder<T> builder() {
+ return new TaskBuilder<T>();
+ }
+
+ public TaskBuilder<T> name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public TaskBuilder<T> description(String description) {
+ this.description = description;
+ return this;
+ }
+
+ /** whether task that is built has been explicitly specified to be a dynamic task
+ * (ie a Task which is also a {@link TaskQueueingContext}
+ * whereby new tasks can be added after creation */
+ public TaskBuilder<T> dynamic(boolean dynamic) {
+ this.dynamic = dynamic;
+ return this;
+ }
+
+ /** whether task that is built should be parallel; cannot (currently) also be dynamic */
+ public TaskBuilder<T> parallel(boolean parallel) {
+ this.parallel = parallel;
+ return this;
+ }
+
+ public TaskBuilder<T> body(Callable<T> body) {
+ this.body = body;
+ return this;
+ }
+
+ /** sets up a dynamic task not to fail even if children fail */
+ public TaskBuilder<T> swallowChildrenFailures(boolean swallowChildrenFailures) {
+ this.swallowChildrenFailures = swallowChildrenFailures;
+ return this;
+ }
+
+ public TaskBuilder<T> body(Runnable body) {
+ this.body = JavaGroovyEquivalents.<T>toCallable(body);
+ return this;
+ }
+
+ /** adds a child to the given task; the semantics of how the child is executed is set using
+ * {@link #dynamic(boolean)} and {@link #parallel(boolean)} */
+ public TaskBuilder<T> add(TaskAdaptable<?> child) {
+ children.add(child);
+ return this;
+ }
+
+ public TaskBuilder<T> addAll(Iterable<? extends TaskAdaptable<?>> additionalChildren) {
+ Iterables.addAll(children, additionalChildren);
+ return this;
+ }
+
+ public TaskBuilder<T> add(TaskAdaptable<?>... additionalChildren) {
+ children.addAll(Arrays.asList(additionalChildren));
+ return this;
+ }
+
+ /** adds a tag to the given task */
+ public TaskBuilder<T> tag(Object tag) {
+ tags.add(tag);
+ return this;
+ }
+
+ /** adds a flag to the given task */
+ public TaskBuilder<T> flag(String flag, Object value) {
+ flags.put(flag, value);
+ return this;
+ }
+
+ /** adds the given flags to the given task */
+ public TaskBuilder<T> flags(Map<String,Object> flags) {
+ this.flags.putAll(flags);
+ return this;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public Task<T> build() {
+ MutableMap<String, Object> taskFlags = MutableMap.copyOf(flags);
+ if (name!=null) taskFlags.put("displayName", name);
+ if (description!=null) taskFlags.put("description", description);
+ if (!tags.isEmpty()) taskFlags.put("tags", tags);
+
+ if (Boolean.FALSE.equals(dynamic) && children.isEmpty()) {
+ if (swallowChildrenFailures!=null)
+ throw new IllegalArgumentException("Cannot set swallowChildrenFailures for non-dynamic task: "+this);
+ return new BasicTask<T>(taskFlags, body);
+ }
+
+ // prefer dynamic set unless (a) user has said not dynamic, or (b) it's parallel (since there is no dynamic parallel yet)
+ // dynamic has better cancel (will interrupt the thread) and callers can submit tasks flexibly;
+ // however dynamic uses an extra thread and task and is noisy for contexts which don't need it
+ if (Boolean.TRUE.equals(dynamic) || (dynamic==null && !parallel)) {
+ if (parallel)
+ throw new UnsupportedOperationException("No implementation of parallel dynamic aggregate task available");
+ DynamicSequentialTask<T> result = new DynamicSequentialTask<T>(taskFlags, body);
+ if (swallowChildrenFailures!=null && swallowChildrenFailures.booleanValue()) result.swallowChildrenFailures();
+ for (TaskAdaptable t: children)
+ result.queue(t.asTask());
+ return result;
+ }
+
+ // T must be of type List<V> for these to be valid
+ if (body != null) {
+ throw new UnsupportedOperationException("No implementation of non-dynamic task with both body and children");
+ }
+ if (swallowChildrenFailures!=null) {
+ throw new IllegalArgumentException("Cannot set swallowChildrenFailures for non-dynamic task: "+this);
+ }
+
+ if (parallel)
+ return new ParallelTask(taskFlags, children);
+ else
+ return new SequentialTask(taskFlags, children);
+ }
+
+ /** returns a a factory based on this builder */
+ public TaskFactory<Task<T>> buildFactory() {
+ return new TaskFactory<Task<T>>() {
+ public Task<T> newTask() {
+ return build();
+ }
+ };
+ }
+
+ @Override
+ public String toString() {
+ return super.toString()+"["+name+"]";
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/TaskInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/TaskInternal.java b/core/src/main/java/org/apache/brooklyn/core/util/task/TaskInternal.java
new file mode 100644
index 0000000..b4a6569
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/TaskInternal.java
@@ -0,0 +1,125 @@
+/*
+ * 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.util.task;
+
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+
+import org.apache.brooklyn.api.management.ExecutionManager;
+import org.apache.brooklyn.api.management.Task;
+
+import brooklyn.util.time.Duration;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Function;
+import com.google.common.util.concurrent.ExecutionList;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * All tasks being passed to the {@link ExecutionManager} should implement this.
+ * Users are strongly encouraged to use (or extend) {@link BasicTask}, rather than
+ * implementing a task from scratch.
+ *
+ * The methods on this interface will change in subsequent releases. Because this is
+ * marked as beta, the normal deprecation policy for these methods does not apply.
+ *
+ * @author aled
+ */
+@Beta
+public interface TaskInternal<T> extends Task<T> {
+
+ /** sets the internal future object used to record the association to a job submitted to an {@link ExecutorService} */
+ void initInternalFuture(ListenableFuture<T> result);
+
+ /** returns the underlying future where this task's results will come in; see {@link #initInternalFuture(ListenableFuture)} */
+ Future<T> getInternalFuture();
+
+ /** if the job is queued for submission (e.g. by another task) it can indicate that fact (and time) here;
+ * note tasks can (and often are) submitted without any queueing, in which case this value may be -1 */
+ long getQueuedTimeUtc();
+
+ boolean isQueuedOrSubmitted();
+ boolean isQueuedAndNotSubmitted();
+ boolean isQueued();
+
+ /** marks the task as queued for execution */
+ void markQueued();
+
+ boolean cancel();
+
+ boolean blockUntilStarted(Duration timeout);
+
+ /** allows a task user to specify why a task is blocked; for use immediately before a blocking/wait,
+ * and typically cleared immediately afterwards; referenced by management api to inspect a task
+ * which is blocking
+ * <p>
+ * returns previous details, in case caller wishes to recall and restore it (e.g. if it is doing a sub-blocking)
+ */
+ String setBlockingDetails(String blockingDetails);
+
+ /** as {@link #setBlockingDetails(String)} but records a task which is blocking,
+ * for use e.g. in a gui to navigate to the current active subtask
+ * <p>
+ * returns previous blocking task, in case caller wishes to recall and restore it
+ */
+ Task<?> setBlockingTask(Task<?> blockingTask);
+
+ void resetBlockingDetails();
+
+ void resetBlockingTask();
+
+ /** returns a textual message giving details while the task is blocked */
+ String getBlockingDetails();
+
+ /** returns a task that this task is blocked on */
+ Task<?> getBlockingTask();
+
+ void setExtraStatusText(Object extraStatus);
+
+ Object getExtraStatusText();
+
+ void runListeners();
+
+ void setEndTimeUtc(long val);
+
+ void setThread(Thread thread);
+
+ Callable<T> getJob();
+
+ void setJob(Callable<T> job);
+
+ ExecutionList getListeners();
+
+ void setSubmitTimeUtc(long currentTimeMillis);
+
+ void setSubmittedByTask(Task<?> task);
+
+ Set<Object> getMutableTags();
+
+ void setStartTimeUtc(long currentTimeMillis);
+
+ void applyTagModifier(Function<Set<Object>,Void> modifier);
+
+ /** if a task is a proxy for another one (used mainly for internal tasks),
+ * this returns the "real" task represented by this one */
+ Task<?> getProxyTarget();
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/TaskScheduler.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/TaskScheduler.java b/core/src/main/java/org/apache/brooklyn/core/util/task/TaskScheduler.java
new file mode 100644
index 0000000..7c5d8a2
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/TaskScheduler.java
@@ -0,0 +1,41 @@
+/*
+ * 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.util.task;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+
+import org.apache.brooklyn.api.management.Task;
+
+/**
+ * The scheduler is an internal mechanism to decorate {@link Task}s.
+ *
+ * It can control how the tasks are scheduled for execution (e.g. single-threaded execution,
+ * prioritised, etc).
+ */
+public interface TaskScheduler {
+
+ public void injectExecutor(ExecutorService executor);
+
+ /**
+ * Called by {@link BasicExecutionManager} to schedule tasks.
+ */
+ public <T> Future<T> submit(Callable<T> c);
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/TaskTags.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/TaskTags.java b/core/src/main/java/org/apache/brooklyn/core/util/task/TaskTags.java
new file mode 100644
index 0000000..e404e87
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/TaskTags.java
@@ -0,0 +1,71 @@
+/*
+ * 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.util.task;
+
+import java.util.Set;
+
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.api.management.TaskAdaptable;
+
+import com.google.common.base.Function;
+
+public class TaskTags {
+
+ /** marks a task which is allowed to fail without failing his parent */
+ public static final String INESSENTIAL_TASK = "inessential";
+
+ /** marks a task which is a subtask of another */
+ public static final String SUB_TASK_TAG = "SUB-TASK";
+
+ public static void addTagDynamically(TaskAdaptable<?> task, final Object tag) {
+ ((BasicTask<?>)task.asTask()).applyTagModifier(new Function<Set<Object>, Void>() {
+ public Void apply(@Nullable Set<Object> input) {
+ input.add(tag);
+ return null;
+ }
+ });
+ }
+
+ public static void addTagsDynamically(TaskAdaptable<?> task, final Object tag1, final Object ...tags) {
+ ((BasicTask<?>)task.asTask()).applyTagModifier(new Function<Set<Object>, Void>() {
+ public Void apply(@Nullable Set<Object> input) {
+ input.add(tag1);
+ for (Object tag: tags) input.add(tag);
+ return null;
+ }
+ });
+ }
+
+
+ public static boolean isInessential(Task<?> task) {
+ return hasTag(task, INESSENTIAL_TASK);
+ }
+
+ public static boolean hasTag(Task<?> task, Object tag) {
+ return task.getTags().contains(tag);
+ }
+
+ public static <U,V extends TaskAdaptable<U>> V markInessential(V task) {
+ addTagDynamically(task, INESSENTIAL_TASK);
+ return task;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/org/apache/brooklyn/core/util/task/Tasks.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/util/task/Tasks.java b/core/src/main/java/org/apache/brooklyn/core/util/task/Tasks.java
new file mode 100644
index 0000000..d391a90
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/util/task/Tasks.java
@@ -0,0 +1,488 @@
+/*
+ * 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.util.task;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.FutureTask;
+
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.api.management.ExecutionContext;
+import org.apache.brooklyn.api.management.HasTaskChildren;
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.api.management.TaskAdaptable;
+import org.apache.brooklyn.api.management.TaskFactory;
+import org.apache.brooklyn.api.management.TaskQueueingContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.exceptions.ReferenceWithError;
+import brooklyn.util.repeat.Repeater;
+import brooklyn.util.time.CountdownTimer;
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Time;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.collect.Iterables;
+
+public class Tasks {
+
+ private static final Logger log = LoggerFactory.getLogger(Tasks.class);
+
+ /** convenience for setting "blocking details" on any task where the current thread is running;
+ * typically invoked prior to a wait, for transparency to a user;
+ * then invoked with 'null' just after the wait */
+ public static String setBlockingDetails(String description) {
+ Task<?> current = current();
+ if (current instanceof TaskInternal)
+ return ((TaskInternal<?>)current).setBlockingDetails(description);
+ return null;
+ }
+ public static void resetBlockingDetails() {
+ Task<?> current = current();
+ if (current instanceof TaskInternal)
+ ((TaskInternal<?>)current).resetBlockingDetails();
+ }
+ public static Task<?> setBlockingTask(Task<?> blocker) {
+ Task<?> current = current();
+ if (current instanceof TaskInternal)
+ return ((TaskInternal<?>)current).setBlockingTask(blocker);
+ return null;
+ }
+ public static void resetBlockingTask() {
+ Task<?> current = current();
+ if (current instanceof TaskInternal)
+ ((TaskInternal<?>)current).resetBlockingTask();
+ }
+
+ /** convenience for setting "blocking details" on any task where the current thread is running,
+ * while the passed code is executed; often used from groovy as
+ * <pre>{@code withBlockingDetails("sleeping 5s") { Thread.sleep(5000); } }</pre>
+ * If code block is null, the description is set until further notice (not cleareed). */
+ @SuppressWarnings("rawtypes")
+ public static <T> T withBlockingDetails(String description, Callable<T> code) throws Exception {
+ Task current = current();
+ if (code==null) {
+ log.warn("legacy invocation of withBlockingDetails with null code block, ignoring");
+ return null;
+ }
+ String prevBlockingDetails = null;
+ if (current instanceof TaskInternal) {
+ prevBlockingDetails = ((TaskInternal)current).setBlockingDetails(description);
+ }
+ try {
+ return code.call();
+ } finally {
+ if (current instanceof TaskInternal)
+ ((TaskInternal)current).setBlockingDetails(prevBlockingDetails);
+ }
+ }
+
+ /** the {@link Task} where the current thread is executing, if executing in a Task, otherwise null;
+ * if the current task is a proxy, this returns the target of that proxy */
+ @SuppressWarnings("rawtypes")
+ public static Task current() {
+ return getFinalProxyTarget(BasicExecutionManager.getPerThreadCurrentTask().get());
+ }
+
+ public static Task<?> getFinalProxyTarget(Task<?> task) {
+ if (task==null) return null;
+ Task<?> proxy = ((TaskInternal<?>)task).getProxyTarget();
+ if (proxy==null || proxy.equals(task)) return task;
+ return getFinalProxyTarget(proxy);
+ }
+
+ /** creates a {@link ValueResolver} instance which allows significantly more customization than
+ * the various {@link #resolveValue(Object, Class, ExecutionContext)} methods here */
+ public static <T> ValueResolver<T> resolving(Object v, Class<T> type) {
+ return new ValueResolver<T>(v, type);
+ }
+
+ public static ValueResolver.ResolverBuilderPretype resolving(Object v) {
+ return new ValueResolver.ResolverBuilderPretype(v);
+ }
+
+ /** @see #resolveValue(Object, Class, ExecutionContext, String) */
+ public static <T> T resolveValue(Object v, Class<T> type, @Nullable ExecutionContext exec) throws ExecutionException, InterruptedException {
+ return new ValueResolver<T>(v, type).context(exec).get();
+ }
+
+ /** attempt to resolve the given value as the given type, waiting on futures, submitting if necessary,
+ * and coercing as allowed by TypeCoercions;
+ * contextMessage (optional) will be displayed in status reports while it waits (e.g. the name of the config key being looked up).
+ * if no execution context supplied (null) this method will throw an exception if the object is an unsubmitted task */
+ public static <T> T resolveValue(Object v, Class<T> type, @Nullable ExecutionContext exec, String contextMessage) throws ExecutionException, InterruptedException {
+ return new ValueResolver<T>(v, type).context(exec).description(contextMessage).get();
+ }
+
+ /**
+ * @see #resolveDeepValue(Object, Class, ExecutionContext, String)
+ */
+ public static Object resolveDeepValue(Object v, Class<?> type, ExecutionContext exec) throws ExecutionException, InterruptedException {
+ return resolveDeepValue(v, type, exec, null);
+ }
+
+ /**
+ * Resolves the given object, blocking on futures and coercing it to the given type. If the object is a
+ * map or iterable (or a list of map of maps, etc, etc) then walks these maps/iterables to convert all of
+ * their values to the given type. For example, the following will return a list containing a map with "1"="true":
+ *
+ * {@code Object result = resolveDeepValue(ImmutableList.of(ImmutableMap.of(1, true)), String.class, exec)}
+ *
+ * To perform a deep conversion of futures contained within Iterables or Maps without coercion of each element,
+ * the type should normally be Object, not the type of the collection. This differs from
+ * {@link #resolveValue(Object, Class, ExecutionContext, String)} which will accept Map and Iterable
+ * as the required type.
+ */
+ public static <T> T resolveDeepValue(Object v, Class<T> type, ExecutionContext exec, String contextMessage) throws ExecutionException, InterruptedException {
+ return new ValueResolver<T>(v, type).context(exec).deep(true).description(contextMessage).get();
+ }
+
+ /** sets extra status details on the current task, if possible (otherwise does nothing).
+ * the extra status is presented in Task.getStatusDetails(true)
+ */
+ public static void setExtraStatusDetails(String notes) {
+ Task<?> current = current();
+ if (current instanceof TaskInternal)
+ ((TaskInternal<?>)current).setExtraStatusText(notes);
+ }
+
+ public static <T> TaskBuilder<T> builder() {
+ return TaskBuilder.<T>builder();
+ }
+
+ private static Task<?>[] asTasks(TaskAdaptable<?> ...tasks) {
+ Task<?>[] result = new Task<?>[tasks.length];
+ for (int i=0; i<tasks.length; i++)
+ result[i] = tasks[i].asTask();
+ return result;
+ }
+
+ public static Task<List<?>> parallel(TaskAdaptable<?> ...tasks) {
+ return parallelInternal("parallelised tasks", asTasks(tasks));
+ }
+ public static Task<List<?>> parallel(String name, TaskAdaptable<?> ...tasks) {
+ return parallelInternal(name, asTasks(tasks));
+ }
+ public static Task<List<?>> parallel(Iterable<? extends TaskAdaptable<?>> tasks) {
+ return parallel(asTasks(Iterables.toArray(tasks, TaskAdaptable.class)));
+ }
+ public static Task<List<?>> parallel(String name, Iterable<? extends TaskAdaptable<?>> tasks) {
+ return parallelInternal(name, asTasks(Iterables.toArray(tasks, TaskAdaptable.class)));
+ }
+ private static Task<List<?>> parallelInternal(String name, Task<?>[] tasks) {
+ return Tasks.<List<?>>builder().name(name).parallel(true).add(tasks).build();
+ }
+
+ public static Task<List<?>> sequential(TaskAdaptable<?> ...tasks) {
+ return sequentialInternal("sequential tasks", asTasks(tasks));
+ }
+ public static Task<List<?>> sequential(String name, TaskAdaptable<?> ...tasks) {
+ return sequentialInternal(name, asTasks(tasks));
+ }
+ public static TaskFactory<?> sequential(TaskFactory<?> ...taskFactories) {
+ return sequentialInternal("sequential tasks", taskFactories);
+ }
+ public static TaskFactory<?> sequential(String name, TaskFactory<?> ...taskFactories) {
+ return sequentialInternal(name, taskFactories);
+ }
+ public static Task<List<?>> sequential(List<? extends TaskAdaptable<?>> tasks) {
+ return sequential(asTasks(Iterables.toArray(tasks, TaskAdaptable.class)));
+ }
+ public static Task<List<?>> sequential(String name, List<? extends TaskAdaptable<?>> tasks) {
+ return sequential(name, asTasks(Iterables.toArray(tasks, TaskAdaptable.class)));
+ }
+ private static Task<List<?>> sequentialInternal(String name, Task<?>[] tasks) {
+ return Tasks.<List<?>>builder().name(name).parallel(false).add(tasks).build();
+ }
+ private static TaskFactory<?> sequentialInternal(final String name, final TaskFactory<?> ...taskFactories) {
+ return new TaskFactory<TaskAdaptable<?>>() {
+ @Override
+ public TaskAdaptable<?> newTask() {
+ TaskBuilder<List<?>> tb = Tasks.<List<?>>builder().name(name).parallel(false);
+ for (TaskFactory<?> tf: taskFactories)
+ tb.add(tf.newTask().asTask());
+ return tb.build();
+ }
+ };
+ }
+
+ /** returns the first tag found on the given task which matches the given type, looking up the submission hierarachy if necessary */
+ @SuppressWarnings("unchecked")
+ public static <T> T tag(@Nullable Task<?> task, Class<T> type, boolean recurseHierarchy) {
+ // support null task to make it easier for callers to walk hierarchies
+ if (task==null) return null;
+ for (Object tag: task.getTags())
+ if (type.isInstance(tag)) return (T)tag;
+ if (!recurseHierarchy) return null;
+ return tag(task.getSubmittedByTask(), type, true);
+ }
+
+ public static boolean isAncestorCancelled(Task<?> t) {
+ if (t==null) return false;
+ if (t.isCancelled()) return true;
+ return isAncestorCancelled(t.getSubmittedByTask());
+ }
+
+ public static boolean isQueued(TaskAdaptable<?> task) {
+ return ((TaskInternal<?>)task.asTask()).isQueued();
+ }
+
+ public static boolean isSubmitted(TaskAdaptable<?> task) {
+ return ((TaskInternal<?>)task.asTask()).isSubmitted();
+ }
+
+ public static boolean isQueuedOrSubmitted(TaskAdaptable<?> task) {
+ return ((TaskInternal<?>)task.asTask()).isQueuedOrSubmitted();
+ }
+
+ /**
+ * Adds the given task to the given context. Does not throw an exception if the addition fails.
+ * @return true if the task was added, false otherwise.
+ */
+ public static boolean tryQueueing(TaskQueueingContext adder, TaskAdaptable<?> task) {
+ if (task==null || isQueued(task))
+ return false;
+ try {
+ adder.queue(task.asTask());
+ return true;
+ } catch (Exception e) {
+ if (log.isDebugEnabled())
+ log.debug("Could not add task "+task+" at "+adder+": "+e);
+ return false;
+ }
+ }
+
+ /** see also {@link #resolving(Object)} which gives much more control about submission, timeout, etc */
+ public static <T> Supplier<T> supplier(final TaskAdaptable<T> task) {
+ return new Supplier<T>() {
+ @Override
+ public T get() {
+ return task.asTask().getUnchecked();
+ }
+ };
+ }
+
+ /** return all children tasks of the given tasks, if it has children, else empty list */
+ public static Iterable<Task<?>> children(Task<?> task) {
+ if (task instanceof HasTaskChildren)
+ return ((HasTaskChildren)task).getChildren();
+ return Collections.emptyList();
+ }
+
+ /** returns failed tasks */
+ public static Iterable<Task<?>> failed(Iterable<Task<?>> subtasks) {
+ return Iterables.filter(subtasks, new Predicate<Task<?>>() {
+ @Override
+ public boolean apply(Task<?> input) {
+ return input.isError();
+ }
+ });
+ }
+
+ /** returns the task, its children, and all its children, and so on;
+ * @param root task whose descendants should be iterated
+ * @param parentFirst whether to put parents before children or after
+ */
+ public static Iterable<Task<?>> descendants(Task<?> root, final boolean parentFirst) {
+ Iterable<Task<?>> descs = Iterables.concat(Iterables.transform(Tasks.children(root), new Function<Task<?>,Iterable<Task<?>>>() {
+ @Override
+ public Iterable<Task<?>> apply(Task<?> input) {
+ return descendants(input, parentFirst);
+ }
+ }));
+ if (parentFirst) return Iterables.concat(Collections.singleton(root), descs);
+ else return Iterables.concat(descs, Collections.singleton(root));
+ }
+
+ /** returns the error thrown by the task if {@link Task#isError()}, or null if no error or not done */
+ public static Throwable getError(Task<?> t) {
+ if (t==null) return null;
+ if (!t.isDone()) return null;
+ if (t.isCancelled()) return new CancellationException();
+ try {
+ t.get();
+ return null;
+ } catch (Throwable error) {
+ // do not propagate as we are pretty much guaranteed above that it wasn't this
+ // thread which originally threw the error
+ return error;
+ }
+ }
+ public static Task<Void> fail(final String name, final Throwable optionalError) {
+ return Tasks.<Void>builder().dynamic(false).name(name).body(new Runnable() { public void run() {
+ if (optionalError!=null) throw Exceptions.propagate(optionalError); else throw new RuntimeException("Failed: "+name);
+ } }).build();
+ }
+ public static Task<Void> warning(final String message, final Throwable optionalError) {
+ log.warn(message);
+ return TaskTags.markInessential(fail(message, optionalError));
+ }
+
+ /** marks the current task inessential; this mainly matters if the task is running in a parent
+ * {@link TaskQueueingContext} and we don't want the parent to fail if this task fails
+ * <p>
+ * no-op (silently ignored) if not in a task */
+ public static void markInessential() {
+ Task<?> task = Tasks.current();
+ if (task==null) {
+ TaskQueueingContext qc = DynamicTasks.getTaskQueuingContext();
+ if (qc!=null) task = qc.asTask();
+ }
+ if (task!=null) {
+ TaskTags.markInessential(task);
+ }
+ }
+
+ /** causes failures in subtasks of the current task not to fail the parent;
+ * no-op if not in a {@link TaskQueueingContext}.
+ * <p>
+ * essentially like a {@link #markInessential()} on all tasks in the current
+ * {@link TaskQueueingContext}, including tasks queued subsequently */
+ @Beta
+ public static void swallowChildrenFailures() {
+ Preconditions.checkNotNull(DynamicTasks.getTaskQueuingContext(), "Task queueing context required here");
+ TaskQueueingContext qc = DynamicTasks.getTaskQueuingContext();
+ if (qc!=null) {
+ qc.swallowChildrenFailures();
+ }
+ }
+
+ /** as {@link TaskTags#addTagDynamically(TaskAdaptable, Object)} but for current task, skipping if no current task */
+ public static void addTagDynamically(Object tag) {
+ Task<?> t = Tasks.current();
+ if (t!=null) TaskTags.addTagDynamically(t, tag);
+ }
+
+ /**
+ * Workaround for limitation described at {@link Task#cancel(boolean)};
+ * internal method used to allow callers to wait for underlying tasks to finished in the case of cancellation.
+ * <p>
+ * It is irritating that {@link FutureTask} sync's object clears the runner thread,
+ * so even if {@link BasicTask#getInternalFuture()} is used, there is no means of determining if the underlying object is done.
+ * The {@link Task#getEndTimeUtc()} seems the only way.
+ *
+ * @return true if tasks ended; false if timed out
+ **/
+ @Beta
+ public static boolean blockUntilInternalTasksEnded(Task<?> t, Duration timeout) {
+ CountdownTimer timer = timeout.countdownTimer();
+
+ if (t==null)
+ return true;
+
+ if (t instanceof ScheduledTask) {
+ boolean result = ((ScheduledTask)t).blockUntilNextRunFinished(timer.getDurationRemaining());
+ if (!result) return false;
+ }
+
+ t.blockUntilEnded(timer.getDurationRemaining());
+
+ while (true) {
+ if (t.getEndTimeUtc()>=0) return true;
+ // above should be sufficient; but just in case, trying the below
+ Thread tt = t.getThread();
+ if (t instanceof ScheduledTask) {
+ ((ScheduledTask)t).blockUntilNextRunFinished(timer.getDurationRemaining());
+ return true;
+ } else {
+ if (tt==null || !tt.isAlive()) {
+ if (!t.isCancelled()) {
+ // may happen for a cancelled task, interrupted after submit but before start
+ log.warn("Internal task thread is dead or null ("+tt+") but task not ended: "+t.getEndTimeUtc()+" ("+t+")");
+ }
+ return true;
+ }
+ }
+ if (timer.isExpired())
+ return false;
+ Time.sleep(Repeater.DEFAULT_REAL_QUICK_PERIOD);
+ }
+ }
+
+ /** returns true if either the current thread or the current task is interrupted/cancelled */
+ public static boolean isInterrupted() {
+ if (Thread.currentThread().isInterrupted()) return true;
+ Task<?> t = current();
+ if (t==null) return false;
+ return t.isCancelled();
+ }
+
+ private static class WaitForRepeaterCallable implements Callable<Boolean> {
+ protected Repeater repeater;
+ protected boolean requireTrue;
+
+ public WaitForRepeaterCallable(Repeater repeater, boolean requireTrue) {
+ this.repeater = repeater;
+ this.requireTrue = requireTrue;
+ }
+
+ @Override
+ public Boolean call() {
+ ReferenceWithError<Boolean> result;
+ Tasks.setBlockingDetails(repeater.getDescription());
+ try {
+ result = repeater.runKeepingError();
+ } finally {
+ Tasks.resetBlockingDetails();
+ }
+
+ if (Boolean.TRUE.equals(result.getWithoutError()))
+ return true;
+ if (result.hasError())
+ throw Exceptions.propagate(result.getError());
+ if (requireTrue)
+ throw new IllegalStateException("timeout - "+repeater.getDescription());
+ return false;
+ }
+ }
+
+ /** @return a {@link TaskBuilder} which tests whether the repeater terminates with success in its configured timeframe,
+ * returning true or false depending on whether repeater succeed */
+ public static TaskBuilder<Boolean> testing(Repeater repeater) {
+ return Tasks.<Boolean>builder().body(new WaitForRepeaterCallable(repeater, false))
+ .name("waiting for condition")
+ .description("Testing whether " + getTimeoutString(repeater) + ": "+repeater.getDescription());
+ }
+
+ /** @return a {@link TaskBuilder} which requires that the repeater terminate with success in its configured timeframe,
+ * throwing if it does not */
+ public static TaskBuilder<?> requiring(Repeater repeater) {
+ return Tasks.<Boolean>builder().body(new WaitForRepeaterCallable(repeater, true))
+ .name("waiting for condition")
+ .description("Requiring " + getTimeoutString(repeater) + ": " + repeater.getDescription());
+ }
+
+ private static String getTimeoutString(Repeater repeater) {
+ Duration timeout = repeater.getTimeLimit();
+ if (timeout==null || Duration.PRACTICALLY_FOREVER.equals(timeout))
+ return "eventually";
+ return "in "+timeout;
+ }
+
+}
[40/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/ResourceUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/ResourceUtils.java b/core/src/main/java/brooklyn/util/ResourceUtils.java
deleted file mode 100644
index 338b223..0000000
--- a/core/src/main/java/brooklyn/util/ResourceUtils.java
+++ /dev/null
@@ -1,639 +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 brooklyn.util;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-import java.net.InetAddress;
-import java.net.JarURLConnection;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLDecoder;
-import java.util.List;
-import java.util.NoSuchElementException;
-import java.util.Properties;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
-import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
-import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog.BrooklynLoaderTracker;
-import org.apache.brooklyn.core.internal.BrooklynInitialization;
-import org.apache.brooklyn.core.management.classloading.JavaBrooklynClassLoadingContext;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.auth.Credentials;
-import org.apache.http.auth.UsernamePasswordCredentials;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.util.EntityUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.brooklyn.location.basic.SshMachineLocation;
-
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.http.HttpTool;
-import brooklyn.util.http.HttpTool.HttpClientBuilder;
-import brooklyn.util.javalang.Threads;
-import brooklyn.util.net.Urls;
-import brooklyn.util.os.Os;
-import brooklyn.util.stream.Streams;
-import brooklyn.util.text.DataUriSchemeParser;
-import brooklyn.util.text.Strings;
-
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.base.Throwables;
-import com.google.common.collect.Lists;
-
-public class ResourceUtils {
-
- private static final Logger log = LoggerFactory.getLogger(ResourceUtils.class);
- private static final List<Function<Object,BrooklynClassLoadingContext>> classLoaderProviders = Lists.newCopyOnWriteArrayList();
-
- private BrooklynClassLoadingContext loader = null;
- private String context = null;
- private Object contextObject = null;
-
- static { BrooklynInitialization.initNetworking(); }
-
- /**
- * Creates a {@link ResourceUtils} object with a specific class loader and context.
- * <p>
- * Use the provided {@link ClassLoader} object for class loading with the
- * {@code contextObject} for context and the {@code contextMessage} string for
- * error messages.
- *
- * @see ResourceUtils#create(Object, String)
- * @see ResourceUtils#create(Object)
- */
- public static final ResourceUtils create(ClassLoader loader, Object contextObject, String contextMessage) {
- return new ResourceUtils(loader, contextObject, contextMessage);
- }
-
- /**
- * Creates a {@link ResourceUtils} object with a specific class loader and context.
- * <p>
- * Use the provided {@link BrooklynClassLoadingContext} object for class loading with the
- * {@code contextObject} for context and the {@code contextMessage} string for
- * error messages.
- *
- * @see ResourceUtils#create(Object, String)
- * @see ResourceUtils#create(Object)
- */
- public static final ResourceUtils create(BrooklynClassLoadingContext loader, Object contextObject, String contextMessage) {
- return new ResourceUtils(loader, contextObject, contextMessage);
- }
-
- /**
- * Creates a {@link ResourceUtils} object with the given context.
- * <p>
- * Uses the {@link ClassLoader} of the given {@code contextObject} for class
- * loading and the {@code contextMessage} string for error messages.
- *
- * @see ResourceUtils#create(ClassLoader, Object, String)
- * @see ResourceUtils#create(Object)
- */
- public static final ResourceUtils create(Object contextObject, String contextMessage) {
- return new ResourceUtils(contextObject, contextMessage);
- }
-
- /**
- * Creates a {@link ResourceUtils} object with the given context.
- * <p>
- * Uses the {@link ClassLoader} of the given {@code contextObject} for class
- * loading and its {@link Object#toString()} (preceded by the word 'for') as
- * the string used in error messages.
- *
- * @see ResourceUtils#create(ClassLoader, Object, String)
- * @see ResourceUtils#create(Object)
- */
- public static final ResourceUtils create(Object contextObject) {
- return new ResourceUtils(contextObject);
- }
-
- /**
- * Creates a {@link ResourceUtils} object with itself as the context.
- *
- * @see ResourceUtils#create(Object)
- */
- public static final ResourceUtils create() {
- return new ResourceUtils(null);
- }
-
- public ResourceUtils(ClassLoader loader, Object contextObject, String contextMessage) {
- this(getClassLoadingContextInternal(loader, contextObject), contextObject, contextMessage);
- }
-
- public ResourceUtils(BrooklynClassLoadingContext loader, Object contextObject, String contextMessage) {
- this.loader = loader;
- this.contextObject = contextObject;
- this.context = contextMessage;
- }
-
- public ResourceUtils(Object contextObject, String contextMessage) {
- this(contextObject==null ? null : getClassLoadingContextInternal(null, contextObject), contextObject, contextMessage);
- }
-
- public ResourceUtils(Object contextObject) {
- this(contextObject, Strings.toString(contextObject));
- }
-
- /** used to register custom mechanisms for getting classloaders given an object */
- public static void addClassLoaderProvider(Function<Object,BrooklynClassLoadingContext> provider) {
- classLoaderProviders.add(provider);
- }
-
- // TODO rework this class so it accepts but does not require a BCLC ?
- @SuppressWarnings("deprecation")
- protected static BrooklynClassLoadingContext getClassLoadingContextInternal(ClassLoader loader, Object contextObject) {
- if (contextObject instanceof BrooklynClassLoadingContext)
- return (BrooklynClassLoadingContext) contextObject;
-
- for (Function<Object,BrooklynClassLoadingContext> provider: classLoaderProviders) {
- BrooklynClassLoadingContext result = provider.apply(contextObject);
- if (result!=null) return result;
- }
-
- BrooklynClassLoadingContext bl = BrooklynLoaderTracker.getLoader();
- ManagementContext mgmt = (bl!=null ? bl.getManagementContext() : null);
-
- ClassLoader cl = loader;
- if (cl==null) cl = contextObject instanceof Class ? ((Class<?>)contextObject).getClassLoader() :
- contextObject instanceof ClassLoader ? ((ClassLoader)contextObject) :
- contextObject.getClass().getClassLoader();
-
- return JavaBrooklynClassLoadingContext.create(mgmt, cl);
- }
-
- /** This should not be exposed as it risks it leaking into places where it would be serialized.
- * Better for callers use {@link CatalogUtils#getClassLoadingContext(org.apache.brooklyn.api.entity.Entity)} or similar. }.
- */
- private BrooklynClassLoadingContext getLoader() {
- return (loader!=null ? loader : getClassLoadingContextInternal(null, contextObject!=null ? contextObject : this));
- }
-
- /**
- * @return all resources in Brooklyn's {@link BrooklynClassLoadingContext} with the given name.
- */
- public Iterable<URL> getResources(String name) {
- return getLoader().getResources(name);
- }
-
- /**
- * Takes a string which is treated as a URL (with some extended "schemes" also expected),
- * or as a path to something either on the classpath (absolute only) or the local filesystem (relative or absolute, depending on leading slash)
- * <p>
- * URLs can be of the form <b>classpath://com/acme/Foo.properties</b>
- * as well as <b>file:///home/...</b> and <b>http://acme.com/...</b>.
- * <p>
- * Throws exception if not found, using the context parameter passed into the constructor.
- * <p>
- * TODO may want OSGi, or typed object; should consider pax url
- *
- * @return a stream, or throws exception (never returns null)
- */
- public InputStream getResourceFromUrl(String url) {
- try {
- if (url==null) throw new NullPointerException("Cannot read from null");
- if (url=="") throw new NullPointerException("Cannot read from empty string");
- String orig = url;
- String protocol = Urls.getProtocol(url);
- if (protocol!=null) {
- if ("classpath".equals(protocol)) {
- try {
- return getResourceViaClasspath(url);
- } catch (IOException e) {
- //catch the above because both orig and modified url may be interesting
- throw new IOException("Error accessing "+orig+": "+e, e);
- }
- }
- if ("sftp".equals(protocol)) {
- try {
- return getResourceViaSftp(url);
- } catch (IOException e) {
- throw new IOException("Error accessing "+orig+": "+e, e);
- }
- }
-
- if ("file".equals(protocol))
- url = tidyFileUrl(url);
-
- if ("data".equals(protocol)) {
- return new DataUriSchemeParser(url).lax().parse().getDataAsInputStream();
- }
-
- if ("http".equals(protocol) || "https".equals(protocol)) {
- return getResourceViaHttp(url);
- }
-
- return new URL(url).openStream();
- }
-
- try {
- //try as classpath reference, then as file
- try {
- URL u = getLoader().getResource(url);
- if (u!=null) return u.openStream();
- } catch (IllegalArgumentException e) {
- //Felix installs an additional URL to the system classloader
- //which throws an IllegalArgumentException when passed a
- //windows path. See ExtensionManager.java static initializer.
-
- //ignore, not a classpath resource
- }
- if (url.startsWith("/")) {
- //some getResource calls fail if argument starts with /
- String urlNoSlash = url;
- while (urlNoSlash.startsWith("/")) urlNoSlash = urlNoSlash.substring(1);
- URL u = getLoader().getResource(urlNoSlash);
- if (u!=null) return u.openStream();
-// //Class.getResource can require a / (else it attempts to be relative) but Class.getClassLoader doesn't
-// u = getLoader().getResource("/"+urlNoSlash);
-// if (u!=null) return u.openStream();
- }
- File f;
- // but first, if it starts with tilde, treat specially
- if (url.startsWith("~/")) {
- f = new File(Os.home(), url.substring(2));
- } else if (url.startsWith("~\\")) {
- f = new File(Os.home(), url.substring(2));
- } else {
- f = new File(url);
- }
- if (f.exists()) return new FileInputStream(f);
- } catch (IOException e) {
- //catch the above because both u and modified url will be interesting
- throw new IOException("Error accessing "+orig+": "+e, e);
- }
- throw new IOException("'"+orig+"' not found on classpath or filesystem");
- } catch (Exception e) {
- if (context!=null) {
- throw new RuntimeException("Error getting resource '"+url+"' for "+context+": "+e, e);
- } else {
- throw Exceptions.propagate(e);
- }
- }
- }
-
- private final static Pattern pattern = Pattern.compile("^file:/*~/+(.*)$");
-
- public static URL tidy(URL url) {
- // File class has helpful methods for URIs but not URLs. So we convert.
- URI in;
- try {
- in = url.toURI();
- } catch (URISyntaxException e) {
- throw Exceptions.propagate(e);
- }
- URI out;
-
- Matcher matcher = pattern.matcher(in.toString());
- if (matcher.matches()) {
- // home-relative
- File home = new File(Os.home());
- File file = new File(home, matcher.group(1));
- out = file.toURI();
- } else if (in.getScheme().equals("file:")) {
- // some other file, so canonicalize
- File file = new File(in);
- out = file.toURI();
- } else {
- // some other scheme, so no-op
- out = in;
- }
-
- URL urlOut;
- try {
- urlOut = out.toURL();
- } catch (MalformedURLException e) {
- throw Exceptions.propagate(e);
- }
- if (!urlOut.equals(url) && log.isDebugEnabled()) {
- log.debug("quietly changing " + url + " to " + urlOut);
- }
- return urlOut;
- }
-
- public static String tidyFileUrl(String url) {
- try {
- return tidy(new URL(url)).toString();
- } catch (MalformedURLException e) {
- throw Exceptions.propagate(e);
- }
- }
-
- /** @deprecated since 0.7.0; use method {@link Os#mergePaths(String...)} */ @Deprecated
- public static String mergeFilePaths(String... items) {
- return Os.mergePaths(items);
- }
-
- /** @deprecated since 0.7.0; use method {@link Os#tidyPath(String)} */ @Deprecated
- public static String tidyFilePath(String path) {
- return Os.tidyPath(path);
- }
-
- /** @deprecated since 0.7.0; use method {@link Urls#getProtocol(String)} */ @Deprecated
- public static String getProtocol(String url) {
- return Urls.getProtocol(url);
- }
-
- private InputStream getResourceViaClasspath(String url) throws IOException {
- assert url.startsWith("classpath:");
- String subUrl = url.substring("classpath:".length());
- while (subUrl.startsWith("/")) subUrl = subUrl.substring(1);
- URL u = getLoader().getResource(subUrl);
- if (u!=null) return u.openStream();
- else throw new IOException(subUrl+" not found on classpath");
- }
-
- private InputStream getResourceViaSftp(String url) throws IOException {
- assert url.startsWith("sftp://");
- String subUrl = url.substring("sftp://".length());
- String user;
- String address;
- String path;
- int atIndex = subUrl.indexOf("@");
- int colonIndex = subUrl.indexOf(":", (atIndex > 0 ? atIndex : 0));
- if (colonIndex <= 0 || colonIndex <= atIndex) {
- throw new IllegalArgumentException("Invalid sftp url ("+url+"); IP or hostname must be specified, such as sftp://localhost:/path/to/file");
- }
- if (subUrl.length() <= (colonIndex+1)) {
- throw new IllegalArgumentException("Invalid sftp url ("+url+"); must specify path of remote file, such as sftp://localhost:/path/to/file");
- }
- if (atIndex >= 0) {
- user = subUrl.substring(0, atIndex);
- } else {
- user = null;
- }
- address = subUrl.substring(atIndex + 1, colonIndex);
- path = subUrl.substring(colonIndex+1);
-
- // TODO messy way to get an SCP session
- SshMachineLocation machine = new SshMachineLocation(MutableMap.builder()
- .putIfNotNull("user", user)
- .put("address", InetAddress.getByName(address))
- .build());
- try {
- final File tempFile = Os.newTempFile("brooklyn-sftp", "tmp");
- tempFile.setReadable(true, true);
- machine.copyFrom(path, tempFile.getAbsolutePath());
- return new FileInputStream(tempFile) {
- @Override
- public void close() throws IOException {
- super.close();
- tempFile.delete();
- }
- };
- } finally {
- Streams.closeQuietly(machine);
- }
- }
-
- //For HTTP(S) targets use HttpClient so
- //we can do authentication
- private InputStream getResourceViaHttp(String resource) throws IOException {
- URI uri = URI.create(resource);
- HttpClientBuilder builder = HttpTool.httpClientBuilder()
- .laxRedirect(true)
- .uri(uri);
- Credentials credentials = getUrlCredentials(uri.getRawUserInfo());
- if (credentials != null) {
- builder.credentials(credentials);
- }
- HttpClient client = builder.build();
- HttpResponse result = client.execute(new HttpGet(resource));
- int statusCode = result.getStatusLine().getStatusCode();
- if (HttpTool.isStatusCodeHealthy(statusCode)) {
- HttpEntity entity = result.getEntity();
- if (entity != null) {
- return entity.getContent();
- } else {
- return new ByteArrayInputStream(new byte[0]);
- }
- } else {
- EntityUtils.consume(result.getEntity());
- throw new IllegalStateException("Invalid response invoking " + resource + ": response code " + statusCode);
- }
- }
-
- private Credentials getUrlCredentials(String userInfo) {
- if (userInfo != null) {
- String[] arr = userInfo.split(":");
- String username;
- String password = null;
- if (arr.length == 1) {
- username = urlDecode(arr[0]);
- } else if (arr.length == 2) {
- username = urlDecode(arr[0]);
- password = urlDecode(arr[1]);
- } else {
- return null;
- }
- return new UsernamePasswordCredentials(username, password);
- } else {
- return null;
- }
- }
-
- private String urlDecode(String str) {
- try {
- return URLDecoder.decode(str, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- throw Exceptions.propagate(e);
- }
- }
-
- /** takes {@link #getResourceFromUrl(String)} and reads fully, into a string */
- public String getResourceAsString(String url) {
- try {
- return readFullyString(getResourceFromUrl(url));
- } catch (Exception e) {
- log.debug("ResourceUtils got error reading "+url+(context==null?"":" "+context)+" (rethrowing): "+e);
- throw Throwables.propagate(e);
- }
- }
-
- /** allows failing-fast if URL cannot be read */
- public String checkUrlExists(String url) {
- return checkUrlExists(url, null);
- }
-
- public String checkUrlExists(String url, String message) {
- if (url==null) throw new NullPointerException("URL "+(message!=null ? message+" " : "")+"must not be null");
- InputStream s;
- try {
- s = getResourceFromUrl(url);
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- throw new IllegalArgumentException("Unable to access URL "+(message!=null ? message : "")+": "+url, e);
- }
- Streams.closeQuietly(s);
- return url;
- }
-
- /** tests whether the url exists, returning true or false */
- public boolean doesUrlExist(String url) {
- InputStream s = null;
- try {
- s = getResourceFromUrl(url);
- return true;
- } catch (Exception e) {
- return false;
- } finally {
- Streams.closeQuietly(s);
- }
- }
-
- /** returns the first available URL */
- public Optional<String> firstAvailableUrl(String ...urls) {
- for (String url: urls) {
- if (doesUrlExist(url)) return Optional.of(url);
- }
- return Optional.absent();
- }
-
- /** returns the base directory or JAR from which the context is class-loaded, if possible;
- * throws exception if not found */
- public String getClassLoaderDir() {
- if (contextObject==null) throw new IllegalArgumentException("No suitable context ("+context+") to auto-detect classloader dir");
- Class<?> cc = contextObject instanceof Class ? (Class<?>)contextObject : contextObject.getClass();
- return getClassLoaderDir(cc.getCanonicalName().replace('.', '/')+".class");
- }
-
- public String getClassLoaderDir(String resourceInThatDir) {
- resourceInThatDir = Strings.removeFromStart(resourceInThatDir, "/");
- URL resourceUrl = getLoader().getResource(resourceInThatDir);
- if (resourceUrl==null) throw new NoSuchElementException("Resource ("+resourceInThatDir+") not found");
-
- URL containerUrl = getContainerUrl(resourceUrl, resourceInThatDir);
-
- if (!"file".equals(containerUrl.getProtocol())) throw new IllegalStateException("Resource ("+resourceInThatDir+") not on file system (at "+containerUrl+")");
-
- //convert from file: URL to File
- File file;
- try {
- file = new File(containerUrl.toURI());
- } catch (URISyntaxException e) {
- throw new IllegalStateException("Resource ("+resourceInThatDir+") found at invalid URI (" + containerUrl + ")", e);
- }
-
- if (!file.exists()) throw new IllegalStateException("Context class url substring ("+containerUrl+") not found on filesystem");
- return file.getPath();
-
- }
-
- public static URL getContainerUrl(URL url, String resourceInThatDir) {
- //Switching from manual parsing of jar: and file: URLs to java provided functionality.
- //The old code was breaking on any Windows path and instead of fixing it, using
- //the provided Java APIs seemed like the better option since they are already tested
- //on multiple platforms.
- boolean isJar = "jar".equals(url.getProtocol());
- if(isJar) {
- try {
- //let java handle the parsing of jar URL, no network connection is established.
- //Strips the jar protocol:
- // jar:file:/<path to jar>!<resourceInThatDir>
- // becomes
- // file:/<path to jar>
- JarURLConnection connection = (JarURLConnection) url.openConnection();
- url = connection.getJarFileURL();
- } catch (IOException e) {
- throw new IllegalStateException(e);
- }
- } else {
- //Remove the trailing resouceInThatDir path from the URL, thus getting the parent folder.
- String path = url.toString();
- int i = path.indexOf(resourceInThatDir);
- if (i==-1) throw new IllegalStateException("Resource path ("+resourceInThatDir+") not in url substring ("+url+")");
- String parent = path.substring(0, i);
- try {
- url = new URL(parent);
- } catch (MalformedURLException e) {
- throw new IllegalStateException("Resource ("+resourceInThatDir+") found at invalid URL parent (" + parent + ")", e);
- }
- }
- return url;
- }
-
- /** @deprecated since 0.7.0 use {@link Streams#readFullyString(InputStream) */ @Deprecated
- public static String readFullyString(InputStream is) throws IOException {
- return Streams.readFullyString(is);
- }
-
- /** @deprecated since 0.7.0 use {@link Streams#readFully(InputStream) */ @Deprecated
- public static byte[] readFullyBytes(InputStream is) throws IOException {
- return Streams.readFully(is);
- }
-
- /** @deprecated since 0.7.0 use {@link Streams#copy(InputStream, OutputStream)} */ @Deprecated
- public static void copy(InputStream input, OutputStream output) throws IOException {
- Streams.copy(input, output);
- }
-
- /** @deprecated since 0.7.0; use same method in {@link Os} */ @Deprecated
- public static File mkdirs(File dir) {
- return Os.mkdirs(dir);
- }
-
- /** @deprecated since 0.7.0; use same method in {@link Os} */ @Deprecated
- public static File writeToTempFile(InputStream is, String prefix, String suffix) {
- return Os.writeToTempFile(is, prefix, suffix);
- }
-
- /** @deprecated since 0.7.0; use same method in {@link Os} */ @Deprecated
- public static File writeToTempFile(InputStream is, File tempDir, String prefix, String suffix) {
- return Os.writeToTempFile(is, tempDir, prefix, suffix);
- }
-
- /** @deprecated since 0.7.0; use method {@link Os#writePropertiesToTempFile(Properties, String, String)} */ @Deprecated
- public static File writeToTempFile(Properties props, String prefix, String suffix) {
- return Os.writePropertiesToTempFile(props, prefix, suffix);
- }
-
- /** @deprecated since 0.7.0; use method {@link Os#writePropertiesToTempFile(Properties, File, String, String)} */ @Deprecated
- public static File writeToTempFile(Properties props, File tempDir, String prefix, String suffix) {
- return Os.writePropertiesToTempFile(props, tempDir, prefix, suffix);
- }
-
- /** @deprecated since 0.7.0; use method {@link Threads#addShutdownHook(Runnable)} */ @Deprecated
- public static Thread addShutdownHook(final Runnable task) {
- return Threads.addShutdownHook(task);
- }
- /** @deprecated since 0.7.0; use method {@link Threads#removeShutdownHook(Thread)} */ @Deprecated
- public static boolean removeShutdownHook(Thread hook) {
- return Threads.removeShutdownHook(hook);
- }
-
- /** returns the items with exactly one "/" between items (whether or not the individual items start or end with /),
- * except where character before the / is a : (url syntax) in which case it will permit multiple (will not remove any)
- * @deprecated since 0.7.0 use either {@link Os#mergePathsUnix(String...)} {@link Urls#mergePaths(String...) */ @Deprecated
- public static String mergePaths(String ...items) {
- return Urls.mergePaths(items);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/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
deleted file mode 100644
index 2f17748..0000000
--- a/core/src/main/java/brooklyn/util/config/ConfigBag.java
+++ /dev/null
@@ -1,588 +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 brooklyn.util.config;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.ConcurrentModificationException;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-import javax.annotation.Nonnull;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.config.ConfigKey.HasConfigKey;
-import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.flags.TypeCoercions;
-import brooklyn.util.guava.Maybe;
-import brooklyn.util.javalang.JavaClassNames;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Objects;
-import com.google.common.collect.Sets;
-
-/**
- * Stores config in such a way that usage can be tracked.
- * Either {@link ConfigKey} or {@link String} keys can be inserted;
- * they will be stored internally as strings.
- * It is recommended to use {@link ConfigKey} instances to access,
- * although in some cases (such as setting fields from flags, or copying a map)
- * it may be necessary to mark things as used, or put, when only a string key is available.
- * <p>
- * This bag is order-preserving and thread-safe except where otherwise indicated,
- * currently by synching on this instance (but that behaviour may change).
- * <p>
- * @author alex
- */
-public class ConfigBag {
-
- private static final Logger log = LoggerFactory.getLogger(ConfigBag.class);
-
- /** an immutable, empty ConfigBag */
- public static final ConfigBag EMPTY = new ConfigBag().setDescription("immutable empty config bag").seal();
-
- protected String description;
-
- private Map<String,Object> config;
- private final Map<String,Object> unusedConfig;
- private final boolean live;
- private boolean sealed = false;
-
- /** creates a new ConfigBag instance, empty and ready for population */
- public static ConfigBag newInstance() {
- return new ConfigBag();
- }
-
- /**
- * Creates an instance that is backed by a "live map" (e.g. storage in a datagrid).
- * The order-preserving nature of this class is only guaranteed if the
- * provided storage has those properties. External modifications to the store can cause
- * {@link ConcurrentModificationException} to be thrown, here or elsewhere.
- */
- public static ConfigBag newLiveInstance(Map<String,Object> storage) {
- return new ConfigBag(checkNotNull(storage, "storage map must be specified"));
- }
-
- public static ConfigBag newInstance(Map<?, ?> config) {
- ConfigBag result = new ConfigBag();
- result.putAll(config);
- return result;
- }
-
- /** creates a new ConfigBag instance which includes all of the supplied ConfigBag's values,
- * but which tracks usage separately (already used values are marked as such,
- * but uses in the original set will not be marked here, and vice versa) */
- public static ConfigBag newInstanceCopying(final ConfigBag configBag) {
- return new ConfigBag().copy(configBag).setDescription(configBag.getDescription());
- }
-
- /** creates a new ConfigBag instance which includes all of the supplied ConfigBag's values,
- * plus an additional set of <ConfigKey,Object> or <String,Object> pairs
- * <p>
- * values from the original set which are used here will be marked as used in the original set
- * (note: this applies even for values which are overridden and the overridden value is used);
- * however subsequent uses in the original set will not be marked here
- */
- @Beta
- public static ConfigBag newInstanceExtending(final ConfigBag parentBag) {
- return new ConfigBagExtendingParent(parentBag);
- }
-
- /** @see #newInstanceExtending(ConfigBag) */
- private static class ConfigBagExtendingParent extends ConfigBag {
- ConfigBag parentBag;
- private ConfigBagExtendingParent(ConfigBag parentBag) {
- this.parentBag = parentBag;
- copy(parentBag);
- }
- @Override
- public void markUsed(String key) {
- super.markUsed(key);
- if (parentBag!=null)
- parentBag.markUsed(key);
- }
- }
-
- /** As {@link #newInstanceExtending(ConfigBag)} but also putting the supplied values. */
- @Beta
- public static ConfigBag newInstanceExtending(final ConfigBag configBag, Map<?,?> optionalAdditionalValues) {
- return newInstanceExtending(configBag).putAll(optionalAdditionalValues);
- }
-
- /** @deprecated since 0.7.0, not used; kept only for rebind compatibility where the inner class is used
- * (now replaced by a static class above) */
- @Beta @Deprecated
- public static ConfigBag newInstanceWithInnerClass(final ConfigBag configBag, Map<?,?> optionalAdditionalValues) {
- return new ConfigBag() {
- @Override
- public void markUsed(String key) {
- super.markUsed(key);
- configBag.markUsed(key);
- }
- }.copy(configBag).putAll(optionalAdditionalValues);
- }
-
- public ConfigBag() {
- config = new LinkedHashMap<String,Object>();
- unusedConfig = new LinkedHashMap<String,Object>();
- live = false;
- }
-
- private ConfigBag(Map<String,Object> storage) {
- this.config = storage;
- unusedConfig = new LinkedHashMap<String,Object>();
- live = true;
- }
-
- public ConfigBag setDescription(String description) {
- if (sealed)
- throw new IllegalStateException("Cannot set description to '"+description+"': this config bag has been sealed and is now immutable.");
- this.description = description;
- return this;
- }
-
- /** optional description used to provide context for operations */
- public String getDescription() {
- return description;
- }
-
- /** current values for all entries
- * @return non-modifiable map of strings to object */
- public synchronized Map<String,Object> getAllConfig() {
- return MutableMap.copyOf(config).asUnmodifiable();
- }
-
- /** current values for all entries in a map where the keys are converted to {@link ConfigKey} instances */
- public synchronized Map<ConfigKey<?>, ?> getAllConfigAsConfigKeyMap() {
- Map<ConfigKey<?>,Object> result = MutableMap.of();
- for (Map.Entry<String,Object> entry: config.entrySet()) {
- result.put(ConfigKeys.newConfigKey(Object.class, entry.getKey()), entry.getValue());
- }
- return result;
- }
-
- /** Returns the internal map containing the current values for all entries;
- * for use where the caller wants to modify this directly and knows it is safe to do so
- * <p>
- * Accesses to the returned map must be synchronized on this bag if the
- * thread-safe behaviour is required. */
- public Map<String,Object> getAllConfigMutable() {
- if (live) {
- // TODO sealed no longer works as before, because `config` is the backing storage map.
- // Therefore returning it is dangerous! Even if we were to replace our field with an immutable copy,
- // the underlying datagrid's map would still be modifiable. We need a way to switch the returned
- // value's behaviour to sealable (i.e. wrapping the returned map).
- return (sealed) ? MutableMap.copyOf(config).asUnmodifiable() : config;
- } else {
- return config;
- }
- }
-
- /** current values for all entries which have not yet been used
- * @return non-modifiable map of strings to object */
- public synchronized Map<String,Object> getUnusedConfig() {
- return MutableMap.copyOf(unusedConfig).asUnmodifiable();
- }
-
- /** Returns the internal map containing the current values for all entries which have not yet been used;
- * for use where the caller wants to modify this directly and knows it is safe to do so
- * <p>
- * Accesses to the returned map must be synchronized on this bag if the
- * thread-safe behaviour is required. */
- public Map<String,Object> getUnusedConfigMutable() {
- return unusedConfig;
- }
-
- public ConfigBag putAll(Map<?,?> addlConfig) {
- if (addlConfig==null) return this;
- for (Map.Entry<?,?> e: addlConfig.entrySet()) {
- putAsStringKey(e.getKey(), e.getValue());
- }
- return this;
- }
-
- public ConfigBag putAll(ConfigBag addlConfig) {
- return putAll(addlConfig.getAllConfig());
- }
-
- public <T> ConfigBag putIfAbsent(ConfigKey<T> key, T value) {
- return putIfAbsent(MutableMap.of(key, value));
- }
-
- public ConfigBag putAsStringKeyIfAbsent(Object key, Object value) {
- return putIfAbsent(MutableMap.of(key, value));
- }
-
- public synchronized ConfigBag putIfAbsent(Map<?, ?> propertiesToSet) {
- if (propertiesToSet==null)
- return this;
- for (Map.Entry<?, ?> entry: propertiesToSet.entrySet()) {
- Object key = entry.getKey();
- if (key instanceof HasConfigKey<?>)
- key = ((HasConfigKey<?>)key).getConfigKey();
- if (key instanceof ConfigKey<?>) {
- if (!containsKey((ConfigKey<?>)key))
- putAsStringKey(key, entry.getValue());
- } else if (key instanceof String) {
- if (!containsKey((String)key))
- putAsStringKey(key, entry.getValue());
- } else {
- logInvalidKey(key);
- }
- }
- return this;
- }
-
- public ConfigBag putIfAbsent(ConfigBag addlConfig) {
- return putIfAbsent(addlConfig.getAllConfig());
- }
-
-
- @SuppressWarnings("unchecked")
- public <T> T put(ConfigKey<T> key, T value) {
- return (T) putStringKey(key.getName(), value);
- }
-
- public <T> ConfigBag putIfNotNull(ConfigKey<T> key, T value) {
- if (value!=null) put(key, value);
- return this;
- }
-
- public <T> ConfigBag putIfAbsentAndNotNull(ConfigKey<T> key, T value) {
- if (value!=null) putIfAbsent(key, value);
- return this;
- }
-
- /** as {@link #put(ConfigKey, Object)} but returning this ConfigBag for fluent-style coding */
- public <T> ConfigBag configure(ConfigKey<T> key, T value) {
- putStringKey(key.getName(), value);
- return this;
- }
-
- public <T> ConfigBag configureStringKey(String key, T value) {
- putStringKey(key, value);
- return this;
- }
-
- protected synchronized void putAsStringKey(Object key, Object value) {
- if (key instanceof HasConfigKey<?>) key = ((HasConfigKey<?>)key).getConfigKey();
- if (key instanceof ConfigKey<?>) key = ((ConfigKey<?>)key).getName();
- if (key instanceof String) {
- putStringKey((String)key, value);
- } else {
- logInvalidKey(key);
- }
- }
-
- protected void logInvalidKey(Object key) {
- String message = (key == null ? "Invalid key 'null'" : "Invalid key type "+key.getClass().getCanonicalName()+" ("+key+")") +
- " being used for configuration, ignoring";
- log.debug(message, new Throwable("Source of "+message));
- log.warn(message);
- }
-
- /** recommended to use {@link #put(ConfigKey, Object)} but there are times
- * (e.g. when copying a map) where we want to put a string key directly
- */
- public synchronized Object putStringKey(String key, Object value) {
- if (sealed)
- throw new IllegalStateException("Cannot insert "+key+"="+value+": this config bag has been sealed and is now immutable.");
- boolean isNew = !config.containsKey(key);
- boolean isUsed = !isNew && !unusedConfig.containsKey(key);
- Object old = config.put(key, value);
- if (!isUsed)
- unusedConfig.put(key, value);
- //if (!isNew && !isUsed) log.debug("updating config value which has already been used");
- return old;
- }
- public Object putStringKeyIfHasValue(String key, Maybe<?> value) {
- if (value.isPresent())
- return putStringKey(key, value.get());
- return null;
- }
- public Object putStringKeyIfNotNull(String key, Object value) {
- if (value!=null)
- return putStringKey(key, value);
- return null;
- }
-
- public boolean containsKey(HasConfigKey<?> key) {
- return containsKey(key.getConfigKey());
- }
-
- public boolean containsKey(ConfigKey<?> key) {
- return containsKey(key.getName());
- }
-
- public synchronized boolean containsKey(String key) {
- return config.containsKey(key);
- }
-
- /** returns the value of this config key, falling back to its default (use containsKey to see whether it was contained);
- * also marks it as having been used (use peek to prevent marking as used)
- */
- public <T> T get(ConfigKey<T> key) {
- return get(key, true);
- }
-
- /** gets a value from a string-valued key or null; ConfigKey is preferred, but this is useful in some contexts (e.g. setting from flags) */
- public Object getStringKey(String key) {
- return getStringKeyMaybe(key).orNull();
- }
- /** gets a {@link Maybe}-wrapped value from a string-valued key; ConfigKey is preferred, but this is useful in some contexts (e.g. setting from flags) */
- public @Nonnull Maybe<Object> getStringKeyMaybe(String key) {
- return getStringKeyMaybe(key, true);
- }
-
- /** gets a {@link Maybe}-wrapped value from a key, inferring the type of that key (e.g. {@link ConfigKey} or {@link String}) */
- @Beta
- public Maybe<Object> getObjKeyMaybe(Object key) {
- if (key instanceof HasConfigKey<?>) key = ((HasConfigKey<?>)key).getConfigKey();
- if (key instanceof ConfigKey<?>) key = ((ConfigKey<?>)key).getName();
- if (key instanceof String) {
- return getStringKeyMaybe((String)key, true);
- } else {
- logInvalidKey(key);
- return Maybe.absent();
- }
- }
-
- /** like get, but without marking it as used */
- public <T> T peek(ConfigKey<T> key) {
- return get(key, false);
- }
-
- /** returns the first key in the list for which a value is explicitly set, then defaulting to defaulting value of preferred key */
- public synchronized <T> T getFirst(ConfigKey<T> preferredKey, ConfigKey<T> ...otherCurrentKeysInOrderOfPreference) {
- if (containsKey(preferredKey))
- return get(preferredKey);
- for (ConfigKey<T> key: otherCurrentKeysInOrderOfPreference) {
- if (containsKey(key))
- return get(key);
- }
- return get(preferredKey);
- }
-
- /** convenience for @see #getWithDeprecation(ConfigKey[], ConfigKey...) */
- public Object getWithDeprecation(ConfigKey<?> key, ConfigKey<?> ...deprecatedKeys) {
- return getWithDeprecation(new ConfigKey[] { key }, deprecatedKeys);
- }
-
- /** returns the value for the first key in the list for which a value is set,
- * warning if any of the deprecated keys have a value which is different to that set on the first set current key
- * (including warning if a deprecated key has a value but no current key does) */
- public synchronized Object getWithDeprecation(ConfigKey<?>[] currentKeysInOrderOfPreference, ConfigKey<?> ...deprecatedKeys) {
- // Get preferred key (or null)
- ConfigKey<?> preferredKeyProvidingValue = null;
- Object result = null;
- boolean found = false;
- for (ConfigKey<?> key: currentKeysInOrderOfPreference) {
- if (containsKey(key)) {
- preferredKeyProvidingValue = key;
- result = get(preferredKeyProvidingValue);
- found = true;
- break;
- }
- }
-
- // Check if any deprecated keys are set
- ConfigKey<?> deprecatedKeyProvidingValue = null;
- Object deprecatedResult = null;
- boolean foundDeprecated = false;
- for (ConfigKey<?> deprecatedKey: deprecatedKeys) {
- Object x = null;
- boolean foundX = false;
- if (containsKey(deprecatedKey)) {
- x = get(deprecatedKey);
- foundX = true;
- }
- if (foundX) {
- if (found) {
- if (!Objects.equal(result, x)) {
- log.warn("Conflicting value from deprecated key " +deprecatedKey+", value "+x+
- "; using preferred key "+preferredKeyProvidingValue+" value "+result);
- } else {
- log.info("Deprecated key " +deprecatedKey+" ignored; has same value as preferred key "+preferredKeyProvidingValue+" ("+result+")");
- }
- } else if (foundDeprecated) {
- if (!Objects.equal(result, x)) {
- log.warn("Conflicting values from deprecated keys: using " +deprecatedKeyProvidingValue+" instead of "+deprecatedKey+
- " (value "+deprecatedResult+" instead of "+x+")");
- } else {
- log.info("Deprecated key " +deprecatedKey+" ignored; has same value as other deprecated key "+preferredKeyProvidingValue+" ("+deprecatedResult+")");
- }
- } else {
- // new value, from deprecated key
- log.warn("Deprecated key " +deprecatedKey+" detected (supplying value "+x+"), "+
- "; recommend changing to preferred key '"+currentKeysInOrderOfPreference[0]+"'; this will not be supported in future versions");
- deprecatedResult = x;
- deprecatedKeyProvidingValue = deprecatedKey;
- foundDeprecated = true;
- }
- }
- }
-
- if (found) {
- return result;
- } else if (foundDeprecated) {
- return deprecatedResult;
- } else {
- return currentKeysInOrderOfPreference[0].getDefaultValue();
- }
- }
-
- protected <T> T get(ConfigKey<T> key, boolean markUsed) {
- // TODO for now, no evaluation -- maps / closure content / other smart (self-extracting) keys are NOT supported
- // (need a clean way to inject that behaviour, as well as desired TypeCoercions)
- // this method, and the coercion, is not synchronized, nor does it need to be, because the "get" is synchronized.
- return coerceFirstNonNullKeyValue(key, getStringKey(key.getName(), markUsed));
- }
-
- /** returns the first non-null value to be the type indicated by the key, or the keys default value if no non-null values are supplied */
- public static <T> T coerceFirstNonNullKeyValue(ConfigKey<T> key, Object ...values) {
- for (Object o: values)
- if (o!=null) return TypeCoercions.coerce(o, key.getTypeToken());
- return TypeCoercions.coerce(key.getDefaultValue(), key.getTypeToken());
- }
-
- protected Object getStringKey(String key, boolean markUsed) {
- return getStringKeyMaybe(key, markUsed).orNull();
- }
- protected synchronized Maybe<Object> getStringKeyMaybe(String key, boolean markUsed) {
- if (config.containsKey(key)) {
- if (markUsed) markUsed(key);
- return Maybe.of(config.get(key));
- }
- return Maybe.absent();
- }
-
- /** indicates that a string key in the config map has been accessed */
- public synchronized void markUsed(String key) {
- unusedConfig.remove(key);
- }
-
- public synchronized void clear() {
- if (sealed)
- throw new IllegalStateException("Cannot clear this config bag has been sealed and is now immutable.");
- config.clear();
- unusedConfig.clear();
- }
-
- public ConfigBag removeAll(ConfigKey<?> ...keys) {
- for (ConfigKey<?> key: keys) remove(key);
- return this;
- }
-
- public synchronized void remove(ConfigKey<?> key) {
- remove(key.getName());
- }
-
- public ConfigBag removeAll(Iterable<String> keys) {
- for (String key: keys) remove(key);
- return this;
- }
-
- public synchronized void remove(String key) {
- if (sealed)
- throw new IllegalStateException("Cannot remove "+key+": this config bag has been sealed and is now immutable.");
- config.remove(key);
- unusedConfig.remove(key);
- }
-
- public ConfigBag copy(ConfigBag other) {
- // ensure locks are taken in a canonical order to prevent deadlock
- if (other==null) {
- synchronized (this) {
- return copyWhileSynched(other);
- }
- }
- if (System.identityHashCode(other) < System.identityHashCode(this)) {
- synchronized (other) {
- synchronized (this) {
- return copyWhileSynched(other);
- }
- }
- } else {
- synchronized (this) {
- synchronized (other) {
- return copyWhileSynched(other);
- }
- }
- }
- }
-
- protected ConfigBag copyWhileSynched(ConfigBag other) {
- if (sealed)
- throw new IllegalStateException("Cannot copy "+other+" to "+this+": this config bag has been sealed and is now immutable.");
- putAll(other.getAllConfig());
- markAll(Sets.difference(other.getAllConfig().keySet(), other.getUnusedConfig().keySet()));
- setDescription(other.getDescription());
- return this;
- }
-
- public synchronized int size() {
- return config.size();
- }
-
- public synchronized boolean isEmpty() {
- return config.isEmpty();
- }
-
- public ConfigBag markAll(Iterable<String> usedFlags) {
- for (String flag: usedFlags)
- markUsed(flag);
- return this;
- }
-
- public synchronized boolean isUnused(ConfigKey<?> key) {
- return unusedConfig.containsKey(key.getName());
- }
-
- /** makes this config bag immutable; any attempts to change subsequently
- * (apart from marking fields as used) will throw an exception
- * <p>
- * copies will be unsealed however
- * <p>
- * returns this for convenience (fluent usage) */
- public ConfigBag seal() {
- sealed = true;
- if (live) {
- // TODO How to ensure sealed?!
- } else {
- config = getAllConfig();
- }
- return this;
- }
-
- // TODO why have both this and mutable
- /** @see #getAllConfigMutable() */
- public Map<String, Object> getAllConfigRaw() {
- return getAllConfigMutable();
- }
-
- @Override
- public String toString() {
- return JavaClassNames.simpleClassName(this)+"["+getAllConfigRaw()+"]";
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/crypto/FluentKeySigner.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/crypto/FluentKeySigner.java b/core/src/main/java/brooklyn/util/crypto/FluentKeySigner.java
deleted file mode 100644
index a1bc125..0000000
--- a/core/src/main/java/brooklyn/util/crypto/FluentKeySigner.java
+++ /dev/null
@@ -1,192 +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 brooklyn.util.crypto;
-
-import java.math.BigInteger;
-import java.security.KeyPair;
-import java.security.PublicKey;
-import java.security.SecureRandom;
-import java.security.cert.CertificateParsingException;
-import java.security.cert.X509Certificate;
-import java.util.Date;
-
-import javax.security.auth.x500.X500Principal;
-
-import org.apache.brooklyn.core.internal.BrooklynInitialization;
-import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
-import org.bouncycastle.asn1.x509.X509Extension;
-import org.bouncycastle.jce.X509Principal;
-
-import brooklyn.util.exceptions.Exceptions;
-
-/** A fluent API which simplifies generating certificates (signed keys) */
-/* NB - re deprecation - we use deprecated X509V3CertificateGenerator still
- * because the official replacement, X509v3CertificateBuilder,
- * drags in an add'l dependency (bcmail) and is harder to use. */
-public class FluentKeySigner {
-
- static { BrooklynInitialization.initSecureKeysBouncyCastleProvider(); }
-
- protected X500Principal issuerPrincipal;
- protected KeyPair issuerKey;
-
- protected SecureRandom srand = new SecureRandom();
-
- protected Date validityStartDate, validityEndDate;
- protected BigInteger serialNumber;
-
- protected String signatureAlgorithm = "MD5WithRSAEncryption";
- protected AuthorityKeyIdentifier authorityKeyIdentifier;
- protected X509Certificate authorityCertificate;
-
- public FluentKeySigner(X500Principal issuerPrincipal, KeyPair issuerKey) {
- this.issuerPrincipal = issuerPrincipal;
- this.issuerKey = issuerKey;
- validFromDaysAgo(7);
- validForYears(10);
- }
- public FluentKeySigner(String issuerCommonName, KeyPair issuerKey) {
- this(SecureKeys.getX500PrincipalWithCommonName(issuerCommonName), issuerKey);
- }
-
- public FluentKeySigner(String issuerCommonName) {
- this(issuerCommonName, SecureKeys.newKeyPair());
- }
-
- public FluentKeySigner(X509Certificate caCert, KeyPair caKey) {
- this(caCert.getIssuerX500Principal(), caKey);
- authorityCertificate(caCert);
- }
-
- public KeyPair getKey() {
- return issuerKey;
- }
-
- public X500Principal getPrincipal() {
- return issuerPrincipal;
- }
-
- @SuppressWarnings("deprecation")
- public String getCommonName() {
-// TODO see deprecation note at top of file
- // for modernising, would RFC4519Style.cn work ?
- return (String) new X509Principal(issuerPrincipal.getName()).getValues(org.bouncycastle.asn1.x509.X509Name.CN).elementAt(0);
- }
-
- public X509Certificate getAuthorityCertificate() {
- return authorityCertificate;
- }
-
- public FluentKeySigner validFromDaysAgo(long days) {
- return validFrom(new Date( (System.currentTimeMillis() / (1000L*60*60*24) - days) * 1000L*60*60*24));
- }
-
- public FluentKeySigner validFrom(Date d) {
- validityStartDate = d;
- return this;
- }
-
- public FluentKeySigner validForYears(long years) {
- return validUntil(new Date( (System.currentTimeMillis() / (1000L*60*60*24) + 365*years) * 1000L*60*60*24));
- }
-
- public FluentKeySigner validUntil(Date d) {
- validityEndDate = d;
- return this;
- }
-
- /** use a hard-coded serial number; or make one up, if null */
- public FluentKeySigner serialNumber(BigInteger serialNumber) {
- this.serialNumber = serialNumber;
- return this;
- }
-
- public FluentKeySigner signatureAlgorithm(String signatureAlgorithm) {
- this.signatureAlgorithm = signatureAlgorithm;
- return this;
- }
-
- @SuppressWarnings("deprecation")
- public FluentKeySigner authorityCertificate(X509Certificate certificate) {
- try {
- authorityKeyIdentifier(new org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure(certificate));
- this.authorityCertificate = certificate;
- return this;
- } catch (CertificateParsingException e) {
- throw Exceptions.propagate(e);
- }
- }
-
- public FluentKeySigner authorityKeyIdentifier(AuthorityKeyIdentifier authorityKeyIdentifier) {
- this.authorityKeyIdentifier = authorityKeyIdentifier;
- return this;
- }
-
- public FluentKeySigner selfsign() {
- if (authorityCertificate!=null) throw new IllegalStateException("Signer already has certificate");
- authorityCertificate(newCertificateFor(getCommonName(), getKey()));
- return this;
- }
-
- // TODO see note re deprecation at start of file
- @SuppressWarnings("deprecation")
- public X509Certificate newCertificateFor(X500Principal subject, PublicKey keyToCertify) {
- try {
- org.bouncycastle.x509.X509V3CertificateGenerator v3CertGen = new org.bouncycastle.x509.X509V3CertificateGenerator();
-
- v3CertGen.setSerialNumber(
- serialNumber != null ? serialNumber :
- // must be positive
- BigInteger.valueOf(srand.nextLong()).abs().add(BigInteger.ONE));
- v3CertGen.setIssuerDN(issuerPrincipal);
- v3CertGen.setNotBefore(validityStartDate);
- v3CertGen.setNotAfter(validityEndDate);
- v3CertGen.setSignatureAlgorithm(signatureAlgorithm);
-
- v3CertGen.setSubjectDN(subject);
- v3CertGen.setPublicKey(keyToCertify);
-
- v3CertGen.addExtension(X509Extension.subjectKeyIdentifier, false,
- new org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure(keyToCertify));
-
- if (authorityKeyIdentifier!=null)
- v3CertGen.addExtension(X509Extension.authorityKeyIdentifier, false,
- authorityKeyIdentifier);
-
- X509Certificate pkCertificate = v3CertGen.generate(issuerKey.getPrivate(), "BC");
- return pkCertificate;
-
- } catch (Exception e) {
- throw Exceptions.propagate(e);
- }
- }
-
- public X509Certificate newCertificateFor(String commonName, PublicKey key) {
-// SecureKeys.getX509PrincipalWithCommonName(commonName)
- return newCertificateFor(
- SecureKeys.getX500PrincipalWithCommonName(commonName)
-// new X509Principal("CN=" + commonName + ", OU=None, O=None, L=None, C=None")
- , key);
- }
-
- public X509Certificate newCertificateFor(String commonName, KeyPair key) {
- return newCertificateFor(commonName, key.getPublic());
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/crypto/SecureKeys.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/crypto/SecureKeys.java b/core/src/main/java/brooklyn/util/crypto/SecureKeys.java
deleted file mode 100644
index 29fcf32..0000000
--- a/core/src/main/java/brooklyn/util/crypto/SecureKeys.java
+++ /dev/null
@@ -1,184 +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 brooklyn.util.crypto;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.StringWriter;
-import java.security.KeyPair;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.Security;
-
-import org.apache.brooklyn.core.internal.BrooklynInitialization;
-import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
-import org.bouncycastle.jce.X509Principal;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.openssl.PEMDecryptorProvider;
-import org.bouncycastle.openssl.PEMEncryptedKeyPair;
-import org.bouncycastle.openssl.PEMKeyPair;
-import org.bouncycastle.openssl.PEMParser;
-import org.bouncycastle.openssl.PEMWriter;
-import org.bouncycastle.openssl.PasswordFinder;
-import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
-import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.stream.Streams;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Throwables;
-
-/**
- * Utility methods for generating and working with keys,
- * extending the parent class with useful things provided by BouncyCastle crypto library.
- * (Parent class is in a different project where BC is not included as a dependency.)
- */
-public class SecureKeys extends SecureKeysWithoutBouncyCastle {
-
- private static final Logger log = LoggerFactory.getLogger(SecureKeys.class);
-
- static { BrooklynInitialization.initSecureKeysBouncyCastleProvider(); }
-
- public static void initBouncyCastleProvider() {
- Security.addProvider(new BouncyCastleProvider());
- }
-
- public static class PassphraseProblem extends IllegalStateException {
- private static final long serialVersionUID = -3382824813899223447L;
- public PassphraseProblem(String message) { super("Passphrase problem with this key: "+message); }
- public PassphraseProblem(String message, Exception cause) { super("Passphrase problem with this key: "+message, cause); }
- }
-
- private SecureKeys() {}
-
- /** RFC1773 order, with None for other values. Normally prefer X500Principal. */
- public static X509Principal getX509PrincipalWithCommonName(String commonName) {
- return new X509Principal("" + "C=None," + "L=None," + "O=None," + "OU=None," + "CN=" + commonName);
- }
-
- /** reads RSA or DSA / pem style private key files (viz {@link #toPem(KeyPair)}), extracting also the public key if possible
- * @throws IllegalStateException on errors, in particular {@link PassphraseProblem} if that is the problem */
- public static KeyPair readPem(InputStream input, final String passphrase) {
- // TODO cache is only for fallback "reader" strategy (2015-01); delete when Parser confirmed working
- byte[] cache = Streams.readFully(input);
- input = new ByteArrayInputStream(cache);
-
- try {
- PEMParser pemParser = new PEMParser(new InputStreamReader(input));
-
- Object object = pemParser.readObject();
- pemParser.close();
-
- JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
- KeyPair kp = null;
- if (object==null) {
- throw new IllegalStateException("PEM parsing failed: missing or invalid data");
- } else if (object instanceof PEMEncryptedKeyPair) {
- if (passphrase==null) throw new PassphraseProblem("passphrase required");
- try {
- PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(passphrase.toCharArray());
- kp = converter.getKeyPair(((PEMEncryptedKeyPair) object).decryptKeyPair(decProv));
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- throw new PassphraseProblem("wrong passphrase", e);
- }
- } else if (object instanceof PEMKeyPair) {
- kp = converter.getKeyPair((PEMKeyPair) object);
- } else if (object instanceof PrivateKeyInfo) {
- PrivateKey privKey = converter.getPrivateKey((PrivateKeyInfo) object);
- kp = new KeyPair(null, privKey);
- } else {
- throw new IllegalStateException("PEM parser support missing for: "+object);
- }
-
- return kp;
-
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
-
- // older code relied on PEMReader, now deprecated
- // replaced with above based on http://stackoverflow.com/questions/14919048/bouncy-castle-pemreader-pemparser
- // passes the same tests (Jan 2015) but leaving the old code as a fallback for the time being
-
- input = new ByteArrayInputStream(cache);
- try {
- Security.addProvider(new BouncyCastleProvider());
- @SuppressWarnings("deprecation")
- org.bouncycastle.openssl.PEMReader pr = new org.bouncycastle.openssl.PEMReader(new InputStreamReader(input), new PasswordFinder() {
- public char[] getPassword() {
- return passphrase!=null ? passphrase.toCharArray() : new char[0];
- }
- });
- @SuppressWarnings("deprecation")
- KeyPair result = (KeyPair) pr.readObject();
- pr.close();
- if (result==null)
- throw Exceptions.propagate(e);
-
- log.warn("PEMParser failed when deprecated PEMReader succeeded, with "+result+"; had: "+e);
-
- return result;
-
- } catch (Exception e2) {
- Exceptions.propagateIfFatal(e2);
- throw Exceptions.propagate(e);
- }
- }
- }
-
- /** because KeyPair.equals is not implemented :( */
- public static boolean equal(KeyPair k1, KeyPair k2) {
- return Objects.equal(k2.getPrivate(), k1.getPrivate()) && Objects.equal(k2.getPublic(), k1.getPublic());
- }
-
- /** returns the PEM (base64, ie for id_rsa) string for the private key / key pair;
- * this starts -----BEGIN PRIVATE KEY----- and ends similarly, like id_rsa.
- * also see {@link #readPem(InputStream, String)} */
- public static String toPem(KeyPair key) {
- return stringPem(key);
- }
-
- /** returns id_rsa.pub style file, of public key */
- public static String toPub(KeyPair key) {
- return AuthorizedKeysParser.encodePublicKey(key.getPublic());
- }
-
- /** opposite of {@link #toPub(KeyPair)}, given text */
- public static PublicKey fromPub(String pubText) {
- return AuthorizedKeysParser.decodePublicKey(pubText);
- }
-
- /** @deprecated since 0.7.0, use {@link #toPem(KeyPair)} */ @Deprecated
- public static String stringPem(KeyPair key) {
- try {
- StringWriter sw = new StringWriter();
- PEMWriter w = new PEMWriter(sw);
- w.writeObject(key);
- w.close();
- return sw.toString();
- } catch (IOException e) {
- throw Throwables.propagate(e);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/file/ArchiveBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/file/ArchiveBuilder.java b/core/src/main/java/brooklyn/util/file/ArchiveBuilder.java
deleted file mode 100644
index 6985406..0000000
--- a/core/src/main/java/brooklyn/util/file/ArchiveBuilder.java
+++ /dev/null
@@ -1,423 +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 brooklyn.util.file;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Collections;
-import java.util.Map;
-import java.util.jar.Attributes;
-import java.util.jar.JarEntry;
-import java.util.jar.JarOutputStream;
-import java.util.jar.Manifest;
-import java.util.zip.ZipOutputStream;
-
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.file.ArchiveUtils.ArchiveType;
-import brooklyn.util.os.Os;
-
-import com.google.common.annotations.Beta;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.LinkedHashMultimap;
-import com.google.common.collect.Multimap;
-import com.google.common.io.Files;
-
-/**
- * Build a Zip or Jar archive.
- * <p>
- * Supports creating temporary archives that will be deleted on exit, if no name is
- * specified. The created file must be a Java archive type, with the extension {@code .zip},
- * {@code .jar}, {@code .war} or {@code .ear}.
- * <p>
- * Example:
- * <pre> File zip = ArchiveBuilder.archive("data/archive.zip")
- * .addAt(new File("./pom.xml"), "")
- * .addDirContentsAt(new File("./src"), "src/")
- * .addAt(new File("/tmp/Extra.java"), "src/main/java/")
- * .addDirContentsAt(new File("/tmp/overlay/"), "")
- * .create();
- * </pre>
- * <p>
- */
-@Beta
-public class ArchiveBuilder {
-
- /**
- * Create an {@link ArchiveBuilder} for an archive with the given name.
- */
- public static ArchiveBuilder archive(String archive) {
- return new ArchiveBuilder(archive);
- }
-
- /**
- * Create an {@link ArchiveBuilder} for a {@link ArchiveType#ZIP Zip} format archive.
- */
- public static ArchiveBuilder zip() {
- return new ArchiveBuilder(ArchiveType.ZIP);
- }
-
- /**
- * Create an {@link ArchiveBuilder} for a {@link ArchiveType#JAR Jar} format archive.
- */
- public static ArchiveBuilder jar() {
- return new ArchiveBuilder(ArchiveType.JAR);
- }
-
- // TODO would be nice to support TAR and TGZ
- // e.g. using commons-compress
- // TarArchiveOutputStream out = new TarArchiveOutputStream(new GZIPOutputStream(bytes));
- // but I think the way entries are done is slightly different so we'd need a bit of refactoring
-
- private final ArchiveType type;
- private File archive;
- private Manifest manifest;
- private Multimap<String, File> entries = LinkedHashMultimap.create();
-
- private ArchiveBuilder() {
- this(ArchiveType.ZIP);
- }
-
- private ArchiveBuilder(String filename) {
- this(ArchiveType.of(filename));
-
- named(filename);
- }
-
- private ArchiveBuilder(ArchiveType type) {
- checkNotNull(type);
- checkArgument(ArchiveType.ZIP_ARCHIVES.contains(type));
-
- this.type = type;
- this.manifest = new Manifest();
- }
-
- /**
- * Set the location of the generated archive file.
- */
- public ArchiveBuilder named(String name) {
- checkNotNull(name);
- String ext = Files.getFileExtension(name);
- if (ext.isEmpty()) {
- name = name + "." + type.toString();
- } else if (type != ArchiveType.of(name)) {
- throw new IllegalArgumentException(String.format("Extension for '%s' did not match archive type of %s", ext, type));
- }
- this.archive = new File(Os.tidyPath(name));
- return this;
- }
-
- /**
- * @see #named(String)
- */
- public ArchiveBuilder named(File file) {
- checkNotNull(file);
- return named(file.getPath());
- }
-
- /**
- * Add a manifest entry with the given {@code key} and {@code value}.
- */
- public ArchiveBuilder manifest(Object key, Object value) {
- checkNotNull(key, "key");
- checkNotNull(value, "value");
- manifest.getMainAttributes().put(key, value);
- return this;
- }
-
- /**
- * Add the file located at the {@code filePath} to the archive,
- * with some complicated base-name strategies.
- *
- * @deprecated since 0.7.0 use one of the other add methods which makes the strategy explicit */ @Deprecated
- public ArchiveBuilder add(String filePath) {
- checkNotNull(filePath, "filePath");
- return add(new File(Os.tidyPath(filePath)));
- }
-
- /**
- * Add the {@code file} to the archive.
- * <p>
- * If the file path is absolute, or points to a file above the current directory,
- * the file is added to the archive as a top-level entry, using the file name only.
- * For relative {@code filePath}s below the current directory, the file is added
- * using the path given and is assumed to be located relative to the current
- * working directory.
- * <p>
- * No checks for file existence are made at this stage.
- *
- * @see #entry(String, File)
- * @deprecated since 0.7.0 use one of the other add methods which makes the strategy explicit */ @Deprecated
- public ArchiveBuilder add(File file) {
- checkNotNull(file, "file");
- String filePath = Os.tidyPath(file.getPath());
- if (file.isAbsolute() || filePath.startsWith("../")) {
- return entry(Os.mergePaths(".", file.getName()), file);
- } else {
- return entry(Os.mergePaths(".", filePath), file);
- }
- }
-
- /**
- * Add the file located at the {@code fileSubPath}, relative to the {@code baseDir} on the local system,
- * to the archive.
- * <p>
- * Uses the {@code fileSubPath} as the name of the file in the archive. Note that the
- * file is found by concatenating the two path components using {@link Os#mergePaths(String...)},
- * thus {@code fileSubPath} should not be absolute or point to a location above the current directory.
- * <p>
- * Use {@link #entry(String, String)} directly or {@link #entries(Map)} for complete
- * control over file locations and names in the archive.
- *
- * @see #entry(String, String)
- */
- public ArchiveBuilder addFromLocalBaseDir(File baseDir, String fileSubPath) {
- checkNotNull(baseDir, "baseDir");
- checkNotNull(fileSubPath, "filePath");
- return entry(Os.mergePaths(".", fileSubPath), Os.mergePaths(baseDir.getPath(), fileSubPath));
- }
- /** @deprecated since 0.7.0 use {@link #addFromLocalBaseDir(File, String)}, or
- * one of the other add methods if adding relative to baseDir was not intended */ @Deprecated
- public ArchiveBuilder addFromLocalBaseDir(String baseDir, String fileSubPath) {
- return addFromLocalBaseDir(new File(baseDir), fileSubPath);
- }
- /** @deprecated since 0.7.0 use {@link #addFromLocalBaseDir(File, String)}, or
- * one of the other add methods if adding relative to baseDir was not intended */ @Deprecated
- public ArchiveBuilder add(String baseDir, String fileSubPath) {
- return addFromLocalBaseDir(baseDir, fileSubPath);
- }
-
- /** adds the given file to the archive, preserving its name but putting under the given directory in the archive (may be <code>""</code> or <code>"./"</code>) */
- public ArchiveBuilder addAt(File file, String archiveParentDir) {
- checkNotNull(archiveParentDir, "archiveParentDir");
- checkNotNull(file, "file");
- return entry(Os.mergePaths(archiveParentDir, file.getName()), file);
- }
-
- /**
- * Add the contents of the directory named {@code dirName} to the archive.
- *
- * @see #addDir(File)
- * @deprecated since 0.7.0 use {@link #addDirContentsAt(File, String) */ @Deprecated
- public ArchiveBuilder addDir(String dirName) {
- checkNotNull(dirName, "dirName");
- return addDir(new File(Os.tidyPath(dirName)));
- }
-
- /**
- * Add the contents of the directory {@code dir} to the archive.
- * The directory's name is not included; use {@link #addAtRoot(File)} if you want that behaviour.
- * <p>
- * Uses {@literal .} as the parent directory name for the contents.
- *
- * @see #entry(String, File)
- */
- public ArchiveBuilder addDirContentsAt(File dir, String archiveParentDir) {
- checkNotNull(dir, "dir");
- if (!dir.isDirectory()) throw new IllegalArgumentException(dir+" is not a directory; cannot add contents to archive");
- return entry(archiveParentDir, dir);
- }
- /**
- * As {@link #addDirContentsAt(File, String)},
- * using {@literal .} as the parent directory name for the contents.
- *
- * @deprecated since 0.7.0 use {@link #addDirContentsAt(File, String)
- * to clarify API, argument types, and be explicit about where it should be installed,
- * because JARs seem to require <code>""<code> whereas ZIPs might want <code>"./"</code>. */ @Deprecated
- public ArchiveBuilder addDir(File dir) {
- return addDirContentsAt(dir, ".");
- }
-
- /**
- * Add the collection of {@code files} to the archive.
- *
- * @see #add(String)
- * @deprecated since 0.7.0 use one of the other add methods if keeping this file's path was not intended */ @Deprecated
- public ArchiveBuilder add(Iterable<String> files) {
- checkNotNull(files, "files");
- for (String filePath : files) {
- add(filePath);
- }
- return this;
- }
-
- /**
- * Add the collection of {@code files}, relative to the {@code baseDir}, to
- * the archive.
- *
- * @see #add(String, String)
- * @deprecated since 0.7.0 use one of the other add methods if keeping this file's path was not intended */ @Deprecated
- public ArchiveBuilder add(String baseDir, Iterable<String> files) {
- checkNotNull(baseDir, "baseDir");
- checkNotNull(files, "files");
- for (String filePath : files) {
- add(baseDir, filePath);
- }
- return this;
- }
-
- /**
- * Add the {@code file} to the archive with the path {@code entryPath}.
- *
- * @see #entry(String, File)
- */
- public ArchiveBuilder entry(String entryPath, String filePath) {
- checkNotNull(entryPath, "entryPath");
- checkNotNull(filePath, "filePath");
- return entry(entryPath, new File(filePath));
- }
-
- /**
- * Add the {@code file} to the archive with the path {@code entryPath}.
- */
- public ArchiveBuilder entry(String entryPath, File file) {
- checkNotNull(entryPath, "entryPath");
- checkNotNull(file, "file");
- this.entries.put(entryPath, file);
- return this;
- }
-
- /**
- * Add a {@link Map} of entries to the archive.
- * <p>
- * The keys should be the names of the file entries to be added to the archive and
- * the value should point to the actual {@link File} to be added.
- * <p>
- * This allows complete control over the directory structure of the eventual archive,
- * as the entry names do not need to bear any relationship to the name or location
- * of the files on the filesystem.
- */
- public ArchiveBuilder entries(Map<String, File> entries) {
- checkNotNull(entries, "entries");
- for (Map.Entry<String, File> entry: entries.entrySet())
- this.entries.put(entry.getKey(), entry.getValue());
- return this;
- }
-
- /**
- * Generates the archive and outputs it to the given stream, ignoring any file name.
- * <p>
- * This will add a manifest file if the type is a Jar archive.
- */
- public void stream(OutputStream output) {
- try {
- ZipOutputStream target;
- if (type == ArchiveType.ZIP) {
- target = new ZipOutputStream(output);
- } else {
- manifest(Attributes.Name.MANIFEST_VERSION, "1.0");
- target = new JarOutputStream(output, manifest);
- }
- for (String entry : entries.keySet()) {
- addToArchive(entry, entries.get(entry), target);
- }
- target.close();
- } catch (IOException ioe) {
- throw Exceptions.propagate(ioe);
- }
- }
-
- /**
- * Generates the archive, saving it with the given name.
- */
- public File create(String archiveFile) {
- return named(archiveFile).create();
- }
-
- /**
- * Generates the archive.
- * <p>
- * If no name has been specified, the archive will be created as a temporary file with
- * a unique name, that is deleted on exit. Otherwise, the given name will be used.
- */
- public File create() {
- if (archive == null) {
- File temp = Os.newTempFile("brooklyn-archive", type.toString());
- temp.deleteOnExit();
- named(temp);
- }
- try {
- OutputStream output = new FileOutputStream(archive);
- stream(output);
- output.close();
- } catch (IOException ioe) {
- throw Exceptions.propagate(ioe);
- }
- return archive;
- }
-
- /**
- * Recursively add files to the archive.
- * <p>
- * Code adapted from this <a href="http://stackoverflow.com/questions/1281229/how-to-use-jaroutputstream-to-create-a-jar-file">example</a>
- * <p>
- * <strong>Note</strong> {@link File} provides no support for symbolic links, and as such there is
- * no way to ensure that a symbolic link to a directory is not followed when traversing the
- * tree. In this case, iterables created by this traverser could contain files that are
- * outside of the given directory or even be infinite if there is a symbolic link loop.
- */
- private void addToArchive(String path, Iterable<File> sources, ZipOutputStream target) throws IOException {
- int size = Iterables.size(sources);
- if (size==0) return;
- boolean isDirectory;
- if (size>1) {
- // it must be directories if we are putting multiple things here
- isDirectory = true;
- } else {
- isDirectory = Iterables.getOnlyElement(sources).isDirectory();
- }
-
- String name = path.replace("\\", "/");
- if (isDirectory) {
- name += "/";
- JarEntry entry = new JarEntry(name);
-
- long lastModified=-1;
- for (File source: sources)
- if (source.lastModified()>lastModified)
- lastModified = source.lastModified();
-
- entry.setTime(lastModified);
- target.putNextEntry(entry);
- target.closeEntry();
-
- for (File source: sources) {
- if (!source.isDirectory()) {
- throw new IllegalStateException("Cannot add multiple items at a path in archive unless they are directories: "+sources+" at "+path+" is not valid.");
- }
- Iterable<File> children = Files.fileTreeTraverser().children(source);
- for (File child : children) {
- addToArchive(Os.mergePaths(path, child.getName()), Collections.singleton(child), target);
- }
- }
- return;
- }
-
- File source = Iterables.getOnlyElement(sources);
- JarEntry entry = new JarEntry(name);
- entry.setTime(source.lastModified());
- target.putNextEntry(entry);
- Files.asByteSource(source).copyTo(target);
- target.closeEntry();
- }
-}
[41/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/basic/EntityTransientCopyInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/EntityTransientCopyInternal.java b/core/src/main/java/brooklyn/entity/basic/EntityTransientCopyInternal.java
index 63b49b5..56e73d1 100644
--- a/core/src/main/java/brooklyn/entity/basic/EntityTransientCopyInternal.java
+++ b/core/src/main/java/brooklyn/entity/basic/EntityTransientCopyInternal.java
@@ -38,12 +38,12 @@ import org.apache.brooklyn.api.mementos.EntityMemento;
import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.core.management.internal.EntityManagementSupport;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import brooklyn.config.ConfigKey;
import brooklyn.config.ConfigKey.HasConfigKey;
import brooklyn.entity.basic.EntityInternal.FeedSupport;
import brooklyn.entity.proxying.EntityProxyImpl;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.guava.Maybe;
import com.google.common.annotations.Beta;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/basic/Lifecycle.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/Lifecycle.java b/core/src/main/java/brooklyn/entity/basic/Lifecycle.java
index 9bb0177..97e3ada 100644
--- a/core/src/main/java/brooklyn/entity/basic/Lifecycle.java
+++ b/core/src/main/java/brooklyn/entity/basic/Lifecycle.java
@@ -24,7 +24,6 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import brooklyn.config.render.RendererHints;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.text.StringFunctions;
import com.google.common.base.CaseFormat;
@@ -33,6 +32,7 @@ import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
/**
* An enumeration representing the status of an {@link org.apache.brooklyn.api.entity.Entity}.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/basic/MethodEffector.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/MethodEffector.java b/core/src/main/java/brooklyn/entity/basic/MethodEffector.java
index 121f70f..f5978b7 100644
--- a/core/src/main/java/brooklyn/entity/basic/MethodEffector.java
+++ b/core/src/main/java/brooklyn/entity/basic/MethodEffector.java
@@ -28,6 +28,7 @@ import org.apache.brooklyn.api.entity.Effector;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.ParameterType;
import org.apache.brooklyn.core.management.internal.EffectorUtils;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import org.codehaus.groovy.runtime.MethodClosure;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -35,7 +36,6 @@ import org.slf4j.LoggerFactory;
import brooklyn.entity.annotation.EffectorParam;
import brooklyn.util.GroovyJavaMethods;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.TypeCoercions;
import com.google.common.collect.Lists;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/basic/Sanitizer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/Sanitizer.java b/core/src/main/java/brooklyn/entity/basic/Sanitizer.java
index 88ca756..7e81bb2 100644
--- a/core/src/main/java/brooklyn/entity/basic/Sanitizer.java
+++ b/core/src/main/java/brooklyn/entity/basic/Sanitizer.java
@@ -22,7 +22,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
-import brooklyn.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import com.google.api.client.util.Lists;
import com.google.common.base.Predicate;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/basic/ServiceStateLogic.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/ServiceStateLogic.java b/core/src/main/java/brooklyn/entity/basic/ServiceStateLogic.java
index 2a551b4..bf4bd43 100644
--- a/core/src/main/java/brooklyn/entity/basic/ServiceStateLogic.java
+++ b/core/src/main/java/brooklyn/entity/basic/ServiceStateLogic.java
@@ -37,6 +37,7 @@ import org.apache.brooklyn.api.event.SensorEventListener;
import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.EnricherSpec;
import org.apache.brooklyn.api.policy.EnricherSpec.ExtensibleEnricherSpec;
+import org.apache.brooklyn.core.util.task.ValueResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -57,7 +58,6 @@ import brooklyn.util.collections.QuorumCheck;
import brooklyn.util.guava.Functionals;
import brooklyn.util.guava.Maybe;
import brooklyn.util.repeat.Repeater;
-import brooklyn.util.task.ValueResolver;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/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
index eef3cf9..0119dd1 100644
--- a/core/src/main/java/brooklyn/entity/effector/AddChildrenEffector.java
+++ b/core/src/main/java/brooklyn/entity/effector/AddChildrenEffector.java
@@ -25,13 +25,13 @@ import org.apache.brooklyn.api.entity.Effector;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.core.management.internal.EntityManagementUtils;
import org.apache.brooklyn.core.management.internal.EntityManagementUtils.CreationResult;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.effector.Effectors.EffectorBuilder;
-import brooklyn.util.config.ConfigBag;
import com.google.common.annotations.Beta;
import com.google.gson.Gson;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/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 c0d986d..0db7c40 100644
--- a/core/src/main/java/brooklyn/entity/effector/AddEffector.java
+++ b/core/src/main/java/brooklyn/entity/effector/AddEffector.java
@@ -25,13 +25,13 @@ import org.apache.brooklyn.api.entity.Effector;
import org.apache.brooklyn.api.entity.ParameterType;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.entity.proxying.EntityInitializer;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.effector.Effectors.EffectorBuilder;
import brooklyn.event.basic.MapConfigKey;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.text.Strings;
import com.google.common.annotations.Beta;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/effector/AddSensor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/effector/AddSensor.java b/core/src/main/java/brooklyn/entity/effector/AddSensor.java
index 8e29baa..2aa95a6 100644
--- a/core/src/main/java/brooklyn/entity/effector/AddSensor.java
+++ b/core/src/main/java/brooklyn/entity/effector/AddSensor.java
@@ -23,12 +23,12 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.entity.proxying.EntityInitializer;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.guava.Maybe;
import brooklyn.util.javalang.Boxing;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/effector/EffectorBody.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/effector/EffectorBody.java b/core/src/main/java/brooklyn/entity/effector/EffectorBody.java
index 98c8153..1a60cbe 100644
--- a/core/src/main/java/brooklyn/entity/effector/EffectorBody.java
+++ b/core/src/main/java/brooklyn/entity/effector/EffectorBody.java
@@ -21,14 +21,14 @@ package brooklyn.entity.effector;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.management.TaskAdaptable;
import org.apache.brooklyn.api.management.TaskFactory;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
+import org.apache.brooklyn.core.util.task.DynamicSequentialTask;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.Tasks;
import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.entity.basic.EntityInternal;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.flags.TypeCoercions;
-import brooklyn.util.task.DynamicSequentialTask;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.Tasks;
import com.google.common.annotations.Beta;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/effector/EffectorTasks.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/effector/EffectorTasks.java b/core/src/main/java/brooklyn/entity/effector/EffectorTasks.java
index 6094686..f9a702e 100644
--- a/core/src/main/java/brooklyn/entity/effector/EffectorTasks.java
+++ b/core/src/main/java/brooklyn/entity/effector/EffectorTasks.java
@@ -28,6 +28,11 @@ import org.apache.brooklyn.api.entity.ParameterType;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.management.TaskAdaptable;
import org.apache.brooklyn.core.management.internal.EffectorUtils;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.task.DynamicSequentialTask;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.TaskBuilder;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -39,12 +44,7 @@ import org.apache.brooklyn.location.basic.Machines;
import org.apache.brooklyn.location.basic.SshMachineLocation;
import org.apache.brooklyn.location.basic.WinRmMachineLocation;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.javalang.Reflections;
-import brooklyn.util.task.DynamicSequentialTask;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.TaskBuilder;
-import brooklyn.util.task.Tasks;
import com.google.common.annotations.Beta;
import com.google.common.base.Preconditions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/effector/Effectors.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/effector/Effectors.java b/core/src/main/java/brooklyn/entity/effector/Effectors.java
index ff595e7..c0b6306 100644
--- a/core/src/main/java/brooklyn/entity/effector/Effectors.java
+++ b/core/src/main/java/brooklyn/entity/effector/Effectors.java
@@ -31,6 +31,8 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.ParameterType;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.management.TaskAdaptable;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -43,8 +45,6 @@ import brooklyn.entity.effector.EffectorTasks.EffectorBodyTaskFactory;
import brooklyn.entity.effector.EffectorTasks.EffectorMarkingTaskFactory;
import brooklyn.entity.effector.EffectorTasks.EffectorTaskFactory;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.task.Tasks;
import brooklyn.util.text.Strings;
import com.google.common.base.Objects;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/group/Cluster.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/group/Cluster.java b/core/src/main/java/brooklyn/entity/group/Cluster.java
index b618c66..ac066a7 100644
--- a/core/src/main/java/brooklyn/entity/group/Cluster.java
+++ b/core/src/main/java/brooklyn/entity/group/Cluster.java
@@ -19,11 +19,11 @@
package brooklyn.entity.group;
import org.apache.brooklyn.api.entity.Group;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.entity.trait.Resizable;
import brooklyn.entity.trait.Startable;
import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.util.flags.SetFromFlag;
/**
* Intended to represent a group of homogeneous entities in a single location.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/group/DynamicCluster.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/group/DynamicCluster.java b/core/src/main/java/brooklyn/entity/group/DynamicCluster.java
index ab14f49..435308e 100644
--- a/core/src/main/java/brooklyn/entity/group/DynamicCluster.java
+++ b/core/src/main/java/brooklyn/entity/group/DynamicCluster.java
@@ -29,6 +29,7 @@ import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.annotation.Effector;
@@ -46,7 +47,6 @@ import brooklyn.entity.trait.MemberReplaceable;
import brooklyn.event.basic.BasicAttributeSensor;
import brooklyn.event.basic.BasicNotificationSensor;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.time.Duration;
import com.google.common.annotations.Beta;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java b/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java
index 5025026..1cdbd8e 100644
--- a/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java
+++ b/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java
@@ -38,6 +38,10 @@ import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.TaskTags;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -62,13 +66,9 @@ import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.exceptions.ReferenceWithError;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.guava.Maybe;
import brooklyn.util.javalang.JavaClassNames;
import brooklyn.util.javalang.Reflections;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.TaskTags;
-import brooklyn.util.task.Tasks;
import brooklyn.util.text.StringPredicates;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/group/DynamicFabric.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/group/DynamicFabric.java b/core/src/main/java/brooklyn/entity/group/DynamicFabric.java
index f7decf9..dc23e7c 100644
--- a/core/src/main/java/brooklyn/entity/group/DynamicFabric.java
+++ b/core/src/main/java/brooklyn/entity/group/DynamicFabric.java
@@ -21,6 +21,7 @@ package brooklyn.entity.group;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.AbstractGroup;
@@ -31,7 +32,6 @@ import brooklyn.entity.basic.Lifecycle;
import brooklyn.entity.trait.Startable;
import brooklyn.event.basic.MapConfigKey;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.collect.ImmutableMap;
import com.google.common.reflect.TypeToken;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/group/DynamicMultiGroup.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/group/DynamicMultiGroup.java b/core/src/main/java/brooklyn/entity/group/DynamicMultiGroup.java
index 3a49634..d5a8c9a 100644
--- a/core/src/main/java/brooklyn/entity/group/DynamicMultiGroup.java
+++ b/core/src/main/java/brooklyn/entity/group/DynamicMultiGroup.java
@@ -25,13 +25,13 @@ import org.apache.brooklyn.api.entity.Group;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.BasicGroup;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.DynamicGroup;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.annotations.Beta;
import com.google.common.base.Function;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/group/QuarantineGroupImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/group/QuarantineGroupImpl.java b/core/src/main/java/brooklyn/entity/group/QuarantineGroupImpl.java
index 9f8c14e..4a6b75e 100644
--- a/core/src/main/java/brooklyn/entity/group/QuarantineGroupImpl.java
+++ b/core/src/main/java/brooklyn/entity/group/QuarantineGroupImpl.java
@@ -23,6 +23,8 @@ import java.util.Set;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -32,8 +34,6 @@ import brooklyn.entity.basic.Entities;
import brooklyn.entity.effector.Effectors;
import brooklyn.entity.trait.Startable;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.Tasks;
import brooklyn.util.text.Strings;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/proxying/EntityProxyImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/proxying/EntityProxyImpl.java b/core/src/main/java/brooklyn/entity/proxying/EntityProxyImpl.java
index 647ad76..b121179 100644
--- a/core/src/main/java/brooklyn/entity/proxying/EntityProxyImpl.java
+++ b/core/src/main/java/brooklyn/entity/proxying/EntityProxyImpl.java
@@ -36,6 +36,9 @@ import org.apache.brooklyn.api.management.TaskAdaptable;
import org.apache.brooklyn.core.management.internal.EffectorUtils;
import org.apache.brooklyn.core.management.internal.EntityManagerInternal;
import org.apache.brooklyn.core.management.internal.ManagementTransitionMode;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.TaskTags;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -45,9 +48,6 @@ import brooklyn.entity.basic.EntityTransientCopyInternal;
import brooklyn.entity.basic.EntityTransientCopyInternal.SpecialEntityTransientCopyInternal;
import brooklyn.entity.effector.EffectorWithBody;
import brooklyn.entity.rebind.RebindManagerImpl.RebindTracker;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.TaskTags;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Objects;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java b/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
index c2a4bfd..1c1a920 100644
--- a/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
+++ b/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
@@ -37,6 +37,8 @@ import org.apache.brooklyn.api.policy.EnricherSpec;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.util.flags.FlagUtils;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -50,9 +52,7 @@ import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.FlagUtils;
import brooklyn.util.javalang.AggregateClassLoader;
-import brooklyn.util.task.Tasks;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/proxying/InternalLocationFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/proxying/InternalLocationFactory.java b/core/src/main/java/brooklyn/entity/proxying/InternalLocationFactory.java
index 10338b8..464d2a4 100644
--- a/core/src/main/java/brooklyn/entity/proxying/InternalLocationFactory.java
+++ b/core/src/main/java/brooklyn/entity/proxying/InternalLocationFactory.java
@@ -27,15 +27,15 @@ import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.core.management.internal.LocalLocationManager;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.FlagUtils;
import brooklyn.config.ConfigKey;
import org.apache.brooklyn.location.basic.AbstractLocation;
import org.apache.brooklyn.location.basic.LocationInternal;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.FlagUtils;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/proxying/InternalPolicyFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/proxying/InternalPolicyFactory.java b/core/src/main/java/brooklyn/entity/proxying/InternalPolicyFactory.java
index aeb371c..7c53404 100644
--- a/core/src/main/java/brooklyn/entity/proxying/InternalPolicyFactory.java
+++ b/core/src/main/java/brooklyn/entity/proxying/InternalPolicyFactory.java
@@ -27,13 +27,13 @@ import org.apache.brooklyn.api.policy.EnricherSpec;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import brooklyn.config.ConfigKey;
import brooklyn.enricher.basic.AbstractEnricher;
import brooklyn.entity.basic.AbstractEntity;
import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
/**
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/rebind/BasicCatalogItemRebindSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/BasicCatalogItemRebindSupport.java b/core/src/main/java/brooklyn/entity/rebind/BasicCatalogItemRebindSupport.java
index 52e87a6..6ee5eb2 100644
--- a/core/src/main/java/brooklyn/entity/rebind/BasicCatalogItemRebindSupport.java
+++ b/core/src/main/java/brooklyn/entity/rebind/BasicCatalogItemRebindSupport.java
@@ -21,11 +21,11 @@ package brooklyn.entity.rebind;
import org.apache.brooklyn.api.entity.rebind.RebindContext;
import org.apache.brooklyn.api.mementos.CatalogItemMemento;
import org.apache.brooklyn.core.catalog.internal.CatalogItemDtoAbstract;
+import org.apache.brooklyn.core.util.flags.FlagUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.flags.FlagUtils;
public class BasicCatalogItemRebindSupport extends AbstractBrooklynObjectRebindSupport<CatalogItemMemento> {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/rebind/BasicEnricherRebindSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/BasicEnricherRebindSupport.java b/core/src/main/java/brooklyn/entity/rebind/BasicEnricherRebindSupport.java
index d6b289f..e3e4598 100644
--- a/core/src/main/java/brooklyn/entity/rebind/BasicEnricherRebindSupport.java
+++ b/core/src/main/java/brooklyn/entity/rebind/BasicEnricherRebindSupport.java
@@ -20,10 +20,10 @@ package brooklyn.entity.rebind;
import org.apache.brooklyn.api.entity.rebind.RebindContext;
import org.apache.brooklyn.api.mementos.EnricherMemento;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.FlagUtils;
import brooklyn.enricher.basic.AbstractEnricher;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.flags.FlagUtils;
public class BasicEnricherRebindSupport extends AbstractBrooklynObjectRebindSupport<EnricherMemento> {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/rebind/BasicFeedRebindSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/BasicFeedRebindSupport.java b/core/src/main/java/brooklyn/entity/rebind/BasicFeedRebindSupport.java
index 5507e6b..f3358e2 100644
--- a/core/src/main/java/brooklyn/entity/rebind/BasicFeedRebindSupport.java
+++ b/core/src/main/java/brooklyn/entity/rebind/BasicFeedRebindSupport.java
@@ -20,10 +20,10 @@ package brooklyn.entity.rebind;
import org.apache.brooklyn.api.entity.rebind.RebindContext;
import org.apache.brooklyn.api.mementos.FeedMemento;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.FlagUtils;
import brooklyn.event.feed.AbstractFeed;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.flags.FlagUtils;
public class BasicFeedRebindSupport extends AbstractBrooklynObjectRebindSupport<FeedMemento> {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/rebind/BasicLocationRebindSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/BasicLocationRebindSupport.java b/core/src/main/java/brooklyn/entity/rebind/BasicLocationRebindSupport.java
index edf8867..7f1f286 100644
--- a/core/src/main/java/brooklyn/entity/rebind/BasicLocationRebindSupport.java
+++ b/core/src/main/java/brooklyn/entity/rebind/BasicLocationRebindSupport.java
@@ -26,6 +26,8 @@ import java.util.NoSuchElementException;
import org.apache.brooklyn.api.entity.rebind.RebindContext;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.mementos.LocationMemento;
+import org.apache.brooklyn.core.util.flags.FlagUtils;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -35,8 +37,6 @@ import brooklyn.entity.rebind.dto.MementosGenerators;
import org.apache.brooklyn.location.basic.AbstractLocation;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.flags.FlagUtils;
-import brooklyn.util.flags.TypeCoercions;
import com.google.common.collect.Sets;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/rebind/BasicPolicyRebindSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/BasicPolicyRebindSupport.java b/core/src/main/java/brooklyn/entity/rebind/BasicPolicyRebindSupport.java
index 9b22d65..4623225 100644
--- a/core/src/main/java/brooklyn/entity/rebind/BasicPolicyRebindSupport.java
+++ b/core/src/main/java/brooklyn/entity/rebind/BasicPolicyRebindSupport.java
@@ -20,10 +20,10 @@ package brooklyn.entity.rebind;
import org.apache.brooklyn.api.entity.rebind.RebindContext;
import org.apache.brooklyn.api.mementos.PolicyMemento;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.FlagUtils;
import brooklyn.policy.basic.AbstractPolicy;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.flags.FlagUtils;
public class BasicPolicyRebindSupport extends AbstractBrooklynObjectRebindSupport<PolicyMemento> {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/rebind/PeriodicDeltaChangeListener.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/PeriodicDeltaChangeListener.java b/core/src/main/java/brooklyn/entity/rebind/PeriodicDeltaChangeListener.java
index d204ecc..2c55e7f 100644
--- a/core/src/main/java/brooklyn/entity/rebind/PeriodicDeltaChangeListener.java
+++ b/core/src/main/java/brooklyn/entity/rebind/PeriodicDeltaChangeListener.java
@@ -46,6 +46,8 @@ import org.apache.brooklyn.api.mementos.BrooklynMementoPersister;
import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
+import org.apache.brooklyn.core.util.task.ScheduledTask;
+import org.apache.brooklyn.core.util.task.Tasks;
import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.entity.basic.EntityInternal;
@@ -56,8 +58,6 @@ import brooklyn.util.collections.MutableSet;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.exceptions.RuntimeInterruptedException;
import brooklyn.util.repeat.Repeater;
-import brooklyn.util.task.ScheduledTask;
-import brooklyn.util.task.Tasks;
import brooklyn.util.time.CountdownTimer;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java b/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
index 1164fff..67d20ae 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
@@ -73,6 +73,7 @@ import org.apache.brooklyn.core.management.internal.EntityManagerInternal;
import org.apache.brooklyn.core.management.internal.LocationManagerInternal;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.core.management.internal.ManagementTransitionMode;
+import org.apache.brooklyn.core.util.flags.FlagUtils;
import brooklyn.config.BrooklynLogging;
import brooklyn.config.BrooklynLogging.LoggingLevel;
@@ -95,7 +96,6 @@ import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.FlagUtils;
import brooklyn.util.guava.Maybe;
import brooklyn.util.javalang.Reflections;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
index 862c86b..f810a98 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
@@ -46,6 +46,9 @@ import org.apache.brooklyn.api.mementos.TreeNode;
import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
import org.apache.brooklyn.core.management.ha.HighAvailabilityManagerImpl;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.util.task.BasicExecutionContext;
+import org.apache.brooklyn.core.util.task.ScheduledTask;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -65,9 +68,6 @@ import brooklyn.util.collections.QuorumCheck;
import brooklyn.util.collections.QuorumCheck.QuorumChecks;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.exceptions.RuntimeInterruptedException;
-import brooklyn.util.task.BasicExecutionContext;
-import brooklyn.util.task.ScheduledTask;
-import brooklyn.util.task.Tasks;
import brooklyn.util.time.Duration;
import com.google.common.annotations.Beta;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/rebind/dto/BasicLocationMemento.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/dto/BasicLocationMemento.java b/core/src/main/java/brooklyn/entity/rebind/dto/BasicLocationMemento.java
index a0578bb..6fbf66a 100644
--- a/core/src/main/java/brooklyn/entity/rebind/dto/BasicLocationMemento.java
+++ b/core/src/main/java/brooklyn/entity/rebind/dto/BasicLocationMemento.java
@@ -24,10 +24,10 @@ import java.util.Set;
import org.apache.brooklyn.api.mementos.LocationMemento;
import org.apache.brooklyn.api.mementos.TreeNode;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.Sanitizer;
-import brooklyn.util.config.ConfigBag;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.collect.Maps;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java b/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java
index dbe6e26..5c52788 100644
--- a/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java
+++ b/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java
@@ -50,6 +50,8 @@ import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.EntityAdjunct;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.core.catalog.internal.CatalogItemDo;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.FlagUtils;
import brooklyn.config.ConfigKey;
import brooklyn.enricher.basic.AbstractEnricher;
@@ -64,8 +66,6 @@ import org.apache.brooklyn.location.basic.LocationInternal;
import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.flags.FlagUtils;
import com.google.common.annotations.Beta;
import com.google.common.base.Function;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
index b5ca9c1..f146999 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
@@ -50,6 +50,7 @@ import org.apache.brooklyn.api.mementos.CatalogItemMemento;
import org.apache.brooklyn.api.mementos.Memento;
import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.classloading.ClassLoaderFromBrooklynClassLoadingContext;
+import org.apache.brooklyn.core.util.xstream.XmlUtil;
import brooklyn.config.ConfigKey;
import brooklyn.config.StringConfigMap;
@@ -66,7 +67,6 @@ import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Duration;
import brooklyn.util.time.Time;
-import brooklyn.util.xstream.XmlUtil;
import com.google.common.annotations.Beta;
import com.google.common.annotations.VisibleForTesting;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynPersistenceUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynPersistenceUtils.java b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynPersistenceUtils.java
index 68074e9..3db8106 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynPersistenceUtils.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynPersistenceUtils.java
@@ -45,6 +45,7 @@ import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.core.management.ha.ManagementPlaneSyncRecordPersisterToObjectStore;
import org.apache.brooklyn.core.management.internal.LocalLocationManager;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.util.ResourceUtils;
import brooklyn.config.BrooklynServerConfig;
import brooklyn.config.BrooklynServerPaths;
@@ -56,7 +57,6 @@ import brooklyn.entity.rebind.transformer.CompoundTransformerLoader;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/rebind/persister/FileBasedObjectStore.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/FileBasedObjectStore.java b/core/src/main/java/brooklyn/entity/rebind/persister/FileBasedObjectStore.java
index c1df659..764d55f 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/FileBasedObjectStore.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/FileBasedObjectStore.java
@@ -36,6 +36,7 @@ import javax.annotation.Nullable;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
+import org.apache.brooklyn.core.util.internal.ssh.process.ProcessTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -44,7 +45,6 @@ import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.exceptions.FatalConfigurationRuntimeException;
-import brooklyn.util.internal.ssh.process.ProcessTool;
import brooklyn.util.io.FileUtil;
import brooklyn.util.os.Os;
import brooklyn.util.os.Os.DeletionResult;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java b/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java
index 99ee2e5..6ff75e5 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java
@@ -47,6 +47,7 @@ import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.classloading.BrooklynClassLoadingContextSequential;
import org.apache.brooklyn.core.management.classloading.ClassLoaderFromBrooklynClassLoadingContext;
import org.apache.brooklyn.core.management.classloading.JavaBrooklynClassLoadingContext;
+import org.apache.brooklyn.core.util.xstream.XmlSerializer;
import brooklyn.entity.basic.BasicParameterType;
import brooklyn.entity.effector.EffectorAndBody;
@@ -63,7 +64,6 @@ import brooklyn.event.basic.BasicAttributeSensor;
import brooklyn.event.basic.BasicConfigKey;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.text.Strings;
-import brooklyn.util.xstream.XmlSerializer;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformer.java b/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformer.java
index 33d9422..030cd53 100644
--- a/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformer.java
+++ b/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformer.java
@@ -26,13 +26,13 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.rebind.BrooklynObjectType;
import org.apache.brooklyn.api.entity.rebind.RebindExceptionHandler;
import org.apache.brooklyn.api.mementos.BrooklynMementoRawData;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.text.TemplateProcessor;
import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
import brooklyn.entity.rebind.transformer.impl.XsltTransformer;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.text.Strings;
-import brooklyn.util.text.TemplateProcessor;
import com.google.common.annotations.Beta;
import com.google.common.annotations.VisibleForTesting;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformerLoader.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformerLoader.java b/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformerLoader.java
index 8a2d4bb..b36328c 100644
--- a/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformerLoader.java
+++ b/core/src/main/java/brooklyn/entity/rebind/transformer/CompoundTransformerLoader.java
@@ -22,13 +22,13 @@ import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.text.TemplateProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.entity.rebind.transformer.CompoundTransformer.Builder;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.text.TemplateProcessor;
import brooklyn.util.yaml.Yamls;
import com.google.common.annotations.Beta;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/entity/trait/Startable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/trait/Startable.java b/core/src/main/java/brooklyn/entity/trait/Startable.java
index 19c7f9d..dad2152 100644
--- a/core/src/main/java/brooklyn/entity/trait/Startable.java
+++ b/core/src/main/java/brooklyn/entity/trait/Startable.java
@@ -23,6 +23,8 @@ import java.util.Collection;
import org.apache.brooklyn.api.entity.Effector;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,8 +35,6 @@ import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.MethodEffector;
import brooklyn.entity.effector.EffectorBody;
import brooklyn.entity.effector.Effectors;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.task.Tasks;
/**
* This interface describes an {@link org.apache.brooklyn.api.entity.Entity} that can be started and stopped.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/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 6188d14..0e14058 100644
--- a/core/src/main/java/brooklyn/entity/trait/StartableMethods.java
+++ b/core/src/main/java/brooklyn/entity/trait/StartableMethods.java
@@ -26,6 +26,9 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.management.TaskAdaptable;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.TaskTags;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,10 +36,7 @@ import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityPredicates;
import brooklyn.entity.effector.Effectors;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.CompoundRuntimeException;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.TaskTags;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/event/basic/AttributeMap.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/basic/AttributeMap.java b/core/src/main/java/brooklyn/event/basic/AttributeMap.java
index aa8dcc1..281adfd 100644
--- a/core/src/main/java/brooklyn/event/basic/AttributeMap.java
+++ b/core/src/main/java/brooklyn/event/basic/AttributeMap.java
@@ -26,12 +26,12 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.config.BrooklynLogging;
import brooklyn.entity.basic.AbstractEntity;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.guava.Maybe;
import com.google.common.base.Function;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/event/basic/AttributeSensorAndConfigKey.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/basic/AttributeSensorAndConfigKey.java b/core/src/main/java/brooklyn/event/basic/AttributeSensorAndConfigKey.java
index fda8063..f9cec48 100644
--- a/core/src/main/java/brooklyn/event/basic/AttributeSensorAndConfigKey.java
+++ b/core/src/main/java/brooklyn/event/basic/AttributeSensorAndConfigKey.java
@@ -22,6 +22,7 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,7 +34,6 @@ import brooklyn.entity.basic.BrooklynConfigKeys;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.event.feed.ConfigToAttributes;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.TypeCoercions;
/**
* A {@link Sensor} describing an attribute that can be configured with inputs that are used to derive the final value.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/event/basic/BasicConfigKey.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/basic/BasicConfigKey.java b/core/src/main/java/brooklyn/event/basic/BasicConfigKey.java
index 1e41aad..f3b9204 100644
--- a/core/src/main/java/brooklyn/event/basic/BasicConfigKey.java
+++ b/core/src/main/java/brooklyn/event/basic/BasicConfigKey.java
@@ -28,6 +28,8 @@ import java.util.concurrent.ExecutionException;
import javax.annotation.Nullable;
import org.apache.brooklyn.api.management.ExecutionContext;
+import org.apache.brooklyn.core.util.internal.ConfigKeySelfExtracting;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -35,8 +37,6 @@ import brooklyn.config.ConfigInheritance;
import brooklyn.config.ConfigKey;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.guava.TypeTokens;
-import brooklyn.util.internal.ConfigKeySelfExtracting;
-import brooklyn.util.task.Tasks;
import com.google.common.annotations.Beta;
import com.google.common.base.Objects;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/event/basic/DependentConfiguration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/basic/DependentConfiguration.java b/core/src/main/java/brooklyn/event/basic/DependentConfiguration.java
index 44d8688..4f990cf 100644
--- a/core/src/main/java/brooklyn/event/basic/DependentConfiguration.java
+++ b/core/src/main/java/brooklyn/event/basic/DependentConfiguration.java
@@ -44,6 +44,14 @@ import org.apache.brooklyn.api.management.SubscriptionHandle;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.management.TaskAdaptable;
import org.apache.brooklyn.api.management.TaskFactory;
+import org.apache.brooklyn.core.util.task.BasicExecutionContext;
+import org.apache.brooklyn.core.util.task.BasicTask;
+import org.apache.brooklyn.core.util.task.DeferredSupplier;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.ParallelTask;
+import org.apache.brooklyn.core.util.task.TaskInternal;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.core.util.task.ValueResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -63,14 +71,6 @@ import brooklyn.util.exceptions.NotManagedException;
import brooklyn.util.exceptions.RuntimeTimeoutException;
import brooklyn.util.guava.Functionals;
import brooklyn.util.guava.Maybe;
-import brooklyn.util.task.BasicExecutionContext;
-import brooklyn.util.task.BasicTask;
-import brooklyn.util.task.DeferredSupplier;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.ParallelTask;
-import brooklyn.util.task.TaskInternal;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.task.ValueResolver;
import brooklyn.util.text.Strings;
import brooklyn.util.time.CountdownTimer;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/event/basic/PortAttributeSensorAndConfigKey.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/basic/PortAttributeSensorAndConfigKey.java b/core/src/main/java/brooklyn/event/basic/PortAttributeSensorAndConfigKey.java
index fd7100a..ffd8229 100644
--- a/core/src/main/java/brooklyn/event/basic/PortAttributeSensorAndConfigKey.java
+++ b/core/src/main/java/brooklyn/event/basic/PortAttributeSensorAndConfigKey.java
@@ -29,6 +29,7 @@ import org.apache.brooklyn.api.location.PortRange;
import org.apache.brooklyn.api.location.PortSupplier;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.core.internal.BrooklynInitialization;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -37,7 +38,6 @@ import brooklyn.entity.basic.BrooklynConfigKeys;
import org.apache.brooklyn.location.basic.Locations;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.guava.Maybe;
import com.google.common.base.Optional;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/event/basic/TemplatedStringAttributeSensorAndConfigKey.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/basic/TemplatedStringAttributeSensorAndConfigKey.java b/core/src/main/java/brooklyn/event/basic/TemplatedStringAttributeSensorAndConfigKey.java
index 0a57b62..8537f49 100644
--- a/core/src/main/java/brooklyn/event/basic/TemplatedStringAttributeSensorAndConfigKey.java
+++ b/core/src/main/java/brooklyn/event/basic/TemplatedStringAttributeSensorAndConfigKey.java
@@ -21,12 +21,12 @@ package brooklyn.event.basic;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.util.text.TemplateProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.EntityInternal;
-import brooklyn.util.text.TemplateProcessor;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/event/feed/AttributePollHandler.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/feed/AttributePollHandler.java b/core/src/main/java/brooklyn/event/feed/AttributePollHandler.java
index fbfe65c..ff4ef6e 100644
--- a/core/src/main/java/brooklyn/event/feed/AttributePollHandler.java
+++ b/core/src/main/java/brooklyn/event/feed/AttributePollHandler.java
@@ -22,6 +22,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -32,8 +34,6 @@ import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.basic.Lifecycle;
import brooklyn.entity.basic.Lifecycle.Transition;
-import brooklyn.util.flags.TypeCoercions;
-import brooklyn.util.task.Tasks;
import brooklyn.util.time.Duration;
/**
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/event/feed/Poller.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/feed/Poller.java b/core/src/main/java/brooklyn/event/feed/Poller.java
index 1bd97cd..2f14f22 100644
--- a/core/src/main/java/brooklyn/event/feed/Poller.java
+++ b/core/src/main/java/brooklyn/event/feed/Poller.java
@@ -24,6 +24,9 @@ import java.util.concurrent.Callable;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.task.DynamicSequentialTask;
+import org.apache.brooklyn.core.util.task.ScheduledTask;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -32,9 +35,6 @@ import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.task.DynamicSequentialTask;
-import brooklyn.util.task.ScheduledTask;
-import brooklyn.util.task.Tasks;
import brooklyn.util.time.Duration;
import com.google.common.base.Objects;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/event/feed/http/HttpFeed.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/feed/http/HttpFeed.java b/core/src/main/java/brooklyn/event/feed/http/HttpFeed.java
index 342e430..39f008a 100644
--- a/core/src/main/java/brooklyn/event/feed/http/HttpFeed.java
+++ b/core/src/main/java/brooklyn/event/feed/http/HttpFeed.java
@@ -29,6 +29,9 @@ import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
+import org.apache.brooklyn.core.util.http.HttpTool;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
+import org.apache.brooklyn.core.util.http.HttpTool.HttpClientBuilder;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.HttpClient;
@@ -42,9 +45,6 @@ import brooklyn.event.feed.AbstractFeed;
import brooklyn.event.feed.AttributePollHandler;
import brooklyn.event.feed.DelegatingPollHandler;
import brooklyn.event.feed.Poller;
-import brooklyn.util.http.HttpTool;
-import brooklyn.util.http.HttpTool.HttpClientBuilder;
-import brooklyn.util.http.HttpToolResponse;
import brooklyn.util.time.Duration;
import com.google.common.base.Objects;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/event/feed/http/HttpPollConfig.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/feed/http/HttpPollConfig.java b/core/src/main/java/brooklyn/event/feed/http/HttpPollConfig.java
index 923995f..b27fede 100644
--- a/core/src/main/java/brooklyn/event/feed/http/HttpPollConfig.java
+++ b/core/src/main/java/brooklyn/event/feed/http/HttpPollConfig.java
@@ -24,12 +24,12 @@ import java.util.Map;
import javax.annotation.Nullable;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.http.HttpTool;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
import brooklyn.event.feed.PollConfig;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.http.HttpTool;
-import brooklyn.util.http.HttpToolResponse;
import brooklyn.util.time.Duration;
import com.google.common.base.Predicate;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/event/feed/http/HttpPollValue.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/feed/http/HttpPollValue.java b/core/src/main/java/brooklyn/event/feed/http/HttpPollValue.java
index 81fe325..1df1f9a 100644
--- a/core/src/main/java/brooklyn/event/feed/http/HttpPollValue.java
+++ b/core/src/main/java/brooklyn/event/feed/http/HttpPollValue.java
@@ -21,7 +21,7 @@ package brooklyn.event.feed.http;
import java.util.List;
import java.util.Map;
-import brooklyn.util.http.HttpToolResponse;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
/** @deprecated since 0.7.0, use {@link HttpToolResponse}.
* the old {@link HttpPollValue} concrete class has been renamed {@link HttpToolResponse}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/event/feed/http/HttpPolls.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/feed/http/HttpPolls.java b/core/src/main/java/brooklyn/event/feed/http/HttpPolls.java
index 2e53618..94391ce 100644
--- a/core/src/main/java/brooklyn/event/feed/http/HttpPolls.java
+++ b/core/src/main/java/brooklyn/event/feed/http/HttpPolls.java
@@ -20,11 +20,10 @@ package brooklyn.event.feed.http;
import java.net.URI;
+import org.apache.brooklyn.core.util.http.HttpTool;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
import org.apache.http.impl.client.DefaultHttpClient;
-import brooklyn.util.http.HttpTool;
-import brooklyn.util.http.HttpToolResponse;
-
import com.google.common.collect.ImmutableMap;
/**
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/event/feed/http/HttpValueFunctions.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/feed/http/HttpValueFunctions.java b/core/src/main/java/brooklyn/event/feed/http/HttpValueFunctions.java
index 3e7e6b2..f6ab2b5 100644
--- a/core/src/main/java/brooklyn/event/feed/http/HttpValueFunctions.java
+++ b/core/src/main/java/brooklyn/event/feed/http/HttpValueFunctions.java
@@ -20,8 +20,9 @@ package brooklyn.event.feed.http;
import java.util.List;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
+
import brooklyn.util.guava.Functionals;
-import brooklyn.util.http.HttpToolResponse;
import com.google.common.base.Function;
import com.google.common.base.Functions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/event/feed/shell/ShellFeed.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/feed/shell/ShellFeed.java b/core/src/main/java/brooklyn/event/feed/shell/ShellFeed.java
index 7362666..5c82be7 100644
--- a/core/src/main/java/brooklyn/event/feed/shell/ShellFeed.java
+++ b/core/src/main/java/brooklyn/event/feed/shell/ShellFeed.java
@@ -29,6 +29,9 @@ import java.util.concurrent.TimeUnit;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.management.ExecutionContext;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskFactory;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
+import org.apache.brooklyn.core.util.task.system.internal.SystemProcessTaskFactory.ConcreteSystemProcessTaskFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -42,9 +45,6 @@ import brooklyn.event.feed.Poller;
import brooklyn.event.feed.function.FunctionFeed;
import brooklyn.event.feed.ssh.SshFeed;
import brooklyn.event.feed.ssh.SshPollValue;
-import brooklyn.util.task.system.ProcessTaskFactory;
-import brooklyn.util.task.system.ProcessTaskWrapper;
-import brooklyn.util.task.system.internal.SystemProcessTaskFactory.ConcreteSystemProcessTaskFactory;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/event/feed/ssh/SshFeed.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/feed/ssh/SshFeed.java b/core/src/main/java/brooklyn/event/feed/ssh/SshFeed.java
index 200e2fb..46c751b 100644
--- a/core/src/main/java/brooklyn/event/feed/ssh/SshFeed.java
+++ b/core/src/main/java/brooklyn/event/feed/ssh/SshFeed.java
@@ -30,6 +30,8 @@ import java.util.concurrent.TimeUnit;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.internal.ssh.SshTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -39,11 +41,11 @@ import brooklyn.event.feed.AbstractFeed;
import brooklyn.event.feed.AttributePollHandler;
import brooklyn.event.feed.DelegatingPollHandler;
import brooklyn.event.feed.Poller;
+
import org.apache.brooklyn.location.basic.Locations;
import org.apache.brooklyn.location.basic.Machines;
import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.internal.ssh.SshTool;
+
import brooklyn.util.time.Duration;
import com.google.common.base.Objects;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/event/feed/windows/WindowsPerformanceCounterFeed.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/feed/windows/WindowsPerformanceCounterFeed.java b/core/src/main/java/brooklyn/event/feed/windows/WindowsPerformanceCounterFeed.java
index 040d887..c06c013 100644
--- a/core/src/main/java/brooklyn/event/feed/windows/WindowsPerformanceCounterFeed.java
+++ b/core/src/main/java/brooklyn/event/feed/windows/WindowsPerformanceCounterFeed.java
@@ -38,6 +38,7 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.management.ExecutionContext;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -49,9 +50,10 @@ import brooklyn.event.basic.Sensors;
import brooklyn.event.feed.AbstractFeed;
import brooklyn.event.feed.PollHandler;
import brooklyn.event.feed.Poller;
+
import org.apache.brooklyn.location.basic.WinRmMachineLocation;
+
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.time.Duration;
import com.google.common.annotations.VisibleForTesting;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java b/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
index ab303a0..afa015f 100644
--- a/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
+++ b/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
@@ -41,6 +41,10 @@ import org.apache.brooklyn.api.management.SubscriptionHandle;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.policy.EntityAdjunct;
import org.apache.brooklyn.core.management.internal.SubscriptionTracker;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.flags.FlagUtils;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -53,10 +57,6 @@ import brooklyn.enricher.basic.AbstractEnricher;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityInternal;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.flags.FlagUtils;
-import brooklyn.util.flags.SetFromFlag;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.guava.Maybe;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/policy/basic/ConfigMapImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/policy/basic/ConfigMapImpl.java b/core/src/main/java/brooklyn/policy/basic/ConfigMapImpl.java
index 825720a..467eb05 100644
--- a/core/src/main/java/brooklyn/policy/basic/ConfigMapImpl.java
+++ b/core/src/main/java/brooklyn/policy/basic/ConfigMapImpl.java
@@ -25,6 +25,8 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.management.ExecutionContext;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
+import org.apache.brooklyn.core.util.internal.ConfigKeySelfExtracting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -38,9 +40,7 @@ import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.basic.Sanitizer;
import brooklyn.event.basic.StructuredConfigKey;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.guava.Maybe;
-import brooklyn.util.internal.ConfigKeySelfExtracting;
public class ConfigMapImpl extends AbstractConfigMapImpl {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/BrooklynLanguageExtensions.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/BrooklynLanguageExtensions.java b/core/src/main/java/brooklyn/util/BrooklynLanguageExtensions.java
deleted file mode 100644
index 86aac7e..0000000
--- a/core/src/main/java/brooklyn/util/BrooklynLanguageExtensions.java
+++ /dev/null
@@ -1,48 +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 brooklyn.util;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.apache.brooklyn.core.internal.BrooklynInitialization;
-
-import brooklyn.util.internal.TimeExtras;
-
-/** @deprecated since 0.7.0 use {@link BrooklynInitialization} */
-public class BrooklynLanguageExtensions {
-
- private BrooklynLanguageExtensions() {}
-
- private static AtomicBoolean done = new AtomicBoolean(false);
-
- public synchronized static void reinit() {
- done.set(false);
- init();
- }
-
- /** performs the language extensions required for this project */
- public synchronized static void init() {
- if (done.getAndSet(true)) return;
- TimeExtras.init();
- BrooklynInitialization.initPortRanges();
- }
-
- static { BrooklynInitialization.initLegacyLanguageExtensions(); }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/BrooklynMavenArtifacts.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/BrooklynMavenArtifacts.java b/core/src/main/java/brooklyn/util/BrooklynMavenArtifacts.java
deleted file mode 100644
index 50a5879..0000000
--- a/core/src/main/java/brooklyn/util/BrooklynMavenArtifacts.java
+++ /dev/null
@@ -1,58 +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 brooklyn.util;
-
-import brooklyn.BrooklynVersion;
-import brooklyn.util.maven.MavenArtifact;
-import brooklyn.util.maven.MavenRetriever;
-import brooklyn.util.text.Strings;
-
-public class BrooklynMavenArtifacts {
-
- public static MavenArtifact jar(String artifactId) {
- return artifact(null, artifactId, "jar");
- }
-
- public static MavenArtifact artifact(String subgroupUnderIoBrooklyn, String artifactId, String packaging) {
- return artifact(subgroupUnderIoBrooklyn, artifactId, packaging, null);
- }
-
- public static MavenArtifact artifact(String subgroupUnderIoBrooklyn, String artifactId, String packaging, String classifier) {
- return new MavenArtifact(
- Strings.isEmpty(subgroupUnderIoBrooklyn) ? "org.apache.brooklyn" : "org.apache.brooklyn."+subgroupUnderIoBrooklyn,
- artifactId, packaging, classifier, BrooklynVersion.get());
- }
-
- public static String localUrlForJar(String artifactId) {
- return MavenRetriever.localUrl(jar(artifactId));
- }
-
- public static String localUrl(String subgroupUnderIoBrooklyn, String artifactId, String packaging) {
- return MavenRetriever.localUrl(artifact(subgroupUnderIoBrooklyn, artifactId, packaging));
- }
-
- public static String hostedUrlForJar(String artifactId) {
- return MavenRetriever.hostedUrl(jar(artifactId));
- }
-
- public static String hostedUrl(String subgroupUnderIoBrooklyn, String artifactId, String packaging) {
- return MavenRetriever.hostedUrl(artifact(subgroupUnderIoBrooklyn, artifactId, packaging));
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/main/java/brooklyn/util/BrooklynNetworkUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/BrooklynNetworkUtils.java b/core/src/main/java/brooklyn/util/BrooklynNetworkUtils.java
deleted file mode 100644
index 0c1d39d..0000000
--- a/core/src/main/java/brooklyn/util/BrooklynNetworkUtils.java
+++ /dev/null
@@ -1,41 +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 brooklyn.util;
-
-import java.net.InetAddress;
-
-import brooklyn.config.BrooklynServiceAttributes;
-import org.apache.brooklyn.location.geo.LocalhostExternalIpLoader;
-import brooklyn.util.flags.TypeCoercions;
-import brooklyn.util.net.Networking;
-
-public class BrooklynNetworkUtils {
-
- /** returns the externally-facing IP address from which this host comes, or 127.0.0.1 if not resolvable */
- public static String getLocalhostExternalIp() {
- return LocalhostExternalIpLoader.getLocalhostIpQuicklyOrDefault();
- }
-
- /** returns a IP address for localhost paying attention to a system property to prevent lookup in some cases */
- public static InetAddress getLocalhostInetAddress() {
- return TypeCoercions.coerce(JavaGroovyEquivalents.elvis(BrooklynServiceAttributes.LOCALHOST_IP_ADDRESS.getValue(),
- Networking.getLocalHost()), InetAddress.class);
- }
-
-}
[06/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/messaging/src/main/java/brooklyn/entity/messaging/qpid/QpidDestinationImpl.java
----------------------------------------------------------------------
diff --git a/software/messaging/src/main/java/brooklyn/entity/messaging/qpid/QpidDestinationImpl.java b/software/messaging/src/main/java/brooklyn/entity/messaging/qpid/QpidDestinationImpl.java
index 83e0af0..0dc6390 100644
--- a/software/messaging/src/main/java/brooklyn/entity/messaging/qpid/QpidDestinationImpl.java
+++ b/software/messaging/src/main/java/brooklyn/entity/messaging/qpid/QpidDestinationImpl.java
@@ -24,6 +24,7 @@ import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,7 +34,6 @@ import brooklyn.entity.messaging.jms.JMSDestinationImpl;
import brooklyn.event.feed.jmx.JmxFeed;
import brooklyn.event.feed.jmx.JmxHelper;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.SetFromFlag;
public abstract class QpidDestinationImpl extends JMSDestinationImpl implements QpidDestination {
public static final Logger log = LoggerFactory.getLogger(QpidDestination.class);
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/messaging/src/main/java/brooklyn/entity/messaging/rabbit/RabbitBroker.java
----------------------------------------------------------------------
diff --git a/software/messaging/src/main/java/brooklyn/entity/messaging/rabbit/RabbitBroker.java b/software/messaging/src/main/java/brooklyn/entity/messaging/rabbit/RabbitBroker.java
index a641638..a70bfce 100644
--- a/software/messaging/src/main/java/brooklyn/entity/messaging/rabbit/RabbitBroker.java
+++ b/software/messaging/src/main/java/brooklyn/entity/messaging/rabbit/RabbitBroker.java
@@ -25,6 +25,7 @@ import com.google.common.annotations.Beta;
import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
@@ -35,7 +36,6 @@ import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
import brooklyn.event.basic.BasicConfigKey;
import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
/**
* An {@link org.apache.brooklyn.api.entity.Entity} that represents a single Rabbit MQ broker instance, using AMQP 0-9-1.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/messaging/src/main/java/brooklyn/entity/messaging/storm/Storm.java
----------------------------------------------------------------------
diff --git a/software/messaging/src/main/java/brooklyn/entity/messaging/storm/Storm.java b/software/messaging/src/main/java/brooklyn/entity/messaging/storm/Storm.java
index e38aa6a..ced7bef 100644
--- a/software/messaging/src/main/java/brooklyn/entity/messaging/storm/Storm.java
+++ b/software/messaging/src/main/java/brooklyn/entity/messaging/storm/Storm.java
@@ -22,6 +22,7 @@ import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.config.render.RendererHints;
@@ -32,7 +33,6 @@ import brooklyn.entity.zookeeper.ZooKeeperEnsemble;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
/**
* An {@link org.apache.brooklyn.api.entity.Entity} that represents a Storm node (UI, Nimbus or Supervisor).
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/messaging/src/main/java/brooklyn/entity/messaging/storm/StormDeployment.java
----------------------------------------------------------------------
diff --git a/software/messaging/src/main/java/brooklyn/entity/messaging/storm/StormDeployment.java b/software/messaging/src/main/java/brooklyn/entity/messaging/storm/StormDeployment.java
index 92ce3aa..fda29fd 100644
--- a/software/messaging/src/main/java/brooklyn/entity/messaging/storm/StormDeployment.java
+++ b/software/messaging/src/main/java/brooklyn/entity/messaging/storm/StormDeployment.java
@@ -21,11 +21,11 @@ package brooklyn.entity.messaging.storm;
import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.trait.Startable;
-import brooklyn.util.flags.SetFromFlag;
@Catalog(name="Storm Deployment", description="A Storm cluster. Apache Storm is a distributed realtime computation system. "
+ "Storm makes it easy to reliably process unbounded streams of data, doing for realtime processing "
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/messaging/src/main/java/brooklyn/entity/messaging/storm/StormDeploymentImpl.java
----------------------------------------------------------------------
diff --git a/software/messaging/src/main/java/brooklyn/entity/messaging/storm/StormDeploymentImpl.java b/software/messaging/src/main/java/brooklyn/entity/messaging/storm/StormDeploymentImpl.java
index d5b79cc..cf90db8 100644
--- a/software/messaging/src/main/java/brooklyn/entity/messaging/storm/StormDeploymentImpl.java
+++ b/software/messaging/src/main/java/brooklyn/entity/messaging/storm/StormDeploymentImpl.java
@@ -24,6 +24,7 @@ import static brooklyn.entity.messaging.storm.Storm.Role.SUPERVISOR;
import static brooklyn.entity.messaging.storm.Storm.Role.UI;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.core.util.ResourceUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -32,7 +33,6 @@ import brooklyn.entity.basic.Attributes;
import brooklyn.entity.basic.BasicStartableImpl;
import brooklyn.entity.group.DynamicCluster;
import brooklyn.entity.zookeeper.ZooKeeperEnsemble;
-import brooklyn.util.ResourceUtils;
public class StormDeploymentImpl extends BasicStartableImpl implements StormDeployment {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/messaging/src/main/java/brooklyn/entity/zookeeper/ZooKeeperEnsemble.java
----------------------------------------------------------------------
diff --git a/software/messaging/src/main/java/brooklyn/entity/zookeeper/ZooKeeperEnsemble.java b/software/messaging/src/main/java/brooklyn/entity/zookeeper/ZooKeeperEnsemble.java
index b09e7f8..e5869c5 100644
--- a/software/messaging/src/main/java/brooklyn/entity/zookeeper/ZooKeeperEnsemble.java
+++ b/software/messaging/src/main/java/brooklyn/entity/zookeeper/ZooKeeperEnsemble.java
@@ -23,13 +23,13 @@ import java.util.List;
import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.group.DynamicCluster;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.reflect.TypeToken;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/messaging/src/main/java/brooklyn/entity/zookeeper/ZooKeeperNode.java
----------------------------------------------------------------------
diff --git a/software/messaging/src/main/java/brooklyn/entity/zookeeper/ZooKeeperNode.java b/software/messaging/src/main/java/brooklyn/entity/zookeeper/ZooKeeperNode.java
index 4d6ecdf..504a894 100644
--- a/software/messaging/src/main/java/brooklyn/entity/zookeeper/ZooKeeperNode.java
+++ b/software/messaging/src/main/java/brooklyn/entity/zookeeper/ZooKeeperNode.java
@@ -21,6 +21,7 @@ package brooklyn.entity.zookeeper;
import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
@@ -28,7 +29,6 @@ import brooklyn.entity.basic.SoftwareProcess;
import brooklyn.event.basic.BasicAttributeSensor;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
-import brooklyn.util.flags.SetFromFlag;
/**
* An {@link org.apache.brooklyn.api.entity.Entity} that represents a single Apache ZooKeeper instance.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/messaging/src/test/java/brooklyn/entity/messaging/storm/StormAbstractCloudLiveTest.java
----------------------------------------------------------------------
diff --git a/software/messaging/src/test/java/brooklyn/entity/messaging/storm/StormAbstractCloudLiveTest.java b/software/messaging/src/test/java/brooklyn/entity/messaging/storm/StormAbstractCloudLiveTest.java
index 758ace7..d79b2da 100644
--- a/software/messaging/src/test/java/brooklyn/entity/messaging/storm/StormAbstractCloudLiveTest.java
+++ b/software/messaging/src/test/java/brooklyn/entity/messaging/storm/StormAbstractCloudLiveTest.java
@@ -31,6 +31,8 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.file.ArchiveBuilder;
import org.apache.brooklyn.test.EntityTestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -52,9 +54,7 @@ import brooklyn.entity.basic.Entities;
import brooklyn.entity.messaging.storm.topologies.ExclamationBolt;
import brooklyn.entity.trait.Startable;
import brooklyn.entity.zookeeper.ZooKeeperEnsemble;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.file.ArchiveBuilder;
import brooklyn.util.os.Os;
import brooklyn.util.time.Duration;
import brooklyn.util.time.Time;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/monit/MonitNode.java
----------------------------------------------------------------------
diff --git a/software/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/monit/MonitNode.java b/software/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/monit/MonitNode.java
index 7e0ca22..064a54b 100644
--- a/software/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/monit/MonitNode.java
+++ b/software/monitoring/src/main/java/org/apache/brooklyn/entity/monitoring/monit/MonitNode.java
@@ -27,6 +27,7 @@ import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.entity.trait.HasShortName;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.Attributes;
@@ -35,7 +36,6 @@ import brooklyn.entity.basic.SoftwareProcess;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey.StringAttributeSensorAndConfigKey;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
@Catalog(name="Monit Node", description="Monit is a free open source utility for managing and monitoring, processes, programs, files, directories and filesystems on a UNIX system")
@ImplementedBy(MonitNodeImpl.class)
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/network/src/main/java/org/apache/brooklyn/entity/network/bind/BindDnsServer.java
----------------------------------------------------------------------
diff --git a/software/network/src/main/java/org/apache/brooklyn/entity/network/bind/BindDnsServer.java b/software/network/src/main/java/org/apache/brooklyn/entity/network/bind/BindDnsServer.java
index 032a471..fc27b19 100644
--- a/software/network/src/main/java/org/apache/brooklyn/entity/network/bind/BindDnsServer.java
+++ b/software/network/src/main/java/org/apache/brooklyn/entity/network/bind/BindDnsServer.java
@@ -29,6 +29,7 @@ import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.annotation.Effector;
@@ -37,8 +38,9 @@ import brooklyn.entity.basic.DynamicGroup;
import brooklyn.entity.basic.SoftwareProcess;
import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
import brooklyn.event.basic.Sensors;
+
import org.apache.brooklyn.location.basic.PortRanges;
-import brooklyn.util.flags.SetFromFlag;
+
import brooklyn.util.net.Cidr;
/**
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraDatacenter.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraDatacenter.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraDatacenter.java
index dc01fd5..07e7f96 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraDatacenter.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraDatacenter.java
@@ -26,6 +26,7 @@ import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.entity.nosql.cassandra.TokenGenerators.PosNeg63TokenGenerator;
import brooklyn.config.ConfigKey;
@@ -37,7 +38,6 @@ import brooklyn.entity.effector.Effectors;
import brooklyn.entity.group.DynamicCluster;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.time.Duration;
import com.google.common.base.Supplier;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraDatacenterImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraDatacenterImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraDatacenterImpl.java
index a2ed4c4..5b5cb9b 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraDatacenterImpl.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraDatacenterImpl.java
@@ -35,6 +35,8 @@ import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -51,11 +53,9 @@ import brooklyn.entity.group.DynamicClusterImpl;
import org.apache.brooklyn.location.basic.Machines;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Time;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNode.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNode.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNode.java
index 21fbbb7..f779de8 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNode.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNode.java
@@ -26,6 +26,7 @@ import org.apache.brooklyn.api.entity.Effector;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.BrooklynConfigKeys;
@@ -38,8 +39,9 @@ import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
import brooklyn.event.basic.BasicConfigKey;
import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
import brooklyn.event.basic.Sensors;
+
import org.apache.brooklyn.location.basic.PortRanges;
-import brooklyn.util.flags.SetFromFlag;
+
import brooklyn.util.time.Duration;
import com.google.common.reflect.TypeToken;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNodeDriver.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNodeDriver.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNodeDriver.java
index eab6672..befaa6d 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNodeDriver.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNodeDriver.java
@@ -18,8 +18,9 @@
*/
package org.apache.brooklyn.entity.nosql.cassandra;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
+
import brooklyn.entity.java.JavaSoftwareProcessDriver;
-import brooklyn.util.task.system.ProcessTaskWrapper;
public interface CassandraNodeDriver extends JavaSoftwareProcessDriver {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNodeImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNodeImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNodeImpl.java
index 2d82d19..b27b957 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNodeImpl.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNodeImpl.java
@@ -36,6 +36,8 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.location.MachineLocation;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.text.TemplateProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -59,11 +61,9 @@ import org.apache.brooklyn.location.basic.Machines;
import org.apache.brooklyn.location.cloud.CloudLocationConfig;
import brooklyn.util.collections.MutableSet;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.guava.Maybe;
import brooklyn.util.text.Strings;
-import brooklyn.util.text.TemplateProcessor;
import brooklyn.util.time.Duration;
import com.google.common.base.Function;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNodeSshDriver.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNodeSshDriver.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNodeSshDriver.java
index c3a57b0..7806979 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNodeSshDriver.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraNodeSshDriver.java
@@ -31,6 +31,10 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.management.TaskWrapper;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.core.util.task.system.ProcessTaskWrapper;
+import org.apache.brooklyn.core.util.text.TemplateProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -58,12 +62,8 @@ import brooklyn.util.net.Networking;
import brooklyn.util.os.Os;
import brooklyn.util.ssh.BashCommands;
import brooklyn.util.stream.Streams;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.task.system.ProcessTaskWrapper;
import brooklyn.util.text.Identifiers;
import brooklyn.util.text.Strings;
-import brooklyn.util.text.TemplateProcessor;
import brooklyn.util.time.Duration;
import brooklyn.util.time.Time;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseCluster.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseCluster.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseCluster.java
index 65b7dd0..a46e1a8 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseCluster.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseCluster.java
@@ -26,12 +26,12 @@ import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.group.DynamicCluster;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.time.Duration;
import com.google.common.reflect.TypeToken;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
index 3196428..fcb944d 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseClusterImpl.java
@@ -33,6 +33,9 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.TaskBuilder;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -62,9 +65,6 @@ import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.guava.Functionals;
import brooklyn.util.guava.IfFunctions;
import brooklyn.util.math.MathPredicates;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.TaskBuilder;
-import brooklyn.util.task.Tasks;
import brooklyn.util.text.ByteSizeStrings;
import brooklyn.util.text.StringFunctions;
import brooklyn.util.text.Strings;
@@ -565,8 +565,8 @@ public class CouchbaseClusterImpl extends DynamicClusterImpl implements Couchbas
.onFailureOrException(new Function<Object, Boolean>() {
@Override
public Boolean apply(Object input) {
- if (input instanceof brooklyn.util.http.HttpToolResponse) {
- if (((brooklyn.util.http.HttpToolResponse) input).getResponseCode() == 404) {
+ if (input instanceof org.apache.brooklyn.core.util.http.HttpToolResponse) {
+ if (((org.apache.brooklyn.core.util.http.HttpToolResponse) input).getResponseCode() == 404) {
return true;
}
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseNode.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseNode.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseNode.java
index bd244b9..5f3269a 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseNode.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseNode.java
@@ -23,6 +23,7 @@ import java.net.URI;
import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.config.render.RendererHints;
@@ -36,7 +37,6 @@ import brooklyn.entity.effector.Effectors;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.text.ByteSizeStrings;
@Catalog(name="CouchBase Node", description="Couchbase Server is an open source, distributed (shared-nothing architecture) "
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseNodeImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseNodeImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseNodeImpl.java
index 07b34b4..d27f7db 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseNodeImpl.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseNodeImpl.java
@@ -30,6 +30,10 @@ import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
+import org.apache.brooklyn.core.util.config.ConfigBag;
+import org.apache.brooklyn.core.util.http.HttpTool;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -47,15 +51,11 @@ import org.apache.brooklyn.location.cloud.CloudLocationConfig;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.guava.Functionals;
import brooklyn.util.guava.MaybeFunctions;
import brooklyn.util.guava.TypeTokens;
-import brooklyn.util.http.HttpTool;
-import brooklyn.util.http.HttpToolResponse;
import brooklyn.util.net.Urls;
-import brooklyn.util.task.Tasks;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java
index 41bef9f..f894937 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseNodeSshDriver.java
@@ -33,6 +33,12 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.Group;
import org.apache.brooklyn.api.location.OsDetails;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.util.http.HttpTool;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.TaskBuilder;
+import org.apache.brooklyn.core.util.task.TaskTags;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.apache.http.auth.UsernamePasswordCredentials;
import brooklyn.entity.basic.AbstractSoftwareProcessSshDriver;
@@ -49,14 +55,8 @@ import org.apache.brooklyn.location.access.BrooklynAccessUtils;
import org.apache.brooklyn.location.basic.SshMachineLocation;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.http.HttpTool;
-import brooklyn.util.http.HttpToolResponse;
import brooklyn.util.repeat.Repeater;
import brooklyn.util.ssh.BashCommands;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.TaskBuilder;
-import brooklyn.util.task.TaskTags;
-import brooklyn.util.task.Tasks;
import brooklyn.util.text.NaturalOrderComparator;
import brooklyn.util.text.StringEscapes.BashStringEscapes;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseSyncGateway.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseSyncGateway.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseSyncGateway.java
index 2e8dba9..07665a3 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseSyncGateway.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseSyncGateway.java
@@ -21,6 +21,7 @@ package org.apache.brooklyn.entity.nosql.couchbase;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
@@ -28,7 +29,6 @@ import brooklyn.entity.basic.SoftwareProcess;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
@ImplementedBy(CouchbaseSyncGatewayImpl.class)
public interface CouchbaseSyncGateway extends SoftwareProcess {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchdb/CouchDBCluster.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchdb/CouchDBCluster.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchdb/CouchDBCluster.java
index 2964da7..94b33c1 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchdb/CouchDBCluster.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchdb/CouchDBCluster.java
@@ -20,11 +20,11 @@ package org.apache.brooklyn.entity.nosql.couchdb;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.entity.group.DynamicCluster;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
/**
* A cluster of {@link CouchDBNode}s based on {@link DynamicCluster} which can be resized by a policy if required.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchdb/CouchDBNode.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchdb/CouchDBNode.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchdb/CouchDBNode.java
index f438de6..9d89349 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchdb/CouchDBNode.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchdb/CouchDBNode.java
@@ -20,13 +20,13 @@ package org.apache.brooklyn.entity.nosql.couchdb;
import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.entity.webapp.WebAppService;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.SoftwareProcess;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
-import brooklyn.util.flags.SetFromFlag;
/**
* An {@link org.apache.brooklyn.api.entity.Entity} that represents a CouchDB node in a {@link CouchDBCluster}.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchdb/CouchDBNodeImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchdb/CouchDBNodeImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchdb/CouchDBNodeImpl.java
index b200f6e..7f8f639 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchdb/CouchDBNodeImpl.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/couchdb/CouchDBNodeImpl.java
@@ -22,6 +22,7 @@ import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
+import org.apache.brooklyn.core.util.flags.TypeCoercions;
import org.apache.brooklyn.entity.webapp.JavaWebAppSoftwareProcessImpl;
import org.apache.brooklyn.entity.webapp.WebAppServiceMethods;
import org.slf4j.Logger;
@@ -31,7 +32,6 @@ import brooklyn.entity.basic.SoftwareProcessImpl;
import brooklyn.event.feed.http.HttpFeed;
import brooklyn.event.feed.http.HttpPollConfig;
import brooklyn.event.feed.http.HttpValueFunctions;
-import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.guava.Functionals;
import com.google.common.base.Function;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchCluster.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchCluster.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchCluster.java
index f73a911..c8b9bd3 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchCluster.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchCluster.java
@@ -20,10 +20,10 @@ package org.apache.brooklyn.entity.nosql.elasticsearch;
import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.entity.group.DynamicCluster;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
-import brooklyn.util.flags.SetFromFlag;
/**
* A cluster of {@link ElasticSearchNode}s based on {@link DynamicCluster} which can be resized by a policy if required.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchNode.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchNode.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchNode.java
index a2d82c0..d82e34b 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchNode.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchNode.java
@@ -21,6 +21,7 @@ package org.apache.brooklyn.entity.nosql.elasticsearch;
import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.entity.webapp.WebAppServiceConstants;
import brooklyn.config.ConfigKey;
@@ -31,8 +32,8 @@ import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey.StringAttributeSensorAndConfigKey;
import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
import brooklyn.event.basic.Sensors;
+
import org.apache.brooklyn.location.basic.PortRanges;
-import brooklyn.util.flags.SetFromFlag;
/**
* An {@link org.apache.brooklyn.api.entity.Entity} that represents an ElasticSearch node
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchNodeImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchNodeImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchNodeImpl.java
index 4478ac3..eb81a93 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchNodeImpl.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchNodeImpl.java
@@ -21,18 +21,20 @@ package org.apache.brooklyn.entity.nosql.elasticsearch;
import static com.google.common.base.Preconditions.checkNotNull;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
import brooklyn.entity.basic.SoftwareProcessImpl;
import brooklyn.event.feed.http.HttpFeed;
import brooklyn.event.feed.http.HttpPollConfig;
import brooklyn.event.feed.http.HttpValueFunctions;
import brooklyn.event.feed.http.JsonFunctions;
+
import org.apache.brooklyn.location.access.BrooklynAccessUtils;
+
import brooklyn.util.guava.Functionals;
import brooklyn.util.guava.Maybe;
import brooklyn.util.guava.MaybeFunctions;
import brooklyn.util.guava.TypeTokens;
-import brooklyn.util.http.HttpToolResponse;
import com.google.common.base.Function;
import com.google.common.base.Functions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/AbstractMongoDBServer.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/AbstractMongoDBServer.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/AbstractMongoDBServer.java
index 81ea23c..b2c8410 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/AbstractMongoDBServer.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/AbstractMongoDBServer.java
@@ -19,6 +19,7 @@
package org.apache.brooklyn.entity.nosql.mongodb;
import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
@@ -26,7 +27,6 @@ import brooklyn.entity.basic.SoftwareProcess;
import brooklyn.event.basic.AttributeSensorAndConfigKey;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
-import brooklyn.util.flags.SetFromFlag;
public interface AbstractMongoDBServer extends SoftwareProcess, Entity {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBClient.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBClient.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBClient.java
index 3dbe34e..3bc3a88 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBClient.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBClient.java
@@ -28,10 +28,9 @@ import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.MethodEffector;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.entity.nosql.mongodb.sharding.MongoDBShardedDeployment;
-import brooklyn.util.flags.SetFromFlag;
-
import com.google.common.reflect.TypeToken;
@ImplementedBy(MongoDBClientImpl.class)
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSet.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSet.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSet.java
index 2ebd8bb..a19bd1e 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSet.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBReplicaSet.java
@@ -23,13 +23,13 @@ import java.util.List;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.group.Cluster;
import brooklyn.entity.group.DynamicCluster;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.reflect.TypeToken;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBServer.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBServer.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBServer.java
index f45070a..0ef0274 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBServer.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBServer.java
@@ -23,13 +23,13 @@ import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.event.AttributeSensor.SensorPersistenceMode;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.event.basic.BasicConfigKey;
import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
@Catalog(name="MongoDB Server",
description="MongoDB (from \"humongous\") is a scalable, high-performance, open source NoSQL database",
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/CoLocatedMongoDBRouter.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/CoLocatedMongoDBRouter.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/CoLocatedMongoDBRouter.java
index b9a088b..a458ec7 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/CoLocatedMongoDBRouter.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/CoLocatedMongoDBRouter.java
@@ -24,12 +24,12 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.SameServerEntity;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.reflect.TypeToken;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeployment.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeployment.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeployment.java
index ba8fc10..3bab3b8 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeployment.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeployment.java
@@ -24,6 +24,7 @@ import org.apache.brooklyn.api.entity.Group;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.entity.nosql.mongodb.MongoDBReplicaSet;
import org.apache.brooklyn.entity.nosql.mongodb.MongoDBServer;
@@ -31,7 +32,6 @@ import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.trait.Startable;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.time.Duration;
import com.google.common.reflect.TypeToken;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/redis/RedisSlave.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/redis/RedisSlave.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/redis/RedisSlave.java
index 3688057..84bfe0e 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/redis/RedisSlave.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/redis/RedisSlave.java
@@ -19,10 +19,10 @@
package org.apache.brooklyn.entity.nosql.redis;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.util.flags.SetFromFlag;
/**
* A {@link RedisStore} configured as a slave.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/redis/RedisStore.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/redis/RedisStore.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/redis/RedisStore.java
index a1a6749..2673426 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/redis/RedisStore.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/redis/RedisStore.java
@@ -21,6 +21,7 @@ package org.apache.brooklyn.entity.nosql.redis;
import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
@@ -28,7 +29,6 @@ import brooklyn.entity.basic.SoftwareProcess;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
/**
* An entity that represents a Redis key-value store service.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakCluster.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakCluster.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakCluster.java
index e1ee7b5..b657267 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakCluster.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakCluster.java
@@ -25,13 +25,13 @@ import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.Attributes;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.group.DynamicCluster;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.time.Duration;
import com.google.common.reflect.TypeToken;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakClusterImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakClusterImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakClusterImpl.java
index 4e72bae..7197787 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakClusterImpl.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakClusterImpl.java
@@ -30,6 +30,7 @@ import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.policy.EnricherSpec;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -45,7 +46,6 @@ import brooklyn.entity.group.AbstractMembershipTrackingPolicy;
import brooklyn.entity.group.DynamicClusterImpl;
import brooklyn.entity.trait.Startable;
import brooklyn.event.basic.DependentConfiguration;
-import brooklyn.util.task.Tasks;
import brooklyn.util.time.Duration;
import brooklyn.util.time.Time;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakNode.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakNode.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakNode.java
index 502aa91..7519709 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakNode.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakNode.java
@@ -24,6 +24,7 @@ import java.util.List;
import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.annotation.Effector;
@@ -36,7 +37,6 @@ import brooklyn.entity.java.UsesJava;
import brooklyn.event.basic.AttributeSensorAndConfigKey;
import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.collect.ImmutableList;
import com.google.common.reflect.TypeToken;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeImpl.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeImpl.java
index 587ffe3..6d0cd81 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeImpl.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeImpl.java
@@ -29,6 +29,7 @@ import javax.annotation.Nullable;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
+import org.apache.brooklyn.core.util.config.ConfigBag;
import org.apache.brooklyn.entity.webapp.WebAppServiceMethods;
import brooklyn.enricher.Enrichers;
@@ -43,7 +44,6 @@ import org.apache.brooklyn.location.access.BrooklynAccessUtils;
import org.apache.brooklyn.location.cloud.CloudLocationConfig;
import brooklyn.util.collections.MutableSet;
-import brooklyn.util.config.ConfigBag;
import brooklyn.util.guava.Functionals;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeSshDriver.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeSshDriver.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeSshDriver.java
index f115ab3..cbeff70 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeSshDriver.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeSshDriver.java
@@ -47,14 +47,14 @@ import brooklyn.entity.basic.lifecycle.ScriptHelper;
import brooklyn.entity.software.SshEffectorTasks;
import org.apache.brooklyn.api.location.OsDetails;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.ssh.SshTasks;
import org.apache.brooklyn.location.basic.SshMachineLocation;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.net.Urls;
import brooklyn.util.os.Os;
import brooklyn.util.ssh.BashCommands;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.ssh.SshTasks;
import brooklyn.util.text.Strings;
import com.google.common.base.Joiner;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/solr/SolrServer.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/solr/SolrServer.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/solr/SolrServer.java
index f813ced..a81a1da 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/solr/SolrServer.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/solr/SolrServer.java
@@ -22,6 +22,7 @@ import java.util.Map;
import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.BrooklynConfigKeys;
@@ -32,8 +33,9 @@ import brooklyn.entity.java.UsesJavaMXBeans;
import brooklyn.entity.java.UsesJmx;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
+
import org.apache.brooklyn.location.basic.PortRanges;
-import brooklyn.util.flags.SetFromFlag;
+
import brooklyn.util.time.Duration;
import com.google.common.collect.Maps;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/solr/SolrServerSshDriver.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/solr/SolrServerSshDriver.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/solr/SolrServerSshDriver.java
index 5f7335a..b66c06f 100644
--- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/solr/SolrServerSshDriver.java
+++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/solr/SolrServerSshDriver.java
@@ -33,10 +33,10 @@ import org.slf4j.LoggerFactory;
import brooklyn.entity.basic.Entities;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.util.file.ArchiveUtils;
import org.apache.brooklyn.location.basic.SshMachineLocation;
import brooklyn.util.collections.MutableMap;
-import brooklyn.util.file.ArchiveUtils;
import brooklyn.util.net.Networking;
import brooklyn.util.net.Urls;
import brooklyn.util.os.Os;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraDatacenterTest.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraDatacenterTest.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraDatacenterTest.java
index 1841cf7..4a78aaa 100644
--- a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraDatacenterTest.java
+++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/cassandra/CassandraDatacenterTest.java
@@ -27,6 +27,8 @@ import java.util.Set;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.text.TemplateProcessor;
import org.apache.brooklyn.test.EntityTestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -42,9 +44,7 @@ import brooklyn.entity.basic.EntityInternal;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.javalang.JavaClassNames;
-import brooklyn.util.text.TemplateProcessor;
import brooklyn.util.time.Duration;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchClusterIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchClusterIntegrationTest.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchClusterIntegrationTest.java
index 8e695c9..bad63b0 100644
--- a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchClusterIntegrationTest.java
+++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchClusterIntegrationTest.java
@@ -27,6 +27,8 @@ import java.net.URISyntaxException;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.util.http.HttpTool;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
import org.apache.brooklyn.test.EntityTestUtils;
import org.apache.http.client.methods.HttpGet;
import org.bouncycastle.util.Strings;
@@ -41,8 +43,6 @@ import brooklyn.entity.group.DynamicCluster;
import brooklyn.entity.trait.Startable;
import brooklyn.event.feed.http.HttpValueFunctions;
import brooklyn.test.Asserts;
-import brooklyn.util.http.HttpTool;
-import brooklyn.util.http.HttpToolResponse;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchNodeIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchNodeIntegrationTest.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchNodeIntegrationTest.java
index 8d5f0d1..5e9b5cb 100644
--- a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchNodeIntegrationTest.java
+++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/elasticsearch/ElasticSearchNodeIntegrationTest.java
@@ -25,6 +25,8 @@ import java.net.URISyntaxException;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.util.http.HttpTool;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
import org.apache.brooklyn.test.EntityTestUtils;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.http.client.methods.HttpGet;
@@ -41,9 +43,6 @@ import brooklyn.event.feed.http.HttpValueFunctions;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
-import brooklyn.util.http.HttpTool;
-import brooklyn.util.http.HttpToolResponse;
-
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/osgi/src/main/java/org/apache/brooklyn/entity/osgi/karaf/KarafContainer.java
----------------------------------------------------------------------
diff --git a/software/osgi/src/main/java/org/apache/brooklyn/entity/osgi/karaf/KarafContainer.java b/software/osgi/src/main/java/org/apache/brooklyn/entity/osgi/karaf/KarafContainer.java
index 6f0bd72..b708e95 100644
--- a/software/osgi/src/main/java/org/apache/brooklyn/entity/osgi/karaf/KarafContainer.java
+++ b/software/osgi/src/main/java/org/apache/brooklyn/entity/osgi/karaf/KarafContainer.java
@@ -23,6 +23,7 @@ import java.util.Map;
import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.annotation.Effector;
@@ -36,7 +37,6 @@ import brooklyn.event.basic.BasicAttributeSensor;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
import brooklyn.event.basic.MapConfigKey;
import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
-import brooklyn.util.flags.SetFromFlag;
/**
* This sets up a Karaf OSGi container
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/AbstractGeoDnsServiceImpl.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/AbstractGeoDnsServiceImpl.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/AbstractGeoDnsServiceImpl.java
index 790aece..5b54f38 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/AbstractGeoDnsServiceImpl.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/AbstractGeoDnsServiceImpl.java
@@ -36,6 +36,7 @@ import java.util.Set;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.Group;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.entity.webapp.WebAppService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -52,7 +53,6 @@ import org.apache.brooklyn.location.geo.HostGeoInfo;
import brooklyn.util.collections.MutableSet;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.net.Networking;
import brooklyn.util.time.Duration;
import brooklyn.util.time.Time;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingDnsService.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingDnsService.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingDnsService.java
index f98314c..b9b8a1f 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingDnsService.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingDnsService.java
@@ -22,6 +22,7 @@ import java.net.URI;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.entity.dns.AbstractGeoDnsService;
import org.apache.brooklyn.entity.webapp.WebAppServiceConstants;
@@ -30,7 +31,6 @@ import brooklyn.entity.basic.Attributes;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.event.basic.BasicAttributeSensor;
import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.util.flags.SetFromFlag;
@ImplementedBy(GeoscalingDnsServiceImpl.class)
public interface GeoscalingDnsService extends AbstractGeoDnsService {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingDnsServiceImpl.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingDnsServiceImpl.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingDnsServiceImpl.java
index c71c00a..48a01f0 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingDnsServiceImpl.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingDnsServiceImpl.java
@@ -25,6 +25,7 @@ import java.net.URI;
import java.util.Collection;
import java.util.Set;
+import org.apache.brooklyn.core.util.http.HttpTool;
import org.apache.brooklyn.entity.dns.AbstractGeoDnsServiceImpl;
import org.apache.brooklyn.entity.dns.geoscaling.GeoscalingWebClient.Domain;
import org.apache.brooklyn.entity.dns.geoscaling.GeoscalingWebClient.SmartSubdomain;
@@ -33,9 +34,10 @@ import org.slf4j.LoggerFactory;
import brooklyn.entity.basic.Lifecycle;
import brooklyn.entity.basic.ServiceStateLogic;
+
import org.apache.brooklyn.location.geo.HostGeoInfo;
+
import brooklyn.util.collections.MutableSet;
-import brooklyn.util.http.HttpTool;
import brooklyn.util.text.Identifiers;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingScriptGenerator.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingScriptGenerator.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingScriptGenerator.java
index e8def56..5c1e578 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingScriptGenerator.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingScriptGenerator.java
@@ -24,8 +24,9 @@ import java.util.Date;
import java.util.Iterator;
import java.util.TimeZone;
+import org.apache.brooklyn.core.util.ResourceUtils;
import org.apache.brooklyn.location.geo.HostGeoInfo;
-import brooklyn.util.ResourceUtils;
+
import brooklyn.util.javalang.JavaClassNames;
import brooklyn.util.os.Os;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingWebClient.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingWebClient.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingWebClient.java
index 7e5c3aa..afaac72 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingWebClient.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/dns/geoscaling/GeoscalingWebClient.java
@@ -28,6 +28,7 @@ import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.apache.brooklyn.core.util.http.HttpTool;
import org.apache.commons.io.FilenameUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
@@ -48,7 +49,6 @@ import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.tidy.Tidy;
-import brooklyn.util.http.HttpTool;
import brooklyn.util.text.Strings;
/**
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/AbstractController.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/AbstractController.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/AbstractController.java
index ca8caa3..de8955d 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/AbstractController.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/AbstractController.java
@@ -22,13 +22,13 @@ import java.util.Set;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.SoftwareProcess;
import brooklyn.entity.group.Cluster;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
-import brooklyn.util.flags.SetFromFlag;
/**
* Represents a controller mechanism for a {@link Cluster}.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/AbstractControllerImpl.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/AbstractControllerImpl.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/AbstractControllerImpl.java
index 5eeeee9..a61da01 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/AbstractControllerImpl.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/AbstractControllerImpl.java
@@ -33,6 +33,7 @@ import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -52,7 +53,6 @@ import org.apache.brooklyn.location.basic.Machines;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.guava.Maybe;
-import brooklyn.util.task.Tasks;
import brooklyn.util.text.Strings;
import com.google.common.base.Objects;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/LoadBalancer.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/LoadBalancer.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/LoadBalancer.java
index 2af3da2..b3d32c0 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/LoadBalancer.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/LoadBalancer.java
@@ -24,6 +24,7 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.Group;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.entity.webapp.WebAppService;
import brooklyn.config.ConfigKey;
@@ -35,7 +36,6 @@ import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
import brooklyn.event.basic.BasicConfigKey;
import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.collect.ImmutableList;
import com.google.common.reflect.TypeToken;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/ProxySslConfig.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/ProxySslConfig.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/ProxySslConfig.java
index 93e1b7f..ad6bf82 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/ProxySslConfig.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/ProxySslConfig.java
@@ -21,12 +21,11 @@ package org.apache.brooklyn.entity.proxy;
import java.io.Serializable;
import java.util.Map;
+import org.apache.brooklyn.core.util.flags.FlagUtils;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import brooklyn.util.flags.FlagUtils;
-import brooklyn.util.flags.SetFromFlag;
-
import com.google.common.base.Objects;
public class ProxySslConfig implements Serializable {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/NginxController.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/NginxController.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/NginxController.java
index de20631..1ae0ea8 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/NginxController.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/NginxController.java
@@ -24,6 +24,7 @@ import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.entity.trait.HasShortName;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.entity.proxy.AbstractController;
import org.apache.brooklyn.entity.proxy.ProxySslConfig;
@@ -35,7 +36,6 @@ import brooklyn.entity.basic.MethodEffector;
import brooklyn.entity.basic.SoftwareProcess;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/NginxControllerImpl.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/NginxControllerImpl.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/NginxControllerImpl.java
index 3d65881..bd3840d 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/NginxControllerImpl.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/NginxControllerImpl.java
@@ -31,6 +31,10 @@ import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
import org.apache.brooklyn.api.management.SubscriptionHandle;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.file.ArchiveUtils;
+import org.apache.brooklyn.core.util.http.HttpTool;
+import org.apache.brooklyn.core.util.http.HttpToolResponse;
import org.apache.brooklyn.entity.proxy.AbstractControllerImpl;
import org.apache.brooklyn.entity.proxy.ProxySslConfig;
import org.apache.brooklyn.entity.proxy.nginx.NginxController.NginxControllerInternal;
@@ -47,11 +51,7 @@ import brooklyn.event.feed.ConfigToAttributes;
import brooklyn.event.feed.http.HttpFeed;
import brooklyn.event.feed.http.HttpPollConfig;
import brooklyn.event.feed.http.HttpValueFunctions;
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.file.ArchiveUtils;
import brooklyn.util.guava.Functionals;
-import brooklyn.util.http.HttpTool;
-import brooklyn.util.http.HttpToolResponse;
import brooklyn.util.stream.Streams;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/NginxSshDriver.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/NginxSshDriver.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/NginxSshDriver.java
index da9bbf9..56d3dc6 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/NginxSshDriver.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/NginxSshDriver.java
@@ -27,6 +27,10 @@ import org.apache.brooklyn.api.entity.drivers.downloads.DownloadResolver;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.OsDetails;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.Tasks;
+import org.apache.brooklyn.core.util.task.ssh.SshTasks;
+import org.apache.brooklyn.core.util.task.ssh.SshTasks.OnFailingTask;
import org.apache.brooklyn.entity.proxy.AbstractController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -46,10 +50,6 @@ import brooklyn.util.net.Networking;
import brooklyn.util.os.Os;
import brooklyn.util.ssh.BashCommands;
import brooklyn.util.stream.Streams;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.task.ssh.SshTasks;
-import brooklyn.util.task.ssh.SshTasks.OnFailingTask;
import brooklyn.util.text.Strings;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/NginxTemplateConfigGenerator.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/NginxTemplateConfigGenerator.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/NginxTemplateConfigGenerator.java
index 34432dd7..3c079d6 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/NginxTemplateConfigGenerator.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/NginxTemplateConfigGenerator.java
@@ -21,14 +21,14 @@ package org.apache.brooklyn.entity.proxy.nginx;
import java.util.Collection;
import java.util.Map;
+import org.apache.brooklyn.core.util.ResourceUtils;
+import org.apache.brooklyn.core.util.text.TemplateProcessor;
import org.apache.brooklyn.entity.proxy.ProxySslConfig;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.text.Strings;
-import brooklyn.util.text.TemplateProcessor;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/UrlMapping.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/UrlMapping.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/UrlMapping.java
index ac937ee..59ec8bb 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/UrlMapping.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/UrlMapping.java
@@ -23,6 +23,7 @@ import java.util.Collection;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.entity.proxy.AbstractController;
import org.apache.brooklyn.entity.proxy.ProxySslConfig;
@@ -32,7 +33,6 @@ import brooklyn.entity.basic.AbstractGroup;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.MethodEffector;
import brooklyn.event.basic.Sensors;
-import brooklyn.util.flags.SetFromFlag;
import com.google.common.reflect.TypeToken;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/ControlledDynamicWebAppCluster.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/ControlledDynamicWebAppCluster.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/ControlledDynamicWebAppCluster.java
index 8315e17..58e206c 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/ControlledDynamicWebAppCluster.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/ControlledDynamicWebAppCluster.java
@@ -24,6 +24,7 @@ import org.apache.brooklyn.api.entity.Group;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import org.apache.brooklyn.entity.proxy.LoadBalancer;
import brooklyn.config.ConfigKey;
@@ -39,7 +40,6 @@ import brooklyn.entity.trait.Resizable;
import brooklyn.entity.trait.Startable;
import brooklyn.event.basic.BasicAttributeSensor;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
-import brooklyn.util.flags.SetFromFlag;
/**
* This entity contains the sub-groups and entities that go in to a single location (e.g. datacenter)
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/DynamicWebAppClusterImpl.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/DynamicWebAppClusterImpl.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/DynamicWebAppClusterImpl.java
index 1c87941..5fe07ac 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/DynamicWebAppClusterImpl.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/DynamicWebAppClusterImpl.java
@@ -29,6 +29,10 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.management.TaskAdaptable;
+import org.apache.brooklyn.core.util.task.DynamicTasks;
+import org.apache.brooklyn.core.util.task.TaskBuilder;
+import org.apache.brooklyn.core.util.task.TaskTags;
+import org.apache.brooklyn.core.util.task.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -42,10 +46,6 @@ import brooklyn.entity.group.DynamicClusterImpl;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.TaskBuilder;
-import brooklyn.util.task.TaskTags;
-import brooklyn.util.task.Tasks;
import brooklyn.util.time.Duration;
import brooklyn.util.time.Time;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/JavaWebAppService.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/JavaWebAppService.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/JavaWebAppService.java
index d863b19..b5e1c48 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/JavaWebAppService.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/JavaWebAppService.java
@@ -24,6 +24,7 @@ import java.util.Set;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.util.flags.SetFromFlag;
import brooklyn.config.ConfigKey;
import brooklyn.entity.annotation.Effector;
@@ -32,7 +33,6 @@ import brooklyn.entity.basic.MethodEffector;
import brooklyn.entity.java.UsesJava;
import brooklyn.event.basic.BasicAttributeSensor;
import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.util.flags.SetFromFlag;
public interface JavaWebAppService extends WebAppService, UsesJava {
[15/42] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/util
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/task/BasicTasksFutureTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/task/BasicTasksFutureTest.java b/core/src/test/java/brooklyn/util/task/BasicTasksFutureTest.java
deleted file mode 100644
index f1c1332..0000000
--- a/core/src/test/java/brooklyn/util/task/BasicTasksFutureTest.java
+++ /dev/null
@@ -1,224 +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 brooklyn.util.task;
-
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.brooklyn.api.management.Task;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.Assert;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.time.Duration;
-import brooklyn.util.time.Time;
-
-import com.google.common.base.Stopwatch;
-
-public class BasicTasksFutureTest {
-
- private static final Logger log = LoggerFactory.getLogger(BasicTasksFutureTest.class);
-
- private BasicExecutionManager em;
- private BasicExecutionContext ec;
- private Map<Object,Object> data;
- private ExecutorService ex;
- private Semaphore started;
- private Semaphore waitInTask;
- private Semaphore cancelledWhileSleeping;
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() {
- em = new BasicExecutionManager("mycontext");
- ec = new BasicExecutionContext(em);
- ex = Executors.newCachedThreadPool();
- data = Collections.synchronizedMap(new LinkedHashMap<Object,Object>());
- started = new Semaphore(0);
- waitInTask = new Semaphore(0);
- cancelledWhileSleeping = new Semaphore(0);
- }
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws Exception {
- if (em != null) em.shutdownNow();
- if (ex != null) ex.shutdownNow();
- }
-
- @Test
- public void testBlockAndGetWithTimeoutsAndListenableFuture() throws InterruptedException {
- Task<String> t = waitForSemaphore(Duration.FIVE_SECONDS, true, "x");
-
- Assert.assertFalse(t.blockUntilEnded(Duration.millis(1)));
- Assert.assertFalse(t.blockUntilEnded(Duration.ZERO));
- boolean didNotThrow = false;
-
- try { t.getUnchecked(Duration.millis(1)); didNotThrow = true; }
- catch (Exception e) { /* expected */ }
- Assert.assertFalse(didNotThrow);
-
- try { t.getUnchecked(Duration.ZERO); didNotThrow = true; }
- catch (Exception e) { /* expected */ }
- Assert.assertFalse(didNotThrow);
-
- addFutureListener(t, "before");
- ec.submit(t);
-
- Assert.assertFalse(t.blockUntilEnded(Duration.millis(1)));
- Assert.assertFalse(t.blockUntilEnded(Duration.ZERO));
-
- try { t.getUnchecked(Duration.millis(1)); didNotThrow = true; }
- catch (Exception e) { /* expected */ }
- Assert.assertFalse(didNotThrow);
-
- try { t.getUnchecked(Duration.ZERO); didNotThrow = true; }
- catch (Exception e) { /* expected */ }
- Assert.assertFalse(didNotThrow);
-
- addFutureListener(t, "during");
-
- synchronized (data) {
- // now let it finish
- waitInTask.release();
- Assert.assertTrue(t.blockUntilEnded(Duration.TEN_SECONDS));
-
- Assert.assertEquals(t.getUnchecked(Duration.millis(1)), "x");
- Assert.assertEquals(t.getUnchecked(Duration.ZERO), "x");
-
- Assert.assertNull(data.get("before"));
- Assert.assertNull(data.get("during"));
- // can't set the data(above) until we release the lock (in assert call below)
- assertSoonGetsData("before");
- assertSoonGetsData("during");
- }
-
- // and see that a listener added late also runs
- synchronized (data) {
- addFutureListener(t, "after");
- Assert.assertNull(data.get("after"));
- assertSoonGetsData("after");
- }
- }
-
- private void addFutureListener(Task<String> t, final String key) {
- t.addListener(new Runnable() { public void run() {
- synchronized (data) {
- log.info("notifying for "+key);
- data.notifyAll();
- data.put(key, true);
- }
- }}, ex);
- }
-
- private void assertSoonGetsData(String key) throws InterruptedException {
- for (int i=0; i<10; i++) {
- if (Boolean.TRUE.equals(data.get(key))) {
- log.info("got data for "+key);
- return;
- }
- data.wait(Duration.ONE_SECOND.toMilliseconds());
- }
- Assert.fail("did not get data for '"+key+"' in time");
- }
-
- private <T> Task<T> waitForSemaphore(final Duration time, final boolean requireSemaphore, final T result) {
- return Tasks.<T>builder().body(new Callable<T>() {
- public T call() {
- try {
- started.release();
- log.info("waiting up to "+time+" to acquire before returning "+result);
- if (!waitInTask.tryAcquire(time.toMilliseconds(), TimeUnit.MILLISECONDS)) {
- log.info("did not get semaphore");
- if (requireSemaphore) Assert.fail("task did not get semaphore");
- } else {
- log.info("got semaphore");
- }
- } catch (Exception e) {
- log.info("cancelled before returning "+result);
- cancelledWhileSleeping.release();
- throw Exceptions.propagate(e);
- }
- log.info("task returning "+result);
- return result;
- }
- }).build();
- }
-
- @Test
- public void testCancelAfterStartTriggersListenableFuture() throws Exception {
- doTestCancelTriggersListenableFuture(Duration.millis(50));
- }
- @Test
- public void testCancelImmediateTriggersListenableFuture() throws Exception {
- // if cancel fires after submit but before it passes to the executor,
- // that needs handling separately; this doesn't guarantee this code path,
- // but it happens sometimes (and it should be handled)
- doTestCancelTriggersListenableFuture(Duration.ZERO);
- }
- public void doTestCancelTriggersListenableFuture(Duration delay) throws Exception {
- Task<String> t = waitForSemaphore(Duration.TEN_SECONDS, true, "x");
- addFutureListener(t, "before");
-
- Stopwatch watch = Stopwatch.createStarted();
- ec.submit(t);
-
- addFutureListener(t, "during");
-
- log.info("test cancelling "+t+" ("+t.getClass()+") after "+delay);
- // NB: two different code paths (callers to this method) for notifying futures
- // depending whether task is started
- Time.sleep(delay);
-
- synchronized (data) {
- t.cancel(true);
-
- assertSoonGetsData("before");
- assertSoonGetsData("during");
-
- addFutureListener(t, "after");
- Assert.assertNull(data.get("after"));
- assertSoonGetsData("after");
- }
-
- Assert.assertTrue(t.isDone());
- Assert.assertTrue(t.isCancelled());
- try {
- t.get();
- Assert.fail("should have thrown CancellationException");
- } catch (CancellationException e) { /* expected */ }
-
- Assert.assertTrue(watch.elapsed(TimeUnit.MILLISECONDS) < Duration.FIVE_SECONDS.toMilliseconds(),
- Time.makeTimeStringRounded(watch.elapsed(TimeUnit.MILLISECONDS))+" is too long; should have cancelled very quickly");
-
- if (started.tryAcquire())
- // if the task is begun, this should get released
- Assert.assertTrue(cancelledWhileSleeping.tryAcquire(5, TimeUnit.SECONDS));
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/task/CompoundTaskExecutionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/task/CompoundTaskExecutionTest.java b/core/src/test/java/brooklyn/util/task/CompoundTaskExecutionTest.java
deleted file mode 100644
index 9fe4ba0..0000000
--- a/core/src/test/java/brooklyn/util/task/CompoundTaskExecutionTest.java
+++ /dev/null
@@ -1,252 +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 brooklyn.util.task;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.Semaphore;
-
-import org.apache.brooklyn.api.management.Task;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-import org.testng.collections.Lists;
-
-import brooklyn.util.time.Duration;
-import brooklyn.util.time.Time;
-
-import com.google.common.base.Throwables;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-
-/**
- * Test the operation of the {@link CompoundTask} class.
- */
-public class CompoundTaskExecutionTest {
-
- private static final Logger LOG = LoggerFactory.getLogger(CompoundTaskExecutionTest.class);
-
- BasicExecutionManager em;
- BasicExecutionContext ec;
-
- @BeforeClass
- public void setup() {
- em = new BasicExecutionManager("mycontext");
- ec = new BasicExecutionContext(em);
- }
-
- @AfterClass
- public void teardown() {
- if (em != null) em.shutdownNow();
- em = null;
- }
-
- private BasicTask<String> taskReturning(final String val) {
- return new BasicTask<String>(new Callable<String>() {
- @Override public String call() {
- return val;
- }
- });
- }
-
- private BasicTask<String> slowTaskReturning(final String val, final Duration pauseTime) {
- return new BasicTask<String>(new Callable<String>() {
- @Override public String call() {
- Time.sleep(pauseTime);
- return val;
- }
- });
- }
-
-
- @Test
- public void runSequenceTask() throws Exception {
- BasicTask<String> t1 = taskReturning("a");
- BasicTask<String> t2 = taskReturning("b");
- BasicTask<String> t3 = taskReturning("c");
- BasicTask<String> t4 = taskReturning("d");
- Task<List<String>> tSequence = ec.submit(new SequentialTask<String>(t1, t2, t3, t4));
- assertEquals(tSequence.get(), ImmutableList.of("a", "b", "c", "d"));
- }
-
- @Test
- public void testSequentialTaskFailsWhenIntermediateTaskThrowsException() throws Exception {
- BasicTask<String> t1 = taskReturning("a");
- BasicTask<String> t2 = new BasicTask<String>(new Callable<String>() {
- @Override public String call() throws Exception {
- throw new IllegalArgumentException("forced exception");
- }
- });
- BasicTask<String> t3 = taskReturning("c");
- SequentialTask<String> task = new SequentialTask<String>(t1, t2, t3);
- Task<List<String>> tSequence = ec.submit(task);
-
- try {
- tSequence.get();
- fail("t2 should have thrown an exception");
- } catch (Exception e) {}
-
- assertTrue(task.isDone());
- assertTrue(task.isError());
- assertTrue(t1.isDone());
- assertFalse(t1.isError());
- assertTrue(t2.isDone());
- assertTrue(t2.isError());
- // t3 not run because of t2 exception
- assertFalse(t3.isDone());
- assertFalse(t3.isBegun());
- }
-
- @Test
- public void testParallelTaskFailsWhenIntermediateTaskThrowsException() throws Exception {
- // differs from test above of SequentialTask in that expect t3 to be executed,
- // despite t2 failing.
- // TODO Do we expect tSequence.get() to block for everything to either fail or complete,
- // and then to throw exception? Currently it does *not* do that so test was previously failing.
-
- BasicTask<String> t1 = taskReturning("a");
- BasicTask<String> t2 = new BasicTask<String>(new Callable<String>() {
- @Override public String call() throws Exception {
- throw new IllegalArgumentException("forced exception");
- }
- });
- BasicTask<String> t3 = slowTaskReturning("c", Duration.millis(100));
- ParallelTask<String> task = new ParallelTask<String>(t1, t2, t3);
- Task<List<String>> tSequence = ec.submit(task);
-
- try {
- tSequence.get();
- fail("t2 should have thrown an exception");
- } catch (Exception e) {}
-
- assertTrue(task.isDone());
- assertTrue(task.isError());
- assertTrue(t1.isDone());
- assertFalse(t1.isError());
- assertTrue(t2.isDone());
- assertTrue(t2.isError());
- assertTrue(t3.isBegun());
- assertTrue(t3.isDone());
- assertFalse(t3.isError());
- }
-
- @Test
- public void runParallelTask() throws Exception {
- BasicTask<String> t1 = taskReturning("a");
- BasicTask<String> t2 = taskReturning("b");
- BasicTask<String> t3 = taskReturning("c");
- BasicTask<String> t4 = taskReturning("d");
- Task<List<String>> tSequence = ec.submit(new ParallelTask<String>(t4, t2, t1, t3));
- assertEquals(new HashSet<String>(tSequence.get()), ImmutableSet.of("a", "b", "c", "d"));
- }
-
- @Test
- public void runParallelTaskWithDelay() throws Exception {
- final Semaphore locker = new Semaphore(0);
- BasicTask<String> t1 = new BasicTask<String>(new Callable<String>() {
- @Override public String call() {
- try {
- locker.acquire();
- } catch (InterruptedException e) {
- throw Throwables.propagate(e);
- }
- return "a";
- }
- });
- BasicTask<String> t2 = taskReturning("b");
- BasicTask<String> t3 = taskReturning("c");
- BasicTask<String> t4 = taskReturning("d");
- final Task<List<String>> tSequence = ec.submit(new ParallelTask<String>(t4, t2, t1, t3));
-
- assertEquals(ImmutableSet.of(t2.get(), t3.get(), t4.get()), ImmutableSet.of("b", "c", "d"));
- assertFalse(t1.isDone());
- assertFalse(tSequence.isDone());
-
- // get blocks until tasks have completed
- Thread t = new Thread() {
- @Override public void run() {
- try {
- tSequence.get();
- } catch (Exception e) {
- throw Throwables.propagate(e);
- }
- locker.release();
- }
- };
- t.start();
- Thread.sleep(30);
- assertTrue(t.isAlive());
-
- locker.release();
-
- assertEquals(new HashSet<String>(tSequence.get()), ImmutableSet.of("a", "b", "c", "d"));
- assertTrue(t1.isDone());
- assertTrue(tSequence.isDone());
-
- locker.acquire();
- }
-
- @Test
- public void testComplexOrdering() throws Exception {
- List<String> data = new CopyOnWriteArrayList<String>();
- SequentialTask<String> taskA = new SequentialTask<String>(
- appendAfterDelay(data, "a1"), appendAfterDelay(data, "a2"), appendAfterDelay(data, "a3"), appendAfterDelay(data, "a4"));
- SequentialTask<String> taskB = new SequentialTask<String>(
- appendAfterDelay(data, "b1"), appendAfterDelay(data, "b2"), appendAfterDelay(data, "b3"), appendAfterDelay(data, "b4"));
- Task<List<String>> t = ec.submit(new ParallelTask<String>(taskA, taskB));
- t.get();
-
- LOG.debug("Tasks happened in order: {}", data);
- assertEquals(data.size(), 8);
- assertEquals(new HashSet<String>(data), ImmutableSet.of("a1", "a2", "a3", "a4", "b1", "b2", "b3", "b4"));
-
- // a1, ..., a4 should be in order
- List<String> as = Lists.newArrayList(), bs = Lists.newArrayList();
- for (String value : data) {
- ((value.charAt(0) == 'a') ? as : bs).add(value);
- }
- assertEquals(as, ImmutableList.of("a1", "a2", "a3", "a4"));
- assertEquals(bs, ImmutableList.of("b1", "b2", "b3", "b4"));
- }
-
- private BasicTask<String> appendAfterDelay(final List<String> list, final String value) {
- return new BasicTask<String>(new Callable<String>() {
- @Override public String call() {
- try {
- Thread.sleep((int) (100 * Math.random()));
- } catch (InterruptedException e) {
- throw Throwables.propagate(e);
- }
- LOG.debug("running {}", value);
- list.add(value);
- return value;
- }
- });
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/task/DynamicSequentialTaskTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/task/DynamicSequentialTaskTest.java b/core/src/test/java/brooklyn/util/task/DynamicSequentialTaskTest.java
deleted file mode 100644
index a5985fe..0000000
--- a/core/src/test/java/brooklyn/util/task/DynamicSequentialTaskTest.java
+++ /dev/null
@@ -1,365 +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 brooklyn.util.task;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.brooklyn.api.management.HasTaskChildren;
-import org.apache.brooklyn.api.management.Task;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.Assert;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.test.Asserts;
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.time.CountdownTimer;
-import brooklyn.util.time.Duration;
-import brooklyn.util.time.Time;
-
-import com.google.common.base.Stopwatch;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-
-public class DynamicSequentialTaskTest {
-
- private static final Logger log = LoggerFactory.getLogger(DynamicSequentialTaskTest.class);
-
- public static final Duration TIMEOUT = Duration.TEN_SECONDS;
- public static final Duration TINY_TIME = Duration.millis(20);
-
- BasicExecutionManager em;
- BasicExecutionContext ec;
- List<String> messages;
- Semaphore cancellations;
- Stopwatch stopwatch;
- Map<String,Semaphore> monitorableJobSemaphoreMap;
- Map<String,Task<String>> monitorableTasksMap;
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() {
- em = new BasicExecutionManager("mycontext");
- ec = new BasicExecutionContext(em);
- cancellations = new Semaphore(0);
- messages = new ArrayList<String>();
- monitorableJobSemaphoreMap = MutableMap.of();
- monitorableTasksMap = MutableMap.of();
- monitorableTasksMap.clear();
- stopwatch = Stopwatch.createStarted();
- }
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws Exception {
- if (em != null) em.shutdownNow();
- }
-
- @Test
- public void testSimple() throws InterruptedException, ExecutionException {
- Callable<String> mainJob = new Callable<String>() {
- public String call() {
- log.info("main job - "+Tasks.current());
- messages.add("main");
- DynamicTasks.queue( sayTask("world") );
- return "bye";
- }
- };
- DynamicSequentialTask<String> t = new DynamicSequentialTask<String>(mainJob);
- // this should be added before anything added when the task is invoked
- t.queue(sayTask("hello"));
-
- Assert.assertEquals(messages, Lists.newArrayList());
- Assert.assertEquals(t.isBegun(), false);
- Assert.assertEquals(Iterables.size(t.getChildren()), 1);
-
- ec.submit(t);
- Assert.assertEquals(t.isSubmitted(), true);
- Assert.assertEquals(t.getUnchecked(Duration.ONE_SECOND), "bye");
- long elapsed = t.getEndTimeUtc() - t.getSubmitTimeUtc();
- Assert.assertTrue(elapsed < 1000, "elapsed time should have been less than 1s but was "+
- Time.makeTimeString(elapsed, true));
- Assert.assertEquals(Iterables.size(t.getChildren()), 2);
- Assert.assertEquals(messages.size(), 3, "expected 3 entries, but had "+messages);
- // either main or hello can be first, but world should be last
- Assert.assertEquals(messages.get(2), "world");
- }
-
- public Callable<String> sayCallable(final String message, final Duration duration, final String message2) {
- return new Callable<String>() {
- public String call() {
- try {
- if (message != null) {
- log.info("saying: "+message+ " - "+Tasks.current());
- synchronized (messages) {
- messages.add(message);
- messages.notifyAll();
- }
- }
- if (message2 != null) {
- log.info("will say "+message2+" after "+duration);
- }
- if (duration != null && duration.toMilliseconds() > 0) {
- Thread.sleep(duration.toMillisecondsRoundingUp());
- }
- } catch (InterruptedException e) {
- cancellations.release();
- throw Exceptions.propagate(e);
- }
- if (message2 != null) {
- log.info("saying: "+message2+ " - "+Tasks.current());
- synchronized (messages) {
- messages.add(message2);
- messages.notifyAll();
- }
- }
- return message;
- }
- };
- }
-
- public Task<String> sayTask(String message) {
- return sayTask(message, null, null);
- }
-
- public Task<String> sayTask(String message, Duration duration, String message2) {
- return Tasks.<String>builder().body(sayCallable(message, duration, message2)).build();
- }
-
- @Test
- public void testComplex() throws InterruptedException, ExecutionException {
- Task<List<?>> t = Tasks.sequential(
- sayTask("1"),
- sayTask("2"),
- Tasks.parallel(sayTask("4"), sayTask("3")),
- sayTask("5")
- );
- ec.submit(t);
- Assert.assertEquals(t.get().size(), 4);
- Asserts.assertEqualsIgnoringOrder((List<?>)t.get().get(2), ImmutableSet.of("3", "4"));
- Assert.assertTrue(messages.equals(Arrays.asList("1", "2", "3", "4", "5")) || messages.equals(Arrays.asList("1", "2", "4", "3", "5")), "messages="+messages);
- }
-
- @Test
- public void testCancelled() throws InterruptedException, ExecutionException {
- Task<List<?>> t = Tasks.sequential(
- sayTask("1"),
- sayTask("2a", Duration.THIRTY_SECONDS, "2b"),
- sayTask("3"));
- ec.submit(t);
- synchronized (messages) {
- while (messages.size() <= 1)
- messages.wait();
- }
- Assert.assertEquals(messages, Arrays.asList("1", "2a"));
- Time.sleep(Duration.millis(50));
- t.cancel(true);
- Assert.assertTrue(t.isDone());
- // 2 should get cancelled, and invoke the cancellation semaphore
- // 3 should get cancelled and not run at all
- Assert.assertEquals(messages, Arrays.asList("1", "2a"));
-
- // Need to ensure that 2 has been started; race where we might cancel it before its run method
- // is even begun. Hence doing "2a; pause; 2b" where nothing is interruptable before pause.
- Assert.assertTrue(cancellations.tryAcquire(10, TimeUnit.SECONDS));
-
- Iterator<Task<?>> ci = ((HasTaskChildren)t).getChildren().iterator();
- Assert.assertEquals(ci.next().get(), "1");
- Task<?> task2 = ci.next();
- Assert.assertTrue(task2.isBegun());
- Assert.assertTrue(task2.isDone());
- Assert.assertTrue(task2.isCancelled());
-
- Task<?> task3 = ci.next();
- Assert.assertFalse(task3.isBegun());
- Assert.assertTrue(task2.isDone());
- Assert.assertTrue(task2.isCancelled());
-
- // but we do _not_ get a mutex from task3 as it does not run (is not interrupted)
- Assert.assertEquals(cancellations.availablePermits(), 0);
- }
-
- protected Task<String> monitorableTask(final String id) {
- return monitorableTask(null, id, null);
- }
- protected Task<String> monitorableTask(final Runnable pre, final String id, final Callable<String> post) {
- Task<String> t = Tasks.<String>builder().body(monitorableJob(pre, id, post)).build();
- monitorableTasksMap.put(id, t);
- return t;
- }
- protected Callable<String> monitorableJob(final String id) {
- return monitorableJob(null, id, null);
- }
- protected Callable<String> monitorableJob(final Runnable pre, final String id, final Callable<String> post) {
- monitorableJobSemaphoreMap.put(id, new Semaphore(0));
- return new Callable<String>() {
- @Override
- public String call() throws Exception {
- if (pre!=null) pre.run();
- // wait for semaphore
- if (!monitorableJobSemaphoreMap.get(id).tryAcquire(1, TIMEOUT.toMilliseconds(), TimeUnit.MILLISECONDS))
- throw new IllegalStateException("timeout for "+id);
- synchronized (messages) {
- messages.add(id);
- messages.notifyAll();
- }
- if (post!=null) return post.call();
- return id;
- }
- };
- }
- protected void releaseMonitorableJob(final String id) {
- monitorableJobSemaphoreMap.get(id).release();
- }
- protected void waitForMessage(final String id) {
- CountdownTimer timer = CountdownTimer.newInstanceStarted(TIMEOUT);
- synchronized (messages) {
- while (!timer.isExpired()) {
- if (messages.contains(id)) return;
- timer.waitOnForExpiryUnchecked(messages);
- }
- }
- Assert.fail("Did not see message "+id);
- }
- protected void releaseAndWaitForMonitorableJob(final String id) {
- releaseMonitorableJob(id);
- waitForMessage(id);
- }
-
- @Test
- public void testChildrenRunConcurrentlyWithPrimary() {
- Task<String> t = Tasks.<String>builder().dynamic(true)
- .body(monitorableJob("main"))
- .add(monitorableTask("1")).add(monitorableTask("2")).build();
- ec.submit(t);
- releaseAndWaitForMonitorableJob("1");
- releaseAndWaitForMonitorableJob("main");
- Assert.assertFalse(t.blockUntilEnded(TINY_TIME));
- releaseMonitorableJob("2");
-
- Assert.assertTrue(t.blockUntilEnded(TIMEOUT));
- Assert.assertEquals(messages, MutableList.of("1", "main", "2"));
- Assert.assertTrue(stopwatch.elapsed(TimeUnit.MILLISECONDS) < TIMEOUT.toMilliseconds(), "took too long: "+stopwatch);
- Assert.assertFalse(t.isError());
- }
-
- protected static class FailRunnable implements Runnable {
- @Override public void run() { throw new RuntimeException("Planned exception for test"); }
- }
- protected static class FailCallable implements Callable<String> {
- @Override public String call() { throw new RuntimeException("Planned exception for test"); }
- }
-
- @Test
- public void testByDefaultChildrenFailureAbortsSecondaryFailsPrimaryButNotAbortsPrimary() {
- Task<String> t1 = monitorableTask(null, "1", new FailCallable());
- Task<String> t = Tasks.<String>builder().dynamic(true)
- .body(monitorableJob("main"))
- .add(t1).add(monitorableTask("2")).build();
- ec.submit(t);
- releaseAndWaitForMonitorableJob("1");
- Assert.assertFalse(t.blockUntilEnded(TINY_TIME));
- releaseMonitorableJob("main");
-
- Assert.assertTrue(t.blockUntilEnded(TIMEOUT));
- Assert.assertEquals(messages, MutableList.of("1", "main"));
- Assert.assertTrue(stopwatch.elapsed(TimeUnit.MILLISECONDS) < TIMEOUT.toMilliseconds(), "took too long: "+stopwatch);
- Assert.assertTrue(t.isError());
- Assert.assertTrue(t1.isError());
- }
-
- @Test
- public void testWhenSwallowingChildrenFailureDoesNotAbortSecondaryOrFailPrimary() {
- Task<String> t1 = monitorableTask(null, "1", new FailCallable());
- Task<String> t = Tasks.<String>builder().dynamic(true)
- .body(monitorableJob("main"))
- .add(t1).add(monitorableTask("2")).swallowChildrenFailures(true).build();
- ec.submit(t);
- releaseAndWaitForMonitorableJob("1");
- Assert.assertFalse(t.blockUntilEnded(TINY_TIME));
- releaseAndWaitForMonitorableJob("2");
- Assert.assertFalse(t.blockUntilEnded(TINY_TIME));
- releaseMonitorableJob("main");
- Assert.assertTrue(t.blockUntilEnded(TIMEOUT));
- Assert.assertEquals(messages, MutableList.of("1", "2", "main"));
- Assert.assertTrue(stopwatch.elapsed(TimeUnit.MILLISECONDS) < TIMEOUT.toMilliseconds(), "took too long: "+stopwatch);
- Assert.assertFalse(t.isError());
- Assert.assertTrue(t1.isError());
- }
-
- @Test
- public void testInessentialChildrenFailureDoesNotAbortSecondaryOrFailPrimary() {
- Task<String> t1 = monitorableTask(null, "1", new FailCallable());
- TaskTags.markInessential(t1);
- Task<String> t = Tasks.<String>builder().dynamic(true)
- .body(monitorableJob("main"))
- .add(t1).add(monitorableTask("2")).build();
- ec.submit(t);
- releaseAndWaitForMonitorableJob("1");
- Assert.assertFalse(t.blockUntilEnded(TINY_TIME));
- releaseAndWaitForMonitorableJob("2");
- Assert.assertFalse(t.blockUntilEnded(TINY_TIME));
- releaseMonitorableJob("main");
- Assert.assertTrue(t.blockUntilEnded(TIMEOUT));
- Assert.assertEquals(messages, MutableList.of("1", "2", "main"));
- Assert.assertTrue(stopwatch.elapsed(TimeUnit.MILLISECONDS) < TIMEOUT.toMilliseconds(), "took too long: "+stopwatch);
- Assert.assertFalse(t.isError());
- Assert.assertTrue(t1.isError());
- }
-
- @Test
- public void testTaskBuilderUsingAddVarargChildren() {
- Task<String> t = Tasks.<String>builder().dynamic(true)
- .body(monitorableJob("main"))
- .add(monitorableTask("1"), monitorableTask("2"))
- .build();
- ec.submit(t);
- releaseAndWaitForMonitorableJob("1");
- releaseAndWaitForMonitorableJob("2");
- releaseAndWaitForMonitorableJob("main");
-
- Assert.assertEquals(messages, MutableList.of("1", "2", "main"));
- }
-
- @Test
- public void testTaskBuilderUsingAddAllChildren() {
- Task<String> t = Tasks.<String>builder().dynamic(true)
- .body(monitorableJob("main"))
- .addAll(ImmutableList.of(monitorableTask("1"), monitorableTask("2")))
- .build();
- ec.submit(t);
- releaseAndWaitForMonitorableJob("1");
- releaseAndWaitForMonitorableJob("2");
- releaseAndWaitForMonitorableJob("main");
-
- Assert.assertEquals(messages, MutableList.of("1", "2", "main"));
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/task/NonBasicTaskExecutionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/task/NonBasicTaskExecutionTest.java b/core/src/test/java/brooklyn/util/task/NonBasicTaskExecutionTest.java
deleted file mode 100644
index 82e3919..0000000
--- a/core/src/test/java/brooklyn/util/task/NonBasicTaskExecutionTest.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 brooklyn.util.task;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertSame;
-import static org.testng.Assert.assertTrue;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.brooklyn.api.management.Task;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.test.Asserts;
-import brooklyn.util.collections.MutableMap;
-
-/**
- * Test the operation of the {@link BasicTask} class.
- *
- * TODO clarify test purpose
- */
-public class NonBasicTaskExecutionTest {
- private static final Logger log = LoggerFactory.getLogger(NonBasicTaskExecutionTest.class);
-
- private static final int TIMEOUT_MS = 10*1000;
-
- public static class ConcreteForwardingTask<T> extends ForwardingTask<T> {
- private final TaskInternal<T> delegate;
-
- ConcreteForwardingTask(TaskInternal<T> delegate) {
- this.delegate = delegate;
- }
-
- @Override
- protected TaskInternal<T> delegate() {
- return delegate;
- }
- }
-
- private BasicExecutionManager em;
- private Map<Integer,String> data;
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() throws Exception {
- em = new BasicExecutionManager("mycontext");
- data = Collections.synchronizedMap(new HashMap<Integer,String>());
- }
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws Exception {
- if (em != null) em.shutdownNow();
- }
-
- @Test
- public void runSimpleTask() throws Exception {
- TaskInternal<Object> t = new ConcreteForwardingTask<Object>(new BasicTask<Object>(new Callable<Object>() {
- @Override public Object call() {
- return data.put(1, "b");
- }}));
- data.put(1, "a");
- Task<?> t2 = em.submit(MutableMap.of("tag", "A"), t);
- assertEquals("a", t.get());
- assertEquals("a", t2.get());
- assertSame(t, t2, "t="+t+"; t2="+t2);
- assertEquals("b", data.get(1));
- }
-
- @Test
- public void runBasicTaskWithWaits() throws Exception {
- final CountDownLatch signalStarted = new CountDownLatch(1);
- final CountDownLatch allowCompletion = new CountDownLatch(1);
- final TaskInternal<Object> t = new ConcreteForwardingTask<Object>(new BasicTask<Object>(new Callable<Object>() {
- @Override public Object call() throws Exception {
- Object result = data.put(1, "b");
- signalStarted.countDown();
- assertTrue(allowCompletion.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
- return result;
- }}));
- data.put(1, "a");
-
- Task<?> t2 = em.submit(MutableMap.of("tag", "A"), t);
- assertEquals(t, t2);
- assertFalse(t.isDone());
-
- assertTrue(signalStarted.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
- assertEquals("b", data.get(1));
- assertFalse(t.isDone());
-
- log.debug("runBasicTaskWithWaits, BasicTask status: {}", t.getStatusDetail(false));
-
- Asserts.succeedsEventually(new Runnable() {
- @Override public void run() {
- t.getStatusDetail(false).toLowerCase().contains("waiting");
- }});
- // "details="+t.getStatusDetail(false))
-
- allowCompletion.countDown();
- assertEquals("a", t.get());
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/task/ScheduledExecutionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/task/ScheduledExecutionTest.java b/core/src/test/java/brooklyn/util/task/ScheduledExecutionTest.java
deleted file mode 100644
index 1ae65f2..0000000
--- a/core/src/test/java/brooklyn/util/task/ScheduledExecutionTest.java
+++ /dev/null
@@ -1,287 +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 brooklyn.util.task;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
-
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.apache.brooklyn.api.management.Task;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-import brooklyn.test.Asserts;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.exceptions.RuntimeInterruptedException;
-import brooklyn.util.javalang.JavaClassNames;
-import brooklyn.util.time.Duration;
-import brooklyn.util.time.Time;
-
-import com.google.common.base.Stopwatch;
-import com.google.common.collect.Lists;
-
-@SuppressWarnings({"unchecked","rawtypes"})
-public class ScheduledExecutionTest {
-
- public static final Logger log = LoggerFactory.getLogger(ScheduledExecutionTest.class);
-
- @Test
- public void testScheduledTask() throws Exception {
- int PERIOD = 20;
- BasicExecutionManager m = new BasicExecutionManager("mycontextid");
- final AtomicInteger i = new AtomicInteger(0);
- ScheduledTask t = new ScheduledTask(MutableMap.of("delay", 2*PERIOD, "period", PERIOD, "maxIterations", 5), new Callable<Task<?>>() {
- public Task<?> call() throws Exception {
- return new BasicTask<Integer>(new Callable<Integer>() {
- public Integer call() {
- log.debug("task running: "+Tasks.current()+" "+Tasks.current().getStatusDetail(false));
- return i.incrementAndGet();
- }});
- }});
-
- log.info("submitting {} {}", t, t.getStatusDetail(false));
- m.submit(t);
- log.info("submitted {} {}", t, t.getStatusDetail(false));
- Integer interimResult = (Integer) t.get();
- log.info("done one ({}) {} {}", new Object[] {interimResult, t, t.getStatusDetail(false)});
- assertTrue(i.get() > 0, "i="+i);
- t.blockUntilEnded();
- Integer finalResult = (Integer) t.get();
- log.info("ended ({}) {} {}", new Object[] {finalResult, t, t.getStatusDetail(false)});
- assertEquals(finalResult, (Integer)5);
- assertEquals(i.get(), 5);
- }
-
- /** like testScheduledTask but the loop is terminated by the task itself adjusting the period */
- @Test
- public void testScheduledTaskSelfEnding() throws Exception {
- int PERIOD = 20;
- BasicExecutionManager m = new BasicExecutionManager("mycontextid");
- final AtomicInteger i = new AtomicInteger(0);
- ScheduledTask t = new ScheduledTask(MutableMap.of("delay", 2*PERIOD, "period", PERIOD), new Callable<Task<?>>() {
- public Task<?> call() throws Exception {
- return new BasicTask<Integer>(new Callable<Integer>() {
- public Integer call() {
- ScheduledTask submitter = (ScheduledTask) ((BasicTask)Tasks.current()).getSubmittedByTask();
- if (i.get() >= 4) submitter.period = null;
- log.info("task running ("+i+"): "+Tasks.current()+" "+Tasks.current().getStatusDetail(false));
- return i.incrementAndGet();
- }});
- }});
-
- log.info("submitting {} {}", t, t.getStatusDetail(false));
- m.submit(t);
- log.info("submitted {} {}", t, t.getStatusDetail(false));
- Integer interimResult = (Integer) t.get();
- log.info("done one ({}) {} {}", new Object[] {interimResult, t, t.getStatusDetail(false)});
- assertTrue(i.get() > 0);
- t.blockUntilEnded();
- Integer finalResult = (Integer) t.get();
- log.info("ended ({}) {} {}", new Object[] {finalResult, t, t.getStatusDetail(false)});
- assertEquals(finalResult, (Integer)5);
- assertEquals(i.get(), 5);
- }
-
- @Test
- public void testScheduledTaskCancelEnding() throws Exception {
- Duration PERIOD = Duration.millis(20);
- BasicExecutionManager m = new BasicExecutionManager("mycontextid");
- final AtomicInteger i = new AtomicInteger();
- ScheduledTask t = new ScheduledTask(MutableMap.of("delay", PERIOD.times(2), "period", PERIOD), new Callable<Task<?>>() {
- public Task<?> call() throws Exception {
- return new BasicTask<Integer>(new Callable<Integer>() {
- public Integer call() {
- log.info("task running ("+i+"): "+Tasks.current()+" "+Tasks.current().getStatusDetail(false));
- ScheduledTask submitter = (ScheduledTask) ((BasicTask)Tasks.current()).getSubmittedByTask();
- i.incrementAndGet();
- if (i.get() >= 5) submitter.cancel();
- return i.get();
- }});
- }});
-
- log.info(JavaClassNames.niceClassAndMethod()+" - submitting {} {}", t, t.getStatusDetail(false));
- m.submit(t);
- log.info("submitted {} {}", t, t.getStatusDetail(false));
- Integer interimResult = (Integer) t.get();
- log.info("done one ({}) {} {}", new Object[] {interimResult, t, t.getStatusDetail(false)});
- assertTrue(i.get() > 0);
- t.blockUntilEnded();
-// int finalResult = t.get()
- log.info("ended ({}) {} {}", new Object[] {i, t, t.getStatusDetail(false)});
-// assertEquals(finalResult, 5)
- assertEquals(i.get(), 5);
- }
-
- @Test(groups="Integration")
- public void testScheduledTaskCancelOuter() throws Exception {
- final Duration PERIOD = Duration.millis(20);
- final Duration CYCLE_DELAY = Duration.ONE_SECOND;
- // this should be enough to start the next cycle, but not so much that the cycle ends;
- // and enough that when a task is interrupted it terminates within this period
- final Duration SMALL_FRACTION_OF_CYCLE_DELAY = PERIOD.add(CYCLE_DELAY.multiply(0.1));
-
- BasicExecutionManager m = new BasicExecutionManager("mycontextid");
- final AtomicInteger i = new AtomicInteger();
- ScheduledTask t = new ScheduledTask(MutableMap.of("delay", PERIOD.times(2), "period", PERIOD), new Callable<Task<?>>() {
- public Task<?> call() throws Exception {
- return new BasicTask<Integer>(new Callable<Integer>() {
- public Integer call() {
- log.info("task running ("+i+"): "+Tasks.current()+" "+Tasks.current().getStatusDetail(false));
- Time.sleep(CYCLE_DELAY);
- i.incrementAndGet();
- return i.get();
- }});
- }});
-
- log.info(JavaClassNames.niceClassAndMethod()+" - submitting {} {}", t, t.getStatusDetail(false));
- m.submit(t);
- log.info("submitted {} {}", t, t.getStatusDetail(false));
- Integer interimResult = (Integer) t.get();
- log.info("done one ({}) {} {}", new Object[] {interimResult, t, t.getStatusDetail(false)});
- assertEquals(i.get(), 1);
-
- Time.sleep(SMALL_FRACTION_OF_CYCLE_DELAY);
- assertEquals(t.get(), 2);
-
- Time.sleep(SMALL_FRACTION_OF_CYCLE_DELAY);
- Stopwatch timer = Stopwatch.createUnstarted();
- t.cancel(true);
- t.blockUntilEnded();
-// int finalResult = t.get()
- log.info("blocked until ended ({}) {} {}, in {}", new Object[] {i, t, t.getStatusDetail(false), Duration.of(timer)});
- try {
- t.get();
- Assert.fail("Should have failed getting result of cancelled "+t);
- } catch (Exception e) {
- /* expected */
- }
- assertEquals(i.get(), 2);
- log.info("ended ({}) {} {}, in {}", new Object[] {i, t, t.getStatusDetail(false), Duration.of(timer)});
- Assert.assertTrue(Duration.of(timer).isShorterThan(SMALL_FRACTION_OF_CYCLE_DELAY));
- }
-
- @Test(groups="Integration")
- public void testScheduledTaskCancelInterrupts() throws Exception {
- final Duration PERIOD = Duration.millis(20);
- final Duration CYCLE_DELAY = Duration.ONE_SECOND;
- // this should be enough to start the next cycle, but not so much that the cycle ends;
- // and enough that when a task is interrupted it terminates within this period
- final Duration SMALL_FRACTION_OF_CYCLE_DELAY = PERIOD.add(CYCLE_DELAY.multiply(0.1));
-
- BasicExecutionManager m = new BasicExecutionManager("mycontextid");
- final Semaphore interruptedSemaphore = new Semaphore(0);
- final AtomicInteger i = new AtomicInteger();
- ScheduledTask t = new ScheduledTask(MutableMap.of("delay", PERIOD.times(2), "period", PERIOD), new Callable<Task<?>>() {
- public Task<?> call() throws Exception {
- return new BasicTask<Integer>(new Callable<Integer>() {
- public Integer call() {
- try {
- log.info("task running ("+i+"): "+Tasks.current()+" "+Tasks.current().getStatusDetail(false));
- Time.sleep(CYCLE_DELAY);
- i.incrementAndGet();
- return i.get();
- } catch (RuntimeInterruptedException e) {
- interruptedSemaphore.release();
- throw Exceptions.propagate(e);
- }
- }});
- }});
-
- log.info(JavaClassNames.niceClassAndMethod()+" - submitting {} {}", t, t.getStatusDetail(false));
- m.submit(t);
- log.info("submitted {} {}", t, t.getStatusDetail(false));
- Integer interimResult = (Integer) t.get();
- log.info("done one ({}) {} {}", new Object[] {interimResult, t, t.getStatusDetail(false)});
- assertEquals(i.get(), 1);
-
- Time.sleep(SMALL_FRACTION_OF_CYCLE_DELAY);
- assertEquals(t.get(), 2);
-
- Time.sleep(SMALL_FRACTION_OF_CYCLE_DELAY);
- Stopwatch timer = Stopwatch.createUnstarted();
- t.cancel(true);
- t.blockUntilEnded();
-// int finalResult = t.get()
- log.info("blocked until ended ({}) {} {}, in {}", new Object[] {i, t, t.getStatusDetail(false), Duration.of(timer)});
- try {
- t.get();
- Assert.fail("Should have failed getting result of cancelled "+t);
- } catch (Exception e) {
- /* expected */
- }
- assertEquals(i.get(), 2);
- Assert.assertTrue(interruptedSemaphore.tryAcquire(1, SMALL_FRACTION_OF_CYCLE_DELAY.toMilliseconds(), TimeUnit.MILLISECONDS), "child thread was not interrupted");
- log.info("ended ({}) {} {}, in {}", new Object[] {i, t, t.getStatusDetail(false), Duration.of(timer)});
- Assert.assertTrue(Duration.of(timer).isShorterThan(SMALL_FRACTION_OF_CYCLE_DELAY));
- }
-
- @Test(groups="Integration")
- public void testScheduledTaskTakesLongerThanPeriod() throws Exception {
- final int PERIOD = 1;
- final int SLEEP_TIME = 100;
- final int EARLY_RETURN_GRACE = 10;
- BasicExecutionManager m = new BasicExecutionManager("mycontextid");
- final List<Long> execTimes = new CopyOnWriteArrayList<Long>();
-
- ScheduledTask t = new ScheduledTask(MutableMap.of("delay", PERIOD, "period", PERIOD), new Callable<Task<?>>() {
- public Task<?> call() throws Exception {
- return new BasicTask<Void>(new Runnable() {
- public void run() {
- execTimes.add(System.currentTimeMillis());
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- throw Exceptions.propagate(e);
- }
- }});
- }});
-
- m.submit(t);
-
- Asserts.succeedsEventually(new Runnable() {
- public void run() {
- assertTrue(execTimes.size() > 3, "size="+execTimes.size());
- }});
-
- List<Long> timeDiffs = Lists.newArrayList();
- long prevExecTime = -1;
- for (Long execTime : execTimes) {
- if (prevExecTime == -1) {
- prevExecTime = execTime;
- } else {
- timeDiffs.add(execTime - prevExecTime);
- prevExecTime = execTime;
- }
- }
-
- for (Long timeDiff : timeDiffs) {
- if (timeDiff < (SLEEP_TIME - EARLY_RETURN_GRACE)) fail("timeDiffs="+timeDiffs+"; execTimes="+execTimes);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/task/SingleThreadedSchedulerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/task/SingleThreadedSchedulerTest.java b/core/src/test/java/brooklyn/util/task/SingleThreadedSchedulerTest.java
deleted file mode 100644
index 265956d..0000000
--- a/core/src/test/java/brooklyn/util/task/SingleThreadedSchedulerTest.java
+++ /dev/null
@@ -1,192 +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 brooklyn.util.task;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.fail;
-
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.test.Asserts;
-import brooklyn.util.collections.MutableMap;
-
-import com.google.common.util.concurrent.Callables;
-
-public class SingleThreadedSchedulerTest {
-
- private static final Logger log = LoggerFactory.getLogger(SingleThreadedSchedulerTest.class);
-
- private BasicExecutionManager em;
-
- @BeforeMethod
- public void setUp() {
- em = new BasicExecutionManager("mycontextid");
- em.setTaskSchedulerForTag("category1", SingleThreadedScheduler.class);
- }
-
- @AfterMethod
- public void tearDown() {
- if (em != null) em.shutdownNow();
- }
-
- @Test
- public void testExecutesInOrder() throws Exception {
- final int NUM_TIMES = 1000;
- final List<Integer> result = new CopyOnWriteArrayList<Integer>();
- for (int i = 0; i < NUM_TIMES; i++) {
- final int counter = i;
- em.submit(MutableMap.of("tag", "category1"), new Runnable() {
- public void run() {
- result.add(counter);
- }});
- }
-
- Asserts.succeedsEventually(new Runnable() {
- @Override public void run() {
- assertEquals(result.size(), NUM_TIMES);
- }});
-
- for (int i = 0; i < NUM_TIMES; i++) {
- assertEquals(result.get(i), (Integer)i);
- }
- }
-
- @Test
- public void testLargeQueueDoesNotConsumeTooManyThreads() throws Exception {
- final int NUM_TIMES = 3000;
- final CountDownLatch latch = new CountDownLatch(1);
- BasicTask<Void> blockingTask = new BasicTask<Void>(newLatchAwaiter(latch));
- em.submit(MutableMap.of("tag", "category1"), blockingTask);
-
- final AtomicInteger counter = new AtomicInteger(0);
- for (int i = 0; i < NUM_TIMES; i++) {
- BasicTask<Void> t = new BasicTask<Void>(new Runnable() {
- public void run() {
- counter.incrementAndGet();
- }});
- em.submit(MutableMap.of("tag", "category1"), t);
- if (i % 500 == 0) log.info("Submitted "+i+" jobs...");
- }
-
- Thread.sleep(100); // give it more of a chance to create the threads before we let them execute
- latch.countDown();
-
- Asserts.succeedsEventually(new Runnable() {
- @Override public void run() {
- assertEquals(counter.get(), NUM_TIMES);
- }});
- }
-
- @Test
- public void testGetResultOfQueuedTaskBeforeItExecutes() throws Exception {
- final CountDownLatch latch = new CountDownLatch(1);
- em.submit(MutableMap.of("tag", "category1"), newLatchAwaiter(latch));
-
- BasicTask<Integer> t = new BasicTask<Integer>(Callables.returning(123));
- Future<Integer> future = em.submit(MutableMap.of("tag", "category1"), t);
-
- Thread thread = new Thread(new Runnable() {
- public void run() {
- try {
- Thread.sleep(10);
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- latch.countDown();
- }});
- thread.start();
- assertEquals(future.get(), (Integer)123);
- }
-
- @Test
- public void testGetResultOfQueuedTaskBeforeItExecutesWithTimeout() throws Exception {
- final CountDownLatch latch = new CountDownLatch(1);
- em.submit(MutableMap.of("tag", "category1"), newLatchAwaiter(latch));
-
- BasicTask<Integer> t = new BasicTask<Integer>(Callables.returning(123));
- Future<Integer> future = em.submit(MutableMap.of("tag", "category1"), t);
-
- try {
- assertEquals(future.get(10, TimeUnit.MILLISECONDS), (Integer)123);
- fail();
- } catch (TimeoutException e) {
- // success
- }
- }
-
- @Test
- public void testCancelQueuedTaskBeforeItExecutes() throws Exception {
- final CountDownLatch latch = new CountDownLatch(1);
- em.submit(MutableMap.of("tag", "category1"), newLatchAwaiter(latch));
-
- final AtomicBoolean executed = new AtomicBoolean();
- BasicTask<?> t = new BasicTask<Void>(new Runnable() {
- public void run() {
- executed.set(true);
- }});
- Future<?> future = em.submit(MutableMap.of("tag", "category1"), t);
-
- future.cancel(true);
- latch.countDown();
- Thread.sleep(10);
- try {
- future.get();
- } catch (CancellationException e) {
- // success
- }
- assertFalse(executed.get());
- }
-
- @Test
- public void testGetResultOfQueuedTaskAfterItExecutes() throws Exception {
- final CountDownLatch latch = new CountDownLatch(1);
- em.submit(MutableMap.of("tag", "category1"), newLatchAwaiter(latch));
-
- BasicTask<Integer> t = new BasicTask<Integer>(Callables.returning(123));
- Future<Integer> future = em.submit(MutableMap.of("tag", "category1"), t);
-
- latch.countDown();
- assertEquals(future.get(), (Integer)123);
- }
-
- private Callable<Void> newLatchAwaiter(final CountDownLatch latch) {
- return new Callable<Void>() {
- public Void call() throws Exception {
- latch.await();
- return null;
- }
- };
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/task/TaskFinalizationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/task/TaskFinalizationTest.java b/core/src/test/java/brooklyn/util/task/TaskFinalizationTest.java
deleted file mode 100644
index 51750ca..0000000
--- a/core/src/test/java/brooklyn/util/task/TaskFinalizationTest.java
+++ /dev/null
@@ -1,62 +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 brooklyn.util.task;
-
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.brooklyn.api.management.Task;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-import brooklyn.util.time.Time;
-
-import com.google.common.base.Stopwatch;
-
-public class TaskFinalizationTest {
-
- private static final Logger log = LoggerFactory.getLogger(TaskFinalizationTest.class);
-
- // integration because it can take a while (and finalizers aren't even guaranteed)
- @Test(groups="Integration")
- public void testFinalizerInvoked() throws InterruptedException {
- BasicTask<?> t = new BasicTask<Void>(new Runnable() { public void run() { /* no op */ }});
- final Semaphore x = new Semaphore(0);
- t.setFinalizer(new BasicTask.TaskFinalizer() {
- public void onTaskFinalization(Task<?> t) {
- synchronized (x) {
- x.release();
- }
- }
- });
- t = null;
- Stopwatch watch = Stopwatch.createStarted();
- for (int i=0; i<30; i++) {
- System.gc(); System.gc();
- if (x.tryAcquire(1, TimeUnit.SECONDS)) {
- log.info("finalizer ran after "+Time.makeTimeStringRounded(watch));
- return;
- }
- }
- Assert.fail("finalizer did not run in time");
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/task/TasksTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/task/TasksTest.java b/core/src/test/java/brooklyn/util/task/TasksTest.java
deleted file mode 100644
index 58ce24f..0000000
--- a/core/src/test/java/brooklyn/util/task/TasksTest.java
+++ /dev/null
@@ -1,181 +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 brooklyn.util.task;
-
-import static brooklyn.event.basic.DependentConfiguration.attributeWhenReady;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Callable;
-
-import org.apache.brooklyn.api.management.ExecutionContext;
-import org.apache.brooklyn.api.management.Task;
-import org.apache.brooklyn.test.entity.TestApplication;
-import org.apache.brooklyn.test.entity.TestEntity;
-import org.testng.Assert;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.entity.BrooklynAppUnitTestSupport;
-import brooklyn.entity.basic.EntityFunctions;
-import brooklyn.util.guava.Functionals;
-import brooklyn.util.repeat.Repeater;
-import brooklyn.util.time.Duration;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.util.concurrent.Callables;
-
-
-public class TasksTest extends BrooklynAppUnitTestSupport {
-
- private ExecutionContext executionContext;
-
- @BeforeMethod(alwaysRun=true)
- @Override
- public void setUp() throws Exception {
- super.setUp();
- executionContext = app.getExecutionContext();
- }
-
- @Test
- public void testResolveNull() throws Exception {
- assertResolvesValue(null, String.class, null);
- }
-
- @Test
- public void testResolveValueCastsToType() throws Exception {
- assertResolvesValue(123, String.class, "123");
- }
-
- @Test
- public void testResolvesAttributeWhenReady() throws Exception {
- app.setAttribute(TestApplication.MY_ATTRIBUTE, "myval");
- assertResolvesValue(attributeWhenReady(app, TestApplication.MY_ATTRIBUTE), String.class, "myval");
- }
-
- @Test
- public void testResolvesMapWithAttributeWhenReady() throws Exception {
- app.setAttribute(TestApplication.MY_ATTRIBUTE, "myval");
- Map<?,?> orig = ImmutableMap.of("mykey", attributeWhenReady(app, TestApplication.MY_ATTRIBUTE));
- Map<?,?> expected = ImmutableMap.of("mykey", "myval");
- assertResolvesValue(orig, String.class, expected);
- }
-
- @Test
- public void testResolvesSetWithAttributeWhenReady() throws Exception {
- app.setAttribute(TestApplication.MY_ATTRIBUTE, "myval");
- Set<?> orig = ImmutableSet.of(attributeWhenReady(app, TestApplication.MY_ATTRIBUTE));
- Set<?> expected = ImmutableSet.of("myval");
- assertResolvesValue(orig, String.class, expected);
- }
-
- @Test
- public void testResolvesMapOfMapsWithAttributeWhenReady() throws Exception {
- app.setAttribute(TestApplication.MY_ATTRIBUTE, "myval");
- Map<?,?> orig = ImmutableMap.of("mykey", ImmutableMap.of("mysubkey", attributeWhenReady(app, TestApplication.MY_ATTRIBUTE)));
- Map<?,?> expected = ImmutableMap.of("mykey", ImmutableMap.of("mysubkey", "myval"));
- assertResolvesValue(orig, String.class, expected);
- }
-
- @SuppressWarnings("unchecked")
- @Test
- public void testResolvesIterableOfMapsWithAttributeWhenReady() throws Exception {
- app.setAttribute(TestApplication.MY_ATTRIBUTE, "myval");
- // using Iterables.concat so that orig is of type FluentIterable rather than List etc
- Iterable<?> orig = Iterables.concat(ImmutableList.of(ImmutableMap.of("mykey", attributeWhenReady(app, TestApplication.MY_ATTRIBUTE))));
- Iterable<Map<?,?>> expected = ImmutableList.<Map<?,?>>of(ImmutableMap.of("mykey", "myval"));
- assertResolvesValue(orig, String.class, expected);
- }
-
- private void assertResolvesValue(Object actual, Class<?> type, Object expected) throws Exception {
- Object result = Tasks.resolveValue(actual, type, executionContext);
- assertEquals(result, expected);
- }
-
- @Test
- public void testErrorsResolvingPropagatesOrSwallowedAllCorrectly() throws Exception {
- app.setConfig(TestEntity.CONF_OBJECT, ValueResolverTest.newThrowTask(Duration.ZERO));
- Task<Object> t = Tasks.builder().body(Functionals.callable(EntityFunctions.config(TestEntity.CONF_OBJECT), app)).build();
- ValueResolver<Object> v = Tasks.resolving(t).as(Object.class).context(app.getExecutionContext());
-
- ValueResolverTest.assertThrowsOnMaybe(v);
- ValueResolverTest.assertThrowsOnGet(v);
-
- v.swallowExceptions();
- ValueResolverTest.assertMaybeIsAbsent(v);
- ValueResolverTest.assertThrowsOnGet(v);
-
- v.defaultValue("foo");
- ValueResolverTest.assertMaybeIsAbsent(v);
- assertEquals(v.clone().get(), "foo");
- assertResolvesValue(v, Object.class, "foo");
- }
-
- @Test
- public void testRepeater() throws Exception {
- Task<?> t;
-
- t = Tasks.requiring(Repeater.create().until(Callables.returning(true)).every(Duration.millis(1))).build();
- app.getExecutionContext().submit(t);
- t.get(Duration.TEN_SECONDS);
-
- t = Tasks.testing(Repeater.create().until(Callables.returning(true)).every(Duration.millis(1))).build();
- app.getExecutionContext().submit(t);
- Assert.assertEquals(t.get(Duration.TEN_SECONDS), true);
-
- t = Tasks.requiring(Repeater.create().until(Callables.returning(false)).limitIterationsTo(2).every(Duration.millis(1))).build();
- app.getExecutionContext().submit(t);
- try {
- t.get(Duration.TEN_SECONDS);
- Assert.fail("Should have failed");
- } catch (Exception e) {
- // expected
- }
-
- t = Tasks.testing(Repeater.create().until(Callables.returning(false)).limitIterationsTo(2).every(Duration.millis(1))).build();
- app.getExecutionContext().submit(t);
- Assert.assertEquals(t.get(Duration.TEN_SECONDS), false);
- }
-
- @Test
- public void testRepeaterDescription() throws Exception{
- final String description = "task description";
- Repeater repeater = Repeater.create(description)
- .repeat(Callables.returning(null))
- .every(Duration.ONE_MILLISECOND)
- .limitIterationsTo(1)
- .until(new Callable<Boolean>() {
- @Override
- public Boolean call() {
- TaskInternal<?> current = (TaskInternal<?>)Tasks.current();
- assertEquals(current.getBlockingDetails(), description);
- return true;
- }
- });
- Task<Boolean> t = Tasks.testing(repeater).build();
- app.getExecutionContext().submit(t);
- assertTrue(t.get(Duration.TEN_SECONDS));
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/task/ValueResolverTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/task/ValueResolverTest.java b/core/src/test/java/brooklyn/util/task/ValueResolverTest.java
deleted file mode 100644
index d50ff54..0000000
--- a/core/src/test/java/brooklyn/util/task/ValueResolverTest.java
+++ /dev/null
@@ -1,132 +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 brooklyn.util.task;
-
-import java.util.concurrent.Callable;
-
-import org.apache.brooklyn.api.management.ExecutionContext;
-import org.apache.brooklyn.api.management.Task;
-import org.testng.Assert;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.entity.BrooklynAppUnitTestSupport;
-import brooklyn.util.guava.Maybe;
-import brooklyn.util.time.Duration;
-import brooklyn.util.time.Time;
-
-/**
- * see also {@link TasksTest} for more tests
- */
-@Test
-public class ValueResolverTest extends BrooklynAppUnitTestSupport {
-
- private ExecutionContext executionContext;
-
- @BeforeMethod(alwaysRun=true)
- @Override
- public void setUp() throws Exception {
- super.setUp();
- executionContext = app.getExecutionContext();
- }
-
- public static final Task<String> newSleepTask(final Duration timeout, final String result) {
- return Tasks.<String>builder().body(new Callable<String>() {
- public String call() {
- Time.sleep(timeout);
- return result;
- }}
- ).build();
- }
-
- public static final Task<String> newThrowTask(final Duration timeout) {
- return Tasks.<String>builder().body(new Callable<String>() {
- public String call() {
- Time.sleep(timeout);
- throw new IllegalStateException("intended, during tests");
- }}
- ).build();
- }
-
- public void testTimeoutZero() {
- Maybe<String> result = Tasks.resolving(newSleepTask(Duration.TEN_SECONDS, "foo")).as(String.class).context(executionContext).timeout(Duration.ZERO).getMaybe();
- Assert.assertFalse(result.isPresent());
- }
-
- public void testTimeoutBig() {
- Maybe<String> result = Tasks.resolving(newSleepTask(Duration.ZERO, "foo")).as(String.class).context(executionContext).timeout(Duration.TEN_SECONDS).getMaybe();
- Assert.assertEquals(result.get(), "foo");
- }
-
- public void testNoExecutionContextOnCompleted() {
- Task<String> t = newSleepTask(Duration.ZERO, "foo");
- executionContext.submit(t).getUnchecked();
- Maybe<String> result = Tasks.resolving(t).as(String.class).timeout(Duration.ZERO).getMaybe();
- Assert.assertEquals(result.get(), "foo");
- }
-
- public static Throwable assertThrowsOnMaybe(ValueResolver<?> result) {
- try {
- result = result.clone();
- result.getMaybe();
- Assert.fail("should have thrown");
- return null;
- } catch (Exception e) { return e; }
- }
- public static Throwable assertThrowsOnGet(ValueResolver<?> result) {
- result = result.clone();
- try {
- result.get();
- Assert.fail("should have thrown");
- return null;
- } catch (Exception e) { return e; }
- }
- public static <T> Maybe<T> assertMaybeIsAbsent(ValueResolver<T> result) {
- result = result.clone();
- Maybe<T> maybe = result.getMaybe();
- Assert.assertFalse(maybe.isPresent());
- return maybe;
- }
-
- public void testSwallowError() {
- ValueResolver<String> result = Tasks.resolving(newThrowTask(Duration.ZERO)).as(String.class).context(executionContext).swallowExceptions();
- assertMaybeIsAbsent(result);
- assertThrowsOnGet(result);
- }
-
-
- public void testDontSwallowError() {
- ValueResolver<String> result = Tasks.resolving(newThrowTask(Duration.ZERO)).as(String.class).context(executionContext);
- assertThrowsOnMaybe(result);
- assertThrowsOnGet(result);
- }
-
- public void testDefaultWhenSwallowError() {
- ValueResolver<String> result = Tasks.resolving(newThrowTask(Duration.ZERO)).as(String.class).context(executionContext).swallowExceptions().defaultValue("foo");
- assertMaybeIsAbsent(result);
- Assert.assertEquals(result.get(), "foo");
- }
-
- public void testDefaultBeforeDelayAndError() {
- ValueResolver<String> result = Tasks.resolving(newThrowTask(Duration.TEN_SECONDS)).as(String.class).context(executionContext).timeout(Duration.ZERO).defaultValue("foo");
- assertMaybeIsAbsent(result);
- Assert.assertEquals(result.get(), "foo");
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a4c0e5fd/core/src/test/java/brooklyn/util/task/ssh/SshTasksTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/task/ssh/SshTasksTest.java b/core/src/test/java/brooklyn/util/task/ssh/SshTasksTest.java
deleted file mode 100644
index 578164f..0000000
--- a/core/src/test/java/brooklyn/util/task/ssh/SshTasksTest.java
+++ /dev/null
@@ -1,207 +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 brooklyn.util.task.ssh;
-
-import java.io.File;
-import java.io.IOException;
-
-import org.apache.brooklyn.api.location.LocationSpec;
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.core.management.internal.LocalManagementContext;
-import org.apache.commons.io.FileUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.Assert;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.entity.basic.BrooklynConfigKeys;
-import brooklyn.entity.basic.Entities;
-
-import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
-import org.apache.brooklyn.location.basic.SshMachineLocation;
-
-import brooklyn.util.net.Urls;
-import brooklyn.util.os.Os;
-import brooklyn.util.ssh.BashCommandsIntegrationTest;
-import brooklyn.util.task.system.ProcessTaskFactory;
-import brooklyn.util.task.system.ProcessTaskWrapper;
-
-/**
- * Some tests for {@link SshTasks}. Note more tests in {@link BashCommandsIntegrationTest},
- * {@link SshEffectorTasksTest}, and {@link SoftwareEffectorTest}.
- */
-public class SshTasksTest {
-
- private static final Logger log = LoggerFactory.getLogger(SshTasksTest.class);
-
- ManagementContext mgmt;
- SshMachineLocation host;
- File tempDir;
-
- boolean failureExpected;
-
- @BeforeMethod(alwaysRun=true)
- public void setup() throws Exception {
- mgmt = new LocalManagementContext();
-
- LocalhostMachineProvisioningLocation lhc = mgmt.getLocationManager().createLocation(LocationSpec.create(LocalhostMachineProvisioningLocation.class));
- host = lhc.obtain();
- clearExpectedFailure();
- tempDir = Os.newTempDir(getClass());
- }
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws Exception {
- if (mgmt != null) Entities.destroyAll(mgmt);
- mgmt = null;
- tempDir = Os.deleteRecursively(tempDir).asNullOrThrowing();
- checkExpectedFailure();
- }
-
- protected void checkExpectedFailure() {
- if (failureExpected) {
- clearExpectedFailure();
- Assert.fail("Test should have thrown an exception but it did not.");
- }
- }
-
- protected void clearExpectedFailure() {
- failureExpected = false;
- }
-
- protected void setExpectingFailure() {
- failureExpected = true;
- }
-
-
- protected <T> ProcessTaskWrapper<T> submit(final ProcessTaskFactory<T> tf) {
- tf.machine(host);
- ProcessTaskWrapper<T> t = tf.newTask();
- mgmt.getExecutionManager().submit(t);
- return t;
- }
-
- protected SshPutTaskWrapper submit(final SshPutTaskFactory tf) {
- SshPutTaskWrapper t = tf.newTask();
- mgmt.getExecutionManager().submit(t);
- return t;
- }
-
- @Test(groups="Integration")
- public void testSshEchoHello() {
- ProcessTaskWrapper<Integer> t = submit(SshTasks.newSshExecTaskFactory(host, "sleep 1 ; echo hello world"));
- Assert.assertFalse(t.isDone());
- Assert.assertEquals(t.get(), (Integer)0);
- Assert.assertEquals(t.getTask().getUnchecked(), (Integer)0);
- Assert.assertEquals(t.getStdout().trim(), "hello world");
- }
-
- @Test(groups="Integration")
- public void testCopyTo() throws IOException {
- String fn = Urls.mergePaths(tempDir.getPath(), "f1");
- SshPutTaskWrapper t = submit(SshTasks.newSshPutTaskFactory(host, fn).contents("hello world"));
- t.block();
- Assert.assertEquals(FileUtils.readFileToString(new File(fn)), "hello world");
- // and make sure this doesn't throw
- Assert.assertTrue(t.isDone());
- Assert.assertTrue(t.isSuccessful());
- Assert.assertEquals(t.get(), null);
- Assert.assertEquals(t.getExitCode(), (Integer)0);
- }
-
- @Test(groups="Integration")
- public void testCopyToFailBadSubdir() throws IOException {
- String fn = Urls.mergePaths(tempDir.getPath(), "non-existent-subdir/file");
- SshPutTaskWrapper t = submit(SshTasks.newSshPutTaskFactory(host, fn).contents("hello world"));
- //this doesn't fail
- t.block();
- Assert.assertTrue(t.isDone());
- setExpectingFailure();
- try {
- // but this does
- t.get();
- } catch (Exception e) {
- log.info("The error if file cannot be written is: "+e);
- clearExpectedFailure();
- }
- checkExpectedFailure();
- // and the results indicate failure
- Assert.assertFalse(t.isSuccessful());
- Assert.assertNotNull(t.getException());
- Assert.assertNotEquals(t.getExitCode(), (Integer)0);
- }
-
- @Test(groups="Integration")
- public void testCopyToFailBadSubdirAllow() throws IOException {
- String fn = Urls.mergePaths(tempDir.getPath(), "non-existent-subdir/file");
- SshPutTaskWrapper t = submit(SshTasks.newSshPutTaskFactory(host, fn).contents("hello world").allowFailure());
- //this doesn't fail
- t.block();
- Assert.assertTrue(t.isDone());
- // and this doesn't fail either
- Assert.assertEquals(t.get(), null);
- // but it's not successful
- Assert.assertNotNull(t.getException());
- Assert.assertFalse(t.isSuccessful());
- // exit code probably null, but won't be zero
- Assert.assertNotEquals(t.getExitCode(), (Integer)0);
- }
-
- @Test(groups="Integration")
- public void testCopyToFailBadSubdirCreate() throws IOException {
- String fn = Urls.mergePaths(tempDir.getPath(), "non-existent-subdir-to-create/file");
- SshPutTaskWrapper t = submit(SshTasks.newSshPutTaskFactory(host, fn).contents("hello world").createDirectory());
- t.block();
- // directory should be created, and file readable now
- Assert.assertEquals(FileUtils.readFileToString(new File(fn)), "hello world");
- Assert.assertEquals(t.getExitCode(), (Integer)0);
- }
-
- @Test(groups="Integration")
- public void testSshFetch() throws IOException {
- String fn = Urls.mergePaths(tempDir.getPath(), "f2");
- FileUtils.write(new File(fn), "hello fetched world");
-
- SshFetchTaskFactory tf = SshTasks.newSshFetchTaskFactory(host, fn);
- SshFetchTaskWrapper t = tf.newTask();
- mgmt.getExecutionManager().submit(t);
-
- t.block();
- Assert.assertTrue(t.isDone());
- Assert.assertEquals(t.get(), "hello fetched world");
- Assert.assertEquals(t.getBytes(), "hello fetched world".getBytes());
- }
-
- @Test(groups="Integration")
- public void testSshWithHeaderProperty() {
- host.setConfig(BrooklynConfigKeys.SSH_CONFIG_SCRIPT_HEADER, "#!/bin/bash -e\necho foo\n");
- ProcessTaskWrapper<Integer> t = submit(SshTasks.newSshExecTaskFactory(host, "echo bar"));
- Assert.assertTrue(t.block().getStdout().trim().matches("foo\\s+bar"), "mismatched output was: "+t.getStdout());
- }
-
- @Test(groups="Integration")
- public void testSshIgnoringHeaderProperty() {
- host.setConfig(BrooklynConfigKeys.SSH_CONFIG_SCRIPT_HEADER, "#!/bin/bash -e\necho foo\n");
- ProcessTaskWrapper<Integer> t = submit(SshTasks.newSshExecTaskFactory(host, false, "echo bar"));
- Assert.assertTrue(t.block().getStdout().trim().matches("bar"), "mismatched output was: "+t.getStdout());
- }
-
-}