org.eclipse.pde.internal.core.SearchablePluginsManager.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.pde.internal.core.SearchablePluginsManager.java

Source

/*******************************************************************************
 * Copyright (c) 2000, 2014 IBM Corporation and others.
 * 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.pde.internal.core;

import java.io.*;
import java.util.*;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.osgi.util.NLS;
import org.eclipse.pde.core.plugin.*;
import org.eclipse.pde.internal.core.util.CoreUtility;

/**
 * This class manages the ability of external plug-ins in the model manager to
 * take part in the Java search. It manages a proxy Java projects and for each
 * external plug-in added to Java search, it adds its Java libraries as external
 * JARs to the proxy project. This makes the libraries visible to the Java
 * model, and they can take part in various Java searches.
 */
public class SearchablePluginsManager implements IFileAdapterFactory, IPluginModelListener {

    private static final String PROXY_FILE_NAME = ".searchable"; //$NON-NLS-1$
    public static final String PROXY_PROJECT_NAME = "External Plug-in Libraries"; //$NON-NLS-1$
    private static final String KEY = "searchablePlugins"; //$NON-NLS-1$

    private Listener fElementListener;
    private Set<String> fPluginIdSet;
    private ArrayList<IPluginModelListener> fListeners;

    class Listener implements IElementChangedListener {
        public void elementChanged(ElementChangedEvent e) {
            if (e.getType() == ElementChangedEvent.POST_CHANGE) {
                handleDelta(e.getDelta());
            }
        }

        private boolean handleDelta(IJavaElementDelta delta) {
            Object element = delta.getElement();
            if (element instanceof IJavaModel) {
                IJavaElementDelta[] projectDeltas = delta.getAffectedChildren();
                for (int i = 0; i < projectDeltas.length; i++) {
                    if (handleDelta(projectDeltas[i]))
                        break;
                }
                return true;
            }
            if (delta.getElement() instanceof IJavaProject) {
                IJavaProject project = (IJavaProject) delta.getElement();
                if (project.getElementName().equals(PROXY_PROJECT_NAME)) {
                    if (delta.getKind() == IJavaElementDelta.REMOVED) {
                        fPluginIdSet.clear();
                    } else if (delta.getKind() == IJavaElementDelta.ADDED) {
                        // We may be getting a queued delta from when the manager was initialized, ignore unless we don't already have data
                        if (fPluginIdSet == null || fPluginIdSet.size() == 0) {
                            // Something other than the manager created the project, check if it has a .searchable file to load from
                            fPluginIdSet = loadStates();
                        }
                    }
                }
                return true;
            }
            return false;
        }
    }

    public SearchablePluginsManager() {
        fPluginIdSet = loadStates();
        fElementListener = new Listener();
        JavaCore.addElementChangedListener(fElementListener);
        PDECore.getDefault().getModelManager().addPluginModelListener(this);
    }

    private static Set<String> loadStates() {
        Set<String> set = new TreeSet<String>();
        IWorkspaceRoot root = PDECore.getWorkspace().getRoot();
        IProject project = root.getProject(PROXY_PROJECT_NAME);
        try {
            if (project.exists() && project.isOpen()) {
                IFile proxyFile = project.getFile(PROXY_FILE_NAME);
                if (proxyFile.exists()) {
                    Properties properties = new Properties();
                    InputStream stream = proxyFile.getContents(true);
                    properties.load(stream);
                    stream.close();
                    String value = properties.getProperty(KEY);
                    if (value != null) {
                        StringTokenizer stok = new StringTokenizer(value, ","); //$NON-NLS-1$
                        while (stok.hasMoreTokens())
                            set.add(stok.nextToken());
                    }
                }
            }
        } catch (IOException e) {
        } catch (CoreException e) {
        }
        return set;
    }

    public IJavaProject getProxyProject() {
        IWorkspaceRoot root = PDECore.getWorkspace().getRoot();
        IProject project = root.getProject(PROXY_PROJECT_NAME);
        try {
            if (project.exists() && project.isOpen() && project.hasNature(JavaCore.NATURE_ID)) {
                return JavaCore.create(project);
            }

        } catch (CoreException e) {
        }
        return null;
    }

    public void shutdown() {
        // remove listener
        JavaCore.removeElementChangedListener(fElementListener);
        PDECore.getDefault().getModelManager().removePluginModelListener(this);
        if (fListeners != null)
            fListeners.clear();
    }

