public ClassLoader extractViewArchive(ViewEntity view, File viewArchive, File archiveDir, List<File> viewsAdditionalClasspath)
      throws ExtractionException {

    String archivePath = archiveDir.getAbsolutePath();

    try {
      // Remove directory if jar was updated since last extracting
      if (archiveDir.exists() && viewArchive != null && viewArchive.lastModified() > archiveDir.lastModified()) {
        FileUtils.deleteDirectory(archiveDir);
      }

      // 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()) {
          JarInputStream jarInputStream = archiveUtility.getJarFileStream(viewArchive);
          try {
            msg = "Extracting files from " + viewArchive.getName() + ".";
            view.setStatusDetail(msg);
            LOG.info(msg);

            // pre-create the META-INF directory since JAR compression ordering
            // can sometimes cause problems with creation of the files inside of
            // META-INF if the directory appears after
            //
            // 473 12-07-2018 11:37   META-INF/MANIFEST.MF
            // 0   12-07-2018 11:37   META-INF/
            // 0   12-07-2018 11:37   META-INF/maven/
            //
            File metaInfDir = archiveUtility.getFile(archivePath + File.separator + "META-INF");
            if (!metaInfDir.mkdir()) {
              msg = "Could not create archive META-INF directory.";

              view.setStatusDetail(msg);
              LOG.error(msg);
              throw new ExtractionException(msg);
            }

            JarEntry jarEntry;
            while ((jarEntry = jarInputStream.getNextJarEntry())!= null){
              try {
                String   entryPath = archivePath + File.separator + jarEntry.getName();

                LOG.debug("Extracting {}", entryPath);

                File entryFile = archiveUtility.getFile(entryPath);

                if (jarEntry.isDirectory()) {

                  // only try to create the directory if it doesn't already
                  // exist (like META-INFO might)
                  if (!entryFile.exists()) {
                    LOG.debug("Making directory {}", entryPath);

                    if (!entryFile.mkdir()) {
                      msg = "Could not create archive entry directory " + entryPath + ".";

                      view.setStatusDetail(msg);
                      LOG.error(msg);
                      throw new ExtractionException(msg);
                    }
                  }
                } else {

                  FileOutputStream fos = archiveUtility.getFileOutputStream(entryFile);
                  try {
                    LOG.debug("Begin copying from {} to {}", jarEntry.getName(), entryPath);

                    byte[] buffer = new byte[BUFFER_SIZE];
                    int n;
                    while((n = jarInputStream.read(buffer)) > -1) {
                      fos.write(buffer, 0, n);
                    }
                    LOG.debug("Finish copying from {} to {}", jarEntry.getName(), entryPath);

                  } finally {
                    fos.flush();
                    fos.close();
                  }
                }
              } finally {
                jarInputStream.closeEntry();
              }
            }
          } finally {
            jarInputStream.close();
          }
        } else {
          msg = "Could not create archive directory " + archivePath + ".";

          view.setStatusDetail(msg);
          LOG.error(msg);
          throw new ExtractionException(msg);
        }
      }

      ViewConfig viewConfig = archiveUtility.getViewConfigFromExtractedArchive(archivePath, false);

      return getArchiveClassLoader(viewConfig, archiveDir, viewsAdditionalClasspath);

    } 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);
    }
  }
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

@param viewsAdditionalClasspath: list of additional paths to be added to every view's classpath
@return the class loader for the archive classes

@throws ExtractionException if the archive can not be extracted
ambari-server/src/main/java/org/apache/ambari/server/view/ViewExtractor.java