org.maven.ide.eclipse.embedder.MavenModelManager.java Source code

Java tutorial

Introduction

Here is the source code for org.maven.ide.eclipse.embedder.MavenModelManager.java

Source

/*
 * Licensed to the Codehaus 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.maven.ide.eclipse.embedder;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.io.StringWriter;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.embedder.MavenEmbedder;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenExecutionResult;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Model;
import org.apache.maven.project.MavenProject;

import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jface.preference.IPreferenceStore;

import org.maven.ide.eclipse.Maven2Plugin;
import org.maven.ide.eclipse.index.MavenRepositoryIndexManager;
import org.maven.ide.eclipse.launch.console.Maven2Console;
import org.maven.ide.eclipse.preferences.Maven2PreferenceConstants;

/**
 * This class maintain the mapping between Eclipse projects and Maven models, and be able to lookup projects and models
 * or artifacts.
 * 
 * @author Scott Cytacki
 * @author Eugene Kuleshov
 */
public class MavenModelManager {
    private final MavenEmbedderManager embedderManager;

    private final MavenRepositoryIndexManager indexManager;

    private final Maven2Console console;

    private final IPreferenceStore preferenceStore;

    /**
     * Map of the project pomFile location to the Model
     */
    private final Map models = new HashMap();

    /**
     * Map of the artifact keys to the pomFile in the Worspace for those artifacts.
     * 
     * @see #getArtifactKey(Artifact)
     */
    private final Map artifacts = new HashMap();

    private final Map projectsToArtifacts = new HashMap();

    private final Map artifactsToProjects = new HashMap();

    private boolean isInitialized = false;

    public MavenModelManager(MavenEmbedderManager embedderManager, MavenRepositoryIndexManager indexManager,
            Maven2Console console, IPreferenceStore preferenceStore) {
        this.embedderManager = embedderManager;
        this.indexManager = indexManager;
        this.console = console;
        this.preferenceStore = preferenceStore;
    }

    public IFile getArtifactFile(Artifact a) {
        IFile file = (IFile) artifacts.get(getArtifactKey(a));
        return file != null && file.isAccessible() ? file : null;
    }

    public Model getMavenModel(IFile pomFile) {
        return (Model) models.get(getPomFileKey(pomFile));
    }

    public synchronized void initModels(IProgressMonitor monitor) {
        if (isInitialized) {
            return;
        }

        isInitialized = true;

        IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();

        Map mavenModels = new HashMap();
        for (int i = 0; i < projects.length; i++) {
            if (monitor.isCanceled()) {
                throw new OperationCanceledException();
            }

            IProject project = projects[i];
            try {
                if (project.isOpen() && project.hasNature(Maven2Plugin.NATURE_ID)) {
                    IFile pomFile = project.getFile(Maven2Plugin.POM_FILE_NAME);
                    if (pomFile == null) {
                        console.logError("Project " + project.getName() + " is missing pom.xml");
                    } else {

                        IJavaProject javaProject = JavaCore.create(project);
                        ResolverConfiguration resolverConfiguration = BuildPathManager
                                .getResolverConfiguration(javaProject);
                        initMavenModel(pomFile, pomFile, mavenModels, monitor, resolverConfiguration);
                    }
                }
            } catch (CoreException ex) {
                console.logError("Unable to read project " + project.getName() + "; " + ex.getMessage());
            }
        }

        Map mavenProjects = new HashMap();
        for (int i = 0; i < projects.length; i++) {
            if (monitor.isCanceled()) {
                throw new OperationCanceledException();
            }

            IProject project = projects[i];
            try {
                if (project.isOpen() && project.hasNature(Maven2Plugin.NATURE_ID)) {
                    IFile pomFile = project.getFile(Maven2Plugin.POM_FILE_NAME);
                    if (pomFile == null) {
                        console.logError("Project " + project.getName() + " is missing pom.xml");
                    } else {
                        IJavaProject javaProject = JavaCore.create(project);
                        ResolverConfiguration resolverConfiguration = BuildPathManager
                                .getResolverConfiguration(javaProject);
                        initMavenProject(pomFile, pomFile, mavenProjects, monitor, resolverConfiguration);
                    }
                }
            } catch (CoreException ex) {
                console.logError("Unable to read project " + project.getName() + "; " + ex.getMessage());
            }
        }
    }