    public IClasspathEntry[] computeContainerClasspathEntries() throws CoreException {
        ArrayList<IClasspathEntry> result = new ArrayList<IClasspathEntry>();

        IPluginModelBase[] wModels = PluginRegistry.getWorkspaceModels();
        for (int i = 0; i < wModels.length; i++) {
            IProject project = wModels[i].getUnderlyingResource().getProject();
            if (project.hasNature(JavaCore.NATURE_ID)) {
                result.add(JavaCore.newProjectEntry(project.getFullPath()));
            }
        }
        Iterator<String> iter = fPluginIdSet.iterator();
        while (iter.hasNext()) {
            ModelEntry entry = PluginRegistry.findEntry(iter.next().toString());
            if (entry != null) {
                boolean addModel = true;
                wModels = entry.getWorkspaceModels();
                for (int i = 0; i < wModels.length; i++) {
                    IProject project = wModels[i].getUnderlyingResource().getProject();
                    if (project.hasNature(JavaCore.NATURE_ID))
                        addModel = false;
                }
                if (!addModel)
                    continue;
                IPluginModelBase[] models = entry.getExternalModels();
                for (int i = 0; i < models.length; i++) {
                    if (models[i].isEnabled())
                        ClasspathUtilCore.addLibraries(models[i], result);
                }
            }
        }

        if (result.size() > 1) {
            // sort
            Map<String, IClasspathEntry> map = new TreeMap<String, IClasspathEntry>();
            for (int i = 0; i < result.size(); i++) {
                IClasspathEntry entry = result.get(i);
                String key = entry.getPath().lastSegment().toString();
                if (map.containsKey(key)) {
                    key += System.currentTimeMillis();
                }
                map.put(key, entry);
            }
            return map.values().toArray(new IClasspathEntry[map.size()]);
        }
        return result.toArray(new IClasspathEntry[result.size()]);
    }

    public Object createAdapterChild(FileAdapter parent, File file) {
        if (!file.isDirectory()) {
            if (file.isFile()) {
                IPackageFragmentRoot root = findPackageFragmentRoot(new Path(file.getAbsolutePath()));
                if (root != null)
                    return root;
            }
        }
        return new FileAdapter(parent, file, this);
    }

    private IPackageFragmentRoot findPackageFragmentRoot(IPath jarPath) {
        IJavaProject jProject = getProxyProject();
        if (jProject != null) {
            try {
                IPackageFragmentRoot[] roots = jProject.getAllPackageFragmentRoots();
                for (int i = 0; i < roots.length; i++) {
                    IPackageFragmentRoot root = roots[i];
                    IPath path = root.getPath();
                    if (path.equals(jarPath))
                        return root;

                }
            } catch (JavaModelException e) {
            }
        }

        // Find in other plug-in (and fragments) projects dependencies
        IPluginModelBase[] pluginModels = PluginRegistry.getWorkspaceModels();
        for (int i = 0; i < pluginModels.length; i++) {
            IProject project = pluginModels[i].getUnderlyingResource().getProject();
            IJavaProject javaProject = JavaCore.create(project);
            try {
                IPackageFragmentRoot[] roots = javaProject.getAllPackageFragmentRoots();
                for (int j = 0; j < roots.length; j++) {
                    IPackageFragmentRoot root = roots[j];
                    IPath path = root.getPath();
                    if (path.equals(jarPath))
                        return root;
                }
            } catch (JavaModelException e) {
            }
        }

        return null;
    }

    private void checkForProxyProject() {
        IWorkspaceRoot root = PDECore.getWorkspace().getRoot();
        try {
            IProject project = root.getProject(SearchablePluginsManager.PROXY_PROJECT_NAME);
            if (!project.exists())
                createProxyProject(new NullProgressMonitor());
        } catch (CoreException e) {
        }
    }

    public void addToJavaSearch(IPluginModelBase[] models) {
        checkForProxyProject();
        PluginModelDelta delta = new PluginModelDelta();
        int size = fPluginIdSet.size();
        for (int i = 0; i < models.length; i++) {
            String id = models[i].getPluginBase().getId();
            if (fPluginIdSet.add(id)) {
                ModelEntry entry = PluginRegistry.findEntry(id);
                if (entry != null)
                    delta.addEntry(entry, PluginModelDelta.CHANGED);
            }
        }
        if (fPluginIdSet.size() > size) {
            resetContainer();
            fireDelta(delta);
        }
    }

    public void removeFromJavaSearch(IPluginModelBase[] models) {
        PluginModelDelta delta = new PluginModelDelta();
        int size = fPluginIdSet.size();
        for (int i = 0; i < models.length; i++) {
            String id = models[i].getPluginBase().getId();
            if (fPluginIdSet.remove(id)) {
                ModelEntry entry = PluginRegistry.findEntry(id);
                if (entry != null) {
                    delta.addEntry(entry, PluginModelDelta.CHANGED);
                }
            }
        }
        if (fPluginIdSet.size() < size) {
            resetContainer();
            fireDelta(delta);
        }
    }

