@Override
  public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
    DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();

    if (deploymentUnit.hasAttachment(ClojureMetaData.ATTACHMENT_KEY)) {
      return;
    }

    Timer t = new Timer("parsing deployment descriptor");
    String deploymentName = deploymentUnit.getName();

    try {
      VirtualFile descriptor = getDescriptorFile(deploymentUnit);
      if (descriptor == null) {
        return;
      }

      ClojureMetaData appMetaData =
          new ClojureMetaData(deploymentName, ClojureMetaData.parse(descriptor.getPhysicalFile()));

      appMetaData.attachTo(deploymentUnit);

      File root = appMetaData.getRoot();

      if (root == null) {
        throw new DeploymentUnitProcessingException("No application root specified.");
      }

      if (!root.exists()) {
        throw new DeploymentUnitProcessingException(
            "Application root does not exist: " + root.getAbsolutePath());
      }

      VirtualFile virtualRoot = VFS.getChild(root.toURI());
      MountHandle mountHandle = null;

      if (!root.isDirectory()) {
        // Expand the referenced root if it's not a directory (ie .ima archive)
        mountHandle =
            new MountHandle(
                VFS.mountZipExpanded(virtualRoot, virtualRoot, TempFileProviderService.provider()));
      }

      deploymentUnit.putAttachment(
          Attachments.DEPLOYMENT_ROOT, new ResourceRoot(virtualRoot, mountHandle));
      deploymentUnit.putAttachment(ClojureMetaData.DESCRIPTOR_FILE, descriptor.getPhysicalFile());

    } catch (Exception e) {
      throw new DeploymentUnitProcessingException(e);
    }
    t.done();
  }
  private void mount(File file, DeploymentUnit unit, JarMountMap mountMap) throws IOException {
    VirtualFile mountPath =
        VFS.getChild(File.createTempFile(file.getName(), ".jar", tmpMountDir(unit)).toURI());
    log.debug(unit.getName() + ": mounting " + file);
    final ResourceRoot childResource =
        new ResourceRoot(
            mountPath,
            new MountHandle(VFS.mountZip(file, mountPath, TempFileProviderService.provider())));
    ModuleRootMarker.mark(childResource);
    unit.addToAttachmentList(Attachments.RESOURCE_ROOTS, childResource);

    mountMap.put(mountPath.toURL().toExternalForm(), file.toURI().toURL().toExternalForm());
  }
  public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
    final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
    final ResourceRoot resourceRoot = deploymentUnit.getAttachment(Attachments.DEPLOYMENT_ROOT);
    if (resourceRoot == null) {
      return;
    }
    final VirtualFile deploymentRoot = resourceRoot.getRoot();
    if (deploymentRoot == null || !deploymentRoot.exists()) {
      return;
    }

    final String deploymentRootName = deploymentRoot.getLowerCaseName();
    if (!deploymentRootName.endsWith(RAR_EXTENSION)) {
      return;
    }
    // we do not load classes from the module resource root
    ModuleRootMarker.mark(resourceRoot, false);

    try {
      final List<VirtualFile> childArchives = deploymentRoot.getChildren(CHILD_ARCHIVE_FILTER);

      for (final VirtualFile child : childArchives) {
        final Closeable closable =
            child.isFile()
                ? VFS.mountZip(child, child, TempFileProviderService.provider())
                : NO_OP_CLOSEABLE;
        final MountHandle mountHandle = new MountHandle(closable);
        final ResourceRoot childResource = new ResourceRoot(child, mountHandle);
        ModuleRootMarker.mark(childResource);
        deploymentUnit.addToAttachmentList(Attachments.RESOURCE_ROOTS, childResource);
        resourceRoot.addToAttachmentList(
            Attachments.INDEX_IGNORE_PATHS, child.getPathNameRelativeTo(deploymentRoot));
      }
    } catch (IOException e) {
      throw new DeploymentUnitProcessingException(
          "Failed to process RA child archives for [" + deploymentRoot + "]", e);
    }
  }