You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by tb...@apache.org on 2015/05/26 19:02:35 UTC

ambari git commit: AMBARI-11208 - Views : expose extra classpath setting (tbeerbower)

Repository: ambari
Updated Branches:
  refs/heads/trunk 2302764c3 -> 591ab4810


AMBARI-11208 - Views : expose extra classpath setting (tbeerbower)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/591ab481
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/591ab481
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/591ab481

Branch: refs/heads/trunk
Commit: 591ab48101065da7561115391b747991d4e47d2d
Parents: 2302764
Author: tbeerbower <tb...@hortonworks.com>
Authored: Tue May 26 13:01:05 2015 -0400
Committer: tbeerbower <tb...@hortonworks.com>
Committed: Tue May 26 13:01:14 2015 -0400

----------------------------------------------------------------------
 .../ambari/server/view/ViewClassLoader.java     | 29 +++++++++++++-------
 .../ambari/server/view/ViewExtractor.java       | 13 +++++----
 .../server/view/configuration/ViewConfig.java   | 18 ++++++++++++
 .../ambari/server/view/ViewClassLoaderTest.java | 16 +++++++----
 .../ambari/server/view/ViewRegistryTest.java    | 12 ++++----
 .../view/configuration/ViewConfigTest.java      | 21 ++++++++++++++
 ambari-views/src/main/resources/view.xsd        | 18 +++++++++++-
 7 files changed, 99 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/591ab481/ambari-server/src/main/java/org/apache/ambari/server/view/ViewClassLoader.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewClassLoader.java b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewClassLoader.java
index b7cb594..f339b9a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewClassLoader.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewClassLoader.java
@@ -18,6 +18,7 @@
 
 package org.apache.ambari.server.view;
 
+import org.apache.ambari.server.view.configuration.ViewConfig;
 import org.eclipse.jetty.webapp.WebAppClassLoader;
 import org.eclipse.jetty.webapp.WebAppContext;
 
