protected ClassLoader createClassLoader(Method method) {
   try {
     return new URLClassLoader(ClassPathUtil.getClassPathURLs(CLASS_PATH), null);
   } catch (MalformedURLException murle) {
     throw new RuntimeException(murle);
   }
 }
  @Override
  protected Metadata extractMetadata(String extension, String mimeType, InputStream inputStream) {

    Metadata metadata = super.extractMetadata(extension, mimeType, inputStream);

    boolean forkProcess = false;

    if (PropsValues.TEXT_EXTRACTION_FORK_PROCESS_ENABLED) {
      if (ArrayUtil.contains(PropsValues.TEXT_EXTRACTION_FORK_PROCESS_MIME_TYPES, mimeType)) {

        forkProcess = true;
      }
    }

    if (forkProcess) {
      File file = FileUtil.createTempFile();

      try {
        FileUtil.write(file, inputStream);

        ExtractMetadataProcessCallable extractMetadataProcessCallable =
            new ExtractMetadataProcessCallable(file, metadata, _parser);

        Future<Metadata> future =
            ProcessExecutor.execute(
                ClassPathUtil.getPortalProcessConfig(), extractMetadataProcessCallable);

        return future.get();
      } catch (Exception e) {
        throw new SystemException(e);
      } finally {
        file.delete();
      }
    }

    try {
      return extractMetadata(inputStream, metadata, _parser);
    } catch (IOException ioe) {
      throw new SystemException(ioe);
    }
  }
  public NewJVMJUnitTestRunner(Class<?> clazz) throws InitializationError {
    super(clazz);

    _classPath = ClassPathUtil.getJVMClassPath(false);
  }
/** @author Shuyang Zhou */
public class NewEnvMethodRule implements MethodRule {

  @Override
  public Statement apply(Statement statement, FrameworkMethod frameworkMethod, Object target) {

    Method method = frameworkMethod.getMethod();

    Class<?> targetClass = target.getClass();

    NewEnv newEnv = findNewEnv(method, targetClass);

    if ((newEnv == null) || (newEnv.type() == NewEnv.Type.NONE)) {
      return statement;
    }

    if (NewEnv.Type.CLASSLOADER == newEnv.type()) {
      return new RunInNewClassLoaderStatement(
          targetClass.getName(),
          getMethodKeys(targetClass, Before.class),
          method,
          getMethodKeys(targetClass, After.class));
    }

    Builder builder = new Builder();

    builder.setArguments(createArguments(method));
    builder.setBootstrapClassPath(CLASS_PATH);
    builder.setRuntimeClassPath(CLASS_PATH);

    return new RunInNewJVMStatment(
        builder.build(),
        targetClass.getName(),
        getMethodKeys(targetClass, Before.class),
        new MethodKey(method),
        getMethodKeys(targetClass, After.class));
  }

  protected static void attachProcess(String message) {
    if (Boolean.getBoolean("attached")) {
      return;
    }

    ProcessContext.attach(
        message,
        1000,
        new ShutdownHook() {

          @Override
          public boolean shutdown(int shutdownCode, Throwable shutdownThrowable) {

            System.exit(shutdownCode);

            return true;
          }
        });

    System.setProperty("attached", StringPool.TRUE);
  }

  protected static List<MethodKey> getMethodKeys(
      Class<?> targetClass, Class<? extends Annotation> annotationClass) {

    TestClass testClass = new TestClass(targetClass);

    List<FrameworkMethod> frameworkMethods = testClass.getAnnotatedMethods(annotationClass);

    List<MethodKey> methodKeys = new ArrayList<MethodKey>(frameworkMethods.size());

    for (FrameworkMethod annotatedFrameworkMethod : frameworkMethods) {
      methodKeys.add(new MethodKey(annotatedFrameworkMethod.getMethod()));
    }

    return methodKeys;
  }

