ResourcePredicates.urlExists()

Adds a predicate that is true if a resource is available via a
configurable context object. ConfigConstraints looks for instances of the
Brooklyn-object-aware predicate and calls apply(T, BrooklynObject) if
possible.

Requires non-deployment management contexts to return useful entitlement
and OSGi managers.

Rework contextual predicates

Context must be passed to apply, not set as a field on the predicate.


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

Branch: refs/heads/master
Commit: 60d85fa41f566785663c45948d7a01612d3e92d5
Parents: 7a728b4
Author: Sam Corbett <[email protected]>
Authored: Fri Sep 11 17:14:17 2015 +0100
Committer: Sam Corbett <[email protected]>
Committed: Thu Oct 8 17:54:39 2015 +0100

----------------------------------------------------------------------
 .../brooklyn/core/config/ConfigConstraints.java | 17 ++++--
 .../NonDeploymentManagementContext.java         | 18 +++---
 .../core/objs/BrooklynObjectPredicate.java      | 33 +++++++++++
 .../brooklyn/util/core/ResourcePredicates.java  | 61 ++++++++++++++++++++
 .../core/config/ConfigKeyConstraintTest.java    | 55 +++++++++++++++---
 .../util/guava/PredicateWithContext.java        | 33 +++++++++++
 6 files changed, 197 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/60d85fa4/core/src/main/java/org/apache/brooklyn/core/config/ConfigConstraints.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/config/ConfigConstraints.java 
b/core/src/main/java/org/apache/brooklyn/core/config/ConfigConstraints.java
index 24142a5..6c6445f 100644
--- a/core/src/main/java/org/apache/brooklyn/core/config/ConfigConstraints.java
+++ b/core/src/main/java/org/apache/brooklyn/core/config/ConfigConstraints.java
@@ -27,6 +27,7 @@ import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.api.objs.EntityAdjunct;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.objs.AbstractEntityAdjunct;
+import org.apache.brooklyn.core.objs.BrooklynObjectPredicate;
 import org.apache.brooklyn.core.objs.BrooklynObjectInternal;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -44,8 +45,8 @@ public abstract class ConfigConstraints<T extends 