    private void initMavenModel(IFile pomFile, IFile rootPomFile, Map mavenModels, IProgressMonitor monitor,
            ResolverConfiguration resolverConfiguration) throws CoreException {
        String pomKey = getPomFileKey(pomFile);
        Model mavenModel = (Model) mavenModels.get(pomKey);
        if (mavenModel == null) {
            mavenModel = updateMavenModel(pomFile, false, monitor);
            mavenModels.put(pomKey, mavenModel);
        }

        if (resolverConfiguration.shouldIncludeModules()) {
            IContainer parent = pomFile.getParent();
            for (Iterator it = mavenModel.getModules().iterator(); it.hasNext();) {
                if (monitor.isCanceled()) {
                    throw new OperationCanceledException();
                }
                String module = (String) it.next();
                IResource memberPom = parent.findMember(module + "/" + Maven2Plugin.POM_FILE_NAME); //$NON-NLS-1$
                if (memberPom != null && memberPom.getType() == IResource.FILE && memberPom.isAccessible()) {
                    initMavenModel((IFile) memberPom, rootPomFile, mavenModels, monitor, resolverConfiguration);
                }
            }
        }
    }

    private void initMavenProject(IFile pomFile, IFile rootPomFile, Map mavenProjects, IProgressMonitor monitor,
            ResolverConfiguration resolverConfiguration) throws CoreException {
        String pomKey = getPomFileKey(pomFile);
        if (mavenProjects.containsKey(pomKey)) {
            return;
        }

        MavenExecutionResult result = readMavenProject(pomFile.getLocation().toFile(), monitor, true, false,
                resolverConfiguration);
        MavenProject mavenProject = result.getProject();
        if (mavenProject == null) {
            return;
        }

        mavenProjects.put(pomKey, mavenProject);

        Set artifacts = mavenProject.getArtifacts();
        for (Iterator it = artifacts.iterator(); it.hasNext();) {
            if (monitor.isCanceled()) {
                throw new OperationCanceledException();
            }
            Artifact artifact = (Artifact) it.next();
            addProjectArtifact(pomFile, artifact);
            addProjectArtifact(rootPomFile, artifact);
        }

        if (resolverConfiguration.shouldIncludeModules()) {
            IContainer parent = pomFile.getParent();
            for (Iterator it = mavenProject.getModules().iterator(); it.hasNext();) {
                if (monitor.isCanceled()) {
                    throw new OperationCanceledException();
                }
                String module = (String) it.next();
                IResource memberPom = parent.findMember(module + "/" + Maven2Plugin.POM_FILE_NAME); //$NON-NLS-1$
                if (memberPom != null && memberPom.getType() == IResource.FILE && memberPom.isAccessible()) {
                    initMavenProject((IFile) memberPom, rootPomFile, mavenProjects, monitor, resolverConfiguration);
                }
            }
        }
    }

    // add artefact as dependency in project with pomFile
    public void addProjectArtifact(IFile pomFile, Artifact a) {
        String artifactKey = getArtifactKey(a);
        String pomKey = getPomFileKey(pomFile);

        getSet(projectsToArtifacts, pomKey).add(artifactKey);
        getSet(artifactsToProjects, artifactKey).add(pomKey);
    }

    private Set getSet(Map map, String key) {
        Set s = (Set) map.get(key);
        if (s == null) {
            s = new HashSet();
            map.put(key, s);
        }
        return s;
    }

    /**
     * @return Set of IProject
     */
    public Set getDependentProjects(IFile pomFile) {
        Set projects = new HashSet();

        Model model = getMavenModel(pomFile);
        if (model != null) {
            String artifactKey = getArtifactKey(model);
            Set a = (Set) artifactsToProjects.get(artifactKey);
            if (a != null) {
                for (Iterator it = a.iterator(); it.hasNext();) {
                    String pomKey = (String) it.next();
                    Model m = (Model) models.get(pomKey);
                    if (m != null) {
                        IFile f = (IFile) this.artifacts.get(getArtifactKey(m));
                        if (f != null) {
                            projects.add(f.getProject());
                        }
                    }
                }
            }
        }

        return projects;
    }

