Package org.mevenide.idea.global

Source Code of org.mevenide.idea.global.MavenPluginsManager$MavenHomeListener

package org.mevenide.idea.global;

import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.mevenide.idea.project.goals.DefaultPluginGoal;
import org.mevenide.idea.project.goals.DefaultPluginGoalContainer;
import org.mevenide.idea.project.goals.PluginGoal;
import org.mevenide.idea.project.goals.PluginGoalContainer;
import org.mevenide.idea.project.properties.PropertiesManager;
import org.mevenide.idea.psi.util.PsiUtils;
import org.mevenide.idea.psi.util.XmlTagPath;
import org.mevenide.idea.util.FileUtils;
import org.mevenide.idea.util.IDEUtils;
import org.mevenide.idea.util.components.AbstractProjectComponent;

/**
* @author Arik
*/
public class MavenPluginsManager extends AbstractProjectComponent {
    /**
     * The name of the Maven property that denotes the location of the plugins JAR files.
     */
    private static final String CACHE_DIR_PROPERTY = "maven.plugin.unpacked.dir";
    private static final String POM_ID_XPATH = "project/id";
    private static final String POM_GROUP_ID_XPATH = "project/groupId";
    private static final String POM_ARTIFACT_ID_XPATH = "project/artifactId";
    private static final String POM_VERSION_XPATH = "project/currentVersion";
    private static final String POM_NAME_XPATH = "project/name";
    private static final String POM_DESC_XPATH = "project/description";
    private static final String[] EMPTY_STRING_ARRAY = new String[0];

    private VirtualFile pluginsCacheFile = null;

    /**
     * Cache for loaded plugin descriptors.
     */
    private PluginGoalContainer[] plugins = new PluginGoalContainer[0];
    private final MavenHomeListener MAVEN_HOME_LISTENER = new MavenHomeListener();

    /**
     * Creates an instance for the given project.
     *
     * @param pProject the project this component instance will be registered for
     */
    public MavenPluginsManager(final Project pProject) {
        super(pProject);
    }

    @Override
    public void projectOpened() {
        final MavenManager mvnMgr = MavenManager.getInstance();
        mvnMgr.addPropertyChangeListener("mavenHome", MAVEN_HOME_LISTENER);
    }

    @Override
    public void projectClosed() {
        final MavenManager mvnMgr = MavenManager.getInstance();
        mvnMgr.removePropertyChangeListener("mavenHome", MAVEN_HOME_LISTENER);
    }

    public PluginGoalContainer getPlugin(final String pId) {
        synchronized (this) {
            final PluginGoalContainer[] plugins = getPlugins();
            for (PluginGoalContainer plugin : plugins) {
                if (plugin.getId().equals(pId))
                    return plugin;
            }

            return null;
        }
    }

    public PluginGoalContainer getPlugin(final String pGroupId, final String pArtifactId) {
        synchronized (this) {
            final PluginGoalContainer[] plugins = getPlugins();
            for (PluginGoalContainer plugin : plugins) {
                if (plugin.getGroupId().equals(pGroupId) && plugin.getArtifactId().equals(
                        pArtifactId))
                    return plugin;
            }

            return null;
        }
    }

    /**
     * Parses all plugins in the Maven installation.
     *
     * @return list of plugins found in the maven installation
     */
    public PluginGoalContainer[] getPlugins() {
        synchronized (this) {
            boolean reload = true;
            final VirtualFile cacheFile = getPluginsCacheFile();
            if (pluginsCacheFile == cacheFile)
                reload = false;
            else if (pluginsCacheFile != null && pluginsCacheFile.equals(cacheFile))
                reload = false;

            if (reload)
                refresh(cacheFile);

            return plugins;
        }
    }

    public void refresh() {
        refresh(getPluginsCacheFile());
    }

