You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by jo...@apache.org on 2014/09/13 01:53:53 UTC

[25/30] git commit: AMBARI-7227 - Views : Extract System view on ambari-server setup

AMBARI-7227 - Views : Extract System view on ambari-server setup


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

Branch: refs/heads/branch-alerts-dev
Commit: 093ed17d46e6b3e2e1528e27e4cbd42e18a9d610
Parents: bd28cd9
Author: tbeerbower <tb...@hortonworks.com>
Authored: Thu Sep 11 16:38:57 2014 -0400
Committer: tbeerbower <tb...@hortonworks.com>
Committed: Fri Sep 12 14:59:48 2014 -0400

----------------------------------------------------------------------
 .../ambari/server/view/ViewArchiveUtility.java  | 120 ++++++
 .../ambari/server/view/ViewExtractor.java       | 223 ++++++++++
 .../apache/ambari/server/view/ViewRegistry.java | 429 ++++++-------------
 ambari-server/src/main/python/ambari-server.py  |  29 ++
 .../AmbariPrivilegeResourceProviderTest.java    |   2 +-
 .../ViewPrivilegeResourceProviderTest.java      |   2 +-
 .../ambari/server/view/ViewExtractorTest.java   | 262 +++++++++++
 .../ambari/server/view/ViewRegistryTest.java    | 105 +++--
 .../src/test/python/TestAmbariServer.py         |   8 +-
 9 files changed, 834 insertions(+), 346 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/093ed17d/ambari-server/src/main/java/org/apache/ambari/server/view/ViewArchiveUtility.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewArchiveUtility.java b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewArchiveUtility.java