  protected static void invoke(ClassLoader classLoader, MethodKey methodKey, Object object)
      throws Exception {

    methodKey = methodKey.transform(classLoader);

    Method method = methodKey.getMethod();

    method.invoke(object);
  }

  protected List<String> createArguments(Method method) {
    List<String> arguments = new ArrayList<String>();

    String agentLine = System.getProperty("junit.cobertura.agent");

    if (Validator.isNotNull(agentLine)) {
      arguments.add(agentLine);
      arguments.add("-Djunit.cobertura.agent=" + agentLine);
    }

    boolean coberturaParentDynamicallyInstrumented =
        Boolean.getBoolean("cobertura.parent.dynamically.instrumented");

    if (coberturaParentDynamicallyInstrumented) {
      arguments.add("-Dcobertura.parent.dynamically.instrumented=true");
    }

    boolean junitCodeCoverage = Boolean.getBoolean("junit.code.coverage");

    if (junitCodeCoverage) {
      arguments.add("-Djunit.code.coverage=true");
    }

    boolean junitCodeCoverageDump = Boolean.getBoolean("junit.code.coverage.dump");

    if (junitCodeCoverageDump) {
      arguments.add("-Djunit.code.coverage.dump=true");
    }

    boolean junitDebug = Boolean.getBoolean("junit.debug");

    if (junitDebug) {
      arguments.add(_JPDA_OPTIONS);
      arguments.add("-Djunit.debug=true");
    }

    arguments.add("-Djava.net.preferIPv4Stack=true");

    String fileName = System.getProperty("net.sourceforge.cobertura.datafile");

    if (fileName != null) {
      arguments.add("-Dnet.sourceforge.cobertura.datafile=" + fileName);
    }

    return arguments;
  }

  protected ClassLoader createClassLoader(Method method) {
    try {
      return new URLClassLoader(ClassPathUtil.getClassPathURLs(CLASS_PATH), null);
    } catch (MalformedURLException murle) {
      throw new RuntimeException(murle);
    }
  }

  protected NewEnv findNewEnv(Method method, Class<?> clazz) {
    NewEnv newEnv = method.getAnnotation(NewEnv.class);

    if (newEnv == null) {
      newEnv = clazz.getAnnotation(NewEnv.class);
    }

    return newEnv;
  }

  protected ProcessCallable<Serializable> processProcessCallable(
      ProcessCallable<Serializable> processCallable, MethodKey testMethodKey) {

    return processCallable;
  }

  protected static final String CLASS_PATH = ClassPathUtil.getJVMClassPath(true);

  private static final String _JPDA_OPTIONS =
      "-agentlib:jdwp=transport=dt_socket,address=8001,server=y,suspend=y";

  private static final ProcessExecutor _processExecutor = new LocalProcessExecutor();

  static {
    Thread currentThread = Thread.currentThread();

    ClassLoader contextClassLoader = currentThread.getContextClassLoader();

    PortalClassLoaderUtil.setClassLoader(contextClassLoader);
  }

  private static class TestProcessCallable implements ProcessCallable<Serializable> {

    public TestProcessCallable(
        String testClassName,
        List<MethodKey> beforeMethodKeys,
        MethodKey testMethodKey,
        List<MethodKey> afterMethodKeys) {

      _testClassName = testClassName;
      _beforeMethodKeys = beforeMethodKeys;
      _testMethodKey = testMethodKey;
      _afterMethodKeys = afterMethodKeys;
    }

    @Override
    public Serializable call() throws ProcessException {
      attachProcess("Attached " + toString());

      Thread currentThread = Thread.currentThread();

      ClassLoader contextClassLoader = currentThread.getContextClassLoader();

      try {
        Class<?> clazz = contextClassLoader.loadClass(_testClassName);

        Object object = clazz.newInstance();

        for (MethodKey beforeMethodKey : _beforeMethodKeys) {
          invoke(contextClassLoader, beforeMethodKey, object);
        }

        invoke(contextClassLoader, _testMethodKey, object);

        for (MethodKey afterMethodKey : _afterMethodKeys) {
          invoke(contextClassLoader, afterMethodKey, object);
        }
      } catch (Exception e) {
        throw new ProcessException(e);
      }

      return StringPool.BLANK;
    }