@@ -38,10 +39,11 @@ public class ViewClassLoader extends WebAppClassLoader {
    * The URLs will be searched in the order specified for classes and resources before searching
    * the parent class loader.
    *
-   * @param urls  the URLs from which to load classes and resources
+   * @param viewConfig  the view configuration
+   * @param urls        the URLs from which to load classes and resources
    */
-  public ViewClassLoader(URL[] urls) throws IOException {
-    this(null, urls);
+  public ViewClassLoader(ViewConfig viewConfig, URL[] urls) throws IOException {
+    this(viewConfig, null, urls);
   }
 
   /**
@@ -49,11 +51,12 @@ public class ViewClassLoader extends WebAppClassLoader {
    * The URLs will be searched in the order specified for classes and resources before searching the specified
    * parent class loader.
    *
-   * @param parent  the parent class loader
-   * @param urls    the URLs from which to load classes and resources
+   * @param viewConfig  the view configuration
+   * @param parent      the parent class loader
+   * @param urls        the URLs from which to load classes and resources
    */
-  public ViewClassLoader(ClassLoader parent, URL[] urls) throws IOException {
-    super(parent, getInitContext());
+  public ViewClassLoader(ViewConfig viewConfig, ClassLoader parent, URL[] urls) throws IOException {
+    super(parent, getInitContext(viewConfig));
 
     for (URL url : urls) {
       addURL(url);
@@ -64,9 +67,8 @@ public class ViewClassLoader extends WebAppClassLoader {
   // ----- helper methods ----------------------------------------------------
 
   // Get a context to initialize the class loader.
-  private static WebAppContext getInitContext() {
-    // For now we are using defaults or setting the values for things like parent loader priority and
-    // system classes.  In the future we may allow overrides at the view level.
+  private static WebAppContext getInitContext(ViewConfig viewConfig) {
+
     WebAppContext webAppContext = new WebAppContext();
 
     // add com.google.inject as system classes to allow for injection in view components using the google annotation
@@ -74,6 +76,13 @@ public class ViewClassLoader extends WebAppClassLoader {
     // add org.slf4j as system classes to avoid linkage errors
     webAppContext.addSystemClass("org.slf4j.");
 
+    // set the class loader settings from the configuration
+    if (viewConfig != null) {
+      String extraClasspath = viewConfig.getExtraClasspath();
+      if (extraClasspath != null) {
+        webAppContext.setExtraClasspath(extraClasspath);
+      }
+    }
     return webAppContext;
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/591ab481/ambari-server/src/main/java/org/apache/ambari/server/view/ViewExtractor.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewExtractor.java b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewExtractor.java
index 43efc7d..3350726 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewExtractor.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewExtractor.java
@@ -19,6 +19,7 @@
 package org.apache.ambari.server.view;
 
 import org.apache.ambari.server.orm.entities.ViewEntity;
+import org.apache.ambari.server.view.configuration.ViewConfig;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -26,7 +27,6 @@ import javax.inject.Inject;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.LinkedList;
 import java.util.List;
@@ -151,7 +151,10 @@ public class ViewExtractor {
           throw new ExtractionException(msg);
         }
       }
-      return getArchiveClassLoader(archiveDir);
+
+      ViewConfig viewConfig = archiveUtility.getViewConfigFromExtractedArchive(archivePath, false);
+
+      return getArchiveClassLoader(viewConfig, archiveDir);
 
     } catch (Exception e) {
       String msg = "Caught exception trying to extract the view archive " + archivePath + ".";
@@ -180,8 +183,8 @@ public class ViewExtractor {
   // ----- archiveUtility methods ----------------------------------------------------
 
   // get a class loader for the given archive directory
-  private ClassLoader getArchiveClassLoader(File archiveDir)
-      throws MalformedURLException, IOException {
+  private ClassLoader getArchiveClassLoader(ViewConfig viewConfig, File archiveDir)
+      throws IOException {
 
     String    archivePath = archiveDir.getAbsolutePath();
     List<URL> urlList     = new LinkedList<URL>();
@@ -210,7 +213,7 @@ public class ViewExtractor {
     // include the archive directory
     urlList.add(archiveDir.toURI().toURL());
 
-    return new ViewClassLoader(urlList.toArray(new URL[urlList.size()]));
+    return new ViewClassLoader(viewConfig, urlList.toArray(new URL[urlList.size()]));
   }
 
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/591ab481/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java b/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java
index 6164bb7..f9b898d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ViewConfig.java
@@ -27,6 +27,7 @@ import org.apache.commons.lang.StringUtils;
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
 
 import java.util.Collections;
@@ -86,6 +87,13 @@ public class ViewConfig {
   private boolean system;
 
   /**
+   * The list of extra classpath elements.
+   */
+  @XmlElementWrapper
+  @XmlElement(name="path")
+  private List<String> classpath;
+
+  /**
    * The main view class name.
    */
   @XmlElement(name="view-class")
@@ -236,6 +244,16 @@ public class ViewConfig {
   }
 
   /**
+   * Get the extra classpath as a comma separated path of filenames or URLs pointing to
+   * directories or jar files.
+   *
+   * @return the extra classpath
+   */
+  public String getExtraClasspath() {
+    return classpath == null ? null : StringUtils.join(classpath, ",");
+  }
+
+  /**
    * Get the view class name.
    *
    * @return the view class name

http://git-wip-us.apache.org/repos/asf/ambari/blob/591ab481/ambari-server/src/test/java/org/apache/ambari/server/view/ViewClassLoaderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/ViewClassLoaderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewClassLoaderTest.java
index 8e22c49..ed701fd 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/view/ViewClassLoaderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewClassLoaderTest.java
@@ -19,12 +19,14 @@
 package org.apache.ambari.server.view;
 
 import junit.framework.Assert;
+import org.apache.ambari.server.view.configuration.ViewConfig;
 import org.junit.Test;
 
 import java.io.File;
 import java.net.URL;
 
 import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.createNiceMock;
 import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.replay;
 import static org.easymock.EasyMock.verify;
@@ -38,17 +40,18 @@ public class ViewClassLoaderTest {
   public void testGetResource() throws Exception {
     ClassLoader parentClassLoader = createMock(ClassLoader.class);
     URL parentResource = new File("parent-resource").toURI().toURL();
+    ViewConfig viewConfig = createNiceMock(ViewConfig.class);
 
     expect(parentClassLoader.getResource("parent-resource")).andReturn(parentResource).once();
 
-    replay(parentClassLoader);
+    replay(parentClassLoader, viewConfig);
 
     File file = new File("./src/test/resources");
     URL testURL = file.toURI().toURL();
 
     URL[] urls = new URL[]{testURL};
 
-    ViewClassLoader classLoader = new ViewClassLoader(parentClassLoader, urls);
+    ViewClassLoader classLoader = new ViewClassLoader(viewConfig, parentClassLoader, urls);
 
     URL url = classLoader.getResource("ambari.properties");
 
@@ -59,13 +62,14 @@ public class ViewClassLoaderTest {
     Assert.assertNotNull(url);
     Assert.assertSame(parentResource, url);
 
-    verify(parentClassLoader);
+    verify(parentClassLoader, viewConfig);
   }
 
   @Test
   public void testLoadClass() throws Exception {
     TestClassLoader parentClassLoader = createMock(TestClassLoader.class);
     Class parentClass = Object.class;
+    ViewConfig viewConfig = createNiceMock(ViewConfig.class);
 
     expect(parentClassLoader.getPackage("org.apache.ambari.server.view")).andReturn(null).anyTimes();
     expect(parentClassLoader.loadClass("java.lang.Object")).andReturn(parentClass).anyTimes();
@@ -74,14 +78,14 @@ public class ViewClassLoaderTest {
     expect(parentClassLoader.loadClass("com.google.inject.AbstractModule")).andReturn(parentClass).once();
     expect(parentClassLoader.loadClass("org.slf4j.LoggerFactory")).andReturn(parentClass).once();
 
-    replay(parentClassLoader);
+    replay(parentClassLoader, viewConfig);
 
     File file = new File("./target/test-classes");
     URL testURL = file.toURI().toURL();
 
     URL[] urls = new URL[]{testURL};
 
-    ViewClassLoader classLoader = new ViewClassLoader(parentClassLoader, urls);
+    ViewClassLoader classLoader = new ViewClassLoader(viewConfig, parentClassLoader, urls);
 
     Class clazz = classLoader.loadClass("org.apache.ambari.server.view.ViewClassLoaderTest");
 
@@ -110,7 +114,7 @@ public class ViewClassLoaderTest {
     Assert.assertNotNull(clazz);
     Assert.assertSame(parentClass, clazz);
 
-    verify(parentClassLoader);
+    verify(parentClassLoader, viewConfig);
   }
 
   public class TestClassLoader extends ClassLoader {

http://git-wip-us.apache.org/repos/asf/ambari/blob/591ab481/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java
index a0ee6b3..c66a9ce 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java
@@ -493,26 +493,26 @@ public class ViewRegistryTest {
     jarFiles.put(viewArchive, viewJarFile);
 
     // set expectations
-    expect(configuration.getViewsDir()).andReturn(viewDir);
+    expect(configuration.getViewsDir()).andReturn(viewDir).anyTimes();
     if (System.getProperty("os.name").contains("Windows")) {
-      expect(viewDir.getAbsolutePath()).andReturn("\\var\\lib\\ambari-server\\resources\\views");
+      expect(viewDir.getAbsolutePath()).andReturn("\\var\\lib\\ambari-server\\resources\\views").anyTimes();
     }
     else {
-      expect(viewDir.getAbsolutePath()).andReturn("/var/lib/ambari-server/resources/views");
+      expect(viewDir.getAbsolutePath()).andReturn("/var/lib/ambari-server/resources/views").anyTimes();
     }
 
     expect(configuration.getViewExtractionThreadPoolCoreSize()).andReturn(2).anyTimes();
     expect(configuration.getViewExtractionThreadPoolMaxSize()).andReturn(3).anyTimes();
     expect(configuration.getViewExtractionThreadPoolTimeout()).andReturn(10000L).anyTimes();
 
-    expect(viewDir.listFiles()).andReturn(new File[]{viewArchive});
+    expect(viewDir.listFiles()).andReturn(new File[]{viewArchive}).anyTimes();
 
     expect(viewArchive.isDirectory()).andReturn(false);
     if (System.getProperty("os.name").contains("Windows")) {
-      expect(viewArchive.getAbsolutePath()).andReturn("\\var\\lib\\ambari-server\\resources\\views\\work\\MY_VIEW{1.0.0}");
+      expect(viewArchive.getAbsolutePath()).andReturn("\\var\\lib\\ambari-server\\resources\\views\\work\\MY_VIEW{1.0.0}").anyTimes();
     }
     else {
-      expect(viewArchive.getAbsolutePath()).andReturn("/var/lib/ambari-server/resources/views/work/MY_VIEW{1.0.0}");
+      expect(viewArchive.getAbsolutePath()).andReturn("/var/lib/ambari-server/resources/views/work/MY_VIEW{1.0.0}").anyTimes();
     }
 
     expect(archiveDir.exists()).andReturn(false);

http://git-wip-us.apache.org/repos/asf/ambari/blob/591ab481/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ViewConfigTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ViewConfigTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ViewConfigTest.java
index beb8bde..2391ad6 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ViewConfigTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ViewConfigTest.java
@@ -165,6 +165,16 @@ public class ViewConfigTest {
       "    <max-ambari-version>2.0.0</max-ambari-version>\n" +
       "</view>";
 
+  private static String EXTRA_CLASSPATH_XML = "<view>\n" +
+      "    <name>MY_VIEW</name>\n" +
+      "    <label>My View!</label>\n" +
+      "    <version>1.0.0</version>\n" +
+      "    <classpath>" +
+      "      <path>/var/lib/</path>" +
+      "      <path>/tmp/foo.jar</path>" +
+      "    </classpath>\n" +
+      "</view>";
+
   @Test
   public void testGetName() throws Exception {
     ViewConfig config = getConfig();
@@ -281,6 +291,17 @@ public class ViewConfigTest {
   }
 
   @Test
+  public void testGetExtraClasspath() throws Exception {
+    ViewConfig config = getConfig(system_xml);
+
+    Assert.assertNull(config.getExtraClasspath());
+
+    config = getConfig(EXTRA_CLASSPATH_XML);
+
+    Assert.assertEquals("/var/lib/,/tmp/foo.jar", config.getExtraClasspath());
+  }
+
+  @Test
   public void testGetMinAmbariVersion() throws Exception {
     ViewConfig config = getConfig();
     Assert.assertNull(config.getMinAmbariVersion());

http://git-wip-us.apache.org/repos/asf/ambari/blob/591ab481/ambari-views/src/main/resources/view.xsd
----------------------------------------------------------------------
diff --git a/ambari-views/src/main/resources/view.xsd b/ambari-views/src/main/resources/view.xsd
index 37737c1..46adf27 100644
--- a/ambari-views/src/main/resources/view.xsd
+++ b/ambari-views/src/main/resources/view.xsd
@@ -250,7 +250,18 @@
       </xs:extension>
     </xs:complexContent>
   </xs:complexType>
-
+  <xs:complexType name="PathType">
+    <xs:annotation>
+      <xs:documentation>Defines a single classpath.</xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element type="xs:string" name="path" minOccurs="0" maxOccurs="unbounded">
+        <xs:annotation>
+          <xs:documentation>The path of a filename or URL pointing to a directory or jar file. A directory path should end with '/'.</xs:documentation>
+        </xs:annotation>
+      </xs:element>
+    </xs:sequence>
+  </xs:complexType>
   <xs:element name="view">
     <xs:annotation>
       <xs:documentation>Defines a view.</xs:documentation>
@@ -306,6 +317,11 @@
             <xs:documentation>Indicates whether or not this is a system view.</xs:documentation>
           </xs:annotation>
         </xs:element>
+        <xs:element type="PathType" name="classpath" minOccurs="0" maxOccurs="1">
+          <xs:annotation>
+            <xs:documentation>Extra class path entries for this view. A directory path should end with '/'.</xs:documentation>
+          </xs:annotation>
+        </xs:element>
         <xs:element type="xs:string" name="view-class" minOccurs="0" maxOccurs="1">
           <xs:annotation>
             <xs:documentation>The View class to receive framework events.</xs:documentation>