Package org.springframework.ide.eclipse.maven.internal.core

Source Code of org.springframework.ide.eclipse.maven.internal.core.MavenClasspathUpdateJob

/*******************************************************************************
*  Copyright (c) 2012 VMware, Inc.
*  All rights reserved. This program and the accompanying materials
*  are made available under the terms of the Eclipse Public License v1.0
*  which accompanies this distribution, and is available at
*  http://www.eclipse.org/legal/epl-v10.html
*
*  Contributors:
*      VMware, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.maven.internal.core;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.resources.WorkspaceJob;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.IJobChangeListener;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IDebugEventSetListener;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.ui.RefreshTab;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.m2e.actions.MavenLaunchConstants;
import org.eclipse.m2e.core.internal.IMavenConstants;
import org.springframework.ide.eclipse.maven.MavenCorePlugin;


/**
* @author Christian Dupuis
*/
@SuppressWarnings("restriction")
public class MavenClasspathUpdateJob extends WorkspaceJob {

  /** Internal cache of scheduled and <b>unfinished</b> update jobs */
  private static final Queue<IJavaProject> SCHEDULED_PROJECTS = new ConcurrentLinkedQueue<IJavaProject>();

  /** The {@link IJavaProject} this jobs should refresh the class path container for */
  private final IJavaProject javaProject;

  /**
   * Private constructor to create an instance
   * @param javaProject the {@link IJavaProject} the class path container should be updated for
   * @param types the change types happened to the manifest
   */
  private MavenClasspathUpdateJob(IJavaProject javaProject) {
    super("Updating Maven dependencies for project '" + javaProject.getElementName() + "'");
    this.javaProject = javaProject;
  }

  /**
   * Returns the internal {@link IJavaProject}
   */
  public IJavaProject getJavaProject() {
    return javaProject;
  }

  /**
   * Runs the job in the context of the workspace. Simply delegates refreshing of the class path container to
   * {@link ClasspathUtils#updateClasspathContainer(IJavaProject, IProgressMonitor)}.
   */
  @Override
  public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
    if (!javaProject.getProject().isOpen() || monitor.isCanceled()) {
      return Status.CANCEL_STATUS;
    }
    try {
      IContainer basedir = findPomXmlBasedir(javaProject.getProject());
      if (basedir == null) {
        return Status.CANCEL_STATUS;
      }
      ILaunchConfiguration configuration = createLaunchConfiguration(basedir, "eclipse:clean eclipse:eclipse");
      if (configuration != null) {
        ILaunch launch = configuration.launch(ILaunchManager.RUN_MODE, new SubProgressMonitor(monitor, 75));
        DebugPlugin.getDefault().addDebugEventListener(
            new MavenProcessListener(launch.getProcesses()[0], javaProject.getProject()));
      }
    }
    catch (Exception e) {
      return Status.CANCEL_STATUS;
    }

