brooklyn-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From henev...@apache.org
Subject [1/9] incubator-brooklyn git commit: Add EntityAsserts and HttpUtils.
Date Wed, 04 Nov 2015 15:47:46 GMT
Repository: incubator-brooklyn
Updated Branches:
  refs/heads/master 48e4fe3ca -> a5040934d


Add EntityAsserts and HttpUtils.

This are added to allow core code to make assertions on entities without
without having a dependency on TestNG.

For now, deprecate EntityTestUtils and HttpTestUtils, and in the future these
can be removed in favour of the new classes.


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/c316e217
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/c316e217
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/c316e217

Branch: refs/heads/master
Commit: c316e2177b88b2f274637d812e5659e751aeea0d
Parents: 6d00890
Author: Geoff Macartney <geoff.macartney@cloudsoftcorp.com>
Authored: Wed Oct 28 12:10:37 2015 +0000
Committer: Geoff Macartney <geoff.macartney@cloudsoftcorp.com>
Committed: Fri Oct 30 11:34:43 2015 +0000

----------------------------------------------------------------------
 .../brooklyn/core/entity/EntityAsserts.java     | 192 ++++++
 .../deserializingClassRenames.properties        |   2 +-
 .../brooklyn/core/entity/EntityAssertsTest.java | 217 +++++++
 .../apache/brooklyn/test/EntityTestUtils.java   |  51 +-
 .../org/apache/brooklyn/test/HttpTestUtils.java |   4 +
 .../brooklyn/test/TrustingSslSocketFactory.java | 134 ----
 .../java/org/apache/brooklyn/test/Asserts.java  | 615 ++++++++++++++++++-
 .../apache/brooklyn/util/http/HttpUtils.java    | 387 ++++++++++++
 .../util/http/TrustingSslSocketFactory.java     | 134 ++++
 9 files changed, 1577 insertions(+), 159 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c316e217/core/src/main/java/org/apache/brooklyn/core/entity/EntityAsserts.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/EntityAsserts.java b/core/src/main/java/org/apache/brooklyn/core/entity/EntityAsserts.java
