### Eclipse Workspace Patch 1.0 #P org.eclipse.pde.ui Index: plugin.xml =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.pde.ui/plugin.xml,v retrieving revision 1.424 diff -u -r1.424 plugin.xml --- plugin.xml 4 Sep 2007 02:40:34 -0000 1.424 +++ plugin.xml 14 Sep 2007 13:34:37 -0000 @@ -1760,4 +1760,19 @@ id="org.eclipse.jdt.ui.text.correction.QuickFixProcessor"> + + + + + + + + + + + Index: src/org/eclipse/pde/internal/ui/correction/java/UnresolvedImportFixProcessor.java =================================================================== RCS file: src/org/eclipse/pde/internal/ui/correction/java/UnresolvedImportFixProcessor.java diff -N src/org/eclipse/pde/internal/ui/correction/java/UnresolvedImportFixProcessor.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/pde/internal/ui/correction/java/UnresolvedImportFixProcessor.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,251 @@ +/******************************************************************************* + * Copyright (c) 2007 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.ui.correction.java; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Status; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.ui.ISharedImages; +import org.eclipse.jdt.ui.JavaUI; +import org.eclipse.jdt.ui.text.java.ClasspathFixProcessor; +import org.eclipse.ltk.core.refactoring.Change; +import org.eclipse.ltk.core.refactoring.RefactoringStatus; +import org.eclipse.osgi.service.resolver.BundleDescription; +import org.eclipse.osgi.service.resolver.ExportPackageDescription; +import org.eclipse.pde.core.IBaseModel; +import org.eclipse.pde.core.plugin.IPluginImport; +import org.eclipse.pde.internal.core.PDECore; +import org.eclipse.pde.internal.core.WorkspaceModelManager; +import org.eclipse.pde.internal.core.ibundle.IBundlePluginModelBase; +import org.eclipse.pde.internal.ui.util.ModelModification; +import org.eclipse.pde.internal.ui.util.PDEModelUtility; +import org.eclipse.swt.graphics.Image; + +/** + * Offers a classpath fix proposal if the broken import statement can be + * fixed by adding a plugin dependency (required bundle or package import). + * @since 3.4 + */ +public class UnresolvedImportFixProcessor extends ClasspathFixProcessor { + + /* (non-Javadoc) + * @see org.eclipse.jdt.ui.text.java.ClasspathFixProcessor#getFixImportProposals(org.eclipse.jdt.core.IJavaProject, java.lang.String) + */ + public ClasspathFixProposal[] getFixImportProposals(IJavaProject project, String name) throws CoreException { + // TODO Check if project is of a PDE nature (this might be handled already by extension point) + if (project == null || !WorkspaceModelManager.isPluginProject(project.getProject())){ + return null; + } + + int idx= name.lastIndexOf('.'); + String packageName= idx != -1 ? name.substring(0, idx) : null; + String typeName= name.substring(idx + 1); + if (typeName.length() == 1 && typeName.charAt(0) == '*') { + typeName= null; + } + + if (packageName != null){ + // Get the packages exported by all bundles, see if any can provide the required classes + ExportPackageDescription[] knownPackages = PDECore.getDefault().getModelManager().getState().getState().getExportedPackages(); + Set validPackages = new HashSet(); + for (int i = 0; i < knownPackages.length; i++) { + // TODO Is there a better way to compare, currently no checking of class name + if (knownPackages[i].getName().equals(packageName)){ + validPackages.add(knownPackages[i]); + } + } + + // TODO Do we want to create a proposal for every valid package? Consider using a wizard to choose? + ClasspathFixProposal[] proposals = new ClasspathFixProposal[validPackages.size()]; + int counter = 0; + Iterator validPackagesIter = validPackages.iterator(); + while (validPackagesIter.hasNext()) { + ExportPackageDescription currentPackage = (ExportPackageDescription) validPackagesIter.next(); + proposals[counter++] = new RequireBundleFixProposal(project,currentPackage); + } + if (proposals.length > 0){ + return proposals; + } + } + + // TODO Do we want to allow overridden processors to run? + return new ClasspathFixProposal[0]; + } + + /** + * Proposal to fix a broken import by adding a required bundle. + */ + static class RequireBundleFixProposal extends ClasspathFixProposal{ + + private IProject fProject; + private BundleDescription fBundleDescription; + + /** + * Constructor + * @param project The project that needs the new required bundle + * @param packageDescription the package we want a dependency on + */ + public RequireBundleFixProposal(IJavaProject project, ExportPackageDescription packageDescription) { + fProject = project.getProject(); + fBundleDescription = packageDescription.getExporter(); + } + + /* (non-Javadoc) + * @see org.eclipse.jdt.ui.text.java.ClasspathFixProcessor.ClasspathFixProposal#createChange(org.eclipse.core.runtime.IProgressMonitor) + */ + public Change createChange(IProgressMonitor monitor) throws CoreException { + return new BundleRequirementChange(fProject,fBundleDescription, true); + } + + /* (non-Javadoc) + * @see org.eclipse.jdt.ui.text.java.ClasspathFixProcessor.ClasspathFixProposal#getAdditionalProposalInfo() + */ + public String getAdditionalProposalInfo() { + return "Adds a bundle to the required bundles for this project."; + } + + /* (non-Javadoc) + * @see org.eclipse.jdt.ui.text.java.ClasspathFixProcessor.ClasspathFixProposal#getDisplayString() + */ + public String getDisplayString() { + return "Add '" + fBundleDescription.getName() + "' to required bundles"; + } + + /* (non-Javadoc) + * @see org.eclipse.jdt.ui.text.java.ClasspathFixProcessor.ClasspathFixProposal#getImage() + */ + public Image getImage() { + return JavaUI.getSharedImages().getImage(ISharedImages.IMG_OBJS_LIBRARY); + } + + /* (non-Javadoc) + * @see org.eclipse.jdt.ui.text.java.ClasspathFixProcessor.ClasspathFixProposal#getRelevance() + */ + public int getRelevance() { + return 16; + } + } + + /** + * Change that actually adds the required bundle dependency. + */ + static class BundleRequirementChange extends Change{ + + private IProject fBaseProject; + private BundleDescription fBundle; + private boolean fIsAdd; + + /** + * Constructor + * @param project the project to add the dependency to + * @param bundleDescription the bundle to add as a dependency + */ + public BundleRequirementChange(IProject project, BundleDescription bundleDescription, boolean isAdd) { + fBaseProject = project; + fBundle = bundleDescription; + fIsAdd= isAdd; + } + + /* (non-Javadoc) + * @see org.eclipse.ltk.core.refactoring.Change#perform(org.eclipse.core.runtime.IProgressMonitor) + */ + public Change perform(IProgressMonitor pm) throws CoreException { + // TODO if the IBaseModel is a org.eclipse.pde.internal.core.text.plugin.PluginModelBase, the IPluginImport should be a PluginImportNode that will make it work for 3.0 projects also + ModelModification modelMod = new ModelModification(fBaseProject){ + protected void modifyModel(IBaseModel model, IProgressMonitor monitor) throws CoreException { + if (model instanceof IBundlePluginModelBase) { + addOrRemoveRequiredBundle(monitor, (IBundlePluginModelBase)model, fBundle); + } + } + }; + PDEModelUtility.modifyModel(modelMod, pm); + return new BundleRequirementChange(fBaseProject, fBundle, !fIsAdd); + } + + /* (non-Javadoc) + * @see org.eclipse.ltk.core.refactoring.Change#isValid(org.eclipse.core.runtime.IProgressMonitor) + */ + public RefactoringStatus isValid(IProgressMonitor pm) throws CoreException, OperationCanceledException { + return RefactoringStatus.create(Status.OK_STATUS); + } + + /* (non-Javadoc) + * @see org.eclipse.ltk.core.refactoring.Change#initializeValidationData(org.eclipse.core.runtime.IProgressMonitor) + */ + public void initializeValidationData(IProgressMonitor pm) { + } + + /* (non-Javadoc) + * @see org.eclipse.ltk.core.refactoring.Change#getName() + */ + public String getName() { + if (fIsAdd) { + return "Add '" + fBundle.getName() + "' to required bundles"; + } + return "Remove '" + fBundle.getName() + "' from required bundles"; + } + + /* (non-Javadoc) + * @see org.eclipse.ltk.core.refactoring.Change#getModifiedElement() + */ + public Object getModifiedElement() { + return fBaseProject; + } + + /** + * Adds the given bundle to the list of required bundles + * @param monitor + * @param baseBundle + * @param addBundle + * @throws CoreException + */ + private void addOrRemoveRequiredBundle(IProgressMonitor monitor, IBundlePluginModelBase baseBundle, BundleDescription addBundle) throws CoreException { + // TODO Does not check if the bundle already is in the manifest? + IPluginImport pluginImport = baseBundle.createImport(); + pluginImport.setId(addBundle.getSymbolicName()); + if (fIsAdd) { + baseBundle.getPluginBase().add(pluginImport); + } else { + baseBundle.getPluginBase().remove(pluginImport); + } + } + +// public static void organizeImportPackages(IBundle bundle, boolean removeImports) { +// if (!(bundle instanceof Bundle)) +// return; +// ImportPackageHeader header = (ImportPackageHeader)((Bundle)bundle).getManifestHeader(Constants.IMPORT_PACKAGE); +// if (header == null) +// return; +// ImportPackageObject[] importedPackages = header.getPackages(); +// Set availablePackages = getAvailableExportedPackages(); +// // get Preference +// for (int i = 0; i < importedPackages.length; i++) { +// String pkgName = importedPackages[i].getName(); +// if (!availablePackages.contains(pkgName)){ +// if (removeImports) +// header.removePackage(importedPackages[i]); +// else { +// importedPackages[i].setOptional(true); +// } +// } +// } +// } + + } + +}