Repository: ambari Updated Branches: refs/heads/trunk 0d5cc744a -> b4079b950
AMBARI-6231. Views: parameterization of view parameters. Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/b4079b95 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/b4079b95 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/b4079b95 Branch: refs/heads/trunk Commit: b4079b9503bb4c15889134070c6914c5fac4d33d Parents: 0d5cc74 Author: Siddharth Wagle <swa...@hortonworks.com> Authored: Fri Jun 20 14:40:11 2014 -0700 Committer: Siddharth Wagle <swa...@hortonworks.com> Committed: Fri Jun 20 14:40:11 2014 -0700 ---------------------------------------------------------------------- .gitignore | 1 + ambari-server/pom.xml | 8 ++ .../ambari/server/view/ViewContextImpl.java | 109 +++++++++++++++++-- .../ambari/server/view/ViewContextImplTest.java | 48 ++++++++ pom.xml | 3 + 5 files changed, 161 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/b4079b95/.gitignore ---------------------------------------------------------------------- diff --git a/.gitignore b/.gitignore index 246e53e..0430303 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ target derby.log pass.txt ambari-agent/src/test/python/ambari_agent/dummy_files/current-stack +velocity.log* http://git-wip-us.apache.org/repos/asf/ambari/blob/b4079b95/ambari-server/pom.xml ---------------------------------------------------------------------- diff --git a/ambari-server/pom.xml b/ambari-server/pom.xml index b9fe10a..a0dc0a7 100644 --- a/ambari-server/pom.xml +++ b/ambari-server/pom.xml @@ -151,6 +151,9 @@ <exclude>src/test/resources/TestAmbaryServer.samples/**</exclude> <exclude>src/test/resources/*.txt</exclude> <exclude>src/test/resources/users_for_dn_with_space.ldif</exclude> + + <!--Velocity log --> + <exclude>**/velocity.log*</exclude> </excludes> </configuration> <executions> @@ -1288,6 +1291,11 @@ <artifactId>quartz-jobs</artifactId> <version>2.2.1</version> </dependency> + <dependency> + <groupId>org.apache.velocity</groupId> + <artifactId>velocity</artifactId> + <version>1.7</version> + </dependency> </dependencies> <!--<reporting> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>findbugs-maven-plugin</artifactId> <version>2.5.2</version> </plugin> http://git-wip-us.apache.org/repos/asf/ambari/blob/b4079b95/ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java index 042e5c4..e914c75 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java @@ -35,9 +35,16 @@ import org.apache.ambari.view.ViewDefinition; import org.apache.ambari.view.ViewInstanceDefinition; import org.apache.ambari.view.events.Event; import org.apache.ambari.view.events.Listener; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.exception.ParseErrorException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.InputStream; +import java.io.StringWriter; +import java.io.Writer; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -75,6 +82,14 @@ public class ViewContextImpl implements ViewContext, ViewController { */ private DataStore dataStore = null; + private final VelocityContext velocityContext; + + + // ----- Constants --------------------------------------------------------- + + protected final static Logger LOG = + LoggerFactory.getLogger(ViewContext.class); + // ---- Constructors ------------------------------------------------------- @@ -85,10 +100,7 @@ public class ViewContextImpl implements ViewContext, ViewController { * @param viewRegistry the view registry */ public ViewContextImpl(ViewInstanceEntity viewInstanceEntity, ViewRegistry viewRegistry) { - this.viewEntity = viewInstanceEntity.getViewEntity(); - this.viewInstanceEntity = viewInstanceEntity; - this.viewRegistry = viewRegistry; - this.streamProvider = ViewURLStreamProvider.getProvider(); + this(viewInstanceEntity.getViewEntity(), viewInstanceEntity, viewRegistry); } /** @@ -98,10 +110,15 @@ public class ViewContextImpl implements ViewContext, ViewController { * @param viewRegistry the view registry */ public ViewContextImpl(ViewEntity viewEntity, ViewRegistry viewRegistry) { + this(viewEntity, null, viewRegistry); + } + + private ViewContextImpl(ViewEntity viewEntity, ViewInstanceEntity viewInstanceEntity, ViewRegistry viewRegistry) { this.viewEntity = viewEntity; - this.viewInstanceEntity = null; + this.viewInstanceEntity = viewInstanceEntity; this.viewRegistry = viewRegistry; this.streamProvider = ViewURLStreamProvider.getProvider(); + this.velocityContext = initVelocityContext(); } // ----- ViewContext ------------------------------------------------------- @@ -128,8 +145,20 @@ public class ViewContextImpl implements ViewContext, ViewController { @Override public Map<String, String> getProperties() { - return viewInstanceEntity == null ? null : - Collections.unmodifiableMap(viewInstanceEntity.getPropertyMap()); + if (viewInstanceEntity == null) { + return null; + } + Map<String, String> properties = viewInstanceEntity.getPropertyMap(); + String rawValue; + for (String key : properties.keySet()) { + rawValue = properties.get(key); + try { + properties.put(key, parameterize(rawValue)); + } catch (ParseErrorException ex) { + LOG.warn(String.format("Error during parsing '%s' parameter. Leaving original value.", key)); + } + } + return Collections.unmodifiableMap(properties); } @Override @@ -171,7 +200,7 @@ public class ViewContextImpl implements ViewContext, ViewController { @Override public String getUsername() { - return viewInstanceEntity.getUsername(); + return viewInstanceEntity != null ? viewInstanceEntity.getUsername() : null; } @Override @@ -241,6 +270,52 @@ public class ViewContextImpl implements ViewContext, ViewController { } } + /** + * Parameterize string using VelocityContext instance + * + * @param raw original string with parameters in formal or shorthand notation + * + * @return parameterized string + * + * @throws ParseErrorException if original string cannot be parsed by Velocity + */ + private String parameterize(String raw) throws ParseErrorException { + Writer templateWriter = new StringWriter(); + Velocity.evaluate(velocityContext, templateWriter, raw, raw); + return templateWriter.toString(); + } + + /** + * Instantiate and initialize context for parameters processing using Velocity. + * + * @return initialized context instance + */ + private VelocityContext initVelocityContext() { + VelocityContext context = new VelocityContext(); + context.put("username", + new ParameterResolver() { + @Override + protected String getValue() { + return viewContext.getUsername(); + } + }); + context.put("viewName", + new ParameterResolver() { + @Override + protected String getValue() { + return viewContext.getViewName(); + } + }); + context.put("instanceName", + new ParameterResolver() { + @Override + protected String getValue() { + return viewContext.getInstanceName(); + } + }); + return context; + } + // ----- Inner class : ViewURLStreamProvider ------------------------------- @@ -296,4 +371,22 @@ public class ViewContextImpl implements ViewContext, ViewController { return new ViewURLStreamProvider(streamProvider); } } + + // ----- Inner class : ParameterResolver ------------------------------- + + /** + * Represents basic parameter resolver to obtain fields of ViewContext at runtime. + */ + private abstract class ParameterResolver { + + protected final ViewContext viewContext = ViewContextImpl.this; + + protected abstract String getValue(); + + @Override + public String toString() { + String value = getValue(); + return value == null ? "" : value; + } + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/b4079b95/ambari-server/src/test/java/org/apache/ambari/server/view/ViewContextImplTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/ViewContextImplTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewContextImplTest.java index 92608c6..5358162 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/view/ViewContextImplTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewContextImplTest.java @@ -36,6 +36,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import static org.easymock.EasyMock.createMockBuilder; import static org.easymock.EasyMock.createNiceMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; @@ -90,6 +91,53 @@ public class ViewContextImplTest { } @Test + public void testGetPropertiesWithParameters() throws Exception { + InstanceConfig instanceConfig = createNiceMock(InstanceConfig.class); + replay(instanceConfig); + ViewEntity viewDefinition = createNiceMock(ViewEntity.class); + expect(viewDefinition.getCommonName()).andReturn("View").times(2); + replay(viewDefinition); + ViewInstanceEntity viewInstanceDefinition = createMockBuilder(ViewInstanceEntity.class) + .addMockedMethod("getUsername") + .addMockedMethod("getName") + .withConstructor(viewDefinition, instanceConfig).createMock(); + expect(viewInstanceDefinition.getUsername()).andReturn("User").times(1); + expect(viewInstanceDefinition.getUsername()).andReturn("User2").times(1); + expect(viewInstanceDefinition.getName()).andReturn("Instance").times(3); + replay(viewInstanceDefinition); + ViewRegistry viewRegistry = createNiceMock(ViewRegistry.class); + viewInstanceDefinition.putProperty("p1", "/tmp/some/path/${username}"); + viewInstanceDefinition.putProperty("p2", "/tmp/path/$viewName"); + viewInstanceDefinition.putProperty("p3", "/path/$instanceName"); + viewInstanceDefinition.putProperty("p4", "/path/to/${unspecified_parameter}"); + viewInstanceDefinition.putProperty("p5", "/path/to/${incorrect_parameter"); + viewInstanceDefinition.putProperty("p6", "/path/to/\\${username}"); + viewInstanceDefinition.putProperty("p7", "/path/to/\\$viewName"); + + ViewContextImpl viewContext = new ViewContextImpl(viewInstanceDefinition, viewRegistry); + + Map<String, String> properties = viewContext.getProperties(); + Assert.assertEquals(7, properties.size()); + Assert.assertEquals("/tmp/some/path/User", properties.get("p1")); + Assert.assertEquals("/tmp/path/View", properties.get("p2")); + Assert.assertEquals("/path/Instance", properties.get("p3")); + Assert.assertEquals("/path/to/${unspecified_parameter}", properties.get("p4")); + Assert.assertEquals("/path/to/${incorrect_parameter", properties.get("p5")); + Assert.assertEquals("/path/to/${username}", properties.get("p6")); + Assert.assertEquals("/path/to/$viewName", properties.get("p7")); + + properties = viewContext.getProperties(); + Assert.assertEquals(7, properties.size()); + Assert.assertEquals("/tmp/some/path/User2", properties.get("p1")); + Assert.assertEquals("/tmp/path/View", properties.get("p2")); + Assert.assertEquals("/path/Instance", properties.get("p3")); + Assert.assertEquals("/path/to/${unspecified_parameter}", properties.get("p4")); + Assert.assertEquals("/path/to/${incorrect_parameter", properties.get("p5")); + Assert.assertEquals("/path/to/${username}", properties.get("p6")); + Assert.assertEquals("/path/to/$viewName", properties.get("p7")); + } + + @Test public void testGetResourceProvider() throws Exception { InstanceConfig instanceConfig = InstanceConfigTest.getInstanceConfigs().get(0); ViewEntity viewDefinition = ViewEntityTest.getViewEntity(); http://git-wip-us.apache.org/repos/asf/ambari/blob/b4079b95/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index ae01194..67415b1 100644 --- a/pom.xml +++ b/pom.xml @@ -222,6 +222,9 @@ <exclude>contrib/views/*/.classpath</exclude> <exclude>contrib/views/*/.project</exclude> <exclude>contrib/views/*/.settings/**</exclude> + + <!--Velocity log --> + <exclude>**/velocity.log*</exclude> </excludes> </configuration> <executions>