    private void refresh(final VirtualFile pPluginsCacheFile) {
        synchronized (this) {
            final PluginGoalContainer[] oldPlugins = plugins;
            try {
                LOG.trace("Refreshing maven plugins cache");
                final Runnable pluginLoader = new Runnable() {
                    public void run() {
                        try {
                            plugins = loadPlugins(pPluginsCacheFile);
                        }
                        catch (IOException e) {
                            LOG.error(e.getMessage(), e);
                            plugins = new PluginGoalContainer[0];
                        }
                    }
                };
                final Application app = ApplicationManager.getApplication();
                app.runProcessWithProgressSynchronously(
                        pluginLoader,
                        "Loading plugins",
                        false,
                        project);
            }
            finally {
                pluginsCacheFile = pPluginsCacheFile;
                changeSupport.firePropertyChange("plugins", oldPlugins, plugins, false);
            }
        }
    }

    /**
     * Loads and parses all available plugins in the user's cache directory.
     *
     * @return available plugins
     * @throws IOException if an error occurs
     */
    private PluginGoalContainer[] loadPlugins(final VirtualFile pPluginsCacheFile)
            throws IOException {
        final ProgressIndicator prg = IDEUtils.getProgressIndicator();
        if (prg != null) {
            prg.setIndeterminate(true);
            prg.setText("Discovering available plugins...");
            prg.start();
        }

        int counter = 0;
        try {
            if (pPluginsCacheFile == null || !pPluginsCacheFile.isValid() || !FileUtils.exists(
                    pPluginsCacheFile) || pPluginsCacheFile.isDirectory()) {
                if (prg != null) {
                    prg.setText("No available plugins found.");
                    prg.setFraction(1);
                }
                return new PluginGoalContainer[0];
            }

            final VirtualFile pluginsDir = pPluginsCacheFile.getParent();
            if (pluginsDir == null || !pluginsDir.isValid() || !FileUtils.exists(pluginsDir) || !pluginsDir.isDirectory()) {
                if (prg != null) {
                    prg.setText("No available plugins found.");
                    prg.setFraction(1);
                }
                return new PluginGoalContainer[0];
            }

            final Properties props = new Properties();
            final byte[] data = pPluginsCacheFile.contentsToByteArray();
            final ByteArrayInputStream stream = new ByteArrayInputStream(data);
            props.load(stream);

            if (prg != null) {
                prg.setText("Found " + props.size() + " plugins.");
                prg.setIndeterminate(false);
                prg.setFraction(0);
            }

            final Set<PluginGoalContainer> plugins = new HashSet<PluginGoalContainer>(30);
            final Set<Map.Entry<Object, Object>> entries = props.entrySet();

            final int pluginCount = entries.size();

            for (Map.Entry<Object, Object> entry : entries) {
                final String pluginName = entry.getValue().toString();
                final String artifactId = entry.getKey().toString();

                if (prg != null) {
                    prg.setText("Loading plugin '" + pluginName + "'");
                    prg.setFraction((double) counter / (double) pluginCount);
                    counter++;
                }

                final VirtualFile pluginDir = pluginsDir.findChild(artifactId);
                if (pluginDir == null || !pluginDir.isValid() || !FileUtils.exists(pluginDir) || !pluginDir.isDirectory()) {
                    if (prg != null)
                        prg.setText("Could not load plugin '" + pluginName + "'");
                    continue;
                }

                final PluginGoalContainer plugin = parsePlugin(pluginDir);
                if (plugin != null)
                    plugins.add(plugin);
            }

            return plugins.toArray(new PluginGoalContainer[plugins.size()]);
        }
        finally {
            if (prg != null) {
                prg.setText("Done - loaded " + counter + " plugin(s).");
                prg.setFraction(1);
            }
        }
    }