    public Model updateMavenModel(IFile pomFile, boolean includeModules, IProgressMonitor monitor)
            throws CoreException {
        removeMavenModel(pomFile, includeModules, monitor);
        if (!pomFile.isAccessible()) {
            return null;
        }

        Model mavenModel = readMavenModel(pomFile);
        if (mavenModel == null) {
            console.logMessage("Unable to read model for " + pomFile.getFullPath().toString());
            return null;
        }

        String pomKey = getPomFileKey(pomFile);
        models.put(pomKey, mavenModel);

        String artifactKey = getArtifactKey(mavenModel);
        artifacts.put(artifactKey, pomFile);
        if (preferenceStore.getBoolean(Maven2PreferenceConstants.P_DEBUG_OUTPUT)) {
            console.logMessage("Updated model " + pomFile.getFullPath().toString() + " : " + artifactKey);
        }

        if (includeModules) {
            IContainer parent = pomFile.getParent();
            for (Iterator it = mavenModel.getModules().iterator(); it.hasNext();) {
                if (monitor.isCanceled()) {
                    throw new OperationCanceledException();
                }
                String module = (String) it.next();
                IResource memberPom = parent.findMember(module + "/" + Maven2Plugin.POM_FILE_NAME); //$NON-NLS-1$
                if (memberPom != null && memberPom.getType() == IResource.FILE) {
                    updateMavenModel((IFile) memberPom, includeModules, monitor);
                }
            }
        }

        return mavenModel;
    }

    public Model removeMavenModel(IFile pomFile, boolean recursive, IProgressMonitor monitor) {
        String pomKey = getPomFileKey(pomFile);
        Model mavenModel = (Model) models.remove(pomKey);

        projectsToArtifacts.remove(pomKey);
        //    if(artifacts!=null) {
        //      for(Iterator it = artifacts.iterator(); it.hasNext();) {
        //        String artifactKey = (String) it.next();
        //        artifactsToProjects.remove(artifactKey);
        //      }
        //    }

        if (mavenModel != null) {
            String artifactKey = getArtifactKey(mavenModel);

            artifacts.remove(artifactKey);

            if (preferenceStore.getBoolean(Maven2PreferenceConstants.P_DEBUG_OUTPUT)) {
                console.logMessage("Removed model " + pomFile.getFullPath().toString() + " : " + artifactKey);
            }

            if (recursive) {
                IContainer parent = pomFile.getParent();
                for (Iterator it = mavenModel.getModules().iterator(); it.hasNext();) {
                    if (monitor.isCanceled()) {
                        throw new OperationCanceledException();
                    }
                    String module = (String) it.next();
                    IResource memberPom = parent.findMember(module + "/" + Maven2Plugin.POM_FILE_NAME); //$NON-NLS-1$
                    if (memberPom != null && memberPom.getType() == IResource.FILE) {
                        removeMavenModel((IFile) memberPom, recursive, monitor);
                    }
                }
            }
        }

        return mavenModel;
    }

    public Model readMavenModel(Reader reader) throws CoreException {
        try {
            MavenEmbedder projectEmbedder = embedderManager.getWorkspaceEmbedder();
            return projectEmbedder.readModel(reader);
        } catch (XmlPullParserException ex) {
            String msg = "Model parsing error; " + ex.toString();
            console.logError(msg);
            throw new CoreException(new Status(IStatus.ERROR, Maven2Plugin.PLUGIN_ID, IStatus.ERROR, msg, ex));
        } catch (IOException ex) {
            String msg = "Can't read model; " + ex.toString();
            console.logError(msg);
            throw new CoreException(new Status(IStatus.ERROR, Maven2Plugin.PLUGIN_ID, IStatus.ERROR, msg, ex));
        }
    }

    public Model readMavenModel(File pomFile) throws CoreException {
        try {
            MavenEmbedder projectEmbedder = embedderManager.getWorkspaceEmbedder();
            return projectEmbedder.readModel(pomFile);
        } catch (XmlPullParserException ex) {
            String msg = "Parsing error " + pomFile.getAbsolutePath() + "; " + ex.toString();
            console.logError(msg);
            throw new CoreException(new Status(IStatus.ERROR, Maven2Plugin.PLUGIN_ID, IStatus.ERROR, msg, ex));
        } catch (IOException ex) {
            String msg = "Can't read model " + pomFile.getAbsolutePath() + "; " + ex.toString();
            console.logError(msg);
            throw new CoreException(new Status(IStatus.ERROR, Maven2Plugin.PLUGIN_ID, IStatus.ERROR, msg, ex));
        }
    }