    public void removeAllFromJavaSearch() {
        if (fPluginIdSet.size() > 0) {
            PluginModelDelta delta = new PluginModelDelta();
            for (Iterator<String> iterator = fPluginIdSet.iterator(); iterator.hasNext();) {
                String id = iterator.next();
                ModelEntry entry = PluginRegistry.findEntry(id);
                if (entry != null) {
                    delta.addEntry(entry, PluginModelDelta.CHANGED);
                }
            }
            fPluginIdSet.clear();
            resetContainer();
            fireDelta(delta);
        }
    }

    public boolean isInJavaSearch(String symbolicName) {
        return fPluginIdSet.contains(symbolicName);
    }

    private void resetContainer() {
        IJavaProject jProject = getProxyProject();
        try {
            if (jProject != null) {
                JavaCore.setClasspathContainer(PDECore.JAVA_SEARCH_CONTAINER_PATH, new IJavaProject[] { jProject },
                        new IClasspathContainer[] { new ExternalJavaSearchClasspathContainer() }, null);
                saveStates();
            }
        } catch (JavaModelException e) {
        }
    }

    public void modelsChanged(PluginModelDelta delta) {
        ModelEntry[] entries = delta.getRemovedEntries();
        for (int i = 0; i < entries.length; i++) {
            if (fPluginIdSet.contains(entries[i].getId())) {
                fPluginIdSet.remove(entries[i].getId());
            }
        }
        resetContainer();
    }

    private void fireDelta(PluginModelDelta delta) {
        if (fListeners != null) {
            for (int i = 0; i < fListeners.size(); i++) {
                fListeners.get(i).modelsChanged(delta);
            }
        }
    }

    public void addPluginModelListener(IPluginModelListener listener) {
        if (fListeners == null)
            fListeners = new ArrayList<IPluginModelListener>();
        if (!fListeners.contains(listener))
            fListeners.add(listener);
    }

    public void removePluginModelListener(IPluginModelListener listener) {
        if (fListeners != null)
            fListeners.remove(listener);
    }

    private void saveStates() {
        // persist state
        IWorkspaceRoot root = PDECore.getWorkspace().getRoot();
        IProject project = root.getProject(PROXY_PROJECT_NAME);
        if (project.exists() && project.isOpen()) {
            // modify the .searchable file only if there is any change
            if (loadStates().equals(fPluginIdSet))
                return;
            IFile file = project.getFile(PROXY_FILE_NAME);
            Properties properties = new Properties();
            StringBuffer buffer = new StringBuffer();
            Iterator<String> iter = fPluginIdSet.iterator();
            while (iter.hasNext()) {
                if (buffer.length() > 0)
                    buffer.append(","); //$NON-NLS-1$
                buffer.append(iter.next().toString());
            }
            properties.setProperty(KEY, buffer.toString());
            try {
                ByteArrayOutputStream outStream = new ByteArrayOutputStream();
                properties.store(outStream, ""); //$NON-NLS-1$
                outStream.flush();
                outStream.close();
                ByteArrayInputStream inStream = new ByteArrayInputStream(outStream.toByteArray());
                if (file.exists())
                    file.setContents(inStream, true, false, new NullProgressMonitor());
                else
                    file.create(inStream, true, new NullProgressMonitor());
                inStream.close();
            } catch (IOException e) {
                PDECore.log(e);
            } catch (CoreException e) {
                PDECore.log(e);
            }
        }
    }

    public IProject createProxyProject(IProgressMonitor monitor) throws CoreException {
        IWorkspaceRoot root = PDECore.getWorkspace().getRoot();
        IProject project = root.getProject(SearchablePluginsManager.PROXY_PROJECT_NAME);
        if (project.exists()) {
            if (!project.isOpen()) {
                project.open(monitor);
            }
            return project;
        }

        monitor.beginTask(NLS.bind(PDECoreMessages.SearchablePluginsManager_createProjectTaskName,
                SearchablePluginsManager.PROXY_PROJECT_NAME), 5);
        project.create(new SubProgressMonitor(monitor, 1));
        project.open(new SubProgressMonitor(monitor, 1));
        CoreUtility.addNatureToProject(project, JavaCore.NATURE_ID, new SubProgressMonitor(monitor, 1));
        IJavaProject jProject = JavaCore.create(project);
        jProject.setOutputLocation(project.getFullPath(), new SubProgressMonitor(monitor, 1));
        computeClasspath(jProject, new SubProgressMonitor(monitor, 1));
        return project;
    }

    private void computeClasspath(IJavaProject project, IProgressMonitor monitor) {
        IClasspathEntry[] classpath = new IClasspathEntry[2];
        classpath[0] = JavaCore.newContainerEntry(JavaRuntime.newDefaultJREContainerPath());
        classpath[1] = JavaCore.newContainerEntry(PDECore.JAVA_SEARCH_CONTAINER_PATH);
        try {
            project.setRawClasspath(classpath, monitor);
        } catch (JavaModelException e) {
        }
    }

}