    @Override
    public String toString() {
      StringBundler sb = new StringBundler(4);

      sb.append(_testClassName);
      sb.append(StringPool.PERIOD);
      sb.append(_testMethodKey.getMethodName());
      sb.append("()");

      return sb.toString();
    }

    private static final long serialVersionUID = 1L;

    private final List<MethodKey> _afterMethodKeys;
    private final List<MethodKey> _beforeMethodKeys;
    private final String _testClassName;
    private final MethodKey _testMethodKey;
  }

  private class RunInNewClassLoaderStatement extends Statement {

    public RunInNewClassLoaderStatement(
        String testClassName,
        List<MethodKey> beforeMethodKeys,
        Method testMethod,
        List<MethodKey> afterMethodKeys) {

      _testClassName = testClassName;
      _beforeMethodKeys = beforeMethodKeys;
      _testMethodKey = new MethodKey(testMethod);
      _afterMethodKeys = afterMethodKeys;

      _newClassLoader = createClassLoader(testMethod);
    }

    @Override
    public void evaluate() throws Throwable {
      MethodCache.reset();

      Thread currentThread = Thread.currentThread();

      ClassLoader contextClassLoader = currentThread.getContextClassLoader();

      currentThread.setContextClassLoader(_newClassLoader);

      try {
        Class<?> clazz = _newClassLoader.loadClass(_testClassName);

        Object object = clazz.newInstance();

        for (MethodKey beforeMethodKey : _beforeMethodKeys) {
          invoke(_newClassLoader, beforeMethodKey, object);
        }

        invoke(_newClassLoader, _testMethodKey, object);

        for (MethodKey afterMethodKey : _afterMethodKeys) {
          invoke(_newClassLoader, afterMethodKey, object);
        }
      } catch (InvocationTargetException ite) {
        throw ite.getTargetException();
      } finally {
        currentThread.setContextClassLoader(contextClassLoader);
      }
    }

    private final List<MethodKey> _afterMethodKeys;
    private final List<MethodKey> _beforeMethodKeys;
    private final ClassLoader _newClassLoader;
    private final String _testClassName;
    private final MethodKey _testMethodKey;
  }

  private class RunInNewJVMStatment extends Statement {

    public RunInNewJVMStatment(
        ProcessConfig processConfig,
        String testClassName,
        List<MethodKey> beforeMethodKeys,
        MethodKey testMethodKey,
        List<MethodKey> afterMethodKeys) {

      _processConfig = processConfig;
      _testClassName = testClassName;
      _beforeMethodKeys = beforeMethodKeys;
      _testMethodKey = testMethodKey;
      _afterMethodKeys = afterMethodKeys;
    }

    @Override
    public void evaluate() throws Throwable {
      ProcessCallable<Serializable> processCallable =
          new TestProcessCallable(
              _testClassName, _beforeMethodKeys, _testMethodKey, _afterMethodKeys);

      processCallable = processProcessCallable(processCallable, _testMethodKey);

      ProcessChannel<Serializable> processChannel =
          _processExecutor.execute(_processConfig, processCallable);

      Future<Serializable> future = processChannel.getProcessNoticeableFuture();

      try {
        future.get();
      } catch (ExecutionException ee) {
        Throwable cause = ee.getCause();

        while ((cause instanceof ProcessException)
            || (cause instanceof InvocationTargetException)) {

          cause = cause.getCause();
        }

        throw cause;
      }
    }

