You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by al...@apache.org on 2015/10/21 11:12:33 UTC
[2/3] incubator-brooklyn git commit: TemplateProcessor: for location
TemplateProcessor: for location
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/76b098bd
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/76b098bd
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/76b098bd
Branch: refs/heads/master
Commit: 76b098bd1f01732647fb5f85ac2603cd0afb5c03
Parents: c2494dc
Author: Aled Sage <al...@gmail.com>
Authored: Tue Oct 20 14:59:58 2015 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Oct 21 09:50:30 2015 +0100
----------------------------------------------------------------------
.../util/core/text/TemplateProcessor.java | 161 +++++++++++++++++--
.../util/core/text/TemplateProcessorTest.java | 18 +++
2 files changed, 168 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/76b098bd/core/src/main/java/org/apache/brooklyn/util/core/text/TemplateProcessor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/text/TemplateProcessor.java b/core/src/main/java/org/apache/brooklyn/util/core/text/TemplateProcessor.java
index 58efcd4..923f733 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/text/TemplateProcessor.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/text/TemplateProcessor.java
@@ -18,6 +18,8 @@
*/
package org.apache.brooklyn.util.core.text;
+import static com.google.common.base.Preconditions.checkNotNull;
+
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
@@ -33,6 +35,7 @@ import org.apache.brooklyn.api.sensor.AttributeSensor;
import org.apache.brooklyn.core.config.ConfigKeys;
import org.apache.brooklyn.core.entity.Entities;
import org.apache.brooklyn.core.entity.EntityInternal;
+import org.apache.brooklyn.core.location.internal.LocationInternal;
import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
import org.apache.brooklyn.core.sensor.DependentConfiguration;
import org.apache.brooklyn.core.sensor.Sensors;
@@ -115,6 +118,11 @@ public class TemplateProcessor {
return processTemplateContents(templateContents, new EntityAndMapTemplateModel(managementContext, extraSubstitutions));
}
+ /** Processes template contents according to {@link EntityAndMapTemplateModel}. */
+ public static String processTemplateContents(String templateContents, Location location, Map<String,? extends Object> extraSubstitutions) {
+ return processTemplateContents(templateContents, new LocationAndMapTemplateModel((LocationInternal)location, extraSubstitutions));
+ }
+
/**
* A Freemarker {@link TemplateHashModel} which will correctly handle entries of the form "a.b" in this map,
* matching against template requests for "${a.b}".
@@ -181,7 +189,7 @@ public class TemplateProcessor {
/** FreeMarker {@link TemplateHashModel} which resolves keys inside the given entity or management context.
* Callers are required to include dots for dot-separated keys.
- * Freemarker will only due this when in inside bracket notation in an outer map, as in <code>${outer['a.b.']}</code>;
+ * Freemarker will only do this when in inside bracket notation in an outer map, as in <code>${outer['a.b.']}</code>;
* as a result this is intended only for use by {@link EntityAndMapTemplateModel} where
* a caller has used bracked notation, as in <code>${mgmt['key.subkey']}</code>. */
protected static final class EntityConfigTemplateModel implements TemplateHashModel {
@@ -189,13 +197,87 @@ public class TemplateProcessor {
protected final ManagementContext mgmt;
protected EntityConfigTemplateModel(EntityInternal entity) {
- this.entity = entity;
+ this.entity = checkNotNull(entity, "entity");
this.mgmt = entity.getManagementContext();
}
- protected EntityConfigTemplateModel(ManagementContext mgmt) {
- this.entity = null;
- this.mgmt = mgmt;
+ @Override
+ public boolean isEmpty() { return false; }
+
+ @Override
+ public TemplateModel get(String key) throws TemplateModelException {
+ try {
+ Object result = entity.getConfig(ConfigKeys.builder(Object.class).name(key).build());
+
+ if (result==null)
+ result = mgmt.getConfig().getConfig(ConfigKeys.builder(Object.class).name(key).build());
+
+ if (result!=null)
+ return wrapAsTemplateModel( result );
+
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ throw new IllegalStateException("Error accessing config '"+key+"'"+" on "+entity+": "+e, e);
+ }
+
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getName()+"["+entity+"]";
+ }
+ }
+
+ /** FreeMarker {@link TemplateHashModel} which resolves keys inside the given management context.
+ * Callers are required to include dots for dot-separated keys.
+ * Freemarker will only do this when in inside bracket notation in an outer map, as in <code>${outer['a.b.']}</code>;
+ * as a result this is intended only for use by {@link EntityAndMapTemplateModel} where
+ * a caller has used bracked notation, as in <code>${mgmt['key.subkey']}</code>. */
+ protected static final class MgmtConfigTemplateModel implements TemplateHashModel {
+ protected final ManagementContext mgmt;
+
+ protected MgmtConfigTemplateModel(ManagementContext mgmt) {
+ this.mgmt = checkNotNull(mgmt, "mgmt");
+ }
+
+ @Override
+ public boolean isEmpty() { return false; }
+
+ @Override
+ public TemplateModel get(String key) throws TemplateModelException {
+ try {
+ Object result = mgmt.getConfig().getConfig(ConfigKeys.builder(Object.class).name(key).build());
+
+ if (result!=null)
+ return wrapAsTemplateModel( result );
+
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ throw new IllegalStateException("Error accessing config '"+key+"': "+e, e);
+ }
+
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getName()+"["+mgmt+"]";
+ }
+ }
+
+ /** FreeMarker {@link TemplateHashModel} which resolves keys inside the given location.
+ * Callers are required to include dots for dot-separated keys.
+ * Freemarker will only do this when in inside bracket notation in an outer map, as in <code>${outer['a.b.']}</code>;
+ * as a result this is intended only for use by {@link LocationAndMapTemplateModel} where
+ * a caller has used bracked notation, as in <code>${mgmt['key.subkey']}</code>. */
+ protected static final class LocationConfigTemplateModel implements TemplateHashModel {
+ protected final LocationInternal location;
+ protected final ManagementContext mgmt;
+
+ protected LocationConfigTemplateModel(LocationInternal location) {
+ this.location = checkNotNull(location, "location");
+ this.mgmt = location.getManagementContext();
}
@Override
@@ -206,8 +288,8 @@ public class TemplateProcessor {
try {
Object result = null;
- if (entity!=null)
- result = entity.getConfig(ConfigKeys.builder(Object.class).name(key).build());
+ result = location.getConfig(ConfigKeys.builder(Object.class).name(key).build());
+
if (result==null && mgmt!=null)
result = mgmt.getConfig().getConfig(ConfigKeys.builder(Object.class).name(key).build());
@@ -217,7 +299,7 @@ public class TemplateProcessor {
} catch (Exception e) {
Exceptions.propagateIfFatal(e);
throw new IllegalStateException("Error accessing config '"+key+"'"
- + (entity!=null ? " on "+entity : "")+": "+e, e);
+ + (location!=null ? " on "+location : "")+": "+e, e);
}
return null;
@@ -225,7 +307,7 @@ public class TemplateProcessor {
@Override
public String toString() {
- return getClass().getName()+"["+entity+"]";
+ return getClass().getName()+"["+location+"]";
}
}
@@ -311,10 +393,10 @@ public class TemplateProcessor {
if (entity!=null)
return new EntityConfigTemplateModel(entity);
else
- return new EntityConfigTemplateModel(mgmt);
+ return new MgmtConfigTemplateModel(mgmt);
}
if ("mgmt".equals(key)) {
- return new EntityConfigTemplateModel(mgmt);
+ return new MgmtConfigTemplateModel(mgmt);
}
if ("driver".equals(key) && driver!=null)
@@ -351,6 +433,63 @@ public class TemplateProcessor {
}
}
+ /**
+ * Provides access to config on an entity or management context, using
+ * <code>${config['entity.config.key']}</code> or <code>${mgmt['brooklyn.properties.key']}</code> notation,
+ * and also allowing access to <code>getX()</code> methods on entity (interface) or driver
+ * using <code>${entity.x}</code> or <code><${driver.x}</code>.
+ * Optional extra properties can be supplied, treated as per {@link DotSplittingTemplateModel}.
+ */
+ protected static final class LocationAndMapTemplateModel implements TemplateHashModel {
+ protected final LocationInternal location;
+ protected final ManagementContext mgmt;
+ protected final DotSplittingTemplateModel extraSubstitutionsModel;
+
+ protected LocationAndMapTemplateModel(LocationInternal location, Map<String,? extends Object> extraSubstitutions) {
+ this.location = checkNotNull(location, "location");
+ this.mgmt = location.getManagementContext();
+ this.extraSubstitutionsModel = new DotSplittingTemplateModel(extraSubstitutions);
+ }
+
+ @Override
+ public boolean isEmpty() { return false; }
+
+ @Override
+ public TemplateModel get(String key) throws TemplateModelException {
+ if (extraSubstitutionsModel.contains(key))
+ return wrapAsTemplateModel( extraSubstitutionsModel.get(key) );
+
+ if ("location".equals(key))
+ return wrapAsTemplateModel( location );
+ if ("config".equals(key)) {
+ return new LocationConfigTemplateModel(location);
+ }
+ if ("mgmt".equals(key)) {
+ return new MgmtConfigTemplateModel(mgmt);
+ }
+
+ if (mgmt!=null) {
+ // TODO deprecated in 0.7.0, remove after next version
+ // ie not supported to access global props without qualification
+ Object result = mgmt.getConfig().getConfig(ConfigKeys.builder(Object.class).name(key).build());
+ if (result!=null) {
+ log.warn("Deprecated access of global brooklyn.properties value for "+key+"; should be qualified with 'mgmt.'");
+ return wrapAsTemplateModel( result );
+ }
+ }
+
+ if ("javaSysProps".equals(key))
+ return wrapAsTemplateModel( System.getProperties() );
+
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getName()+"["+location+"]";
+ }
+ }
+
/** Processes template contents with the given items in scope as per {@link EntityAndMapTemplateModel}. */
public static String processTemplateContents(String templateContents, final EntityInternal entity, Map<String,? extends Object> extraSubstitutions) {
return processTemplateContents(templateContents, new EntityAndMapTemplateModel(entity, extraSubstitutions));
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/76b098bd/core/src/test/java/org/apache/brooklyn/util/core/text/TemplateProcessorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/util/core/text/TemplateProcessorTest.java b/core/src/test/java/org/apache/brooklyn/util/core/text/TemplateProcessorTest.java
index b2fd6a7..0f2d989 100644
--- a/core/src/test/java/org/apache/brooklyn/util/core/text/TemplateProcessorTest.java
+++ b/core/src/test/java/org/apache/brooklyn/util/core/text/TemplateProcessorTest.java
@@ -26,6 +26,8 @@ import org.apache.brooklyn.core.sensor.DependentConfiguration;
import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
import org.apache.brooklyn.core.test.entity.TestApplication;
import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
import org.apache.brooklyn.test.FixedLocaleTest;
import org.apache.brooklyn.util.core.text.TemplateProcessor;
import org.testng.Assert;
@@ -102,6 +104,22 @@ public class TemplateProcessorTest extends BrooklynAppUnitTestSupport {
}
@Test
+ public void testLocationGetterMethod() {
+ LocalhostMachineProvisioningLocation location = app.newLocalhostProvisioningLocation();
+ String templateContents = "${location.id}";
+ String result = TemplateProcessor.processTemplateContents(templateContents, location, ImmutableMap.<String,Object>of());
+ assertEquals(result, location.getId());
+ }
+
+ @Test
+ public void testLocationConfig() {
+ LocalhostMachineProvisioningLocation location = app.newLocalhostProvisioningLocation(ImmutableMap.of("mykey", "myval"));
+ String templateContents = "${config['mykey']}";//"+TestEntity.CONF_NAME.getName()+"']}";
+ String result = TemplateProcessor.processTemplateContents(templateContents, location, ImmutableMap.<String,Object>of());
+ assertEquals(result, "myval");
+ }
+
+ @Test
public void testManagementContextConfig() {
mgmt.getBrooklynProperties().put("globalmykey", "myval");
String templateContents = "${mgmt.globalmykey}";