    public Model readMavenModel(IFile pomFile) throws CoreException {
        String name = pomFile.getProject().getName() + "/" + pomFile.getProjectRelativePath();
        try {
            MavenEmbedder projectEmbedder = embedderManager.getWorkspaceEmbedder();
            return projectEmbedder.readModel(pomFile.getLocation().toFile());
        } catch (XmlPullParserException ex) {
            String msg = "Parsing error " + name + "; " + ex.getMessage();
            console.logError(msg);
            throw new CoreException(new Status(IStatus.ERROR, Maven2Plugin.PLUGIN_ID, IStatus.ERROR, msg, ex));
        } catch (IOException ex) {
            String msg = "Can't read model " + name + "; " + ex.toString();
            console.logError(msg);
            throw new CoreException(new Status(IStatus.ERROR, Maven2Plugin.PLUGIN_ID, IStatus.ERROR, msg, ex));
        }
    }

    public MavenExecutionResult readMavenProject(File pomFile, IProgressMonitor monitor, boolean offline,
            boolean debug, ResolverConfiguration resolverConfiguration) {
        MavenEmbedder embedder = embedderManager.createEmbedder( // 
                EmbedderFactory.createWorkspaceCustomizer(resolverConfiguration.shouldResolveWorkspaceProjects()));
        return readMavenProject(pomFile, monitor, offline, debug, resolverConfiguration, embedder);
    }

    public MavenExecutionResult readMavenProject(File pomFile, IProgressMonitor monitor, //
            boolean offline, boolean debug, ResolverConfiguration resolverConfiguration, MavenEmbedder embedder) {
        try {
            // monitor.subTask("Reading " + pomFile.getFullPath());
            // File file = pomFile.getLocation().toFile();

            MavenExecutionRequest request = EmbedderFactory.createMavenExecutionRequest(embedder, offline, debug);
            request.setPomFile(pomFile.getAbsolutePath());
            request.setBaseDirectory(pomFile.getParentFile());
            request.setTransferListener(new TransferListenerAdapter(monitor, console, indexManager));
            request.setProfiles(resolverConfiguration.getActiveProfileList());
            request.addActiveProfiles(resolverConfiguration.getActiveProfileList());

            return embedder.readProjectWithDependencies(request);

            // XXX need to manage markers somehow see MNGECLIPSE-***
            // Util.deleteMarkers(pomFile);

            //      if(!result.hasExceptions()) {
            //        return result.getMavenProject();
            //      }
            //      
            //      return result.getMavenProject();

            //    } catch(Exception ex) {
            //      Util.deleteMarkers(this.file);
            //      Util.addMarker(this.file, "Unable to read project; " + ex.toString(), 1, IMarker.SEVERITY_ERROR);
            //      
            //      String msg = "Unable to read " + file.getLocation() + "; " + ex.toString();
            //      console.logError(msg);
            //      Maven2Plugin.log(msg, ex);

        } finally {
            monitor.done();
        }
    }

    public void addDependency(IFile pomFile, Dependency dependency) {
        addDependencies(pomFile, Collections.singletonList(dependency));
    }

    public void addDependencies(IFile pomFile, List dependencies) {
        File pom = pomFile.getLocation().toFile();
        try {
            MavenEmbedder mavenEmbedder = embedderManager.getWorkspaceEmbedder();
            Model model = mavenEmbedder.readModel(pom);
            model.getDependencies().addAll(dependencies);

            StringWriter w = new StringWriter();
            mavenEmbedder.writeModel(w, model, true);
            //      MavenXpp3Writer writer = new MavenXpp3Writer();
            //      writer.write(w, model);

            pomFile.setContents(new ByteArrayInputStream(w.toString().getBytes(model.getModelEncoding())), true,
                    true, null);
            pomFile.refreshLocal(IResource.DEPTH_ONE, null); // TODO ???
        } catch (Exception ex) {
            console.logError("Unable to update POM: " + pom + "; " + ex.getMessage());
        }
    }

    public static String getArtifactKey(Model model) {
        String groupId = model.getGroupId();
        if (groupId == null) {
            // If the groupId is null in the model, then it needs to be inherited
            // from the parent.  And the parent's groupId has to be specified in the
            // in the parent element of the model.
            groupId = model.getParent() == null ? "[unknown]" : model.getParent().getGroupId();
        }

        String version = model.getVersion();
        if (version == null) {
            version = model.getParent() == null ? "[unknown]" : model.getParent().getVersion();
        }

        return groupId + ":" + model.getArtifactId() + ":" + version;
    }

    public static String getArtifactKey(Artifact a) {
        return a.getGroupId() + ":" + a.getArtifactId() + ":" + a.getVersion();
    }

    public static String getPomFileKey(IFile pomFile) {
        return pomFile.getFullPath().toPortableString();
    }

}