com.siteview.mde.internal.ui.search.dependencies.AddNewDependenciesOperation.java Source code

Java tutorial

Introduction

Here is the source code for com.siteview.mde.internal.ui.search.dependencies.AddNewDependenciesOperation.java

Source

/*******************************************************************************
 * Copyright (c) 2005, 2010 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 com.siteview.mde.internal.ui.search.dependencies;

import com.siteview.mde.internal.core.monitor.MonitorImport;

import com.siteview.mde.core.monitor.*;

import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.search.*;
import org.eclipse.osgi.service.resolver.*;
import org.eclipse.osgi.util.ManifestElement;
import org.eclipse.osgi.util.NLS;
import com.siteview.mde.core.build.IBuild;
import com.siteview.mde.core.build.IBuildEntry;
import org.eclipse.pde.internal.build.IPDEBuildConstants;
import com.siteview.mde.internal.core.ICoreConstants;
import com.siteview.mde.internal.core.MDECore;
import com.siteview.mde.internal.core.build.WorkspaceBuildModel;
import com.siteview.mde.internal.core.bundle.BundlePluginBase;
import com.siteview.mde.internal.core.converter.MonitorConverter;
import com.siteview.mde.internal.core.ibundle.*;
import com.siteview.mde.internal.core.project.PDEProject;
import com.siteview.mde.internal.core.search.PluginJavaSearchUtil;
import com.siteview.mde.internal.core.text.bundle.*;
import com.siteview.mde.internal.ui.MDEUIMessages;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
import org.osgi.framework.*;

public class AddNewDependenciesOperation extends WorkspaceModifyOperation {

    protected IProject fProject;
    protected IBundlePluginModelBase fBase;
    private boolean fNewDependencies = false;

    protected static class ReferenceFinder extends SearchRequestor {
        private boolean found = false;

        public void acceptSearchMatch(SearchMatch match) throws CoreException {
            found = true;
        }

        public boolean foundMatches() {
            return found;
        }
    }

    public AddNewDependenciesOperation(IProject project, IBundlePluginModelBase base) {
        fProject = project;
        fBase = base;
    }

    protected void execute(IProgressMonitor monitor)
            throws CoreException, InvocationTargetException, InterruptedException {
        monitor.beginTask(MDEUIMessages.AddNewDependenciesOperation_mainTask, 100);
        final IBundle bundle = fBase.getBundleModel().getBundle();
        final Set ignorePkgs = new HashSet();
        final String[] secDeps = findSecondaryBundles(bundle, ignorePkgs);
        if (secDeps == null || secDeps.length == 0) {
            monitor.done();
            return;
        }
        monitor.worked(4);
        findImportPackages(bundle, ignorePkgs);
        monitor.worked(2);
        addProjectPackages(bundle, ignorePkgs);
        monitor.worked(4);

        final Map additionalDeps = new HashMap();
        monitor.subTask(MDEUIMessages.AddNewDependenciesOperation_searchProject);

        boolean useRequireBundle = new ProjectScope(fProject).getNode(MDECore.PLUGIN_ID)
                .getBoolean(ICoreConstants.RESOLVE_WITH_REQUIRE_BUNDLE, true);
        findSecondaryDependencies(secDeps, ignorePkgs, additionalDeps, bundle, useRequireBundle,
                new SubProgressMonitor(monitor, 80));
        handleNewDependencies(additionalDeps, useRequireBundle, new SubProgressMonitor(monitor, 10));
        monitor.done();
    }

    public boolean foundNewDependencies() {
        return fNewDependencies;
    }

    protected String[] findSecondaryBundles(IBundle bundle, Set ignorePkgs) {
        String[] secDeps = getSecondaryDependencies();
        if (secDeps == null)
            return null;
        Set manifestPlugins = findManifestPlugins(bundle, ignorePkgs);

        List result = new LinkedList();
        for (int i = 0; i < secDeps.length; i++)
            if (!manifestPlugins.contains(secDeps[i]))
                result.add(secDeps[i]);

        return (String[]) result.toArray(new String[result.size()]);
    }

    private String[] getSecondaryDependencies() {
        IBuild build = getBuild();
        if (build != null) {
            IBuildEntry be = build.getEntry(IBuildEntry.SECONDARY_DEPENDENCIES);
            if (be != null)
                return be.getTokens();
        }
        return null;
    }

    protected final IBuild getBuild() {
        IFile buildProps = PDEProject.getBuildProperties(fProject);
        if (buildProps != null) {
            WorkspaceBuildModel model = new WorkspaceBuildModel(buildProps);
            if (model != null)
                return model.getBuild();
        }
        return null;
    }

    private Set findManifestPlugins(IBundle bundle, Set ignorePkgs) {
        IManifestHeader header = bundle.getManifestHeader(Constants.REQUIRE_BUNDLE);
        if (header == null)
            return new HashSet(0);
        Set plugins = (header instanceof RequireBundleHeader)
                ? findManifestPlugins((RequireBundleHeader) header, ignorePkgs)
                : findManifestPlugins(ignorePkgs);
        if (plugins.contains(IPDEBuildConstants.BUNDLE_CORE_RUNTIME))
            plugins.add("system.bundle"); //$NON-NLS-1$
        return plugins;
    }

    private Set findManifestPlugins(RequireBundleHeader header, Set ignorePkgs) {
        RequireBundleObject[] bundles = header.getRequiredBundles();
        Set result = new HashSet((4 / 3) * (bundles.length) + 2);
        ArrayList plugins = new ArrayList();
        for (int i = 0; i < bundles.length; i++) {
            String id = bundles[i].getId();
            result.add(id);
            IMonitorModelBase base = MonitorRegistry.findModel(id);
            if (base != null) {
                ExportPackageDescription[] exportedPkgs = findExportedPackages(base.getBundleDescription());
                for (int j = 0; j < exportedPkgs.length; j++)
                    ignorePkgs.add(exportedPkgs[j].getName());
                plugins.add(base.getMonitorBase());
            }
        }
        return result;
    }

    private Set findManifestPlugins(Set ignorePkgs) {
        BundleSpecification[] bundles = fBase.getBundleDescription().getRequiredBundles();
        Set result = new HashSet((4 / 3) * (bundles.length) + 2);
        ArrayList plugins = new ArrayList();
        for (int i = 0; i < bundles.length; i++) {
            String id = bundles[i].getName();
            result.add(id);
            IMonitorModelBase base = MonitorRegistry.findModel(id);
            if (base != null) {
                ExportPackageDescription[] exportedPkgs = findExportedPackages(base.getBundleDescription());
                for (int j = 0; j < exportedPkgs.length; j++)
                    ignorePkgs.add(exportedPkgs[j].getName());
                plugins.add(base.getMonitorBase());
            }
        }
        return result;
    }

    protected final ExportPackageDescription[] findExportedPackages(BundleDescription desc) {
        if (desc != null) {
            IBundle bundle = fBase.getBundleModel().getBundle();
            String value = bundle.getHeader(Constants.BUNDLE_SYMBOLICNAME);
            int index = (value != null) ? value.indexOf(';') : -1;
            String projectBundleId = (index > 0) ? value.substring(0, index) : value;
            List result = new LinkedList();
            Stack stack = new Stack();
            stack.add(desc);
            while (!stack.isEmpty()) {
                BundleDescription bdesc = (BundleDescription) stack.pop();
                ExportPackageDescription[] expkgs = bdesc.getExportPackages();
                for (int i = 0; i < expkgs.length; i++)
                    if (addPackage(projectBundleId, expkgs[i]))
                        result.add(expkgs[i]);

                // Look at re-exported Require-Bundles for any other exported packages
                BundleSpecification[] requiredBundles = bdesc.getRequiredBundles();
                for (int i = 0; i < requiredBundles.length; i++)
                    if (requiredBundles[i].isExported()) {
                        BaseDescription bd = requiredBundles[i].getSupplier();
                        if (bd != null && bd instanceof BundleDescription)
                            stack.add(bd);
                    }
            }
            return (ExportPackageDescription[]) result.toArray(new ExportPackageDescription[result.size()]);
        }
        return new ExportPackageDescription[0];
    }

    private boolean addPackage(String symbolicName, ExportPackageDescription pkg) {
        if (symbolicName == null)
            return true;
        String[] friends = (String[]) pkg.getDirective(ICoreConstants.FRIENDS_DIRECTIVE);
        if (friends != null) {
            for (int i = 0; i < friends.length; i++) {
                if (symbolicName.equals(friends[i]))
                    return true;
            }
            return false;
        }
        return true;
    }

    protected final void findImportPackages(IBundle bundle, Set ignorePkgs) {
        IManifestHeader header = bundle.getManifestHeader(Constants.IMPORT_PACKAGE);
        if (header == null || header.getValue() == null)
            return;
        if (header instanceof ImportPackageHeader) {
            ImportPackageObject[] pkgs = ((ImportPackageHeader) header).getPackages();
            for (int i = 0; i < pkgs.length; i++)
                ignorePkgs.add(pkgs[i].getName());
        } else {
            ImportPackageSpecification[] pkgs = fBase.getBundleDescription().getImportPackages();
            for (int i = 0; i < pkgs.length; i++)
                ignorePkgs.add(pkgs[i].getName());
        }
    }

    protected void findSecondaryDependencies(String[] secDeps, Set ignorePkgs, Map newDeps, IBundle bundle,
            boolean useRequireBundle, IProgressMonitor monitor) {
        IJavaProject jProject = JavaCore.create(fProject);
        SearchEngine engine = new SearchEngine();
        if (ignorePkgs == null)
            ignorePkgs = new HashSet(2);
        monitor.beginTask(MDEUIMessages.AddNewDependenciesOperation_searchProject, secDeps.length);
        for (int j = 0; j < secDeps.length; j++) {
            try {
                if (monitor.isCanceled())
                    return;
                IProgressMonitor subMonitor = new SubProgressMonitor(monitor, 1);
                String pluginId = secDeps[j];
                IMonitorModelBase base = MonitorRegistry.findModel(secDeps[j]);
                if (base != null) {
                    ExportPackageDescription[] exported = findExportedPackages(base.getBundleDescription());
                    IJavaSearchScope searchScope = PluginJavaSearchUtil.createSeachScope(jProject);
                    subMonitor.beginTask(
                            NLS.bind(MDEUIMessages.AddNewDependenciesOperation_searchForDependency, pluginId),
                            exported.length);
                    for (int i = 0; i < exported.length; i++) {
                        String pkgName = exported[i].getName();
                        if (!ignorePkgs.contains(pkgName)) {
                            ReferenceFinder requestor = new ReferenceFinder();
                            engine.search(
                                    SearchPattern.createPattern(pkgName, IJavaSearchConstants.PACKAGE,
                                            IJavaSearchConstants.REFERENCES, SearchPattern.R_EXACT_MATCH),
                                    new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() },
                                    searchScope, requestor, null);
                            if (requestor.foundMatches()) {
                                fNewDependencies = true;
                                ignorePkgs.add(pkgName);
                                newDeps.put(exported[i], pluginId);
                                if (useRequireBundle) {
                                    // since using require-bundle, rest of packages will be available when bundle is added.  
                                    for (; i < exported.length; i++)
                                        ignorePkgs.add(exported[i].getName());
                                }
                            }
                        }
                        subMonitor.worked(1);
                    }
                }
                subMonitor.done();
            } catch (CoreException e) {
                monitor.done();
            }
        }
    }

    protected void addProjectPackages(IBundle bundle, Set ignorePkgs) {
        IBuild build = getBuild();
        if (build == null)
            return;
        IBuildEntry binIncludes = build.getEntry(IBuildEntry.BIN_INCLUDES);
        if (binIncludes != null) {
            String value = bundle.getHeader(Constants.BUNDLE_CLASSPATH);
            if (value == null)
                value = "."; //$NON-NLS-1$
            ManifestElement elems[];
            try {
                elems = ManifestElement.parseHeader(Constants.BUNDLE_CLASSPATH, value);
            } catch (BundleException e) {
                return;
            }
            IJavaProject jProject = JavaCore.create(fProject);
            for (int i = 0; i < elems.length; i++) {
                String library = elems[i].getValue();
                // we only want to include packages that will be avialable after exporting (ie. whatever is included in bin.includes)
                if (binIncludes.contains(library)) {
                    // if the library is in the bin.includes, see if it is source folder that will be compile.  This way we can search source folders
                    IBuildEntry entry = build.getEntry(IBuildEntry.JAR_PREFIX + library);
                    if (entry != null) {
                        String[] resources = entry.getTokens();
                        for (int j = 0; j < resources.length; j++)
                            addPackagesFromResource(jProject, fProject.findMember(resources[j]), ignorePkgs);
                    } else {
                        // if there is no source entry for the library, assume it is a binary jar and try to add it if it exists
                        addPackagesFromResource(jProject, fProject.findMember(library), ignorePkgs);
                    }
                } else {
                    // if it is not found in the bin.includes, see if a parent folder is.  This is common for binary jar.
                    StringTokenizer tokenizer = new StringTokenizer(library, "/"); //$NON-NLS-1$
                    StringBuffer buffer = new StringBuffer();
                    while (tokenizer.hasMoreTokens()) {
                        buffer.append(tokenizer.nextToken()).append('/');
                        if (binIncludes.contains(buffer.toString()))
                            addPackagesFromResource(jProject, fProject.findMember(library), ignorePkgs);
                    }
                }
            }
        }
    }

    private void addPackagesFromResource(IJavaProject jProject, IResource res, Set ignorePkgs) {
        if (res == null)
            return;
        try {
            IPackageFragmentRoot root = jProject.getPackageFragmentRoot(res);
            IJavaElement[] children = root.getChildren();
            for (int i = 0; i < children.length; i++) {
                String pkgName = children[i].getElementName();
                if (children[i] instanceof IParent)
                    if (pkgName.length() > 0 && ((IParent) children[i]).hasChildren())
                        ignorePkgs.add(children[i].getElementName());
            }
        } catch (JavaModelException e) {
        }
    }

    protected void handleNewDependencies(final Map additionalDeps, final boolean useRequireBundle,
            IProgressMonitor monitor) {
        if (!additionalDeps.isEmpty())
            addDependencies(additionalDeps, useRequireBundle);
        monitor.done();
    }

    protected void addDependencies(final Map depsToAdd, boolean useRequireBundle) {
        if (useRequireBundle) {
            Collection plugins = depsToAdd.values();
            minimizeBundles(plugins);
            IBuild build = getBuild();
            IMonitorBase pbase = fBase.getMonitorBase();
            if (pbase == null) {
                addRequireBundles(plugins, fBase.getBundleModel().getBundle(),
                        build.getEntry(IBuildEntry.SECONDARY_DEPENDENCIES));
            } else
                addRequireBundles(plugins, pbase, build.getEntry(IBuildEntry.SECONDARY_DEPENDENCIES));
            try {
                build.write("", new PrintWriter( //$NON-NLS-1$
                        new FileOutputStream(PDEProject.getBuildProperties(fProject).getFullPath().toFile())));
            } catch (FileNotFoundException e) {
            }
        } else {
            Collection pkgs = depsToAdd.keySet();
            addImportPackages(pkgs, fBase.getBundleModel().getBundle());
        }
    }

    protected final void addImportPackages(final Collection depsToAdd, final IBundle bundle) {
        Iterator it = depsToAdd.iterator();
        IManifestHeader mheader = bundle.getManifestHeader(Constants.IMPORT_PACKAGE);
        // always create header.  When available, ImportPackageHeader will help with formatting (see bug 149976)
        if (mheader == null) {
            bundle.setHeader(Constants.IMPORT_PACKAGE, new String());
            mheader = bundle.getManifestHeader(Constants.IMPORT_PACKAGE);
        }
        if (mheader instanceof ImportPackageHeader) {
            ImportPackageHeader header = (ImportPackageHeader) mheader;
            String versionAttr = (BundlePluginBase.getBundleManifestVersion(bundle) < 2)
                    ? ICoreConstants.PACKAGE_SPECIFICATION_VERSION
                    : Constants.VERSION_ATTRIBUTE;
            while (it.hasNext()) {
                ImportPackageObject obj = new ImportPackageObject(header, (ExportPackageDescription) it.next(),
                        versionAttr);
                header.addPackage(obj);
            }
        } else {
            String currentValue = (mheader != null) ? mheader.getValue() : null;
            StringBuffer buffer = (currentValue == null) ? new StringBuffer()
                    : new StringBuffer(currentValue).append(", "); //$NON-NLS-1$
            while (it.hasNext()) {
                ExportPackageDescription desc = (ExportPackageDescription) it.next();
                String value = (desc.getVersion().equals(Version.emptyVersion)) ? desc.getName()
                        : desc.getName() + "; version=\"" + desc.getVersion() + "\""; //$NON-NLS-1$ //$NON-NLS-2$
                // use same separator as used when writing out Manifest
                buffer.append(value).append(MonitorConverter.LIST_SEPARATOR);
            }
            if (buffer.length() > 0)
                buffer.setLength(buffer.length() - MonitorConverter.LIST_SEPARATOR.length());
            bundle.setHeader(Constants.IMPORT_PACKAGE, buffer.toString());
        }
    }

    protected final void addRequireBundles(final Collection depsToAdd, final IBundle bundle, IBuildEntry entry) {
        if (bundle == null)
            return;
        HashSet added = new HashSet();
        Iterator it = depsToAdd.iterator();
        IManifestHeader mheader = bundle.getManifestHeader(Constants.REQUIRE_BUNDLE);
        if (mheader instanceof RequireBundleHeader) {
            RequireBundleHeader header = (RequireBundleHeader) mheader;
            while (it.hasNext()) {
                String pluginId = (String) it.next();
                if (!added.contains(pluginId))
                    try {
                        header.addBundle(pluginId);
                        added.add(pluginId);
                        entry.removeToken(pluginId);
                    } catch (CoreException e) {
                    }
            }
        } else {
            String currentValue = (mheader != null) ? mheader.getValue() : null;
            StringBuffer buffer = (currentValue == null) ? new StringBuffer()
                    : new StringBuffer(currentValue).append(", "); //$NON-NLS-1$
            while (it.hasNext()) {
                String pluginId = (String) it.next();
                if (!added.contains(pluginId))
                    try {
                        buffer.append(pluginId).append(MonitorConverter.LIST_SEPARATOR);
                        added.add(pluginId);
                        entry.removeToken(pluginId);
                    } catch (CoreException e) {
                    }
            }
            if (buffer.length() > 0)
                buffer.setLength(buffer.length() - MonitorConverter.LIST_SEPARATOR.length());
            bundle.setHeader(Constants.REQUIRE_BUNDLE, buffer.toString());
        }
    }

    protected final void addRequireBundles(final Collection depsToAdd, final IMonitorBase base, IBuildEntry entry) {
        HashSet added = new HashSet();
        Iterator it = depsToAdd.iterator();
        // must call getImports to initialize IPluginBase.  Otherwise the .add(plugin) will not trigger a modification event.
        base.getImports();
        while (it.hasNext()) {
            String pluginId = (String) it.next();
            if (!added.contains(pluginId))
                try {
                    MonitorImport plugin = new MonitorImport();
                    ManifestElement element = ManifestElement.parseHeader(Constants.REQUIRE_BUNDLE, pluginId)[0];
                    plugin.load(element, 1);
                    plugin.setModel(base.getModel());
                    base.add(plugin);
                    added.add(pluginId);
                    if (entry != null && entry.contains(pluginId))
                        entry.removeToken(pluginId);
                } catch (BundleException e) {
                } catch (CoreException e) {
                }
        }
    }

    protected final void minimizeBundles(Collection pluginIds) {
        Stack stack = new Stack();
        Iterator it = pluginIds.iterator();
        while (it.hasNext())
            stack.push(it.next().toString());

        while (!stack.isEmpty()) {
            IMonitorModelBase base = MonitorRegistry.findModel(stack.pop().toString());
            if (base == null)
                continue;
            IMonitorImport[] imports = base.getMonitorBase().getImports();

            for (int j = 0; j < imports.length; j++)
                if (imports[j].isReexported()) {
                    String reExportedId = imports[j].getId();
                    pluginIds.remove(imports[j].getId());
                    stack.push(reExportedId);
                }
        }
    }
}