    return new Status(IStatus.OK, MavenCorePlugin.PLUGIN_ID, "Updated Maven dependencies");
  }

  private IContainer findPomXmlBasedir(IContainer dir) {
    if (dir == null) {
      return null;
    }

    try {
      // loop upwards through the parents as long as we do not cross the project boundary
      while (dir.exists() && dir.getProject() != null && dir.getProject() != dir) {
        // see if pom.xml exists
        if (dir.getType() == IResource.FOLDER) {
          IFolder folder = (IFolder) dir;
          if (folder.findMember(IMavenConstants.POM_FILE_NAME) != null) {
            return folder;
          }
        }
        else if (dir.getType() == IResource.FILE) {
          if (((IFile) dir).getName().equals(IMavenConstants.POM_FILE_NAME)) {
            return dir.getParent();
          }
        }
        dir = dir.getParent();
      }
    }
    catch (Exception e) {
      return dir;
    }
    return dir;
  }

  private ILaunchConfiguration createLaunchConfiguration(IContainer basedir, String goal) {
    try {
      ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
      ILaunchConfigurationType launchConfigurationType = launchManager
          .getLaunchConfigurationType(MavenLaunchConstants.LAUNCH_CONFIGURATION_TYPE_ID);

      ILaunchConfigurationWorkingCopy workingCopy = launchConfigurationType.newInstance(basedir, //
          "Updating Maven dependencies for '" + basedir.getName() + "'");
      workingCopy.setAttribute(MavenLaunchConstants.ATTR_POM_DIR, basedir.getLocation().toOSString());
      workingCopy.setAttribute(MavenLaunchConstants.ATTR_GOALS, goal);
      workingCopy.setAttribute(MavenLaunchConstants.ATTR_WORKSPACE_RESOLUTION, true);

      workingCopy.setAttribute(RefreshTab.ATTR_REFRESH_SCOPE, "${project}");
      workingCopy.setAttribute(RefreshTab.ATTR_REFRESH_RECURSIVE, true);

      String vmArguments = workingCopy.getAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, "");
      vmArguments += "-Declipse.workspace=\"${workspace_loc}\"";
      workingCopy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, vmArguments);

      IPath path = getJREContainerPath(basedir);
      if (path != null) {
        workingCopy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_JRE_CONTAINER_PATH, path
            .toPortableString());
      }

      return workingCopy;
    }
    catch (CoreException ex) {
      MavenCorePlugin.getDefault().getLog().log(
          new Status(IStatus.ERROR, MavenCorePlugin.PLUGIN_ID, "Error occured", ex));
    }
    return null;
  }

  private IPath getJREContainerPath(IContainer basedir) throws CoreException {
    IProject project = basedir.getProject();
    if (project != null && project.hasNature(JavaCore.NATURE_ID)) {
      IJavaProject javaProject = JavaCore.create(project);
      IClasspathEntry[] entries = javaProject.getRawClasspath();
      for (int i = 0; i < entries.length; i++) {
        IClasspathEntry entry = entries[i];
        if (JavaRuntime.JRE_CONTAINER.equals(entry.getPath().segment(0))) {
          return entry.getPath();
        }
      }
    }
    return null;
  }

  /**
   * Helper method to schedule a new {@link MavenClasspathUpdateJob}.
   * @param javaProject the {@link IJavaProject} the class path container should be updated for
   * @param types the change types of the manifest
   */
  public static void scheduleClasspathContainerUpdateJob(IJavaProject javaProject) {
    if (javaProject != null && !SCHEDULED_PROJECTS.contains(javaProject)) {
      newClasspathContainerUpdateJob(javaProject);
    }
  }

  public static void scheduleClasspathContainerUpdateJob(IProject oroject) {
    scheduleClasspathContainerUpdateJob(JavaCore.create(oroject));
  }

  /**
   * Creates a new instance of {@link MavenClasspathUpdateJob} and configures required properties and schedules it to
   * the workbench.
   */
  private static MavenClasspathUpdateJob newClasspathContainerUpdateJob(IJavaProject javaProject) {
    MavenClasspathUpdateJob job = new MavenClasspathUpdateJob(javaProject);
    job.setRule(ResourcesPlugin.getWorkspace().getRuleFactory().buildRule());
    job.setPriority(Job.BUILD);
    job.addJobChangeListener(new DuplicateJobListener());
    job.schedule();
    return job;
  }

  /**
   * Internal {@link IJobChangeListener} to detect duplicates in the scheduled list of {@link MavenClasspathUpdateJob
   * Jobs}.
   */
  private static class DuplicateJobListener extends JobChangeAdapter implements IJobChangeListener {

    @Override
    public void done(IJobChangeEvent event) {
      SCHEDULED_PROJECTS.remove(((MavenClasspathUpdateJob) event.getJob()).getJavaProject());
    }

    @Override
    public void scheduled(IJobChangeEvent event) {
      SCHEDULED_PROJECTS.add(((MavenClasspathUpdateJob) event.getJob()).getJavaProject());
    }
  }

  private class MavenProcessListener implements IDebugEventSetListener {

    private final IProject project;

    private final IProcess newProcess;

    public MavenProcessListener(IProcess process, IProject project) {
      this.project = project;
      this.newProcess = process;
    }

    public void handleDebugEvents(DebugEvent[] events) {
      if (events != null && project != null) {
        int size = events.length;
        for (int i = 0; i < size; i++) {
          if (newProcess != null && newProcess.equals(events[i].getSource())
              && events[i].getKind() == DebugEvent.TERMINATE) {

            DebugPlugin.getDefault().removeDebugEventListener(this);

            Job job = new Job("refresh project") {

              @Override
              protected IStatus run(IProgressMonitor monitor) {
                try {
                  project.refreshLocal(IResource.DEPTH_INFINITE, monitor);
                }
                catch (CoreException e) {
                }
                return Status.OK_STATUS;
              }

            };
            job.setSystem(true);
            job.setRule(ResourcesPlugin.getWorkspace().getRuleFactory().buildRule());
            job.setPriority(Job.INTERACTIVE);
            job.schedule();
          }
        }
      }
    }
  }

}
TOP

Related Classes of org.springframework.ide.eclipse.maven.internal.core.MavenClasspathUpdateJob

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.