    /**
     * Parses the given plugin JAR and extracts general plugin information and available goals.
     *
     * @param pPluginDir the plugin directory
     *
     * @return plugin descriptor
     */
    private PluginGoalContainer parsePlugin(final VirtualFile pPluginDir) {
        final DefaultPluginGoalContainer plugin = new DefaultPluginGoalContainer();

        //
        //parse plugin POM
        //
        final VirtualFile pluginPom = pPluginDir.findChild("project.xml");
        if (pluginPom != null && pluginPom.isValid() && FileUtils.exists(pluginPom))
            plugin.setPomFile(pluginPom);
        else
            return null;

        final XmlFile pomPsi = PsiUtils.findXmlFile(project, pluginPom);
        if (pomPsi == null)
            return null;

        plugin.setId(new XmlTagPath(pomPsi, POM_ID_XPATH).getStringValue());
        plugin.setGroupId(new XmlTagPath(pomPsi, POM_GROUP_ID_XPATH).getStringValue());
        plugin.setArtifactId(new XmlTagPath(pomPsi, POM_ARTIFACT_ID_XPATH).getStringValue());
        plugin.setVersion(new XmlTagPath(pomPsi, POM_VERSION_XPATH).getStringValue());
        plugin.setName(new XmlTagPath(pomPsi, POM_NAME_XPATH).getStringValue());
        plugin.setDescription(new XmlTagPath(pomPsi, POM_DESC_XPATH).getStringValue());

        //
        //parse plugin Jelly script
        //
        final VirtualFile jellyFile = pPluginDir.findChild("plugin.jelly");
        if (jellyFile != null && jellyFile.isValid() && FileUtils.exists(jellyFile))
            plugin.setScriptFile(jellyFile);
        else
            return null;

        final XmlFile jellyPsi = PsiUtils.findXmlFile(project, jellyFile);
        final XmlTagPath goalsPath = new XmlTagPath(jellyPsi, "project/goal");
        final XmlTag[] goalTags = goalsPath.getAllTags();
        final PluginGoal[] goals = new PluginGoal[goalTags.length];
        for (int i = 0; i < goalTags.length; i++) {
            XmlTag tag = goalTags[i];
            final String name = tag.getAttributeValue("name");
            final String lcName = name.toLowerCase();
            if (lcName.equalsIgnoreCase("register") || lcName.equalsIgnoreCase("deregister"))
                continue;

            final String desc = tag.getAttributeValue("description");
            final String preReqsValue = tag.getAttributeValue("prereqs");
            final String[] preReqs = preReqsValue == null ? EMPTY_STRING_ARRAY : preReqsValue.split(
                    ",");

            final DefaultPluginGoal goal = new DefaultPluginGoal();
            goal.setName(name);
            goal.setDescription(desc);
            goal.setContainer(plugin);
            goal.setPrereqs(preReqs);
            goals[i] = goal;
        }
        plugin.setGoals(goals);

        return plugin;
    }

    private VirtualFile getPluginsCacheFile() {
        final PropertiesManager propsMgr = PropertiesManager.getInstance(project);
        final String cacheDir = propsMgr.getProperty(CACHE_DIR_PROPERTY);
        if (cacheDir == null || cacheDir.trim().length() == 0)
            return null;

        final StringBuilder buf = new StringBuilder(100);
        buf.append("file://").append(cacheDir.replace(File.separatorChar, '/'));
        if (buf.charAt(buf.length() - 1) != '/')
            buf.append('/');
        buf.append("artifactIdToPlugin.cache");
        return VirtualFileManager.getInstance().findFileByUrl(buf.toString());
    }

    public static MavenPluginsManager getInstance(final Project pProject) {
        return pProject.getComponent(MavenPluginsManager.class);
    }

    private class MavenHomeListener implements PropertyChangeListener {
        public void propertyChange(
                PropertyChangeEvent evt) {
            if (!evt.getPropertyName().equals(
                    "mavenHome"))
                return;

            refresh();
        }
    }
}
TOP

Related Classes of org.mevenide.idea.global.MavenPluginsManager$MavenHomeListener

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.