new file mode 100644
index 0000000..f5f2732
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewArchiveUtility.java
@@ -0,0 +1,120 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.ambari.server.view;
+
+import org.apache.ambari.server.view.configuration.ViewConfig;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.jar.JarFile;
+
+/**
+ * Helper class for basic view archive utility.
+ */
+public class ViewArchiveUtility {
+
+  /**
+   * Constants
+   */
+  private static final String VIEW_XML = "view.xml";
+
+
+  // ----- ViewArchiveUtility ------------------------------------------------
+
+  /**
+   * Get the view configuration from the given archive file.
+   *
+   * @param archiveFile  the archive file
+   *
+   * @return the associated view configuration
+   */
+  public ViewConfig getViewConfigFromArchive(File archiveFile)
+      throws MalformedURLException, JAXBException {
+    ClassLoader cl = URLClassLoader.newInstance(new URL[]{archiveFile.toURI().toURL()});
+
+    InputStream configStream      = cl.getResourceAsStream(VIEW_XML);
+    JAXBContext jaxbContext       = JAXBContext.newInstance(ViewConfig.class);
+    Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
+
+    return (ViewConfig) jaxbUnmarshaller.unmarshal(configStream);
+  }
+
+  /**
+   * Get the view configuration from the extracted archive file.
+   *
+   * @param archivePath path to extracted archive
+   *
+   * @return the associated view configuration
+   *
+   * @throws JAXBException if xml is malformed
+   * @throws java.io.FileNotFoundException if xml was not found
+   */
+  public ViewConfig getViewConfigFromExtractedArchive(String archivePath)
+      throws JAXBException, FileNotFoundException {
+
+    InputStream configStream      = new FileInputStream(new File(archivePath + File.separator + VIEW_XML));
+    JAXBContext  jaxbContext      = JAXBContext.newInstance(ViewConfig.class);
+    Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
+
+    return (ViewConfig) jaxbUnmarshaller.unmarshal(configStream);
+  }
+
+  /**
+   * Get a new file instance for the given path.
+   *
+   * @param path  the path
+   *
+   * @return a new file instance
+   */
+  public File getFile(String path) {
+    return new File(path);
+  }
+
+  /**
+   * Get a new file output stream for the given file.
+   *
+   * @param file  the file
+   *
+   * @return a new file output stream
+   */
+  public FileOutputStream getFileOutputStream(File file) throws FileNotFoundException {
+    return new FileOutputStream(file);
+  }
+
+  /**
+   * Get a new jar file instance from the given file.
+   *
+   * @param file  the file
+   *
+   * @return a new jar file instance
+   */
+  public JarFile getJarFile(File file) throws IOException {
+    return new JarFile(file);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/093ed17d/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
new file mode 100644
index 0000000..368e92c
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewExtractor.java
@@ -0,0 +1,223 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.ambari.server.view;
+
+import org.apache.ambari.server.orm.entities.ViewEntity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.inject.Inject;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Enumeration;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+/**
+ * Extractor for view archives.
+ */
+public class ViewExtractor {
+
+  /**
+   * Constants
+   */
+  private static final String ARCHIVE_CLASSES_DIR = "WEB-INF/classes";
+  private static final String ARCHIVE_LIB_DIR     = "WEB-INF/lib";
+
+  @Inject
+  ViewArchiveUtility archiveUtility;
+
+  /**
+   * The logger.
+   */
+  protected final static Logger LOG = LoggerFactory.getLogger(ViewExtractor.class);
+
+
+  // ----- ViewExtractor -----------------------------------------------------
+
+  /**
+   * Extract the given view archive to the given archive directory.
+   *
+   * @param view         the view entity
+   * @param viewArchive  the view archive file
+   * @param archiveDir   the view archive directory
+   *
+   * @return the class loader for the archive classes
+   *
+   * @throws ExtractionException if the archive can not be extracted
+   */
+  public ClassLoader extractViewArchive(ViewEntity view, File viewArchive, File archiveDir)
+      throws ExtractionException {
+
+    String archivePath = archiveDir.getAbsolutePath();
+
+    try {
+      // Skip if the archive has already been extracted
+      if (!archiveDir.exists()) {
+
+        String msg = "Creating archive folder " + archivePath + ".";
+
+        view.setStatusDetail(msg);
+        LOG.info(msg);
+
+        if (archiveDir.mkdir()) {
+          JarFile viewJarFile = archiveUtility.getJarFile(viewArchive);
+          Enumeration enumeration = viewJarFile.entries();
+
+          msg = "Extracting files from " + viewArchive.getName() + ".";
+
+          view.setStatusDetail(msg);
+          LOG.info(msg);
+
+          while (enumeration.hasMoreElements()) {
+            JarEntry jarEntry  = (JarEntry) enumeration.nextElement();
+            String   entryPath = archivePath + File.separator + jarEntry.getName();
+
+            File entryFile = archiveUtility.getFile(entryPath);
+
+            if (jarEntry.isDirectory()) {
+              if (!entryFile.mkdir()) {
+                msg = "Could not create archive entry directory " + entryPath + ".";
+
+                view.setStatusDetail(msg);
+                LOG.error(msg);
+                throw new ExtractionException(msg);
+              }
+            } else {
+              InputStream is = viewJarFile.getInputStream(jarEntry);
+              try {
+                FileOutputStream fos = archiveUtility.getFileOutputStream(entryFile);
+                try {
+                  while (is.available() > 0) {
+                    fos.write(is.read());
+                  }
+                } finally {
+                  fos.close();
+                }
+              } finally {
+                is.close();
+              }
+            }
+          }
+        } else {
+          msg = "Could not create archive directory " + archivePath + ".";
+
+          view.setStatusDetail(msg);
+          LOG.error(msg);
+          throw new ExtractionException(msg);
+        }
+      }
+      return getArchiveClassLoader(archiveDir);
+
+    } catch (Exception e) {
+      String msg = "Caught exception trying to extract the view archive " + archivePath + ".";
+
+      view.setStatusDetail(msg);
+      LOG.error(msg, e);
+      throw new ExtractionException(msg, e);
+    }
+  }
+
+  /**
+   * Ensure that the extracted view archive directory exists.
+   *
+   * @param extractedArchivesPath  the path
+   *
+   * @return false if the directory does not exist and can not be created
+   */
+  public boolean ensureExtractedArchiveDirectory(String extractedArchivesPath) {
+
+    File extractedArchiveDir = archiveUtility.getFile(extractedArchivesPath);
+
+    return extractedArchiveDir.exists() || extractedArchiveDir.mkdir();
+  }
+
+
+  // ----- archiveUtility methods ----------------------------------------------------
+
+  // get a class loader for the given archive directory
+  private ClassLoader getArchiveClassLoader(File archiveDir)
+      throws MalformedURLException {
+
+    String    archivePath = archiveDir.getAbsolutePath();
+    List<URL> urlList     = new LinkedList<URL>();
+
+    // include the classes directory
+    String classesPath = archivePath + File.separator + ARCHIVE_CLASSES_DIR;
+    File   classesDir  = archiveUtility.getFile(classesPath);
+    if (classesDir.exists()) {
+      urlList.add(classesDir.toURI().toURL());
+    }
+
+    // include any libraries in the lib directory
+    String libPath = archivePath + File.separator + ARCHIVE_LIB_DIR;
+    File   libDir  = archiveUtility.getFile(libPath);
+    if (libDir.exists()) {
+      File[] files = libDir.listFiles();
+      if (files != null) {
+        for (final File fileEntry : files) {
+          if (!fileEntry.isDirectory()) {
+            urlList.add(fileEntry.toURI().toURL());
+          }
+        }
+      }
+    }
+
+    // include the archive directory
+    urlList.add(archiveDir.toURI().toURL());
+
+    return URLClassLoader.newInstance(urlList.toArray(new URL[urlList.size()]));
+  }
+
+
+  // ----- inner class : ExtractionException ---------------------------------
+
+  /**
+   * General exception for view archive extraction.
+   */
+  public static class ExtractionException extends Exception {
+
+    // ----- Constructors ----------------------------------------------------
+
+    /**
+     * Construct an extraction exception.
+     *
+     * @param msg  the exception message
+     */
+    public ExtractionException(String msg) {
+      super(msg);
+    }
+
+    /**
+     * Construct an extraction exception.
+     *
+     * @param msg        the exception message
+     * @param throwable  the root cause
+     */
+    public ExtractionException(String msg, Throwable throwable) {
+      super(msg, throwable);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/093ed17d/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
index 509e474..1c6c792 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
@@ -18,46 +18,17 @@
 
 package org.apache.ambari.server.view;
 
-import java.beans.IntrospectionException;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBException;
-import javax.xml.bind.Unmarshaller;
-
 import com.google.common.collect.Sets;
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
 import org.apache.ambari.server.api.resources.ResourceInstanceFactoryImpl;
 import org.apache.ambari.server.api.resources.SubResourceDefinition;
 import org.apache.ambari.server.api.resources.ViewExternalSubResourceDefinition;
 import org.apache.ambari.server.api.services.ViewExternalSubResourceService;
 import org.apache.ambari.server.api.services.ViewSubResourceService;
 import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.controller.ControllerModule;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.orm.dao.MemberDAO;
 import org.apache.ambari.server.orm.dao.PrivilegeDAO;
@@ -103,9 +74,22 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.security.core.GrantedAuthority;
 
-import com.google.inject.AbstractModule;
-import com.google.inject.Guice;
-import com.google.inject.Injector;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import java.beans.IntrospectionException;
+import java.io.File;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Registry for view and view instance definitions.
@@ -116,9 +100,6 @@ public class ViewRegistry {
   /**
    * Constants
    */
-  private static final String VIEW_XML = "view.xml";
-  private static final String ARCHIVE_CLASSES_DIR = "WEB-INF/classes";
-  private static final String ARCHIVE_LIB_DIR = "WEB-INF/lib";
   private static final String EXTRACTED_ARCHIVES_DIR = "work";
 
   /**
@@ -150,11 +131,6 @@ public class ViewRegistry {
       new ConcurrentHashMap<String, Set<Listener>>();
 
   /**
-   * Helper class.
-   */
-  private ViewRegistryHelper helper = new ViewRegistryHelper();
-
-  /**
    * The singleton view registry instance.
    */
   private static ViewRegistry singleton;
@@ -224,10 +200,37 @@ public class ViewRegistry {
   @Inject
   ViewInstanceHandlerList handlerList;
 
+  /**
+   * The view extractor;
+   */
+  @Inject
+  ViewExtractor extractor;
+
+  /**
+   * The view archive utility.
+   */
+  @Inject
+  ViewArchiveUtility archiveUtility;
+
 
   // ----- ViewRegistry ------------------------------------------------------
 
   /**
+   * Registry main method.
+   *
+   * @param args  the command line arguments
+   *
+   * @throws Exception if the registry command can not be completed
+   */
+  public static void main(String[] args) throws Exception {
+
+    Injector injector = Guice.createInjector(new ControllerModule());
+    initInstance(injector.getInstance(ViewRegistry.class));
+
+    singleton.readViewArchives(true, false);
+  }
+
+  /**
    * Get the collection of all the view definitions.
    *
    * @return the collection of view definitions
@@ -396,56 +399,10 @@ public class ViewRegistry {
   }
 
   /**
-   * Asynchronously read the view archives.
+   * Read the view archives.
    */
   public void readViewArchives() {
-
-    final ExecutorService executorService = getExecutorService(configuration);
-
-    // submit a task to manage the extraction tasks
-    executorService.submit(new Runnable() {
-      @Override
-      public void run() {
-
-        try {
-          File viewDir = configuration.getViewsDir();
-
-          String extractedArchivesPath = viewDir.getAbsolutePath() +
-              File.separator + EXTRACTED_ARCHIVES_DIR;
-
-          if (ensureExtractedArchiveDirectory(extractedArchivesPath)) {
-            File[] files = viewDir.listFiles();
-
-            if (files != null) {
-              for (final File archiveFile : files) {
-                if (!archiveFile.isDirectory()) {
-
-                  final ViewConfig viewConfig = helper.getViewConfigFromArchive(archiveFile);
-
-                  String commonName = viewConfig.getName();
-                  String version    = viewConfig.getVersion();
-                  String viewName   = ViewEntity.getViewName(commonName, version);
-
-                  final String     archivePath    = extractedArchivesPath + File.separator + viewName;
-                  final ViewEntity viewDefinition = new ViewEntity(viewConfig, configuration, archivePath);
-
-                  // submit a new task for each archive being read
-                  executorService.submit(new Runnable() {
-                    @Override
-                    public void run() {
-                      readViewArchive(viewDefinition, archiveFile, archivePath, viewConfig);
-                    }
-                  });
-                }
-              }
-              removeUndeployedViews();
-            }
-          }
-        } catch (Exception e) {
-          LOG.error("Caught exception reading view archives.", e);
-        }
-      }
-    });
+    readViewArchives(false, true);
   }
 
   /**
@@ -757,15 +714,6 @@ public class ViewRegistry {
     listeners.clear();
   }
 
-  /**
-   * Set the helper.
-   *
-   * @param helper  the helper
-   */
-  protected void setHelper(ViewRegistryHelper helper) {
-    this.helper = helper;
-  }
-
   // get a view entity for the given internal view name
   private ViewEntity getDefinition(String viewName) {
     return viewDefinitions.get(viewName);
@@ -1115,110 +1063,6 @@ public class ViewRegistry {
     return resourceEntity;
   }
 
-  // ensure that the extracted view archive directory exists
-  private boolean ensureExtractedArchiveDirectory(String extractedArchivesPath) {
-    File extractedArchiveDir = helper.getFile(extractedArchivesPath);
-
-    if (!extractedArchiveDir.exists()) {
-      if (!extractedArchiveDir.mkdir()) {
-        LOG.error("Could not create extracted view archive directory " +
-            extractedArchivesPath + ".");
-        return false;
-      }
-    }
-    return true;
-  }
-
-  // extract the given view archive to the given archive directory
-  private ClassLoader extractViewArchive(ViewEntity viewDefinition, File viewArchive, File archiveDir)
-      throws IOException {
-
-    // Skip if the archive has already been extracted
-    if (!archiveDir.exists()) {
-
-      String archivePath = archiveDir.getAbsolutePath();
-
-      String msg = "Creating archive folder " + archivePath + ".";
-      LOG.info(msg);
-      setViewStatus(viewDefinition, ViewDefinition.ViewStatus.LOADING, msg);
-
-      if (archiveDir.mkdir()) {
-        JarFile     viewJarFile = helper.getJarFile(viewArchive);
-        Enumeration enumeration = viewJarFile.entries();
-
-        msg = "Extracting files from " + viewArchive.getName() + ":";
-        LOG.info(msg);
-        setViewStatus(viewDefinition, ViewDefinition.ViewStatus.LOADING, msg);
-
-        while (enumeration.hasMoreElements()) {
-          JarEntry jarEntry  = (JarEntry) enumeration.nextElement();
-          String   entryPath = archivePath + File.separator + jarEntry.getName();
-
-          LOG.info("    " + entryPath);
-
-          File entryFile = helper.getFile(entryPath);
-
-          if (jarEntry.isDirectory()) {
-            if (!entryFile.mkdir()) {
-              LOG.error("Could not create archive entry directory " + entryPath + ".");
-            }
-          } else {
-            InputStream is = viewJarFile.getInputStream(jarEntry);
-            try {
-              FileOutputStream fos = helper.getFileOutputStream(entryFile);
-              try {
-                while (is.available() > 0) {
-                  fos.write(is.read());
-                }
-              } finally {
-                fos.close();
-              }
-            } finally {
-              is.close();
-            }
-          }
-        }
-      } else {
-        LOG.error("Could not create archive directory " + archivePath + ".");
-      }
-    }
-    return getArchiveClassLoader(archiveDir);
-  }
-
-  // get a class loader for the given archive directory
-  private ClassLoader getArchiveClassLoader(File archiveDir)
-      throws MalformedURLException {
-
-    String    archivePath = archiveDir.getAbsolutePath();
-    List<URL> urlList     = new LinkedList<URL>();
-
-    // include the classes directory
-    String classesPath = archivePath + File.separator + ARCHIVE_CLASSES_DIR;
-    File   classesDir  = helper.getFile(classesPath);
-    if (classesDir.exists()) {
-      urlList.add(classesDir.toURI().toURL());
-    }
-
-    // include any libraries in the lib directory
-    String libPath = archivePath + File.separator + ARCHIVE_LIB_DIR;
-    File   libDir  = helper.getFile(libPath);
-    if (libDir.exists()) {
-      File[] files = libDir.listFiles();
-      if (files != null) {
-        for (final File fileEntry : files) {
-          if (!fileEntry.isDirectory()) {
-            urlList.add(fileEntry.toURI().toURL());
-          }
-        }
-      }
-    }
-
-    // include the archive directory
-    urlList.add(archiveDir.toURI().toURL());
-
-    return URLClassLoader.newInstance(urlList.toArray(new URL[urlList.size()]));
-  }
-
   // notify the view identified by the given view name of the given event
   private void fireEvent(Event event, String viewName) {
     Set<Listener> listeners = this.listeners.get(viewName);
@@ -1265,22 +1109,94 @@ public class ViewRegistry {
     }
   }
 
-  // read a view archive and return the set of new view instances
+
+  // read the view archives.
+  private void readViewArchives(boolean systemOnly, boolean useExecutor) {
+    try {
+      File viewDir = configuration.getViewsDir();
+
+      String extractedArchivesPath = viewDir.getAbsolutePath() +
+          File.separator + EXTRACTED_ARCHIVES_DIR;
+
+      if (extractor.ensureExtractedArchiveDirectory(extractedArchivesPath)) {
+
+        File[] files  = viewDir.listFiles();
+
+        if (files != null) {
+
+          Set<Runnable> extractionRunnables = new HashSet<Runnable>();
+
+          for (final File archiveFile : files) {
+            if (!archiveFile.isDirectory()) {
+
+              final ViewConfig viewConfig = archiveUtility.getViewConfigFromArchive(archiveFile);
+
+              String commonName = viewConfig.getName();
+              String version    = viewConfig.getVersion();
+              String viewName   = ViewEntity.getViewName(commonName, version);
+
+              final String extractedArchiveDirPath = extractedArchivesPath + File.separator + viewName;
+              final File extractedArchiveDirFile = archiveUtility.getFile(extractedArchiveDirPath);
+
+              final ViewEntity viewDefinition = new ViewEntity(viewConfig, configuration, extractedArchiveDirPath);
+
+              boolean systemView = viewDefinition.isSystem();
+
+              if (!systemOnly || systemView) {
+                // update the registry with the view
+                addDefinition(viewDefinition);
+
+                // always load system views up front
+                if (systemView || !useExecutor || extractedArchiveDirFile.exists()) {
+                  // if the archive is already extracted then load the view now
+                  readViewArchive(viewDefinition, archiveFile, extractedArchiveDirFile, viewConfig);
+                } else {
+                  // if the archive needs to be extracted then create a runnable to do it
+                  extractionRunnables.add(new Runnable() {
+                    @Override
+                    public void run() {
+                      readViewArchive(viewDefinition, archiveFile, extractedArchiveDirFile, viewConfig);
+                    }
+                  });
+                }
+              }
+            }
+          }
+
+          if (useExecutor && extractionRunnables.size() > 0) {
+            final ExecutorService executorService = getExecutorService(configuration);
+
+            for (Runnable runnable : extractionRunnables) {
+              // submit a new task for each archive that needs extraction
+              executorService.submit(runnable);
+            }
+          }
+
+          removeUndeployedViews();
+        }
+      } else {
+        LOG.error("Could not create extracted view archive directory " + extractedArchivesPath + ".");
+      }
+    } catch (Exception e) {
+      LOG.error("Caught exception reading view archives.", e);
+    }
+  }
+
+  // read a view archive
   private void readViewArchive(ViewEntity viewDefinition,
                                                   File archiveFile,
-                                                  String archivePath,
+                                                  File extractedArchiveDirFile,
                                                   ViewConfig viewConfig) {
 
-    setViewStatus(viewDefinition, ViewEntity.ViewStatus.LOADING, "Loading " + archivePath + ".");
+    setViewStatus(viewDefinition, ViewEntity.ViewStatus.LOADING, "Loading " + extractedArchiveDirFile + ".");
 
-    try {
-      // update the registry with the view
-      addDefinition(viewDefinition);
+    String extractedArchiveDirPath = extractedArchiveDirFile.getAbsolutePath();
 
+    try {
       // extract the archive and get the class loader
-      ClassLoader cl = extractViewArchive(viewDefinition, archiveFile, helper.getFile(archivePath));
+      ClassLoader cl = extractor.extractViewArchive(viewDefinition, archiveFile, extractedArchiveDirFile);
 
-      viewConfig = helper.getViewConfigFromExtractedArchive(archivePath);
+      viewConfig = archiveUtility.getViewConfigFromExtractedArchive(extractedArchiveDirPath);
 
       setupViewDefinition(viewDefinition, viewConfig, cl);
 
@@ -1301,12 +1217,12 @@ public class ViewRegistry {
         addInstanceDefinition(viewDefinition, instanceEntity);
         handlerList.addViewInstance(instanceEntity);
       }
-      setViewStatus(viewDefinition, ViewEntity.ViewStatus.LOADED, "Loaded " + archivePath + ".");
+      setViewStatus(viewDefinition, ViewEntity.ViewStatus.LOADED, "Loaded " + extractedArchiveDirPath + ".");
 
     } catch (Exception e) {
-      String msg = "Caught exception loading view " + viewDefinition.getViewName() + " : " + e.getMessage();
+      String msg = "Caught exception loading view " + viewDefinition.getViewName();
 
-      setViewStatus(viewDefinition, ViewEntity.ViewStatus.ERROR, msg);
+      setViewStatus(viewDefinition, ViewEntity.ViewStatus.ERROR, msg + " : " + e.getMessage());
       LOG.error(msg, e);
     }
   }
@@ -1334,85 +1250,4 @@ public class ViewRegistry {
     }
     return executorService;
   }
-
-
-
-  // ----- inner class : ViewRegistryHelper ----------------------------------
-
-  /**
-   * Registry helper class.
-   */
-  protected static class ViewRegistryHelper {
-
-    /**
-     * Get the view configuration from the given archive file.
-     *
-     * @param archiveFile  the archive file
-     *
-     * @return the associated view configuration
-     */
-    public ViewConfig getViewConfigFromArchive(File archiveFile)
-        throws MalformedURLException, JAXBException {
-      ClassLoader cl = URLClassLoader.newInstance(new URL[]{archiveFile.toURI().toURL()});
-
-      InputStream  configStream     = cl.getResourceAsStream(VIEW_XML);
-      JAXBContext  jaxbContext      = JAXBContext.newInstance(ViewConfig.class);
-      Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
-
-      return (ViewConfig) jaxbUnmarshaller.unmarshal(configStream);
-    }
-
-    /**
-     * Get the view configuration from the extracted archive file.
-     *
-     * @param archivePath path to extracted archive
-     *
-     * @return the associated view configuration
-     *
-     * @throws JAXBException if xml is malformed
-     * @throws FileNotFoundException if xml was not found
-     */
-    public ViewConfig getViewConfigFromExtractedArchive(String archivePath)
-        throws JAXBException, FileNotFoundException {
-
-      InputStream configStream      = new FileInputStream(new File(archivePath + File.separator + VIEW_XML));
-      JAXBContext  jaxbContext      = JAXBContext.newInstance(ViewConfig.class);
-      Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
-
-      return (ViewConfig) jaxbUnmarshaller.unmarshal(configStream);
-    }
-
-    /**
-     * Get a new file instance for the given path.
-     *
-     * @param path  the path
-     *
-     * @return a new file instance
-     */
-    public File getFile(String path) {
-      return new File(path);
-    }
-
-    /**
-     * Get a new file output stream for the given file.
-     *
-     * @param file  the file
-     *
-     * @return a new file output stream
-     */
-    public FileOutputStream getFileOutputStream(File file) throws FileNotFoundException {
-      return new FileOutputStream(file);
-    }
-
-    /**
-     * Get a new jar file instance from the given file.
-     *
-     * @param file  the file
-     *
-     * @return a new jar file instance
-     */
-    public JarFile getJarFile(File file) throws IOException {
-      return new JarFile(file);
-    }
-  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/093ed17d/ambari-server/src/main/python/ambari-server.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/python/ambari-server.py b/ambari-server/src/main/python/ambari-server.py
index 50420b2..319d1d4 100755
--- a/ambari-server/src/main/python/ambari-server.py
+++ b/ambari-server/src/main/python/ambari-server.py
@@ -185,6 +185,14 @@ STACK_UPGRADE_HELPER_CMD = "{0}" + os.sep + "bin" + os.sep + "java -cp {1}" +\
                           os.pathsep + "{2} " +\
                           "org.apache.ambari.server.upgrade.StackUpgradeHelper" +\
                           " {3} {4} > " + SERVER_OUT_FILE + " 2>&1"
+
+
+VIEW_EXTRACT_CMD = "{0}" + os.sep + "bin" + os.sep + "java -cp {1}" +\
+                          os.pathsep + "{2} " +\
+                          "org.apache.ambari.server.view.ViewRegistry " +\
+                          "> " + SERVER_OUT_FILE + " 2>&1"
+
+
 ULIMIT_CMD = "ulimit -n"
 SERVER_INIT_TIMEOUT = 5
 SERVER_START_TIMEOUT = 10
@@ -1215,6 +1223,21 @@ def prompt_db_properties(args):
     password=args.database_password
   ))
 
+# extract the system views
+def extract_views():
+  jdk_path = find_jdk()
+  if jdk_path is None:
+    print_error_msg("No JDK found, please run the \"setup\" "
+                    "command to install a JDK automatically or install any "
+                    "JDK manually to " + JDK_INSTALL_DIR)
+    return 1
+
+  command = VIEW_EXTRACT_CMD.format(jdk_path, get_conf_dir(),
+    get_ambari_classpath())
+  (retcode, stdout, stderr) = run_os_command(command)
+  print_info_msg("Return code from view extraction: " +
+                 str(retcode))
+  return retcode
 
 # Store set of properties for remote database connection
 def store_remote_properties(args):
@@ -2258,6 +2281,12 @@ def setup(args):
       raise FatalException(retcode, err)
     check_jdbc_drivers(args)
 
+  print 'Extracting system views...'
+  retcode = extract_views()
+  if not retcode == 0:
+    err = 'Error while extracting system views. Exiting'
+    raise FatalException(retcode, err)
+
 
 def proceedJDBCProperties(args):
   if not os.path.isfile(args.jdbc_driver):

http://git-wip-us.apache.org/repos/asf/ambari/blob/093ed17d/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AmbariPrivilegeResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AmbariPrivilegeResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AmbariPrivilegeResourceProviderTest.java
index f6a49cf..fa342fe 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AmbariPrivilegeResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AmbariPrivilegeResourceProviderTest.java
@@ -98,7 +98,7 @@ public class AmbariPrivilegeResourceProviderTest {
   @Before
   public void resetGlobalMocks() {
     ViewRegistry.initInstance(ViewRegistryTest.getRegistry(viewDAO, viewInstanceDAO, userDAO,
-        memberDAO, privilegeDAO, resourceDAO, resourceTypeDAO, securityHelper, handlerList));
+        memberDAO, privilegeDAO, resourceDAO, resourceTypeDAO, securityHelper, handlerList, null, null));
     reset(privilegeDAO, userDAO, groupDAO, principalDAO, permissionDAO, resourceDAO, clusterDAO, handlerList);
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/093ed17d/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ViewPrivilegeResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ViewPrivilegeResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ViewPrivilegeResourceProviderTest.java
index eb4ef9c..0e9d3d6 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ViewPrivilegeResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ViewPrivilegeResourceProviderTest.java
@@ -90,7 +90,7 @@ public class ViewPrivilegeResourceProviderTest {
   public void resetGlobalMocks() {
 
     ViewRegistry.initInstance(ViewRegistryTest.getRegistry(viewDAO, viewInstanceDAO, userDAO,
-        memberDAO, privilegeDAO, resourceDAO, resourceTypeDAO, securityHelper, handlerList));
+        memberDAO, privilegeDAO, resourceDAO, resourceTypeDAO, securityHelper, handlerList, null, null));
     reset(privilegeDAO, userDAO, groupDAO, principalDAO, permissionDAO, resourceDAO, handlerList);
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/093ed17d/ambari-server/src/test/java/org/apache/ambari/server/view/ViewExtractorTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/ViewExtractorTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewExtractorTest.java
new file mode 100644
index 0000000..1b71c37
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewExtractorTest.java
@@ -0,0 +1,262 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.ambari.server.view;
+
+import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.orm.dao.ViewDAO;
+import org.apache.ambari.server.orm.entities.ResourceTypeEntity;
+import org.apache.ambari.server.orm.entities.ViewEntity;
+import org.apache.ambari.server.orm.entities.ViewEntityTest;
+import org.apache.ambari.server.view.configuration.ViewConfig;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.xml.bind.JAXBException;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+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.reset;
+import static org.easymock.EasyMock.verify;
+
+/**
+ * ViewExtractor tests.
+ */
+public class ViewExtractorTest {
+
+  private static final File extractedArchiveDir = createNiceMock(File.class);
+  private static final File viewArchive = createNiceMock(File.class);
+  private static final File archiveDir = createNiceMock(File.class);
+  private static final File entryFile  = createNiceMock(File.class);
+  private static final File classesDir = createNiceMock(File.class);
+  private static final File libDir = createNiceMock(File.class);
+  private static final JarFile viewJarFile = createNiceMock(JarFile.class);
+  private static final JarEntry jarEntry = createNiceMock(JarEntry.class);
+  private static final InputStream is = createMock(InputStream.class);
+  private static final FileOutputStream fos = createMock(FileOutputStream.class);
+  private static final Configuration configuration = createNiceMock(Configuration.class);
+  private static final File viewDir = createNiceMock(File.class);
+  private static final Enumeration<JarEntry> enumeration = createMock(Enumeration.class);
+  private static final File fileEntry = createNiceMock(File.class);
+  private static final ViewDAO viewDAO = createMock(ViewDAO.class);
+
+  @Before
+  public void resetGlobalMocks() {
+    reset(extractedArchiveDir, viewArchive,archiveDir,entryFile, classesDir, libDir, viewJarFile,
+        jarEntry, is, fos, configuration, viewDir, enumeration, fileEntry, viewDAO);
+  }
+
+  @Test
+  public void testExtractViewArchive() throws Exception {
+
+    ResourceTypeEntity resourceTypeEntity = new ResourceTypeEntity();
+    resourceTypeEntity.setId(10);
+    resourceTypeEntity.setName("MY_VIEW{1.0.0}");
+
+    ViewEntity viewDefinition = ViewEntityTest.getViewEntity();
+    viewDefinition.setResourceType(resourceTypeEntity);
+
+    // set expectations
+    expect(configuration.getViewExtractionThreadPoolCoreSize()).andReturn(2).anyTimes();
+    expect(configuration.getViewExtractionThreadPoolMaxSize()).andReturn(3).anyTimes();
+    expect(configuration.getViewExtractionThreadPoolTimeout()).andReturn(10000L).anyTimes();
+
+    expect(viewArchive.getAbsolutePath()).andReturn(
+        "/var/lib/ambari-server/resources/views/work/MY_VIEW{1.0.0}").anyTimes();
+
+    expect(archiveDir.exists()).andReturn(false);
+    expect(archiveDir.getAbsolutePath()).andReturn(
+        "/var/lib/ambari-server/resources/views/work/MY_VIEW{1.0.0}").anyTimes();
+    expect(archiveDir.mkdir()).andReturn(true);
+    expect(archiveDir.toURI()).andReturn(new URI("file:./"));
+
+    expect(viewJarFile.entries()).andReturn(enumeration);
+    expect(viewJarFile.getInputStream(jarEntry)).andReturn(is);
+
+    expect(enumeration.hasMoreElements()).andReturn(true);
+    expect(enumeration.hasMoreElements()).andReturn(false);
+    expect(enumeration.nextElement()).andReturn(jarEntry);
+
+    expect(jarEntry.getName()).andReturn("view.xml");
+
+    expect(is.available()).andReturn(1);
+    expect(is.available()).andReturn(0);
+
+    expect(is.read()).andReturn(10);
+    fos.write(10);
+
+    fos.close();
+    is.close();
+
+    expect(classesDir.exists()).andReturn(true);
+    expect(classesDir.toURI()).andReturn(new URI("file:./"));
+
+    expect(libDir.exists()).andReturn(true);
+
+    expect(libDir.listFiles()).andReturn(new File[]{fileEntry});
+    expect(fileEntry.toURI()).andReturn(new URI("file:./"));
+
+    replay(extractedArchiveDir, viewArchive, archiveDir, entryFile, classesDir, libDir, viewJarFile,
+        jarEntry, is, fos, configuration, viewDir, enumeration, fileEntry, viewDAO);
+
+    ViewExtractor viewExtractor = getViewExtractor(viewDefinition);
+    viewExtractor.extractViewArchive(viewDefinition, viewArchive, archiveDir);
+
+    verify(extractedArchiveDir, viewArchive, archiveDir, entryFile, classesDir, libDir, viewJarFile,
+        jarEntry, is, fos, configuration, viewDir, enumeration, fileEntry, viewDAO);
+  }
+
+  @Test
+  public void testEnsureExtractedArchiveDirectory() throws Exception {
+
+    ResourceTypeEntity resourceTypeEntity = new ResourceTypeEntity();
+    resourceTypeEntity.setId(10);
+    resourceTypeEntity.setName("MY_VIEW{1.0.0}");
+
+    ViewEntity viewDefinition = ViewEntityTest.getViewEntity();
+    viewDefinition.setResourceType(resourceTypeEntity);
+
+    expect(extractedArchiveDir.exists()).andReturn(true);
+
+    replay(extractedArchiveDir, viewArchive, archiveDir, entryFile, classesDir, libDir, viewJarFile,
+        jarEntry, is, fos, configuration, viewDir, enumeration, fileEntry, viewDAO);
+
+    ViewExtractor viewExtractor = getViewExtractor(viewDefinition);
+
+    Assert.assertTrue(viewExtractor.ensureExtractedArchiveDirectory("/var/lib/ambari-server/resources/views/work"));
+
+    verify(extractedArchiveDir, viewArchive, archiveDir, entryFile, classesDir, libDir, viewJarFile,
+        jarEntry, is, fos, configuration, viewDir, enumeration, fileEntry, viewDAO);
+
+    reset(extractedArchiveDir);
+
+    expect(extractedArchiveDir.exists()).andReturn(false);
+    expect(extractedArchiveDir.mkdir()).andReturn(true);
+
+    replay(extractedArchiveDir);
+
+    viewExtractor = getViewExtractor(viewDefinition);
+
+    Assert.assertTrue(viewExtractor.ensureExtractedArchiveDirectory("/var/lib/ambari-server/resources/views/work"));
+
+    verify(extractedArchiveDir);
+
+    reset(extractedArchiveDir);
+
+    expect(extractedArchiveDir.exists()).andReturn(false);
+    expect(extractedArchiveDir.mkdir()).andReturn(false);
+
+    replay(extractedArchiveDir);
+
+    viewExtractor = getViewExtractor(viewDefinition);
+
+    Assert.assertFalse(viewExtractor.ensureExtractedArchiveDirectory("/var/lib/ambari-server/resources/views/work"));
+
+    verify(extractedArchiveDir);
+  }
+
+  private ViewExtractor getViewExtractor(ViewEntity viewDefinition) throws Exception {
+
+    Map<File, ViewConfig> viewConfigs =
+        Collections.singletonMap(viewArchive, viewDefinition.getConfiguration());
+
+    Map<String, File> files = new HashMap<String, File>();
+
+    files.put("/var/lib/ambari-server/resources/views/work", extractedArchiveDir);
+    files.put("/var/lib/ambari-server/resources/views/work/MY_VIEW{1.0.0}", archiveDir);
+    files.put("/var/lib/ambari-server/resources/views/work/MY_VIEW{1.0.0}/view.xml", entryFile);
+    files.put("/var/lib/ambari-server/resources/views/work/MY_VIEW{1.0.0}/WEB-INF/classes", classesDir);
+    files.put("/var/lib/ambari-server/resources/views/work/MY_VIEW{1.0.0}/WEB-INF/lib", libDir);
+
+    Map<File, FileOutputStream> outputStreams = new HashMap<File, FileOutputStream>();
+    outputStreams.put(entryFile, fos);
+
+    Map<File, JarFile> jarFiles = new HashMap<File, JarFile>();
+    jarFiles.put(viewArchive, viewJarFile);
+
+    TestViewArchiveUtility archiveUtility = new TestViewArchiveUtility(viewConfigs, files, outputStreams, jarFiles);
+
+
+
+    ViewExtractor viewExtractor = new ViewExtractor();
+    viewExtractor.archiveUtility = archiveUtility;
+
+    return viewExtractor;
+  }
+
+  public static class TestViewArchiveUtility extends ViewArchiveUtility {
+    private final Map<File, ViewConfig> viewConfigs;
+    private final Map<String, File> files;
+    private final Map<File, FileOutputStream> outputStreams;
+    private final Map<File, JarFile> jarFiles;
+
+    public TestViewArchiveUtility(Map<File, ViewConfig> viewConfigs, Map<String, File> files, Map<File,
+        FileOutputStream> outputStreams, Map<File, JarFile> jarFiles) {
+      this.viewConfigs = viewConfigs;
+      this.files = files;
+      this.outputStreams = outputStreams;
+      this.jarFiles = jarFiles;
+    }
+
+    @Override
+    public ViewConfig getViewConfigFromArchive(File archiveFile) throws MalformedURLException, JAXBException {
+      return viewConfigs.get(archiveFile);
+    }
+
+    public ViewConfig getViewConfigFromExtractedArchive(String archivePath)
+        throws JAXBException, FileNotFoundException {
+      for (File viewConfigKey: viewConfigs.keySet()) {
+        if (viewConfigKey.getAbsolutePath().equals(archivePath)) {
+          return viewConfigs.get(viewConfigKey);
+        }
+      }
+      return null;
+    }
+
+    @Override
+    public File getFile(String path) {
+      return files.get(path);
+    }
+
+    @Override
+    public FileOutputStream getFileOutputStream(File file) throws FileNotFoundException {
+      return outputStreams.get(file);
+    }
+
+    @Override
+    public JarFile getJarFile(File file) throws IOException {
+      return jarFiles.get(file);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/093ed17d/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 38c2f9b..0915325 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
@@ -83,6 +83,7 @@ import org.apache.ambari.view.events.Event;
 import org.apache.ambari.view.events.Listener;
 import org.easymock.EasyMock;
 import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
 import org.springframework.security.core.GrantedAuthority;
@@ -164,9 +165,18 @@ public class ViewRegistryTest {
   private static final Configuration configuration = createNiceMock(Configuration.class);
   private static final ViewInstanceHandlerList handlerList = createNiceMock(ViewInstanceHandlerList.class);
 
+
+  @Before
+  public void resetGlobalMocks() {
+    ViewRegistry.initInstance(getRegistry(viewDAO, viewInstanceDAO, userDAO, memberDAO, privilegeDAO,
+        resourceDAO, resourceTypeDAO, securityHelper, handlerList, null, null));
+
+    reset(viewDAO, resourceDAO, viewInstanceDAO, userDAO, memberDAO,
+        privilegeDAO, resourceTypeDAO, securityHelper, configuration, handlerList);
+  }
+
   @Test
   public void testReadViewArchives() throws Exception {
-    ViewRegistry registry = getRegistry();
 
     File viewDir = createNiceMock(File.class);
     File extractedArchiveDir = createNiceMock(File.class);
@@ -275,7 +285,10 @@ public class ViewRegistryTest {
     replay(configuration, viewDir, extractedArchiveDir, viewArchive, archiveDir, entryFile, classesDir,
         libDir, fileEntry, viewJarFile, enumeration, jarEntry, is, fos, resourceDAO, viewDAO, viewInstanceDAO);
 
-    registry.setHelper(new TestViewRegistryHelper(viewConfigs, files, outputStreams, jarFiles));
+    TestViewArchiveUtility archiveUtility = new TestViewArchiveUtility(viewConfigs, files, outputStreams, jarFiles);
+
+    ViewRegistry registry = getRegistry(viewDAO, viewInstanceDAO, userDAO, memberDAO, privilegeDAO,
+        resourceDAO, resourceTypeDAO, securityHelper, handlerList, null, archiveUtility);
 
     registry.readViewArchives();
 
@@ -298,10 +311,8 @@ public class ViewRegistryTest {
         libDir, fileEntry, viewJarFile, enumeration, jarEntry, is, fos, resourceDAO, viewDAO, viewInstanceDAO);
   }
 
-  @Ignore
   @Test
   public void testReadViewArchives_exception() throws Exception {
-    ViewRegistry registry = getRegistry();
 
     File viewDir = createNiceMock(File.class);
     File extractedArchiveDir = createNiceMock(File.class);
@@ -357,6 +368,10 @@ public class ViewRegistryTest {
     expect(configuration.getViewsDir()).andReturn(viewDir);
     expect(viewDir.getAbsolutePath()).andReturn("/var/lib/ambari-server/resources/views");
 
+    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(viewArchive.isDirectory()).andReturn(false);
@@ -405,7 +420,10 @@ public class ViewRegistryTest {
     replay(configuration, viewDir, extractedArchiveDir, viewArchive, archiveDir, entryFile, classesDir,
         libDir, fileEntry, viewJarFile, enumeration, jarEntry, is, fos, viewDAO);
 
-    registry.setHelper(new TestViewRegistryHelper(viewConfigs, files, outputStreams, jarFiles));
+    TestViewArchiveUtility archiveUtility = new TestViewArchiveUtility(viewConfigs, files, outputStreams, jarFiles);
+
+    ViewRegistry registry = getRegistry(viewDAO, viewInstanceDAO, userDAO, memberDAO, privilegeDAO,
+        resourceDAO, resourceTypeDAO, securityHelper, handlerList, null, archiveUtility);
 
     registry.readViewArchives();
 
@@ -428,7 +446,7 @@ public class ViewRegistryTest {
 
   @Test
   public void testListener() throws Exception {
-    ViewRegistry registry = getRegistry();
+    ViewRegistry registry = ViewRegistry.getInstance();
 
     TestListener listener = new TestListener();
     registry.registerListener(listener, "MY_VIEW", "1.0.0");
@@ -460,7 +478,7 @@ public class ViewRegistryTest {
 
   @Test
   public void testListener_allVersions() throws Exception {
-    ViewRegistry registry = getRegistry();
+    ViewRegistry registry = ViewRegistry.getInstance();
 
     TestListener listener = new TestListener();
     registry.registerListener(listener, "MY_VIEW", null); // all versions of MY_VIEW
@@ -502,7 +520,7 @@ public class ViewRegistryTest {
   public void testAddGetDefinitions() throws Exception {
     ViewEntity viewDefinition = ViewEntityTest.getViewEntity();
 
-    ViewRegistry registry = getRegistry();
+    ViewRegistry registry = ViewRegistry.getInstance();
 
     registry.addDefinition(viewDefinition);
 
@@ -520,7 +538,7 @@ public class ViewRegistryTest {
     ViewEntity viewDefinition = ViewEntityTest.getViewEntity();
     ViewInstanceEntity viewInstanceDefinition = ViewInstanceEntityTest.getViewInstanceEntity();
 
-    ViewRegistry registry = getRegistry();
+    ViewRegistry registry = ViewRegistry.getInstance();
 
     registry.addDefinition(viewDefinition);
 
@@ -538,7 +556,7 @@ public class ViewRegistryTest {
   @Test
   public void testGetSubResourceDefinitions() throws Exception {
     ViewEntity viewDefinition = ViewEntityTest.getViewEntity();
-    ViewRegistry registry = getRegistry();
+    ViewRegistry registry = ViewRegistry.getInstance();
 
     ResourceConfig config = ResourceConfigTest.getResourceConfigs().get(0);
     Resource.Type type1 = new Resource.Type("myType");
@@ -556,7 +574,7 @@ public class ViewRegistryTest {
 
   @Test
   public void testAddInstanceDefinition() throws Exception {
-    ViewRegistry registry = getRegistry();
+    ViewRegistry registry = ViewRegistry.getInstance();
 
     ViewEntity viewEntity = ViewEntityTest.getViewEntity();
     InstanceConfig instanceConfig = InstanceConfigTest.getInstanceConfigs().get(0);
@@ -587,7 +605,7 @@ public class ViewRegistryTest {
   @Test
   public void testInstallViewInstance() throws Exception {
 
-    ViewRegistry registry = getRegistry();
+    ViewRegistry registry = ViewRegistry.getInstance();
 
     Properties properties = new Properties();
     properties.put("p1", "v1");
@@ -620,7 +638,7 @@ public class ViewRegistryTest {
   @Test
   public void testInstallViewInstance_invalid() throws Exception {
 
-    ViewRegistry registry = getRegistry();
+    ViewRegistry registry = ViewRegistry.getInstance();
 
     Properties properties = new Properties();
     properties.put("p1", "v1");
@@ -646,7 +664,7 @@ public class ViewRegistryTest {
   @Test
   public void testInstallViewInstance_unknownView() throws Exception {
 
-    ViewRegistry registry = getRegistry();
+    ViewRegistry registry = ViewRegistry.getInstance();
 
     Properties properties = new Properties();
     properties.put("p1", "v1");
@@ -673,7 +691,7 @@ public class ViewRegistryTest {
   @Test
   public void testUpdateViewInstance() throws Exception {
 
-    ViewRegistry registry = getRegistry();
+    ViewRegistry registry = ViewRegistry.getInstance();
 
     Properties properties = new Properties();
     properties.put("p1", "v1");
@@ -707,7 +725,7 @@ public class ViewRegistryTest {
   @Test
   public void testUninstallViewInstance() throws Exception {
 
-    ViewRegistry registry = getRegistry();
+    ViewRegistry registry = ViewRegistry.getInstance();
 
     Configuration ambariConfig = new Configuration(new Properties());
 
@@ -744,7 +762,7 @@ public class ViewRegistryTest {
   @Test
   public void testUpdateViewInstance_invalid() throws Exception {
 
-    ViewRegistry registry = getRegistry();
+    ViewRegistry registry = ViewRegistry.getInstance();
 
     Properties properties = new Properties();
     properties.put("p1", "v1");
@@ -777,7 +795,7 @@ public class ViewRegistryTest {
   @Test
   public void testRemoveInstanceData() throws Exception {
 
-    ViewRegistry registry = getRegistry();
+    ViewRegistry registry = ViewRegistry.getInstance();
 
     ViewInstanceEntity viewInstanceEntity = ViewInstanceEntityTest.getViewInstanceEntity();
 
@@ -797,7 +815,7 @@ public class ViewRegistryTest {
 
   @Test
   public void testIncludeDefinitionForAdmin() {
-    ViewRegistry viewRegistry = getRegistry();
+    ViewRegistry registry = ViewRegistry.getInstance();
     ViewEntity viewEntity = createNiceMock(ViewEntity.class);
     AmbariGrantedAuthority adminAuthority = createNiceMock(AmbariGrantedAuthority.class);
     PrivilegeEntity privilegeEntity = createNiceMock(PrivilegeEntity.class);
@@ -815,14 +833,14 @@ public class ViewRegistryTest {
     expect(configuration.getApiAuthentication()).andReturn(true);
     replay(securityHelper, adminAuthority, privilegeEntity, permissionEntity, configuration);
 
-    Assert.assertTrue(viewRegistry.includeDefinition(viewEntity));
+    Assert.assertTrue(registry.includeDefinition(viewEntity));
 
     verify(securityHelper, adminAuthority, privilegeEntity, permissionEntity, configuration);
   }
 
   @Test
   public void testIncludeDefinitionForUserNoInstances() {
-    ViewRegistry viewRegistry = getRegistry();
+    ViewRegistry registry = ViewRegistry.getInstance();
     ViewEntity viewEntity = createNiceMock(ViewEntity.class);
 
     Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
@@ -836,14 +854,14 @@ public class ViewRegistryTest {
     expect(configuration.getApiAuthentication()).andReturn(true);
     replay(securityHelper, viewEntity, configuration);
 
-    Assert.assertFalse(viewRegistry.includeDefinition(viewEntity));
+    Assert.assertFalse(registry.includeDefinition(viewEntity));
 
     verify(securityHelper, viewEntity, configuration);
   }
 
   @Test
   public void testIncludeDefinitionForUserHasAccess() {
-    ViewRegistry viewRegistry = getRegistry();
+    ViewRegistry registry = ViewRegistry.getInstance();
     ViewEntity viewEntity = createNiceMock(ViewEntity.class);
     ViewInstanceEntity instanceEntity = createNiceMock(ViewInstanceEntity.class);
     ResourceEntity resourceEntity = createNiceMock(ResourceEntity.class);
@@ -868,31 +886,31 @@ public class ViewRegistryTest {
     expect(configuration.getApiAuthentication()).andReturn(true);
     replay(securityHelper, viewEntity, instanceEntity, viewUseAuthority, privilegeEntity, permissionEntity, configuration);
 
-    Assert.assertTrue(viewRegistry.includeDefinition(viewEntity));
+    Assert.assertTrue(registry.includeDefinition(viewEntity));
 
     verify(securityHelper, viewEntity, instanceEntity, viewUseAuthority, privilegeEntity, permissionEntity, configuration);
   }
 
   @Test
   public void testIncludeDefinitionForNoApiAuthentication() {
-    ViewRegistry viewRegistry = getRegistry();
+    ViewRegistry registry = ViewRegistry.getInstance();
     ViewEntity viewEntity = createNiceMock(ViewEntity.class);
 
     expect(configuration.getApiAuthentication()).andReturn(false);
     replay(securityHelper, viewEntity, configuration);
 
-    Assert.assertTrue(viewRegistry.includeDefinition(viewEntity));
+    Assert.assertTrue(registry.includeDefinition(viewEntity));
 
     verify(securityHelper, viewEntity, configuration);
   }
 
-  public class TestViewRegistryHelper extends ViewRegistry.ViewRegistryHelper {
+  public static class TestViewArchiveUtility extends ViewArchiveUtility {
     private final Map<File, ViewConfig> viewConfigs;
     private final Map<String, File> files;
     private final Map<File, FileOutputStream> outputStreams;
     private final Map<File, JarFile> jarFiles;
 
-    public TestViewRegistryHelper(Map<File, ViewConfig> viewConfigs, Map<String, File> files, Map<File,
+    public TestViewArchiveUtility(Map<File, ViewConfig> viewConfigs, Map<String, File> files, Map<File,
         FileOutputStream> outputStreams, Map<File, JarFile> jarFiles) {
       this.viewConfigs = viewConfigs;
       this.files = files;
@@ -948,22 +966,12 @@ public class ViewRegistryTest {
     }
   }
 
-  private static ViewRegistry getRegistry() {
-    ViewRegistry instance = getRegistry(viewDAO, viewInstanceDAO,
-        userDAO, memberDAO, privilegeDAO,
-        resourceDAO, resourceTypeDAO, securityHelper, handlerList);
-
-    reset(viewDAO, resourceDAO, viewInstanceDAO, userDAO, memberDAO,
-        privilegeDAO, resourceTypeDAO, securityHelper, configuration, handlerList);
-
-    return instance;
-  }
-
   public static ViewRegistry getRegistry(ViewDAO viewDAO, ViewInstanceDAO viewInstanceDAO,
-                                  UserDAO userDAO, MemberDAO memberDAO,
-                                  PrivilegeDAO privilegeDAO, ResourceDAO resourceDAO,
-                                  ResourceTypeDAO resourceTypeDAO, SecurityHelper securityHelper,
-                                  ViewInstanceHandlerList handlerList) {
+                                         UserDAO userDAO, MemberDAO memberDAO,
+                                         PrivilegeDAO privilegeDAO, ResourceDAO resourceDAO,
+                                         ResourceTypeDAO resourceTypeDAO, SecurityHelper securityHelper,
+                                         ViewInstanceHandlerList handlerList,
+                                         ViewExtractor viewExtractor, ViewArchiveUtility archiveUtility) {
 
     ViewRegistry instance = new ViewRegistry();
 
@@ -977,13 +985,18 @@ public class ViewRegistryTest {
     instance.securityHelper = securityHelper;
     instance.configuration = configuration;
     instance.handlerList = handlerList;
+    instance.extractor = viewExtractor == null ? new ViewExtractor() : viewExtractor;
+    instance.archiveUtility = archiveUtility == null ? new ViewArchiveUtility() : archiveUtility;
+    instance.extractor.archiveUtility = instance.archiveUtility;
 
     return instance;
   }
 
   public static ViewEntity getViewEntity(ViewConfig viewConfig, Configuration ambariConfig,
                                      ClassLoader cl, String archivePath) throws Exception{
-    ViewRegistry registry = getRegistry();
+
+    ViewRegistry registry = getRegistry(viewDAO, viewInstanceDAO, userDAO, memberDAO, privilegeDAO,
+        resourceDAO, resourceTypeDAO, securityHelper, handlerList, null, null);
 
     ViewEntity viewDefinition = new ViewEntity(viewConfig, ambariConfig, archivePath);
 
@@ -993,7 +1006,9 @@ public class ViewRegistryTest {
   }
 
   public static ViewInstanceEntity getViewInstanceEntity(ViewEntity viewDefinition, InstanceConfig instanceConfig) throws Exception {
-    ViewRegistry registry = getRegistry();
+
+    ViewRegistry registry = getRegistry(viewDAO, viewInstanceDAO, userDAO, memberDAO, privilegeDAO,
+        resourceDAO, resourceTypeDAO, securityHelper, handlerList, null, null);
 
     ViewInstanceEntity viewInstanceDefinition =
         new ViewInstanceEntity(viewDefinition, instanceConfig);

http://git-wip-us.apache.org/repos/asf/ambari/blob/093ed17d/ambari-server/src/test/python/TestAmbariServer.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/python/TestAmbariServer.py b/ambari-server/src/test/python/TestAmbariServer.py
index ebd691d..b11d88e 100644
--- a/ambari-server/src/test/python/TestAmbariServer.py
+++ b/ambari-server/src/test/python/TestAmbariServer.py
@@ -2369,7 +2369,8 @@ MIIFHjCCAwYCCQDpHKOBI+Lt0zANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJV
   @patch.object(ambari_server, "is_root")
   @patch.object(ambari_server, 'is_server_runing')
   @patch.object(ambari_server, 'proceedJDBCProperties')
-  def test_setup(self, proceedJDBCProperties_mock, is_server_runing_mock, is_root_mock, store_local_properties_mock,
+  @patch.object(ambari_server, "extract_views")
+  def test_setup(self, extract_views_mock, proceedJDBCProperties_mock, is_server_runing_mock, is_root_mock, store_local_properties_mock,
                  is_local_database_mock, store_remote_properties_mock,
                  setup_remote_db_mock, check_selinux_mock, check_jdbc_drivers_mock, check_ambari_user_mock,
                  check_postgre_up_mock, setup_db_mock, configure_postgres_mock,
@@ -2387,6 +2388,7 @@ MIIFHjCCAwYCCQDpHKOBI+Lt0zANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJV
     get_os_type_mock.return_value = ""
     get_os_family_mock.return_value = OSConst.REDHAT_FAMILY
     run_os_command_mock.return_value = 3,"",""
+    extract_views_mock.return_value = 0
 
     def reset_mocks():
       is_jdbc_user_changed_mock.reset_mock()
@@ -4966,9 +4968,10 @@ MIIFHjCCAwYCCQDpHKOBI+Lt0zANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJV
   @patch.object(ambari_server, "setup_db")
   @patch.object(ambari_server, "get_is_secure")
   @patch.object(ambari_server, "store_password_file")
+  @patch.object(ambari_server, "extract_views")
   @patch("sys.exit")
   @patch('__builtin__.raw_input')
-  def test_ambariServerSetupWithCustomDbName(self, raw_input, exit_mock, store_password_file_mock,
+  def test_ambariServerSetupWithCustomDbName(self, raw_input, exit_mock, extract_views_mock, store_password_file_mock,
                                              get_is_secure_mock, setup_db_mock, is_root_mock, is_local_database_mock,
                                              check_selinux_mock, check_jdbc_drivers_mock, check_ambari_user_mock,
                                              check_postgre_up_mock, configure_postgres_mock,
@@ -4995,6 +4998,7 @@ MIIFHjCCAwYCCQDpHKOBI+Lt0zANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJV
     setup_db_mock.return_value = (0, None, None)
     get_is_secure_mock.return_value = False
     store_password_file_mock.return_value = "password"
+    extract_views_mock.return_value = 0
     get_os_type_mock.return_value = ""
     get_os_family_mock.return_value = OSConst.REDHAT_FAMILY
     run_os_command_mock.return_value = 3,"",""