You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by ge...@apache.org on 2016/12/20 11:10:30 UTC
[12/13] brooklyn-server git commit: DslAccessible replaces hard-coded
package DSL white-listing
DslAccessible replaces hard-coded package DSL white-listing
Applying the DslAccessible annotation on any method allows it to be called by DSL
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/f564aa81
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/f564aa81
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/f564aa81
Branch: refs/heads/master
Commit: f564aa813a311f9b06d9ab4ef5142875f971d50a
Parents: 60c5c6f
Author: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Authored: Tue Dec 13 17:18:24 2016 +0200
Committer: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Committed: Tue Dec 13 17:18:24 2016 +0200
----------------------------------------------------------------------
.../camp/brooklyn/spi/dsl/DslAccessible.java | 28 ++++++++++++++++++++
.../spi/dsl/DslDeferredFunctionCall.java | 27 ++++++++++++++++---
.../spi/dsl/methods/BrooklynDslCommon.java | 26 ++++++++++++++++++
.../brooklyn/spi/dsl/methods/DslComponent.java | 16 +++++++++++
.../camp/brooklyn/spi/dsl/DslYamlTest.java | 28 ++++++++++++++++++--
.../spi/dsl/methods/DslTestObjects.java | 5 ++++
6 files changed, 125 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f564aa81/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslAccessible.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslAccessible.java b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslAccessible.java
new file mode 100644
index 0000000..6c9de73
--- /dev/null
+++ b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslAccessible.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2016 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.camp.brooklyn.spi.dsl;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Retention(RUNTIME)
+@Target(METHOD)
+public @interface DslAccessible {
+
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f564aa81/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslDeferredFunctionCall.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslDeferredFunctionCall.java b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslDeferredFunctionCall.java
index 638f36f..3353151 100644
--- a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslDeferredFunctionCall.java
+++ b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslDeferredFunctionCall.java
@@ -17,8 +17,11 @@ package org.apache.brooklyn.camp.brooklyn.spi.dsl;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.util.Collections;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
import org.apache.brooklyn.api.mgmt.Task;
import org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.BrooklynDslCommon;
@@ -28,12 +31,16 @@ import org.apache.brooklyn.util.core.task.Tasks;
import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.guava.Maybe;
import org.apache.brooklyn.util.javalang.Reflections;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.google.common.base.Joiner;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
public class DslDeferredFunctionCall extends BrooklynDslDeferredSupplier<Object> {
+ private static final Logger log = LoggerFactory.getLogger(DslDeferredFunctionCall.class);
+ private static final Set<Method> DEPRECATED_ACCESS_WARNINGS = Collections.newSetFromMap(new ConcurrentHashMap<Method, Boolean>());
private static final long serialVersionUID = 3243262633795112155L;
@@ -161,10 +168,24 @@ public class DslDeferredFunctionCall extends BrooklynDslDeferredSupplier<Object>
}
private static void checkCallAllowed(Method m) {
+ DslAccessible dslAccessible = m.getAnnotation(DslAccessible.class);
+ boolean isAnnotationAllowed = dslAccessible != null;
+ if (isAnnotationAllowed) return;
+
+ // TODO white-list using brooklyn.properties (at runtime)
+
Class<?> clazz = m.getDeclaringClass();
- if (clazz.getPackage() == null || // Proxy objects don't have a package
- !(clazz.getPackage().getName().startsWith(BrooklynDslCommon.class.getPackage().getName())))
- throw new IllegalArgumentException("Not permitted to invoke function on '"+clazz+"' (outside allowed package scope)");
+ Package whiteListPackage = BrooklynDslCommon.class.getPackage();
+ boolean isPackageAllowed = (clazz.getPackage() != null && // Proxy objects don't have a package
+ clazz.getPackage().getName().startsWith(whiteListPackage.getName()));
+ if (isPackageAllowed) {
+ if (DEPRECATED_ACCESS_WARNINGS.add(m)) {
+ log.warn("Deprecated since 0.11.0. The method '" + m.toString() + "' called by DSL should be white listed using the " + DslAccessible.class.getSimpleName() + " annotation. Support for DSL callable methods under the " + whiteListPackage + " will be fremoved in a future release.");
+ }
+ return;
+ }
+
+ throw new IllegalArgumentException("Not permitted to invoke function on '"+clazz+"' (outside allowed package scope)");
}
@Override
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f564aa81/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
index bd2cbaf..c17382d 100644
--- a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
+++ b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
@@ -37,6 +37,7 @@ import org.apache.brooklyn.camp.brooklyn.BrooklynCampReservedKeys;
import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynYamlTypeInstantiator;
import org.apache.brooklyn.camp.brooklyn.spi.creation.EntitySpecConfiguration;
import org.apache.brooklyn.camp.brooklyn.spi.dsl.BrooklynDslDeferredSupplier;
+import org.apache.brooklyn.camp.brooklyn.spi.dsl.DslAccessible;
import org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.DslComponent.Scope;
import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.config.ConfigKeys;
@@ -83,37 +84,48 @@ public class BrooklynDslCommon {
// Access specific entities
+ @DslAccessible
public static DslComponent self() {
return new DslComponent(Scope.THIS);
}
+ @DslAccessible
public static DslComponent entity(Object id) {
return DslComponent.newInstance(Scope.GLOBAL, id);
}
+ @DslAccessible
public static DslComponent parent() {
return new DslComponent(Scope.PARENT);
}
+ @DslAccessible
public static DslComponent child(Object id) {
return DslComponent.newInstance(Scope.CHILD, id);
}
+ @DslAccessible
public static DslComponent sibling(Object id) {
return DslComponent.newInstance(Scope.SIBLING, id);
}
+ @DslAccessible
public static DslComponent descendant(Object id) {
return DslComponent.newInstance(Scope.DESCENDANT, id);
}
+ @DslAccessible
public static DslComponent ancestor(Object id) {
return DslComponent.newInstance(Scope.ANCESTOR, id);
}
+ @DslAccessible
public static DslComponent root() {
return new DslComponent(Scope.ROOT);
}
+ @DslAccessible
public static DslComponent scopeRoot() {
return new DslComponent(Scope.SCOPE_ROOT);
}
// prefer the syntax above to the below now, but not deprecating the below
+ @DslAccessible
public static DslComponent component(String id) {
return component("global", id);
}
+ @DslAccessible
public static DslComponent component(String scope, String id) {
if (!DslComponent.Scope.isValid(scope)) {
throw new IllegalArgumentException(scope + " is not a valid scope");
@@ -123,10 +135,12 @@ public class BrooklynDslCommon {
// Access things on entities
+ @DslAccessible
public static BrooklynDslDeferredSupplier<?> config(String keyName) {
return new DslComponent(Scope.THIS, "").config(keyName);
}
+ @DslAccessible
public static BrooklynDslDeferredSupplier<?> config(BrooklynObjectInternal obj, String keyName) {
return new DslBrooklynObjectConfigSupplier(obj, keyName);
}
@@ -194,22 +208,26 @@ public class BrooklynDslCommon {
}
}
+ @DslAccessible
public static BrooklynDslDeferredSupplier<?> attributeWhenReady(String sensorName) {
return new DslComponent(Scope.THIS, "").attributeWhenReady(sensorName);
}
+ @DslAccessible
public static BrooklynDslDeferredSupplier<?> entityId() {
return new DslComponent(Scope.THIS, "").entityId();
}
/** Returns a {@link Sensor}, looking up the sensor on the context if available and using that,
* or else defining an untyped (Object) sensor */
+ @DslAccessible
public static BrooklynDslDeferredSupplier<Sensor<?>> sensor(Object sensorName) {
return new DslComponent(Scope.THIS, "").sensor(sensorName);
}
/** Returns a {@link Sensor} declared on the type (e.g. entity class) declared in the first argument. */
@SuppressWarnings({ "unchecked", "rawtypes" })
+ @DslAccessible
public static Sensor<?> sensor(String clazzName, String sensorName) {
try {
// TODO Should use catalog's classloader, rather than ClassLoaderUtils; how to get that? Should we return a future?!
@@ -238,6 +256,7 @@ public class BrooklynDslCommon {
// Build complex things
+ @DslAccessible
public static EntitySpecConfiguration entitySpec(Map<String, Object> arguments) {
return new EntitySpecConfiguration(arguments);
}
@@ -249,6 +268,7 @@ public class BrooklynDslCommon {
* bundles).
*/
@SuppressWarnings("unchecked")
+ @DslAccessible
public static Object object(Map<String, Object> arguments) {
ConfigBag config = ConfigBag.newInstance(arguments);
String typeName = BrooklynYamlTypeInstantiator.InstantiatorFromKey.extractTypeName("object", config).orNull();
@@ -285,6 +305,7 @@ public class BrooklynDslCommon {
// String manipulation
/** Return the expression as a literal string without any further parsing. */
+ @DslAccessible
public static Object literal(Object expression) {
return expression;
}
@@ -293,6 +314,7 @@ public class BrooklynDslCommon {
* Returns a formatted string or a {@link BrooklynDslDeferredSupplier} if the arguments
* are not yet fully resolved.
*/
+ @DslAccessible
public static Object formatString(final String pattern, final Object...args) {
if (resolved(args)) {
// if all args are resolved, apply the format string now
@@ -302,6 +324,7 @@ public class BrooklynDslCommon {
}
}
+ @DslAccessible
public static Object regexReplacement(final Object source, final Object pattern, final Object replacement) {
if (resolved(Arrays.asList(source, pattern, replacement))) {
return (new Functions.RegexReplacer(String.valueOf(pattern), String.valueOf(replacement))).apply(String.valueOf(source));
@@ -642,6 +665,7 @@ public class BrooklynDslCommon {
* The name of the appropriate {@link ExternalConfigSupplier} is captured, along with the key of
* the desired config value.
*/
+ @DslAccessible
public static DslExternal external(final String providerName, final String key) {
return new DslExternal(providerName, key);
}
@@ -698,6 +722,7 @@ public class BrooklynDslCommon {
}
public static class Functions {
+ @DslAccessible
public static Object regexReplacement(final Object pattern, final Object replacement) {
if (resolved(pattern, replacement)) {
return new org.apache.brooklyn.util.text.StringFunctions.RegexReplacer(String.valueOf(pattern), String.valueOf(replacement));
@@ -788,6 +813,7 @@ public class BrooklynDslCommon {
}
}
+ @DslAccessible
public static Object wrap(Entity entity) {
return DslComponent.newInstance(Scope.GLOBAL, new EntitySupplier(entity.getId()));
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f564aa81/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
index 37b9c59..a947fee 100644
--- a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
+++ b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
@@ -31,6 +31,7 @@ import org.apache.brooklyn.api.sensor.AttributeSensor;
import org.apache.brooklyn.api.sensor.Sensor;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampConstants;
import org.apache.brooklyn.camp.brooklyn.spi.dsl.BrooklynDslDeferredSupplier;
+import org.apache.brooklyn.camp.brooklyn.spi.dsl.DslAccessible;
import org.apache.brooklyn.camp.brooklyn.spi.dsl.DslFunctionSource;
import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.config.ConfigKeys;
@@ -324,41 +325,52 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity> implements
// DSL words which move to a new component
+ @DslAccessible
public DslComponent entity(Object id) {
return DslComponent.newInstance(this, Scope.GLOBAL, id);
}
+ @DslAccessible
public DslComponent child(Object id) {
return DslComponent.newInstance(this, Scope.CHILD, id);
}
+ @DslAccessible
public DslComponent sibling(Object id) {
return DslComponent.newInstance(this, Scope.SIBLING, id);
}
+ @DslAccessible
public DslComponent descendant(Object id) {
return DslComponent.newInstance(this, Scope.DESCENDANT, id);
}
+ @DslAccessible
public DslComponent ancestor(Object id) {
return DslComponent.newInstance(this, Scope.ANCESTOR, id);
}
+ @DslAccessible
public DslComponent root() {
return new DslComponent(this, Scope.ROOT);
}
+ @DslAccessible
public DslComponent scopeRoot() {
return new DslComponent(this, Scope.SCOPE_ROOT);
}
@Deprecated /** @deprecated since 0.7.0 */
+ @DslAccessible
public DslComponent component(Object id) {
return DslComponent.newInstance(this, Scope.GLOBAL, id);
}
+ @DslAccessible
public DslComponent self() {
return new DslComponent(this, Scope.THIS);
}
+ @DslAccessible
public DslComponent parent() {
return new DslComponent(this, Scope.PARENT);
}
+ @DslAccessible
public DslComponent component(String scope, Object id) {
if (!DslComponent.Scope.isValid(scope)) {
throw new IllegalArgumentException(scope + " is not a valid scope");
@@ -368,6 +380,7 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity> implements
// DSL words which return things
+ @DslAccessible
public BrooklynDslDeferredSupplier<?> entityId() {
return new EntityId(this);
}
@@ -411,6 +424,7 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity> implements
}
}
+ @DslAccessible
public BrooklynDslDeferredSupplier<?> attributeWhenReady(final String sensorName) {
return new AttributeWhenReady(this, sensorName);
}
@@ -468,6 +482,7 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity> implements
}
}
+ @DslAccessible
public BrooklynDslDeferredSupplier<?> config(final String keyName) {
return new DslConfigSupplier(this, keyName);
}
@@ -532,6 +547,7 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity> implements
// TODO
// public BrooklynDslDeferredSupplier<?> relation(BrooklynObjectInternal obj, final String relationName) {...}
+ @DslAccessible
public BrooklynDslDeferredSupplier<Sensor<?>> sensor(final Object sensorIndicator) {
return new DslSensorSupplier(this, sensorIndicator);
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f564aa81/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslYamlTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslYamlTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslYamlTest.java
index aca1aba..2196df9 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslYamlTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslYamlTest.java
@@ -521,7 +521,9 @@ public class DslYamlTest extends AbstractYamlTest {
}
public static class InaccessibleType {
- public static void isEvaluated() {}
+ public static boolean doesFail() {return true;}
+ @DslAccessible
+ public static boolean doesSucceed() {return true;}
}
@Test
@@ -530,7 +532,7 @@ public class DslYamlTest extends AbstractYamlTest {
"services:",
"- type: " + BasicApplication.class.getName(),
" brooklyn.config:",
- " dest: $brooklyn:config(\"targetValue\").isEvaluated()");
+ " dest: $brooklyn:config(\"targetValue\").doesFail()");
app.config().set(ConfigKeys.newConfigKey(InaccessibleType.class, "targetValue"), new InaccessibleType());
try {
getConfigEventually(app, DEST);
@@ -541,6 +543,28 @@ public class DslYamlTest extends AbstractYamlTest {
}
@Test
+ public void testDeferredDslAccessible() throws Exception {
+ final Entity app = createAndStartApplication(
+ "services:",
+ "- type: " + BasicApplication.class.getName(),
+ " brooklyn.config:",
+ " dest: $brooklyn:config(\"targetValue\").doesSucceed()");
+ app.config().set(ConfigKeys.newConfigKey(InaccessibleType.class, "targetValue"), new InaccessibleType());
+ assertEquals(getConfigEventually(app, DEST), Boolean.TRUE);
+ }
+
+ @Test
+ public void testDeferredDslWhiteListPackage() throws Exception {
+ final Entity app = createAndStartApplication(
+ "services:",
+ "- type: " + BasicApplication.class.getName(),
+ " brooklyn.config:",
+ " dest: $brooklyn:config(\"targetValue\").isSupplierEvaluated()");
+ app.config().set(ConfigKeys.newConfigKey(TestDslSupplierValue.class, "targetValue"), new TestDslSupplierValue());
+ assertEquals(getConfigEventually(app, DEST), Boolean.TRUE);
+ }
+
+ @Test
public void testDeferredDslUserSuppliedPackage() throws Exception {
final Entity app = createAndStartApplication(
"services:",
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f564aa81/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslTestObjects.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslTestObjects.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslTestObjects.java
index 60225af..3918ebd 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslTestObjects.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslTestObjects.java
@@ -15,6 +15,7 @@
*/
package org.apache.brooklyn.camp.brooklyn.spi.dsl.methods;
+import org.apache.brooklyn.camp.brooklyn.spi.dsl.DslAccessible;
import org.apache.brooklyn.camp.brooklyn.spi.dsl.DslFunctionSource;
import org.apache.brooklyn.util.core.task.DeferredSupplier;
import org.apache.brooklyn.util.core.task.ImmediateSupplier;
@@ -29,15 +30,18 @@ public class DslTestObjects {
this.supplier = supplier;
}
+ @DslAccessible
public Object getSupplier() {
return supplier;
}
}
public static class TestDslSupplierValue {
+ @DslAccessible
public boolean isSupplierEvaluated() {
return true;
}
+ @DslAccessible
public DslComponent self() {
return BrooklynDslCommon.self();
}
@@ -73,6 +77,7 @@ public class DslTestObjects {
throw new IllegalStateException("Not to be called");
}
+ @DslAccessible
public boolean isSupplierCallable() {
return true;
}