浏览代码

AMBARI-6231. Views: parameterization of view parameters.

Siddharth Wagle 11 年之前
父节点
当前提交
b4079b9503

+ 1 - 0
.gitignore

@@ -19,3 +19,4 @@ target
 derby.log
 pass.txt
 ambari-agent/src/test/python/ambari_agent/dummy_files/current-stack
+velocity.log*

+ 8 - 0
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>

+ 101 - 8
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;
+    }
+  }
 }

+ 48 - 0
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;
@@ -89,6 +90,53 @@ public class ViewContextImplTest {
     Assert.assertEquals("v3", properties.get("p3"));
   }
 
+  @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);

+ 3 - 0
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>