    private final List<MethodKey> _afterMethodKeys;
    private final List<MethodKey> _beforeMethodKeys;
    private final ProcessConfig _processConfig;
    private final String _testClassName;
    private final MethodKey _testMethodKey;
  }
}
  private void _generateImagesPB(FileVersion fileVersion, File file) throws Exception {

    String tempFileId =
        DLUtil.getTempFileId(fileVersion.getFileEntryId(), fileVersion.getVersion());

    File thumbnailFile = getThumbnailTempFile(tempFileId);

    int previewFilesCount = 0;

    PDDocument pdDocument = null;

    try {
      pdDocument = PDDocument.load(file);

      previewFilesCount = pdDocument.getNumberOfPages();
    } finally {
      if (pdDocument != null) {
        pdDocument.close();
      }
    }

    File[] previewFiles = new File[previewFilesCount];

    for (int i = 0; i < previewFilesCount; i++) {
      previewFiles[i] = getPreviewTempFile(tempFileId, i);
    }

    boolean generatePreview = _isGeneratePreview(fileVersion);
    boolean generateThumbnail = _isGenerateThumbnail(fileVersion);

    if (PropsValues.DL_FILE_ENTRY_PREVIEW_FORK_PROCESS_ENABLED) {
      ProcessCallable<String> processCallable =
          new LiferayPDFBoxProcessCallable(
              ServerDetector.getServerId(),
              PropsUtil.get(PropsKeys.LIFERAY_HOME),
              Log4JUtil.getCustomLogSettings(),
              file,
              thumbnailFile,
              previewFiles,
              getThumbnailType(fileVersion),
              getPreviewType(fileVersion),
              PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_DPI,
              PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_MAX_HEIGHT,
              PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_MAX_WIDTH,
              generatePreview,
              generateThumbnail);

      Future<String> future =
          ProcessExecutor.execute(ClassPathUtil.getPortalClassPath(), processCallable);

      String processIdentity = String.valueOf(fileVersion.getFileVersionId());

      futures.put(processIdentity, future);

      future.get();
    } else {
      LiferayPDFBoxConverter liferayConverter =
          new LiferayPDFBoxConverter(
              file,
              thumbnailFile,
              previewFiles,
              getPreviewType(fileVersion),
              getThumbnailType(fileVersion),
              PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_DPI,
              PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_MAX_HEIGHT,
              PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_MAX_WIDTH,
              generatePreview,
              generateThumbnail);

      liferayConverter.generateImagesPB();
    }

    if (generateThumbnail) {
      try {
        storeThumbnailImages(fileVersion, thumbnailFile);
      } finally {
        FileUtil.delete(thumbnailFile);
      }

      if (_log.isInfoEnabled()) {
        _log.info("PDFBox generated a thumbnail for " + fileVersion.getFileVersionId());
      }
    }

    if (generatePreview) {
      int index = 0;

      for (File previewFile : previewFiles) {
        try {
          addFileToStore(
              fileVersion.getCompanyId(), PREVIEW_PATH,
              getPreviewFilePath(fileVersion, index + 1), previewFile);
        } finally {
          FileUtil.delete(previewFile);
        }

        index++;
      }

      if (_log.isInfoEnabled()) {
        _log.info(
            "PDFBox generated "
                + getPreviewFileCount(fileVersion)
                + " preview pages for "
                + fileVersion.getFileVersionId());
      }
    }
  }
  private void _generateVideoXuggler(
      FileVersion fileVersion, File sourceFile, File destinationFile, String containerType)
      throws Exception {

    if (hasPreview(fileVersion, containerType)) {
      return;
    }

    StopWatch stopWatch = new StopWatch();

    stopWatch.start();

    if (PropsValues.DL_FILE_ENTRY_PREVIEW_FORK_PROCESS_ENABLED) {
      ProcessCallable<String> processCallable =
          new LiferayVideoProcessCallable(
              ServerDetector.getServerId(),
              PropsUtil.get(PropsKeys.LIFERAY_HOME),
              Log4JUtil.getCustomLogSettings(),
              sourceFile,
              destinationFile,
              containerType,
              PropsUtil.getProperties(PropsKeys.DL_FILE_ENTRY_PREVIEW_VIDEO, false),
              PropsUtil.getProperties(PropsKeys.XUGGLER_FFPRESET, true));

      ProcessChannel<String> processChannel =
          ProcessExecutorUtil.execute(ClassPathUtil.getPortalProcessConfig(), processCallable);

      Future<String> future = processChannel.getProcessNoticeableFuture();

      String processIdentity = String.valueOf(fileVersion.getFileVersionId());

      futures.put(processIdentity, future);

      future.get();
    } else {
      LiferayConverter liferayConverter =
          new LiferayVideoConverter(
              sourceFile.getCanonicalPath(),
              destinationFile.getCanonicalPath(),
              containerType,
              PropsUtil.getProperties(PropsKeys.DL_FILE_ENTRY_PREVIEW_VIDEO, false),
              PropsUtil.getProperties(PropsKeys.XUGGLER_FFPRESET, true));

      liferayConverter.convert();
    }

    addFileToStore(
        fileVersion.getCompanyId(), PREVIEW_PATH,
        getPreviewFilePath(fileVersion, containerType), destinationFile);

    if (_log.isInfoEnabled()) {
      _log.info(
          "Xuggler generated a "
              + containerType
              + " preview video for "
              + fileVersion.getTitle()
              + " in "
              + stopWatch.getTime()
              + " ms");
    }
  }
  private void _generateThumbnailXuggler(FileVersion fileVersion, File file, int height, int width)
      throws Exception {

    StopWatch stopWatch = new StopWatch();

    stopWatch.start();

    String tempFileId =
        DLUtil.getTempFileId(fileVersion.getFileEntryId(), fileVersion.getVersion());

    File thumbnailTempFile = getThumbnailTempFile(tempFileId);

    try {
      try {
        if (PropsValues.DL_FILE_ENTRY_PREVIEW_FORK_PROCESS_ENABLED) {
          ProcessCallable<String> processCallable =
              new LiferayVideoThumbnailProcessCallable(
                  ServerDetector.getServerId(),
                  PropsUtil.get(PropsKeys.LIFERAY_HOME),
                  Log4JUtil.getCustomLogSettings(),
                  file,
                  thumbnailTempFile,
                  THUMBNAIL_TYPE,
                  height,
                  width,
                  PropsValues.DL_FILE_ENTRY_THUMBNAIL_VIDEO_FRAME_PERCENTAGE);

          ProcessChannel<String> processChannel =
              ProcessExecutorUtil.execute(ClassPathUtil.getPortalProcessConfig(), processCallable);

          Future<String> future = processChannel.getProcessNoticeableFuture();

          String processIdentity = String.valueOf(fileVersion.getFileVersionId());

          futures.put(processIdentity, future);

          future.get();
        } else {
          LiferayConverter liferayConverter =
              new LiferayVideoThumbnailConverter(
                  file.getCanonicalPath(),
                  thumbnailTempFile,
                  THUMBNAIL_TYPE,
                  height,
                  width,
                  PropsValues.DL_FILE_ENTRY_THUMBNAIL_VIDEO_FRAME_PERCENTAGE);

          liferayConverter.convert();
        }
      } catch (CancellationException ce) {
        if (_log.isInfoEnabled()) {
          _log.info(
              "Cancellation received for "
                  + fileVersion.getFileVersionId()
                  + " "
                  + fileVersion.getTitle());
        }
      } catch (Exception e) {
        _log.error(e, e);
      }

      storeThumbnailImages(fileVersion, thumbnailTempFile);

      if (_log.isInfoEnabled()) {
        _log.info(
            "Xuggler generated a thumbnail for "
                + fileVersion.getTitle()
                + " in "
                + stopWatch.getTime()
                + " ms");
      }
    } catch (Exception e) {
      throw new SystemException(e);
    } finally {
      FileUtil.delete(thumbnailTempFile);
    }
  }