BrooklynObject> {
     /**
      * Checks all constraints of all config keys available to an entity.
      * <p>
-     * If a constraint is a {@link BrooklynObjectAwarePredicate} then it will 
be
-     * informed of the entity before the predicate is tested.
+     * If a constraint is a {@link BrooklynObjectPredicate} then
+     * {@link BrooklynObjectPredicate#apply(Object, BrooklynObject)} will be 
used.
      */
     public static void assertValid(Entity entity) {
         Iterable<ConfigKey<?>> violations = new 
EntityConfigConstraints(entity).getViolations();
@@ -57,8 +58,8 @@ public abstract class ConfigConstraints<T extends 
BrooklynObject> {
     /**
      * Checks all constraints of all config keys available to an entity 
adjunct.
      * <p>
-     * If a constraint is a {@link BrooklynObjectAwarePredicate} then it will 
be
-     * informed of the adjunct before the predicate is tested.
+     * If a constraint is a {@link BrooklynObjectPredicate} then
+     * {@link BrooklynObjectPredicate#apply(Object, BrooklynObject)} will be 
used.
      */
     public static void assertValid(EntityAdjunct adjunct) {
         Iterable<ConfigKey<?>> violations = new 
EntityAdjunctConstraints(adjunct).getViolations();
@@ -114,7 +115,13 @@ public abstract class ConfigConstraints<T extends 
BrooklynObject> {
                 // keep its type to Predicte<? super T>, where T is 
ConfigKey<T>.
                 try {
                     Predicate<Object> po = (Predicate<Object>) 
configKey.getConstraint();
-                    if (!po.apply(value)) {
+                    boolean isValid;
+                    if (po instanceof BrooklynObjectPredicate) {
+                        isValid = 
BrooklynObjectPredicate.class.cast(po).apply(value, brooklynObject);
+                    } else {
+                        isValid = po.apply(value);
+                    }
+                    if (!isValid) {
                         violating.add(configKey);
                     }
                 } catch (Exception e) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/60d85fa4/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/NonDeploymentManagementContext.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/NonDeploymentManagementContext.java
 
b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/NonDeploymentManagementContext.java
index 1f62add..5223cf8 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/NonDeploymentManagementContext.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/NonDeploymentManagementContext.java
@@ -102,7 +102,6 @@ public class NonDeploymentManagementContext implements 
ManagementContextInternal
     private NonDeploymentLocationManager locationManager;
     private NonDeploymentAccessManager accessManager;
     private NonDeploymentUsageManager usageManager;
-    private EntitlementManager entitlementManager;;
 
     public NonDeploymentManagementContext(AbstractEntity entity, 
NonDeploymentManagementContextMode mode) {
         this.entity = checkNotNull(entity, "entity");
@@ -113,10 +112,6 @@ public class NonDeploymentManagementContext implements 
ManagementContextInternal
         locationManager = new NonDeploymentLocationManager(null);
         accessManager = new NonDeploymentAccessManager(null);
         usageManager = new NonDeploymentUsageManager(null);
-        
-        // TODO might need to be some kind of "system" which can see that the 
system is running at this point
-        // though quite possibly we are entirely behind the auth-wall at this 
point
-        entitlementManager = Entitlements.minimal();
     }
 
     @Override
@@ -213,7 +208,15 @@ public class NonDeploymentManagementContext implements 
ManagementContextInternal
     
     @Override
     public Maybe<OsgiManager> getOsgiManager() {
-        return Maybe.absent();
+        switch (mode) {
+        case PRE_MANAGEMENT:
+        case MANAGEMENT_STARTING:
+        case MANAGEMENT_STARTED:
+            checkInitialManagementContextReal();
+            return initialManagementContext.getOsgiManager();
+        default:
+            return Maybe.absent("Entity " + entity + " is no longer managed; 
OSGi context no longer available");
+        }
     }
 
     @Override
@@ -335,7 +338,8 @@ public class NonDeploymentManagementContext implements 
ManagementContextInternal
     
     @Override
     public EntitlementManager getEntitlementManager() {
-        return entitlementManager;
+        checkInitialManagementContextReal();
+        return initialManagementContext.getEntitlementManager();
     }
     
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/60d85fa4/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynObjectPredicate.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynObjectPredicate.java 
b/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynObjectPredicate.java
new file mode 100644
index 0000000..422e9f8
--- /dev/null
+++ 
b/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynObjectPredicate.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES 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.objs;
+
+import org.apache.brooklyn.api.objs.BrooklynObject;
+import org.apache.brooklyn.util.guava.PredicateWithContext;
+
+/**
+ * A marker interface for predicates that can use a {@link BrooklynObject} in 
their {@link #apply} method.
+ */
+public interface BrooklynObjectPredicate<P> extends PredicateWithContext<P, 
BrooklynObject> {
+
+    @Override
+    boolean apply(P input, BrooklynObject context);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/60d85fa4/core/src/main/java/org/apache/brooklyn/util/core/ResourcePredicates.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/util/core/ResourcePredicates.java 
b/core/src/main/java/org/apache/brooklyn/util/core/ResourcePredicates.java
new file mode 100644
index 0000000..8bf0309
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/util/core/ResourcePredicates.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES 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.core;
+
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.api.objs.BrooklynObject;
+import org.apache.brooklyn.core.objs.BrooklynObjectPredicate;
+import org.apache.brooklyn.util.text.Strings;
+
+import com.google.common.base.Predicate;
+
+public class ResourcePredicates {
+
+    private ResourcePredicates() {}
+
+    /**
+     * @return A predicate that tests whether its input is a resource readable 
by Brooklyn.
+     * @see ResourceUtils#doesUrlExist(String)
+     */
+    public static Predicate<String> urlExists() {
+        return new ResourceExistsPredicate();
+    }
+
+    private static class ResourceExistsPredicate implements 
BrooklynObjectPredicate<String> {
+
+        @Override
+        public boolean apply(@Nullable String resource) {
+            return apply(resource, null);
+        }
+
+        @Override
+        public boolean apply(@Nullable String resource, @Nullable 
BrooklynObject context) {
+            return !Strings.isBlank(resource) && new 
ResourceUtils(context).doesUrlExist(resource);
+        }
+
+        @Override
+        public String toString() {
+            return "ResourcePredicates.exists()";
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/60d85fa4/core/src/test/java/org/apache/brooklyn/core/config/ConfigKeyConstraintTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/org/apache/brooklyn/core/config/ConfigKeyConstraintTest.java
 
b/core/src/test/java/org/apache/brooklyn/core/config/ConfigKeyConstraintTest.java
index 6cf42ab..05e0814 100644
--- 
a/core/src/test/java/org/apache/brooklyn/core/config/ConfigKeyConstraintTest.java
+++ 
b/core/src/test/java/org/apache/brooklyn/core/config/ConfigKeyConstraintTest.java
@@ -25,12 +25,14 @@ import static org.testng.Assert.fail;
 
 import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.entity.ImplementedBy;
+import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.api.policy.Policy;
 import org.apache.brooklyn.api.policy.PolicySpec;
 import org.apache.brooklyn.api.sensor.EnricherSpec;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.enricher.AbstractEnricher;
 import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.objs.BrooklynObjectPredicate;
 import org.apache.brooklyn.core.policy.AbstractPolicy;
 import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
 import org.apache.brooklyn.core.test.entity.TestEntity;
@@ -48,6 +50,8 @@ import com.google.common.collect.Range;
 
 public class ConfigKeyConstraintTest extends BrooklynAppUnitTestSupport {
 
+    // ----------- Setup 
-----------------------------------------------------------------------------------------------
+
     @ImplementedBy(EntityWithNonNullConstraintImpl.class)
     public static interface EntityWithNonNullConstraint extends TestEntity {
         ConfigKey<Object> NON_NULL_CONFIG = ConfigKeys.builder(Object.class)
@@ -56,6 +60,8 @@ public class ConfigKeyConstraintTest extends 
BrooklynAppUnitTestSupport {
                 .constraint(Predicates.notNull())
                 .build();
     }
+    public static class EntityWithNonNullConstraintImpl extends TestEntityImpl 
implements EntityWithNonNullConstraint {
+    }
 
     @ImplementedBy(EntityWithNonNullConstraintWithNonNullDefaultImpl.class)
     public static interface EntityWithNonNullConstraintWithNonNullDefault 
extends TestEntity {
@@ -66,6 +72,8 @@ public class ConfigKeyConstraintTest extends 
BrooklynAppUnitTestSupport {
                 .constraint(Predicates.notNull())
                 .build();
     }
+    public static class EntityWithNonNullConstraintWithNonNullDefaultImpl 
extends TestEntityImpl implements EntityWithNonNullConstraintWithNonNullDefault 
{
+    }
 
     @ImplementedBy(EntityRequiringConfigKeyInRangeImpl.class)
     public static interface EntityRequiringConfigKeyInRange extends TestEntity 
{
@@ -76,22 +84,25 @@ public class ConfigKeyConstraintTest extends 
BrooklynAppUnitTestSupport {
                 .constraint(Range.closed(0, 9))
                 .build();
     }
+    public static class EntityRequiringConfigKeyInRangeImpl extends 
TestEntityImpl implements EntityRequiringConfigKeyInRange {
+    }
 
     @ImplementedBy(EntityProvidingDefaultValueForConfigKeyInRangeImpl.class)
     public static interface EntityProvidingDefaultValueForConfigKeyInRange 
extends EntityRequiringConfigKeyInRange {
         ConfigKey<Integer> REVISED_RANGE = 
ConfigKeys.newConfigKeyWithDefault(RANGE, -1);
     }
-
-    public static class EntityWithNonNullConstraintImpl extends TestEntityImpl 
implements EntityWithNonNullConstraint {
-    }
-
-    public static class EntityWithNonNullConstraintWithNonNullDefaultImpl 
extends TestEntityImpl implements EntityWithNonNullConstraintWithNonNullDefault 
{
+    public static class EntityProvidingDefaultValueForConfigKeyInRangeImpl 
extends TestEntityImpl implements 
EntityProvidingDefaultValueForConfigKeyInRange {
     }
 
-    public static class EntityRequiringConfigKeyInRangeImpl extends 
TestEntityImpl implements EntityRequiringConfigKeyInRange {
+    @ImplementedBy(EntityWithContextAwareConstraintImpl.class)
+    public static interface EntityWithContextAwareConstraint extends 
TestEntity {
+        ConfigKey<String> MUST_BE_DISPLAY_NAME = 
ConfigKeys.builder(String.class)
+                .name("must-be-display-name")
+                .description("Configuration key that must not be null")
+                .constraint(new MatchesEntityDisplayNamePredicate())
+                .build();
     }
-
-    public static class EntityProvidingDefaultValueForConfigKeyInRangeImpl 
extends TestEntityImpl implements 
EntityProvidingDefaultValueForConfigKeyInRange {
+    public static class EntityWithContextAwareConstraintImpl extends 
TestEntityImpl implements EntityWithContextAwareConstraint {
     }
 
     public static class PolicyWithConfigConstraint extends AbstractPolicy {
@@ -110,6 +121,20 @@ public class ConfigKeyConstraintTest extends 
BrooklynAppUnitTestSupport {
                 .build();
     }
 
+    private static class MatchesEntityDisplayNamePredicate implements 
BrooklynObjectPredicate<String> {
+        @Override
+        public boolean apply(String input) {
+            return false;
+        }
+
+        @Override
+        public boolean apply(String input, BrooklynObject context) {
+            return context != null && context.getDisplayName().equals(input);
+        }
+    }
+
+    // ----------- Tests 
-----------------------------------------------------------------------------------------------
+
     @Test
     public void testExceptionWhenEntityHasNullConfig() {
         try {
@@ -240,7 +265,21 @@ public class ConfigKeyConstraintTest extends 
BrooklynAppUnitTestSupport {
                     }
                 })
                 .build();
+        // i.e. no exception.
         assertFalse(key.isValueValid("abc"));
     }
 
+    @Test
+    public void testContextAwarePredicateInformedOfEntity() {
+        try {
+            
app.createAndManageChild(EntitySpec.create(EntityWithContextAwareConstraint.class)
+                    .displayName("Mr. Big")
+                    .configure("must-be-display-name", "Mr. Bag"));
+            fail("Expected exception when managing entity with incorrect 
config");
+        } catch (Exception e) {
+            Throwable t = Exceptions.getFirstThrowableOfType(e, 
ConstraintViolationException.class);
+            assertNotNull(t);
+        }
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/60d85fa4/utils/common/src/main/java/org/apache/brooklyn/util/guava/PredicateWithContext.java
----------------------------------------------------------------------
diff --git 
a/utils/common/src/main/java/org/apache/brooklyn/util/guava/PredicateWithContext.java
 
b/utils/common/src/main/java/org/apache/brooklyn/util/guava/PredicateWithContext.java
new file mode 100644
index 0000000..9e8eb5e
--- /dev/null
+++ 
b/utils/common/src/main/java/org/apache/brooklyn/util/guava/PredicateWithContext.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES 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.guava;
+
+import com.google.common.base.Predicate;
+
+/**
+ * A marker interface for predicates that may take a context object into 
account.
+ * <p>
+ * Such predicates should handle absent contexts sensibly.
+ */
+public interface PredicateWithContext<P, T> extends Predicate<P> {
+
+    boolean apply(P input, T context);
+
+}

Reply via email to