new file mode 100644
index 0000000..046ac52
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/EntityAsserts.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.entity;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.Group;
+import org.apache.brooklyn.api.mgmt.SubscriptionHandle;
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.api.sensor.SensorEvent;
+import org.apache.brooklyn.api.sensor.SensorEventListener;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.test.Asserts;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+import static org.apache.brooklyn.test.Asserts.assertEquals;
+
+/**
+ * Convenience class containing assertions that may be made about entities.
+ */
+public class EntityAsserts {
+
+
+    public static <T> void assertAttributeEquals(Entity entity, AttributeSensor<T> attribute, T expected) {
+        assertEquals(entity.getAttribute(attribute), expected, "entity=" + entity + "; attribute=" + attribute);
+    }
+
+    public static <T> void assertConfigEquals(Entity entity, ConfigKey<T> configKey, T expected) {
+        assertEquals(entity.getConfig(configKey), expected, "entity=" + entity + "; configKey=" + configKey);
+    }
+
+    public static <T> void assertAttributeEqualsEventually(final Entity entity, final AttributeSensor<T> attribute, final T expected) {
+        assertAttributeEqualsEventually(Maps.newLinkedHashMap(), entity, attribute, expected);
+    }
+
+    public static <T> void assertAttributeEqualsEventually(Map<?,?> flags, final Entity entity, final AttributeSensor<T> attribute, final T expected) {
+        // Not using assertAttributeEventually(predicate) so get nicer error message
+        Asserts.succeedsEventually((Map) flags, new Runnable() {
+            @Override
+            public void run() {
+                assertAttributeEquals(entity, attribute, expected);
+            }
+        });
+    }
+
+    public static <T> T assertAttributeEventuallyNonNull(final Entity entity, final AttributeSensor<T> attribute) {
+        return assertAttributeEventuallyNonNull(Maps.newLinkedHashMap(), entity, attribute);
+    }
+
+    public static <T> T assertAttributeEventuallyNonNull(Map<?,?> flags, final Entity entity, final AttributeSensor<T> attribute) {
+        return assertAttributeEventually(flags, entity, attribute, Predicates.notNull());
+    }
+
+    public static <T> T assertAttributeEventually(final Entity entity, final AttributeSensor<T> attribute, Predicate<? super T> predicate) {
+        return assertAttributeEventually(ImmutableMap.of(), entity, attribute, predicate);
+    }
+
+    public static <T> T assertAttributeEventually(Map<?,?> flags, final Entity entity, final AttributeSensor<T> attribute, final Predicate<? super T> predicate) {
+        final AtomicReference<T> result = new AtomicReference<T>();
+        Asserts.succeedsEventually((Map)flags, new Runnable() {
+            @Override public void run() {
+                T val = entity.getAttribute(attribute);
+                Asserts.assertTrue(predicate.apply(val), "val=" + val);
+                result.set(val);
+            }});
+        return result.get();
+    }
+
+    public static <T> T assertAttribute(final Entity entity, final AttributeSensor<T> attribute, final Predicate<? super T> predicate) {
+        T val = entity.getAttribute(attribute);
+        Asserts.assertTrue(predicate.apply(val), "val=" + val);
+        return val;
+    }
+
+
+    public static <T extends Entity> void assertPredicateEventuallyTrue(final T entity, final Predicate<? super T> predicate) {
+        assertPredicateEventuallyTrue(Maps.newLinkedHashMap(), entity, predicate);
+    }
+
+    public static <T extends Entity> void assertPredicateEventuallyTrue(Map<?,?> flags, final T entity, final Predicate<? super T> predicate) {
+        Asserts.succeedsEventually((Map)flags, new Runnable() {
+            @Override public void run() {
+                Asserts.assertTrue(predicate.apply(entity), "predicate unsatisfied");
+            }});
+    }
+
+    public static <T> void assertAttributeEqualsContinually(final Entity entity, final AttributeSensor<T> attribute, final T expected) {
+        assertAttributeEqualsContinually(Maps.newLinkedHashMap(), entity, attribute, expected);
+    }
+
+    public static <T> void assertAttributeEqualsContinually(Map<?,?> flags, final Entity entity, final AttributeSensor<T> attribute, final T expected) {
+        Asserts.succeedsContinually(flags, new Runnable() {
+            @Override public void run() {
+                assertAttributeEquals(entity, attribute, expected);
+            }});
+    }
+
+    public static void assertGroupSizeEqualsEventually(final Group group, int expected) {
+        assertGroupSizeEqualsEventually(ImmutableMap.of(), group, expected);
+    }
+
+    public static void assertGroupSizeEqualsEventually(Map<?,?> flags, final Group group, final int expected) {
+        Asserts.succeedsEventually((Map)flags, new Runnable() {
+            @Override public void run() {
+                Collection<Entity> members = group.getMembers();
+                assertEquals(members.size(), expected, "members=" + members);
+            }});
+    }
+
+
+    /**
+     * Asserts that the entity's value for this attribute changes, by registering a subscription and checking the value.
+     *
+     * @param entity The entity whose attribute will be checked.
+     * @param attribute The attribute to check on the entity.
+     *
+     * @throws AssertionError if the assertion fails.
+     */
+    public static void assertAttributeChangesEventually(final Entity entity, final AttributeSensor<?> attribute) {
+        final Object origValue = entity.getAttribute(attribute);
+        final AtomicBoolean changed = new AtomicBoolean();
+        SubscriptionHandle handle = entity.subscriptions().subscribe(entity, attribute, new SensorEventListener<Object>() {
+            @Override public void onEvent(SensorEvent<Object> event) {
+                if (!Objects.equal(origValue, event.getValue())) {
+                    changed.set(true);
+                }
+            }});
+        try {
+            Asserts.succeedsEventually(new Runnable() {
+                @Override public void run() {
+                    Asserts.assertTrue(changed.get(), entity + " -> " + attribute + " not changed");
+                }});
+        } finally {
+            entity.subscriptions().unsubscribe(entity, handle);
+        }
+    }
+
+
+    @Beta @SafeVarargs
+    public static <T> void assertAttributeNever(final Entity entity, final AttributeSensor<T> attribute, T... disallowed) {
+        final Set<T> reject = Sets.newHashSet(disallowed);
+        Asserts.succeedsContinually(new Runnable() {
+            @Override
+            public void run() {
+                T val = entity.getAttribute(attribute);
+                Asserts.assertFalse(reject.contains(val),
+                        "Attribute " + attribute + " on " + entity + " has disallowed value " + val);
+            }
+        });
+    }
+
+    @Beta @SafeVarargs
+    public static <T> void assertAttributeNever(final Map<?,?> flags, final Entity entity, final AttributeSensor<T> attribute, T... disallowed) {
+        final Set<T> reject = Sets.newHashSet(disallowed);
+        Asserts.succeedsContinually(flags, new Runnable() {
+            @Override
+            public void run() {
+                T val = entity.getAttribute(attribute);
+                Asserts.assertFalse(reject.contains(val),
+                        "Attribute " + attribute + " on " + entity + " has disallowed value " + val);
+            }
+        });
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c316e217/core/src/main/resources/org/apache/brooklyn/core/mgmt/persist/deserializingClassRenames.properties
----------------------------------------------------------------------
diff --git a/core/src/main/resources/org/apache/brooklyn/core/mgmt/persist/deserializingClassRenames.properties b/core/src/main/resources/org/apache/brooklyn/core/mgmt/persist/deserializingClassRenames.properties
index 2bd0c00..006b95a 100644
--- a/core/src/main/resources/org/apache/brooklyn/core/mgmt/persist/deserializingClassRenames.properties
+++ b/core/src/main/resources/org/apache/brooklyn/core/mgmt/persist/deserializingClassRenames.properties
@@ -1415,5 +1415,5 @@ brooklyn.management.internal.UsageManager
 brooklyn.policy.basic.ConfigMapImpl                                              : org.apache.brooklyn.core.objs.AdjunctConfigMap
 brooklyn.util.internal.Repeater                                                  : org.apache.brooklyn.util.core.internal.Repeater
 brooklyn.entity.nosql.redis.RedisClusterImpl                                     : org.apache.brooklyn.entity.nosql.redis.RedisClusterImpl
-brooklyn.test.TrustingSslSocketFactory                                           : org.apache.brooklyn.test.TrustingSslSocketFactory
+brooklyn.test.TrustingSslSocketFactory                                           : org.apache.brooklyn.util.http.TrustingSslSocketFactory
 brooklyn.util.crypto.TrustingSslSocketFactory                                    : org.apache.brooklyn.util.crypto.TrustingSslSocketFactory

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c316e217/core/src/test/java/org/apache/brooklyn/core/entity/EntityAssertsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/entity/EntityAssertsTest.java b/core/src/test/java/org/apache/brooklyn/core/entity/EntityAssertsTest.java
new file mode 100644
index 0000000..563b0ea
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/entity/EntityAssertsTest.java
@@ -0,0 +1,217 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES 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.entity;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.core.location.SimulatedLocation;
+import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.entity.group.DynamicGroup;
+import org.apache.brooklyn.util.time.Duration;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Tests on {@link EntityAsserts}.
+ */
+public class EntityAssertsTest extends BrooklynAppUnitTestSupport {
+
+    private static final int TIMEOUT_MS = 10*1000;
+    private static final String STOOGE = "stooge";
+
+    private SimulatedLocation loc;
+    private TestEntity entity;
+    private ScheduledExecutorService executor;
+    private DynamicGroup stooges;
+
+    @BeforeMethod(alwaysRun=true)
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        loc = app.getManagementContext().getLocationManager().createLocation(LocationSpec.create(SimulatedLocation.class));
+        entity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+        stooges = app.createAndManageChild(EntitySpec.create(DynamicGroup.class));
+        final EntitySpec<TestEntity> stooge =
+                EntitySpec.create(TestEntity.class).configure(TestEntity.CONF_NAME, STOOGE);
+        app.createAndManageChild(stooge);
+        app.createAndManageChild(stooge);
+        app.createAndManageChild(stooge);
+        app.start(ImmutableList.of(loc));
+        executor = Executors.newScheduledThreadPool(3);
+    }
+
+    @AfterMethod(alwaysRun=true)
+    public void tearDown() throws Exception {
+        if (executor != null) executor.shutdownNow();
+        if (app != null) Entities.destroyAll(app.getManagementContext());
+        super.tearDown();
+    }
+
+
+    @Test
+    public void shouldAssertAttributeEquals() {
+        final String myName = "myname";
+        entity.sensors().set(TestEntity.NAME, myName);
+        EntityAsserts.assertAttributeEquals(entity, TestEntity.NAME, myName);
+    }
+
+    @Test(expectedExceptions = AssertionError.class)
+    public void shouldFailToAssertAttributeEquals() {
+        final String myName = "myname";
+        entity.sensors().set(TestEntity.NAME, myName);
+        EntityAsserts.assertAttributeEquals(entity, TestEntity.NAME, "bogus");
+    }
+
+    @Test
+    public void shouldAssertConfigEquals() {
+        EntityAsserts.assertConfigEquals(entity, TestEntity.CONF_NAME, "defaultval");
+    }
+
+    @Test(expectedExceptions = AssertionError.class)
+    public void shouldFailToAssertConfigEquals() {
+        EntityAsserts.assertConfigEquals(entity, TestEntity.CONF_NAME, "bogus");
+    }
+
+    @Test
+    public void shouldAssertAttributeEqualsEventually() {
+        entity.sensors().set(TestEntity.NAME, "before");
+        final String after = "after";
+        setSensorValueLater(TestEntity.NAME, after, Duration.seconds(2));
+        EntityAsserts.assertAttributeEqualsEventually(entity, TestEntity.NAME, after);
+    }
+
+
+    @Test(expectedExceptions = AssertionError.class)
+    public void shouldFailToAssertAttributeEqualsEventually() {
+        entity.sensors().set(TestEntity.NAME, "before");
+        final String after = "after";
+        setSensorValueLater(TestEntity.NAME, after, Duration.seconds(2));
+        EntityAsserts.assertAttributeEqualsEventually(ImmutableMap.of("timeout", "1s"), entity, TestEntity.NAME, after);
+    }
+
+    private <T> void setSensorValueLater(final AttributeSensor<T> sensor, final T value, final Duration delay) {
+        executor.schedule(new Runnable() {
+            @Override
+            public void run() {
+                entity.sensors().set(sensor, value);
+            }
+        }, delay.toUnit(TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS);
+    }
+
+    @Test
+    public void shouldAssertAttributeEventuallyNonNull() {
+        EntityAsserts.assertAttributeEquals(entity, TestEntity.NAME, null);
+        setSensorValueLater(TestEntity.NAME, "something", Duration.seconds(1));
+        EntityAsserts.assertAttributeEventuallyNonNull(entity, TestEntity.NAME);
+    }
+
+    @Test
+    public void shouldAssertAttributeEventually() {
+        setSensorValueLater(TestEntity.NAME, "testing testing 123", Duration.seconds(1));
+        EntityAsserts.assertAttributeEventually(entity, TestEntity.NAME, new Predicate<String>() {
+            @Override
+            public boolean apply(String input) {
+                return input.matches(".*\\d+");
+            }
+        });
+    }
+
+    @Test
+    public void shouldAssertAttribute() {
+        final String before = "before";
+        entity.sensors().set(TestEntity.NAME, before);
+        EntityAsserts.assertAttribute(entity, TestEntity.NAME, Predicates.equalTo(before));
+    }
+
+    @Test
+    public void shouldAssertPredicateEventuallyTrue() {
+        final int testVal = 987654321;
+        executor.schedule(new Runnable() {
+            @Override
+            public void run() {
+                entity.setSequenceValue(testVal);
+            }
+        }, 1, TimeUnit.SECONDS);
+        EntityAsserts.assertPredicateEventuallyTrue(entity, new Predicate<TestEntity>() {
+            @Override
+            public boolean apply(TestEntity input) {
+                return testVal == input.getSequenceValue() ;
+            }
+        });
+    }
+
+    @Test
+    public void shouldAssertAttributeEqualsContinually() {
+        final String myName = "myname";
+        entity.sensors().set(TestEntity.NAME, myName);
+        EntityAsserts.assertAttributeEqualsContinually(
+                ImmutableMap.of("timeout", "2s"), entity, TestEntity.NAME, myName);
+    }
+
+    @Test(expectedExceptions = AssertionError.class)
+    public void shouldFailAssertAttributeEqualsContinually() {
+        final String myName = "myname";
+        entity.sensors().set(TestEntity.NAME, myName);
+        setSensorValueLater(TestEntity.NAME, "something", Duration.seconds(1));
+        EntityAsserts.assertAttributeEqualsContinually(
+                ImmutableMap.of("timeout", "2s"), entity, TestEntity.NAME, myName);
+    }
+
+    @Test
+    public void shouldAssertGroupSizeEqualsEventually() {
+        setGroupFilterLater(STOOGE, 1);
+        EntityAsserts.assertGroupSizeEqualsEventually(ImmutableMap.of("timeout", "2s"), stooges, 3);
+        setGroupFilterLater("Marx Brother", 1);
+        EntityAsserts.assertGroupSizeEqualsEventually(stooges, 0);
+    }
+
+    private void setGroupFilterLater(final String conf, long delaySeconds) {
+        executor.schedule(new Runnable() {
+            @Override
+            public void run() {
+                stooges.setEntityFilter(EntityPredicates.configEqualTo(TestEntity.CONF_NAME, conf));
+            }
+        }, delaySeconds, TimeUnit.SECONDS);
+    }
+
+    @Test
+    public void shouldAssertAttributeChangesEventually () {
+        entity.sensors().set(TestEntity.NAME, "before");
+        setSensorValueLater(TestEntity.NAME, "after", Duration.seconds(2));
+        EntityAsserts.assertAttributeChangesEventually(entity, TestEntity.NAME);
+    }
+
+    @Test
+    public void shouldAssertAttributeNever() {
+        entity.sensors().set(TestEntity.NAME, "ever");
+        EntityAsserts.assertAttributeNever(ImmutableMap.of("timeout", "5s"), entity, TestEntity.NAME, "after");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c316e217/usage/test-support/src/main/java/org/apache/brooklyn/test/EntityTestUtils.java
----------------------------------------------------------------------
diff --git a/usage/test-support/src/main/java/org/apache/brooklyn/test/EntityTestUtils.java b/usage/test-support/src/main/java/org/apache/brooklyn/test/EntityTestUtils.java
index 3baa26d..6a72324 100644
--- a/usage/test-support/src/main/java/org/apache/brooklyn/test/EntityTestUtils.java
+++ b/usage/test-support/src/main/java/org/apache/brooklyn/test/EntityTestUtils.java
@@ -36,7 +36,6 @@ import org.apache.brooklyn.api.sensor.AttributeSensor;
 import org.apache.brooklyn.api.sensor.SensorEvent;
 import org.apache.brooklyn.api.sensor.SensorEventListener;
 import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.test.Asserts;
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.Objects;
@@ -46,6 +45,12 @@ import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 
+/**
+ * A utility class containing tests on Entities.
+ *
+ * @deprecated Prefer core assertions org.apache.brooklyn.entity.EntityAsserts.
+ */
+@Deprecated
 public class EntityTestUtils {
 
     // TODO would be nice to have this... perhaps moving this class, or perhaps this whole project, to core/src/test ?
@@ -55,11 +60,11 @@ public class EntityTestUtils {
     // and deprecate methods in TestUtils until deleted).
     
     public static <T> void assertAttributeEquals(Entity entity, AttributeSensor<T> attribute, T expected) {
-        assertEquals(entity.getAttribute(attribute), expected, "entity="+entity+"; attribute="+attribute);
+        assertEquals(entity.getAttribute(attribute), expected, "entity=" + entity + "; attribute=" + attribute);
     }
     
     public static <T> void assertConfigEquals(Entity entity, ConfigKey<T> configKey, T expected) {
-        assertEquals(entity.getConfig(configKey), expected, "entity="+entity+"; configKey="+configKey);
+        assertEquals(entity.getConfig(configKey), expected, "entity=" + entity + "; configKey=" + configKey);
     }
     
     public static <T> void assertAttributeEqualsEventually(final Entity entity, final AttributeSensor<T> attribute, final T expected) {
@@ -68,10 +73,12 @@ public class EntityTestUtils {
 
     public static <T> void assertAttributeEqualsEventually(Map<?,?> flags, final Entity entity, final AttributeSensor<T> attribute, final T expected) {
         // Not using assertAttributeEventually(predicate) so get nicer error message
-        Asserts.succeedsEventually((Map)flags, new Runnable() {
-            @Override public void run() {
+        Asserts.succeedsEventually((Map) flags, new Runnable() {
+            @Override
+            public void run() {
                 assertAttributeEquals(entity, attribute, expected);
-            }});
+            }
+        });
     }
 
     public static <T> T assertAttributeEventuallyNonNull(final Entity entity, final AttributeSensor<T> attribute) {
@@ -108,10 +115,12 @@ public class EntityTestUtils {
     }
 
     public static <T extends Entity> void assertPredicateEventuallyTrue(Map<?,?> flags, final T entity, final Predicate<? super T> predicate) {
-        Asserts.succeedsEventually((Map)flags, new Runnable() {
-                @Override public void run() {
-                    assertTrue(predicate.apply(entity));
-                }});
+        Asserts.succeedsEventually((Map) flags, new Runnable() {
+            @Override
+            public void run() {
+                assertTrue(predicate.apply(entity));
+            }
+        });
     }
 
     public static <T> void assertAttributeEqualsContinually(final Entity entity, final AttributeSensor<T> attribute, final T expected) {
@@ -120,9 +129,11 @@ public class EntityTestUtils {
     
     public static <T> void assertAttributeEqualsContinually(Map<?,?> flags, final Entity entity, final AttributeSensor<T> attribute, final T expected) {
         Asserts.succeedsContinually(flags, new Runnable() {
-                @Override public void run() {
-                    assertAttributeEquals(entity, attribute, expected);
-                }});
+            @Override
+            public void run() {
+                assertAttributeEquals(entity, attribute, expected);
+            }
+        });
     }
 
     public static void assertGroupSizeEqualsEventually(final Group group, int expected) {
@@ -130,11 +141,13 @@ public class EntityTestUtils {
     }
     
     public static void assertGroupSizeEqualsEventually(Map<?,?> flags, final Group group, final int expected) {
-        Asserts.succeedsEventually((Map)flags, new Runnable() {
-            @Override public void run() {
+        Asserts.succeedsEventually((Map) flags, new Runnable() {
+            @Override
+            public void run() {
                 Collection<Entity> members = group.getMembers();
-                assertEquals(members.size(), expected, "members="+members);
-            }});
+                assertEquals(members.size(), expected, "members=" + members);
+            }
+        });
     }
 
     /** checks that the entity's value for this attribute changes, by registering a subscription and checking the value */
@@ -161,8 +174,8 @@ public class EntityTestUtils {
      * with simpler code, for comparison */
     @Beta
     public static <T> void assertAttributeChangesEventually2(final Entity entity, final AttributeSensor<T> attribute) {
-        assertAttributeEventually(entity, attribute, 
-            Predicates.not(Predicates.equalTo(entity.getAttribute(attribute))));
+        assertAttributeEventually(entity, attribute,
+                Predicates.not(Predicates.equalTo(entity.getAttribute(attribute))));
     }
 
     @Beta

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c316e217/usage/test-support/src/main/java/org/apache/brooklyn/test/HttpTestUtils.java
----------------------------------------------------------------------
diff --git a/usage/test-support/src/main/java/org/apache/brooklyn/test/HttpTestUtils.java b/usage/test-support/src/main/java/org/apache/brooklyn/test/HttpTestUtils.java
index eed5ef4..c0089bd 100644
--- a/usage/test-support/src/main/java/org/apache/brooklyn/test/HttpTestUtils.java
+++ b/usage/test-support/src/main/java/org/apache/brooklyn/test/HttpTestUtils.java
@@ -43,6 +43,7 @@ import org.apache.brooklyn.test.Asserts;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.crypto.SslTrustUtils;
 import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.http.TrustingSslSocketFactory;
 import org.apache.brooklyn.util.stream.Streams;
 import org.apache.brooklyn.util.time.Time;
 import org.slf4j.Logger;
@@ -59,7 +60,10 @@ import com.google.common.util.concurrent.ListeningExecutorService;
  * Utility methods to aid testing HTTP.
  * 
  * @author aled
+ *
+ * @deprecated Prefer org.apache.brooklyn.util.http.HttpUtils which has no TestNG dependencies.
  */
+@Deprecated
 public class HttpTestUtils {
 
     // TODO Delete methods from TestUtils, to just have them here (or switch so TestUtils delegates here,

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c316e217/usage/test-support/src/main/java/org/apache/brooklyn/test/TrustingSslSocketFactory.java
----------------------------------------------------------------------
diff --git a/usage/test-support/src/main/java/org/apache/brooklyn/test/TrustingSslSocketFactory.java b/usage/test-support/src/main/java/org/apache/brooklyn/test/TrustingSslSocketFactory.java
deleted file mode 100644
index 58fb76c..0000000
--- a/usage/test-support/src/main/java/org/apache/brooklyn/test/TrustingSslSocketFactory.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 org.apache.brooklyn.test;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.Socket;
-import java.net.URLConnection;
-import java.net.UnknownHostException;
-import java.security.cert.X509Certificate;
-
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Throwables;
-
-// FIXME copied from brooklyn-core because core not visible here
-
-public class TrustingSslSocketFactory extends SSLSocketFactory {
-    
-    private static final Logger logger = LoggerFactory.getLogger(TrustingSslSocketFactory.class);
-
-    private static TrustingSslSocketFactory INSTANCE;
-    public synchronized static TrustingSslSocketFactory getInstance() {
-        if (INSTANCE==null) INSTANCE = new TrustingSslSocketFactory();
-        return INSTANCE;
-    }
-    
-    private static SSLContext sslContext; 
-    static {
-        try {
-            sslContext = SSLContext.getInstance("TLS");
-        } catch (Exception e) {
-            logger.error("Unable to set up SSLContext with TLS. Https activity will likely fail.", e);
-        }
-    }
-
-    /** configures a connection to accept all certificates, if it is for https */
-    public static <T extends URLConnection> T configure(T connection) {
-        if (connection instanceof HttpsURLConnection) {
-            ((HttpsURLConnection)connection).setSSLSocketFactory(getInstance());
-        }
-        return connection;
-    }
-    
-    /** trusts all SSL certificates */
-    public static final TrustManager TRUST_ALL = new X509TrustManager() {
-        public X509Certificate[] getAcceptedIssuers() {
-            return new X509Certificate[0];
-        }
-        @Override
-        public void checkClientTrusted(X509Certificate[] chain, String authType)
-                throws java.security.cert.CertificateException {
-            
-        }
-        @Override
-        public void checkServerTrusted(X509Certificate[] chain, String authType)
-                throws java.security.cert.CertificateException {
-        }
-    };
-
-    // no reason this can't be public, but no reason it should be necessary;
-    // just use getInstance to get the shared INSTANCE
-    protected TrustingSslSocketFactory() {
-        super();
-        try {
-            sslContext.init(null, new TrustManager[] { TRUST_ALL }, null);
-        } catch (Exception e) {
-            throw Throwables.propagate(e);
-        }
-    }
-
-    @Override
-    public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
-        return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
-    }
-
-    @Override
-    public Socket createSocket() throws IOException {
-        return sslContext.getSocketFactory().createSocket();
-    }
-
-    @Override
-    public String[] getDefaultCipherSuites() {
-        return sslContext.getSocketFactory().getDefaultCipherSuites();
-    }
-
-    @Override
-    public String[] getSupportedCipherSuites() {
-        return sslContext.getSocketFactory().getSupportedCipherSuites();
-    }
-
-    @Override
-    public Socket createSocket(String arg0, int arg1) throws IOException, UnknownHostException {
-        return sslContext.getSocketFactory().createSocket(arg0, arg1);
-    }
-
-    @Override
-    public Socket createSocket(InetAddress arg0, int arg1) throws IOException {
-        return sslContext.getSocketFactory().createSocket(arg0, arg1);
-    }
-
-    @Override
-    public Socket createSocket(String arg0, int arg1, InetAddress arg2, int arg3) throws IOException, UnknownHostException {
-        return sslContext.getSocketFactory().createSocket(arg0, arg1, arg2, arg3);
-    }
-
-    @Override
-    public Socket createSocket(InetAddress arg0, int arg1, InetAddress arg2, int arg3) throws IOException {
-        return sslContext.getSocketFactory().createSocket(arg0, arg1, arg2, arg3);
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c316e217/utils/common/src/main/java/org/apache/brooklyn/test/Asserts.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/test/Asserts.java b/utils/common/src/main/java/org/apache/brooklyn/test/Asserts.java
index 0bf6936..678a181 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/test/Asserts.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/test/Asserts.java
@@ -20,6 +20,7 @@ package org.apache.brooklyn.test;
 
 import groovy.lang.Closure;
 
+import java.lang.reflect.Array;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Enumeration;
@@ -52,8 +53,14 @@ import com.google.common.collect.Sets;
  * TODO should move this to new package brooklyn.util.assertions
  * and TODO should add a repeating() method which returns an AssertingRepeater extending Repeater
  * and:
+ * <ul>
  * <li> adds support for requireAllIterationsTrue
  * <li> convenience run methods equivalent to succeedsEventually and succeedsContinually
+ * </ul>
+ * <p>
+ * NOTE Selected routines in this class are originally copied from <a href="http://testng.org">TestNG</a>, to allow us to make assertions without having to
+ * introduce a runtime dependency on TestNG.
+ * </p>
  */
 @Beta
 public class Asserts {
@@ -67,9 +74,608 @@ public class Asserts {
     private static final Logger log = LoggerFactory.getLogger(Asserts.class);
 
     private Asserts() {}
+
+    private static final Character OPENING_CHARACTER = '[';
+    private static final Character CLOSING_CHARACTER = ']';
+
+    private static final String ASSERT_LEFT = "expected " + OPENING_CHARACTER;
+    private static final String ASSERT_MIDDLE = CLOSING_CHARACTER + " but found " + OPENING_CHARACTER;
+    private static final String ASSERT_RIGHT = Character.toString(CLOSING_CHARACTER);
+
+    static String format(Object actual, Object expected, String message) {
+        String formatted = "";
+        if (null != message) {
+            formatted = message + " ";
+        }
+
+        return formatted + ASSERT_LEFT + expected + ASSERT_MIDDLE + actual + ASSERT_RIGHT;
+    }
+
+    static private void failNotEquals(Object actual , Object expected, String message ) {
+        fail(format(actual, expected, message));
+    }
+
+    /**
+     * Assert that an object reference is null.
+     *
+     * @param object The object reference.
+     *
+     * @throws AssertionError if the assertion fails.
+     */
+    static public void assertNull(final Object object) {
+        assertNull(object, null);
+    }
+
+    /**
+     * Assert that an object reference is not null.
+     *
+     * @param object The object reference.
+     *
+     * @throws AssertionError if the assertion fails.
+     */
+    static public void assertNotNull(final Object object) {
+        assertNotNull(object, null);
+    }
+
+    /**
+     * Assert that an object reference is null.
+     *
+     * @param object The object reference.
+     * @param message The assertion error message.
+     *
+     * @throws AssertionError if the assertion fails.
+     */
+    static public void assertNull(final Object object, final String message) {
+        if (null != object) {
+            throw new AssertionError(message == null ? "object reference is not null" : message);
+        }
+    }
+
+    /**
+     * Assert that an object reference is not null.
+     *
+     * @param object The object reference.
+     * @param message The assertion error message.
+     *
+     * @throws AssertionError if the assertion fails.
+     */
+    static public void assertNotNull(final Object object, final String message) {
+        if (null == object) {
+            throw new AssertionError(message == null ? "object reference is null" : message);
+        }
+    }
+
+    /**
+     * Asserts that two collections contain the same elements in the same order. If they do not,
+     * an AssertionError is thrown.
+     *
+     * @param actual the actual value
+     * @param expected the expected value
+     */
+    static public void assertEquals(Collection<?> actual, Collection<?> expected) {
+        assertEquals(actual, expected, null);
+    }
+
+    /**
+     * Asserts that two collections contain the same elements in the same order. If they do not,
+     * an AssertionError, with the given message, is thrown.
+     * @param actual the actual value
+     * @param expected the expected value
+     * @param message the assertion error message
+     */
+    static public void assertEquals(Collection<?> actual, Collection<?> expected, String message) {
+        if(actual == expected) {
+            return;
+        }
+
+        if (actual == null || expected == null) {
+            if (message != null) {
+                fail(message);
+            } else {
+                fail("Collections not equal: expected: " + expected + " and actual: " + actual);
+            }
+        }
+
+        assertEquals(actual.size(), expected.size(), message + ": lists don't have the same size");
+
+        Iterator<?> actIt = actual.iterator();
+        Iterator<?> expIt = expected.iterator();
+        int i = -1;
+        while(actIt.hasNext() && expIt.hasNext()) {
+            i++;
+            Object e = expIt.next();
+            Object a = actIt.next();
+            String explanation = "Lists differ at element [" + i + "]: " + e + " != " + a;
+            String errorMessage = message == null ? explanation : message + ": " + explanation;
+
+            assertEquals(a, e, errorMessage);
+        }
+    }
+
+    /** Asserts that two iterators return the same elements in the same order. If they do not,
+     * an AssertionError is thrown.
+     * Please note that this assert iterates over the elements and modifies the state of the iterators.
+     * @param actual the actual value
+     * @param expected the expected value
+     */
+    static public void assertEquals(Iterator<?> actual, Iterator<?> expected) {
+        assertEquals(actual, expected, null);
+    }
+
+    /** Asserts that two iterators return the same elements in the same order. If they do not,
+     * an AssertionError, with the given message, is thrown.
+     * Please note that this assert iterates over the elements and modifies the state of the iterators.
+     * @param actual the actual value
+     * @param expected the expected value
+     * @param message the assertion error message
+     */
+    static public void assertEquals(Iterator<?> actual, Iterator<?> expected, String message) {
+        if(actual == expected) {
+            return;
+        }
+
+        if(actual == null || expected == null) {
+            if(message != null) {
+                fail(message);
+            } else {
+                fail("Iterators not equal: expected: " + expected + " and actual: " + actual);
+            }
+        }
+
+        int i = -1;
+        while(actual.hasNext() && expected.hasNext()) {
+
+            i++;
+            Object e = expected.next();
+            Object a = actual.next();
+            String explanation = "Iterators differ at element [" + i + "]: " + e + " != " + a;
+            String errorMessage = message == null ? explanation : message + ": " + explanation;
+
+            assertEquals(a, e, errorMessage);
+
+        }
+
+        if(actual.hasNext()) {
+
+            String explanation = "Actual iterator returned more elements than the expected iterator.";
+            String errorMessage = message == null ? explanation : message + ": " + explanation;
+            fail(errorMessage);
+
+        } else if(expected.hasNext()) {
+
+            String explanation = "Expected iterator returned more elements than the actual iterator.";
+            String errorMessage = message == null ? explanation : message + ": " + explanation;
+            fail(errorMessage);
+
+        }
+
+    }
+
+    /** Asserts that two iterables return iterators with the same elements in the same order. If they do not,
+     * an AssertionError is thrown.
+     * @param actual the actual value
+     * @param expected the expected value
+     */
+    static public void assertEquals(Iterable<?> actual, Iterable<?> expected) {
+        assertEquals(actual, expected, null);
+    }
+
+    /** Asserts that two iterables return iterators with the same elements in the same order. If they do not,
+     * an AssertionError, with the given message, is thrown.
+     * @param actual the actual value
+     * @param expected the expected value
+     * @param message the assertion error message
+     */
+    static public void assertEquals(Iterable<?> actual, Iterable<?> expected, String message) {
+        if(actual == expected) {
+            return;
+        }
+
+        if(actual == null || expected == null) {
+            if(message != null) {
+                fail(message);
+            } else {
+                fail("Iterables not equal: expected: " + expected + " and actual: " + actual);
+            }
+        }
+
+        Iterator<?> actIt = actual.iterator();
+        Iterator<?> expIt = expected.iterator();
+
+        assertEquals(actIt, expIt, message);
+    }
+
+
+
+    /**
+     * Asserts that two sets are equal.
+     */
+    static public void assertEquals(Set<?> actual, Set<?> expected) {
+        assertEquals(actual, expected, null);
+    }
+
+    /**
+     * Assert set equals
+     */
+    static public void assertEquals(Set<?> actual, Set<?> expected, String message) {
+        if (actual == expected) {
+            return;
+        }
+
+        if (actual == null || expected == null) {
+            // Keep the back compatible
+            if (message == null) {
+                fail("Sets not equal: expected: " + expected + " and actual: " + actual);
+            } else {
+                failNotEquals(actual, expected, message);
+            }
+        }
+
+        if (!actual.equals(expected)) {
+            if (message == null) {
+                fail("Sets differ: expected " + expected + " but got " + actual);
+            } else {
+                failNotEquals(actual, expected, message);
+            }
+        }
+    }
+
+    /**
+     * Asserts that two maps are equal.
+     */
+    static public void assertEquals(Map<?, ?> actual, Map<?, ?> expected) {
+        if (actual == expected) {
+            return;
+        }
+
+        if (actual == null || expected == null) {
+            fail("Maps not equal: expected: " + expected + " and actual: " + actual);
+        }
+
+        if (actual.size() != expected.size()) {
+            fail("Maps do not have the same size:" + actual.size() + " != " + expected.size());
+        }
+
+        Set<?> entrySet = actual.entrySet();
+        for (Iterator<?> iterator = entrySet.iterator(); iterator.hasNext();) {
+            Map.Entry<?, ?> entry = (Map.Entry<?, ?>) iterator.next();
+            Object key = entry.getKey();
+            Object value = entry.getValue();
+            Object expectedValue = expected.get(key);
+            assertEquals(value, expectedValue, "Maps do not match for key:" + key + " actual:" + value
+                    + " expected:" + expectedValue);
+        }
+
+    }
+
+
+    /**
+     * Asserts that two arrays contain the same elements in the same order. If they do not,
+     * an AssertionError, with the given message, is thrown.
+     * @param actual the actual value
+     * @param expected the expected value
+     * @param message the assertion error message
+     */
+    static public void assertEquals(Object[] actual, Object[] expected, String message) {
+        if(actual == expected) {
+            return;
+        }
+
+        if ((actual == null && expected != null) || (actual != null && expected == null)) {
+            if (message != null) {
+                fail(message);
+            } else {
+                fail("Arrays not equal: " + Arrays.toString(expected) + " and " + Arrays.toString(actual));
+            }
+        }
+        assertEquals(Arrays.asList(actual), Arrays.asList(expected), message);
+    }
+
+    /**
+     * Asserts that two arrays contain the same elements in the same order. If they do not,
+     * an AssertionError is thrown.
+     *
+     * @param actual the actual value
+     * @param expected the expected value
+     */
+    static public void assertEquals(Object[] actual, Object[] expected) {
+        assertEquals(actual, expected, null);
+    }
+
+    /**
+     * Asserts that two objects are equal. 
+     * @param actual the actual value
+     * @param expected the expected value
+     *                 
+     * @throws AssertionError if the values are not equal.
+     */
+    static public void assertEquals(Object actual, Object expected) {
+        assertEquals(actual, expected, null);
+    }
     
-    // --- selected routines from testng.Assert for visibility without needing that package
-    
+    /**
+     * Asserts that two objects are equal. 
+     * 
+     * @param actual the actual value
+     * @param expected the expected value
+     * @param message the assertion error message
+     *
+     * @throws AssertionError if the values are not equal.
+     */
+    static public void assertEquals(Object actual, Object expected, String message) {
+        if((expected == null) && (actual == null)) {
+            return;
+        }
+        if(expected != null) {
+            if (expected.getClass().isArray()) {
+                assertArrayEquals(actual, expected, message);
+                return;
+            } else if (expected.equals(actual)) {
+                return;
+            }
+        }
+        failNotEquals(actual, expected, message);
+    }
+
+
+    /**
+     * Asserts that two objects are equal. It they are not, an AssertionError,
+     * with given message, is thrown.
+     * @param actual the actual value
+     * @param expected the expected value (should be an non-null array value)
+     * @param message the assertion error message
+     */
+    private static void assertArrayEquals(Object actual, Object expected, String message) {
+        //is called only when expected is an array
+        if (actual.getClass().isArray()) {
+            int expectedLength = Array.getLength(expected);
+            if (expectedLength == Array.getLength(actual)) {
+                for (int i = 0 ; i < expectedLength ; i++) {
+                    Object _actual = Array.get(actual, i);
+                    Object _expected = Array.get(expected, i);
+                    try {
+                        assertEquals(_actual, _expected);
+                    } catch (AssertionError ae) {
+                        failNotEquals(actual, expected, message == null ? "" : message
+                                + " (values at index " + i + " are not the same)");
+                    }
+                }
+                //array values matched
+                return;
+            } else {
+                failNotEquals(Array.getLength(actual), expectedLength, message == null ? "" : message
+                        + " (Array lengths are not the same)");
+            }
+        }
+        failNotEquals(actual, expected, message);
+    }
+
+
+    /**
+     * Asserts that two Strings are equal. If they are not,
+     * an AssertionError, with the given message, is thrown.
+     * @param actual the actual value
+     * @param expected the expected value
+     * @param message the assertion error message
+     */
+    static public void assertEquals(String actual, String expected, String message) {
+        assertEquals((Object) actual, (Object) expected, message);
+    }
+
+    /**
+     * Asserts that two Strings are equal. If they are not,
+     * an AssertionError is thrown.
+     * @param actual the actual value
+     * @param expected the expected value
+     */
+    static public void assertEquals(String actual, String expected) {
+        assertEquals(actual, expected, null);
+    }
+
+    /**
+     * Asserts that two doubles are equal within a delta.  If they are not,
+     * an AssertionError, with the given message, is thrown.  If the expected
+     * value is infinity then the delta value is ignored.
+     * @param actual the actual value
+     * @param expected the expected value
+     * @param delta the absolute tolerable difference between the actual and expected values
+     * @param message the assertion error message
+     */
+    static public void assertEquals(double actual, double expected, double delta, String message) {
+        // handle infinity specially since subtracting to infinite values gives NaN and the
+        // the following test fails
+        if(Double.isInfinite(expected)) {
+            if(!(expected == actual)) {
+                failNotEquals(new Double(actual), new Double(expected), message);
+            }
+        }
+        else if(!(Math.abs(expected - actual) <= delta)) { // Because comparison with NaN always returns false
+            failNotEquals(new Double(actual), new Double(expected), message);
+        }
+    }
+
+    /**
+     * Asserts that two doubles are equal within a delta. If they are not,
+     * an AssertionError is thrown. If the expected value is infinity then the
+     * delta value is ignored.
+     * @param actual the actual value
+     * @param expected the expected value
+     * @param delta the absolute tolerable difference between the actual and expected values
+     */
+    static public void assertEquals(double actual, double expected, double delta) {
+        assertEquals(actual, expected, delta, null);
+    }
+
+    /**
+     * Asserts that two floats are equal within a delta. If they are not,
+     * an AssertionError, with the given message, is thrown.  If the expected
+     * value is infinity then the delta value is ignored.
+     * @param actual the actual value
+     * @param expected the expected value
+     * @param delta the absolute tolerable difference between the actual and expected values
+     * @param message the assertion error message
+     */
+    static public void assertEquals(float actual, float expected, float delta, String message) {
+        // handle infinity specially since subtracting to infinite values gives NaN and the
+        // the following test fails
+        if(Float.isInfinite(expected)) {
+            if(!(expected == actual)) {
+                failNotEquals(new Float(actual), new Float(expected), message);
+            }
+        }
+        else if(!(Math.abs(expected - actual) <= delta)) {
+            failNotEquals(new Float(actual), new Float(expected), message);
+        }
+    }
+
+    /**
+     * Asserts that two floats are equal within a delta. If they are not,
+     * an AssertionError is thrown. If the expected
+     * value is infinity then the delta value is ignored.
+     * @param actual the actual value
+     * @param expected the expected value
+     * @param delta the absolute tolerable difference between the actual and expected values
+     */
+    static public void assertEquals(float actual, float expected, float delta) {
+        assertEquals(actual, expected, delta, null);
+    }
+
+    /**
+     * Asserts that two longs are equal. If they are not,
+     * an AssertionError, with the given message, is thrown.
+     * @param actual the actual value
+     * @param expected the expected value
+     * @param message the assertion error message
+     */
+    static public void assertEquals(long actual, long expected, String message) {
+        assertEquals(Long.valueOf(actual), Long.valueOf(expected), message);
+    }
+
+    /**
+     * Asserts that two longs are equal. If they are not,
+     * an AssertionError is thrown.
+     * @param actual the actual value
+     * @param expected the expected value
+     */
+    static public void assertEquals(long actual, long expected) {
+        assertEquals(actual, expected, null);
+    }
+
+    /**
+     * Asserts that two booleans are equal. If they are not,
+     * an AssertionError, with the given message, is thrown.
+     * @param actual the actual value
+     * @param expected the expected value
+     * @param message the assertion error message
+     */
+    static public void assertEquals(boolean actual, boolean expected, String message) {
+        assertEquals( Boolean.valueOf(actual), Boolean.valueOf(expected), message);
+    }
+
+    /**
+     * Asserts that two booleans are equal. If they are not,
+     * an AssertionError is thrown.
+     * @param actual the actual value
+     * @param expected the expected value
+     */
+    static public void assertEquals(boolean actual, boolean expected) {
+        assertEquals(actual, expected, null);
+    }
+
+    /**
+     * Asserts that two bytes are equal. If they are not,
+     * an AssertionError, with the given message, is thrown.
+     * @param actual the actual value
+     * @param expected the expected value
+     * @param message the assertion error message
+     */
+    static public void assertEquals(byte actual, byte expected, String message) {
+        assertEquals(Byte.valueOf(actual), Byte.valueOf(expected), message);
+    }
+
+    /**
+     * Asserts that two bytes are equal. If they are not,
+     * an AssertionError is thrown.
+     * @param actual the actual value
+     * @param expected the expected value
+     */
+    static public void assertEquals(byte actual, byte expected) {
+        assertEquals(actual, expected, null);
+    }
+
+    /**
+     * Asserts that two chars are equal. If they are not,
+     * an AssertionFailedError, with the given message, is thrown.
+     * @param actual the actual value
+     * @param expected the expected value
+     * @param message the assertion error message
+     */
+    static public void assertEquals(char actual, char expected, String message) {
+        assertEquals(Character.valueOf(actual), Character.valueOf(expected), message);
+    }
+
+    /**
+     * Asserts that two chars are equal. If they are not,
+     * an AssertionError is thrown.
+     * @param actual the actual value
+     * @param expected the expected value
+     */
+    static public void assertEquals(char actual, char expected) {
+        assertEquals(actual, expected, null);
+    }
+
+    /**
+     * Asserts that two shorts are equal. If they are not,
+     * an AssertionFailedError, with the given message, is thrown.
+     * @param actual the actual value
+     * @param expected the expected value
+     * @param message the assertion error message
+     */
+    static public void assertEquals(short actual, short expected, String message) {
+        assertEquals(Short.valueOf(actual), Short.valueOf(expected), message);
+    }
+
+    /**
+     * Asserts that two shorts are equal. If they are not,
+     * an AssertionError is thrown.
+     * @param actual the actual value
+     * @param expected the expected value
+     */
+    static public void assertEquals(short actual, short expected) {
+        assertEquals(actual, expected, null);
+    }
+
+    /**
+     * Asserts that two ints are equal. If they are not,
+     * an AssertionFailedError, with the given message, is thrown.
+     * @param actual the actual value
+     * @param expected the expected value
+     * @param message the assertion error message
+     */
+    static public void assertEquals(int actual,  int expected, String message) {
+        assertEquals(Integer.valueOf(actual), Integer.valueOf(expected), message);
+    }
+
+    /**
+     * Asserts that two ints are equal. If they are not,
+     * an AssertionError is thrown.
+     * @param actual the actual value
+     * @param expected the expected value
+     */
+    static public void assertEquals(int actual, int expected) {
+        assertEquals(actual, expected, null);
+    }
+
+
+
+    /**
+     * Asserts that a condition is true. If it isn't, an AssertionError is thrown.
+     * @param condition the condition to evaluate
+     */
+    public static void assertTrue(boolean condition) {
+        if (!condition) fail(null);
+    }
+
     /**
      * Asserts that a condition is true. If it isn't,
      * an AssertionError, with the given message, is thrown.
@@ -214,7 +820,7 @@ public class Asserts {
     /**
      * Convenience method for cases where we need to test until something is true.
      *
-     * The runnable will be invoked periodically until it succesfully concludes.
+     * The Callable will be invoked periodically until it succesfully concludes.
      * <p>
      * The following flags are supported:
      * <ul>
@@ -233,8 +839,7 @@ public class Asserts {
      * </ul>
      * 
      * @param flags, accepts the flags listed above
-     * @param r
-     * @param finallyBlock
+     * @param c The callable to invoke
      */
     public static <T> T succeedsEventually(Map<String,?> flags, Callable<T> c) {
         boolean abortOnException = get(flags, "abortOnException", false);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c316e217/utils/common/src/main/java/org/apache/brooklyn/util/http/HttpUtils.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/http/HttpUtils.java b/utils/common/src/main/java/org/apache/brooklyn/util/http/HttpUtils.java
new file mode 100644
index 0000000..8eeef19
--- /dev/null
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/http/HttpUtils.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.util.http;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLSession;
+
+import org.apache.brooklyn.test.Asserts;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.crypto.SslTrustUtils;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.stream.Streams;
+import org.apache.brooklyn.util.time.Time;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Throwables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+
+/**
+ * Utility methods to aid testing HTTP.
+ * 
+ * @author aled
+ */
+public class HttpUtils {
+
+    // TODO Delete methods from TestUtils, to just have them here (or switch so TestUtils delegates here,
+    // and deprecate methods in TestUtils until deleted).
+
+    private static final Logger LOG = LoggerFactory.getLogger(HttpUtils.class);
+
+    static final ExecutorService executor = Executors.newCachedThreadPool();
+    
+    /**
+     * Connects to the given url and returns the connection.
+     * Caller should {@code connection.getInputStream().close()} the result of this
+     * (especially if they are making heavy use of this method).
+     */
+    public static URLConnection connectToUrl(String u) throws Exception {
+        final URL url = new URL(u);
+        final AtomicReference<Exception> exception = new AtomicReference<Exception>();
+        
+        // sometimes openConnection hangs, so run in background
+        Future<URLConnection> f = executor.submit(new Callable<URLConnection>() {
+            public URLConnection call() {
+                try {
+                    HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
+                        @Override public boolean verify(String s, SSLSession sslSession) {
+                            return true;
+                        }
+                    });
+                    URLConnection connection = url.openConnection();
+                    TrustingSslSocketFactory.configure(connection);
+                    connection.connect();
+    
+                    connection.getContentLength(); // Make sure the connection is made.
+                    return connection;
+                } catch (Exception e) {
+                    exception.set(e);
+                    LOG.debug("Error connecting to url "+url+" (propagating): "+e, e);
+                }
+                return null;
+            }
+        });
+        try {
+            URLConnection result = null;
+            try {
+                result = f.get(60, TimeUnit.SECONDS);
+            } catch (InterruptedException e) {
+                throw e;
+            } catch (Exception e) {
+                LOG.debug("Error connecting to url "+url+", probably timed out (rethrowing): "+e);
+                throw new IllegalStateException("Connect to URL not complete within 60 seconds, for url "+url+": "+e);
+            }
+            if (exception.get() != null) {
+                LOG.debug("Error connecting to url "+url+", thread caller of "+exception, new Throwable("source of rethrown error "+exception));
+                throw exception.get();
+            } else {
+                return result;
+            }
+        } finally {
+            f.cancel(true);
+        }
+    }
+
+    public static void assertHealthyStatusCode(int code) {
+        if (code>=200 && code<=299) return;
+        Asserts.fail("Wrong status code: " + code);
+    }
+    
+    public static int getHttpStatusCode(String url) throws Exception {
+        URLConnection connection = connectToUrl(url);
+        long startTime = System.currentTimeMillis();
+        int status = ((HttpURLConnection) connection).getResponseCode();
+        
+        // read fully if possible, then close everything, trying to prevent cached threads at server
+        consumeAndCloseQuietly((HttpURLConnection) connection);
+        
+        if (LOG.isDebugEnabled())
+            LOG.debug("connection to {} ({}ms) gives {}", new Object[] { url, (System.currentTimeMillis()-startTime), status });
+        return status;
+    }
+
+    /**
+     * Asserts that gets back any "valid" response - i.e. not an exception. This could be an unauthorized,
+     * a redirect, a 404, or anything else that implies there is web-server listening on that port.
+     */
+    public static void assertUrlReachable(String url) {
+        try {
+            getHttpStatusCode(url);
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+            throw new RuntimeException("Interrupted for "+url+" (in assertion that is reachable)", e);
+        } catch (Exception e) {
+            throw new IllegalStateException("Server at "+url+" Asserts.failed to respond (in assertion that is reachable): "+e, e);
+        }
+    }
+
+    public static void assertUrlUnreachable(String url) {
+        try {
+            int statusCode = getHttpStatusCode(url);
+            Asserts.fail("Expected url " + url + " unreachable, but got status code " + statusCode);
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+            throw new RuntimeException("Interrupted for "+url+" (in assertion that unreachable)", e);
+        } catch (Exception e) {
+            IOException cause = Exceptions.getFirstThrowableOfType(e, IOException.class);
+            if (cause != null) {
+                // success; clean shutdown transitioning from 400 to error
+            } else {
+                Throwables.propagate(e);
+            }                        
+        }
+    }
+
+    public static void assertUrlUnreachableEventually(final String url) {
+        assertUrlUnreachableEventually(Maps.newLinkedHashMap(), url);
+    }
+    
+    public static void assertUrlUnreachableEventually(Map flags, final String url) {
+        Asserts.succeedsEventually(flags, new Runnable() {
+            public void run() {
+                assertUrlUnreachable(url);
+            }
+         });
+    }
+
+    public static void assertHttpStatusCodeEquals(String url, int... acceptableReturnCodes) {
+        List<Integer> acceptableCodes = Lists.newArrayList();
+        for (int code : acceptableReturnCodes) {
+            acceptableCodes.add((Integer)code);
+        }
+        try {
+            int actualCode = getHttpStatusCode(url);
+            Asserts.assertTrue(acceptableCodes.contains(actualCode), "code=" + actualCode + "; expected=" + acceptableCodes + "; url=" + url);
+            
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+            throw new RuntimeException("Interrupted for "+url+" (in assertion that result code is "+acceptableCodes+")", e);
+        } catch (Exception e) {
+            throw new IllegalStateException("Server at "+url+" Asserts.failed to respond (in assertion that result code is "+acceptableCodes+"): "+e, e);
+        }
+    }
+
+    public static void assertHttpStatusCodeEventuallyEquals(final String url, final int expectedCode) {
+        assertHttpStatusCodeEventuallyEquals(Maps.newLinkedHashMap(),  url, expectedCode);
+    }
+
+    public static void assertHttpStatusCodeEventuallyEquals(Map flags, final String url, final int expectedCode) {
+        Asserts.succeedsEventually(flags, new Runnable() {
+            public void run() {
+                assertHttpStatusCodeEquals(url, expectedCode);
+            }
+         });
+    }
+
+    public static void assertContentContainsText(final String url, final String phrase, final String ...additionalPhrases) {
+        try {
+            String contents = getContent(url);
+            Asserts.assertTrue(contents != null && contents.length() > 0);
+            for (String text: Lists.asList(phrase, additionalPhrases)) {
+                if (!contents.contains(text)) {
+                    LOG.warn("CONTENTS OF URL "+url+" MISSING TEXT: "+text+"\n"+contents);
+                    Asserts.fail("URL "+url+" does not contain text: "+text);
+                }
+            }
+        } catch (Exception e) {
+            throw Throwables.propagate(e);
+        }
+    }
+
+    public static void assertContentNotContainsText(final String url, final String phrase, final String ...additionalPhrases) {
+        try {
+            String contents = getContent(url);
+            Asserts.assertTrue(contents != null);
+            for (String text: Lists.asList(phrase, additionalPhrases)) {
+                if (contents.contains(text)) {
+                    LOG.warn("CONTENTS OF URL "+url+" HAS TEXT: "+text+"\n"+contents);
+                    Asserts.fail("URL "+url+" contain text: "+text);
+                }
+            }
+        } catch (Exception e) {
+            throw Throwables.propagate(e);
+        }
+    }
+
+    public static void assertErrorContentContainsText(final String url, final String phrase, final String ...additionalPhrases) {
+        try {
+            String contents = getErrorContent(url);
+            Asserts.assertTrue(contents != null && contents.length() > 0);
+            for (String text: Lists.asList(phrase, additionalPhrases)) {
+                if (!contents.contains(text)) {
+                    LOG.warn("CONTENTS OF URL "+url+" MISSING TEXT: "+text+"\n"+contents);
+                    Asserts.fail("URL "+url+" does not contain text: "+text);
+                }
+            }
+        } catch (Exception e) {
+            throw Throwables.propagate(e);
+        }
+    }
+
+
+    public static void assertErrorContentNotContainsText(final String url, final String phrase, final String ...additionalPhrases) {
+        try {
+            String err = getErrorContent(url);
+            Asserts.assertTrue(err != null);
+            for (String text: Lists.asList(phrase, additionalPhrases)) {
+                if (err.contains(text)) {
+                    LOG.warn("CONTENTS OF URL "+url+" HAS TEXT: "+text+"\n"+err);
+                    Asserts.fail("URL "+url+" contain text: "+text);
+                }
+            }
+        } catch (Exception e) {
+            throw Throwables.propagate(e);
+        }
+    }
+    
+    public static void assertContentEventuallyContainsText(final String url, final String phrase, final String ...additionalPhrases) {
+        assertContentEventuallyContainsText(MutableMap.of(), url, phrase, additionalPhrases);
+    }
+    
+    public static void assertContentEventuallyContainsText(Map flags, final String url, final String phrase, final String ...additionalPhrases) {
+        Asserts.succeedsEventually(flags, new Runnable() {
+            public void run() {
+                assertContentContainsText(url, phrase, additionalPhrases);
+            }
+         });
+    }
+    
+    public static void assertContentMatches(String url, String regex) {
+        String contents = getContent(url);
+        Asserts.assertNotNull(contents);
+        Asserts.assertTrue(contents.matches(regex), "Contents does not match expected regex ("+regex+"): "+contents);
+    }
+
+    public static void assertContentEventuallyMatches(final String url, final String regex) {
+        Asserts.succeedsEventually(new Runnable() {
+            @Override
+            public void run() {
+                assertContentMatches(url, regex);
+            }
+        });
+    }
+    
+    public static String getErrorContent(String url) {
+        try {
+            HttpURLConnection connection = (HttpURLConnection) connectToUrl(url);
+            long startTime = System.currentTimeMillis();
+            
+            String err;
+            int status;
+            try {
+                InputStream errStream = connection.getErrorStream();
+                err = Streams.readFullyString(errStream);
+                status = connection.getResponseCode();
+            } finally {
+                closeQuietly(connection);
+            }
+            
+            if (LOG.isDebugEnabled())
+                LOG.debug("read of err {} ({}ms) complete; http code {}", new Object[] { url, Time.makeTimeStringRounded(System.currentTimeMillis()-startTime), status});
+            return err;
+
+        } catch (Exception e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+    
+    public static String getContent(String url) {
+        try {
+            return Streams.readFullyString(SslTrustUtils.trustAll(new URL(url).openConnection()).getInputStream());
+        } catch (Exception e) {
+            throw Throwables.propagate(e);
+        }
+    }
+
+    /**
+     * Schedules (with the given executor) a poller that repeatedly accesses the given url, to confirm it always gives
+     * back the expected status code.
+     * 
+     * Expected usage is to query the future, such as:
+     * 
+     * <pre>
+     * {@code
+     * Future<?> future = assertAsyncHttpStatusCodeContinuallyEquals(executor, url, 200);
+     * // do other stuff...
+     * if (future.isDone()) future.get(); // get exception if it's Asserts.failed
+     * }
+     * </pre>
+     * 
+     * For stopping it, you can either do future.cancel(true), or you can just do executor.shutdownNow().
+     * 
+     * TODO Look at difference between this and WebAppMonitor, to decide if this should be kept.
+     */
+    public static ListenableFuture<?> assertAsyncHttpStatusCodeContinuallyEquals(ListeningExecutorService executor, final String url, final int expectedStatusCode) {
+        return executor.submit(new Runnable() {
+            @Override public void run() {
+                // TODO Need to drop logging; remove sleep when that's done.
+                while (!Thread.currentThread().isInterrupted()) {
+                    assertHttpStatusCodeEquals(url, expectedStatusCode);
+                    try {
+                        Thread.sleep(1000);
+                    } catch (InterruptedException e) {
+                        return; // graceful return
+                    }
+                }
+            }
+        });
+    }
+    
+    /**
+     * Consumes the input stream entirely and then cleanly closes the connection.
+     * Ignores all exceptions completely, not even logging them!
+     * 
+     * Consuming the stream fully is useful for preventing idle TCP connections.
+     * @see <a href="http://docs.oracle.com/javase/8/docs/technotes/guides/net/http-keepalive.html">Persistent Connections</a>
+     */
+    public static void consumeAndCloseQuietly(HttpURLConnection connection) {
+        try { Streams.readFully(connection.getInputStream()); } catch (Exception e) {}
+        closeQuietly(connection);
+    }
+    
+    /**
+     * Closes all streams of the connection, and disconnects it. Ignores all exceptions completely,
+     * not even logging them!
+     */
+    public static void closeQuietly(HttpURLConnection connection) {
+        try { connection.disconnect(); } catch (Exception e) {}
+        try { connection.getInputStream().close(); } catch (Exception e) {}
+        try { connection.getOutputStream().close(); } catch (Exception e) {}
+        try { connection.getErrorStream().close(); } catch (Exception e) {}
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c316e217/utils/common/src/main/java/org/apache/brooklyn/util/http/TrustingSslSocketFactory.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/http/TrustingSslSocketFactory.java b/utils/common/src/main/java/org/apache/brooklyn/util/http/TrustingSslSocketFactory.java
new file mode 100644
index 0000000..41b753a
--- /dev/null
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/http/TrustingSslSocketFactory.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.util.http;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.URLConnection;
+import java.net.UnknownHostException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Throwables;
+
+// FIXME copied from brooklyn-core because core not visible here
+
+public class TrustingSslSocketFactory extends SSLSocketFactory {
+    
+    private static final Logger logger = LoggerFactory.getLogger(TrustingSslSocketFactory.class);
+
+    private static TrustingSslSocketFactory INSTANCE;
+    public synchronized static TrustingSslSocketFactory getInstance() {
+        if (INSTANCE==null) INSTANCE = new TrustingSslSocketFactory();
+        return INSTANCE;
+    }
+    
+    private static SSLContext sslContext; 
+    static {
+        try {
+            sslContext = SSLContext.getInstance("TLS");
+        } catch (Exception e) {
+            logger.error("Unable to set up SSLContext with TLS. Https activity will likely fail.", e);
+        }
+    }
+
+    /** configures a connection to accept all certificates, if it is for https */
+    public static <T extends URLConnection> T configure(T connection) {
+        if (connection instanceof HttpsURLConnection) {
+            ((HttpsURLConnection)connection).setSSLSocketFactory(getInstance());
+        }
+        return connection;
+    }
+    
+    /** trusts all SSL certificates */
+    public static final TrustManager TRUST_ALL = new X509TrustManager() {
+        public X509Certificate[] getAcceptedIssuers() {
+            return new X509Certificate[0];
+        }
+        @Override
+        public void checkClientTrusted(X509Certificate[] chain, String authType)
+                throws java.security.cert.CertificateException {
+            
+        }
+        @Override
+        public void checkServerTrusted(X509Certificate[] chain, String authType)
+                throws java.security.cert.CertificateException {
+        }
+    };
+
+    // no reason this can't be public, but no reason it should be necessary;
+    // just use getInstance to get the shared INSTANCE
+    protected TrustingSslSocketFactory() {
+        super();
+        try {
+            sslContext.init(null, new TrustManager[] { TRUST_ALL }, null);
+        } catch (Exception e) {
+            throw Throwables.propagate(e);
+        }
+    }
+
+    @Override
+    public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
+        return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
+    }
+
+    @Override
+    public Socket createSocket() throws IOException {
+        return sslContext.getSocketFactory().createSocket();
+    }
+
+    @Override
+    public String[] getDefaultCipherSuites() {
+        return sslContext.getSocketFactory().getDefaultCipherSuites();
+    }
+
+    @Override
+    public String[] getSupportedCipherSuites() {
+        return sslContext.getSocketFactory().getSupportedCipherSuites();
+    }
+
+    @Override
+    public Socket createSocket(String arg0, int arg1) throws IOException, UnknownHostException {
+        return sslContext.getSocketFactory().createSocket(arg0, arg1);
+    }
+
+    @Override
+    public Socket createSocket(InetAddress arg0, int arg1) throws IOException {
+        return sslContext.getSocketFactory().createSocket(arg0, arg1);
+    }
+
+    @Override
+    public Socket createSocket(String arg0, int arg1, InetAddress arg2, int arg3) throws IOException, UnknownHostException {
+        return sslContext.getSocketFactory().createSocket(arg0, arg1, arg2, arg3);
+    }
+
+    @Override
+    public Socket createSocket(InetAddress arg0, int arg1, InetAddress arg2, int arg3) throws IOException {
+        return sslContext.getSocketFactory().createSocket(arg0, arg1, arg2, arg3);
+    }
+}
\ No newline at end of file


Mime
View raw message