Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 88204 | Differences between
and this patch

Collapse All | Expand All

(-)plugin.xml (+15 lines)
Lines 1760-1763 Link Here
1760
                id="org.eclipse.jdt.ui.text.correction.QuickFixProcessor">
1760
                id="org.eclipse.jdt.ui.text.correction.QuickFixProcessor">
1761
          </quickFixProcessor>
1761
          </quickFixProcessor>
1762
       </extension>
1762
       </extension>
1763
       <extension
1764
             point="org.eclipse.jdt.ui.classpathFixProcessors">
1765
          <classpathFixProcessor
1766
                class="org.eclipse.pde.internal.ui.correction.java.UnresolvedImportFixProcessor"
1767
                id="org.eclipse.pde.ui.unresolvedImportQuickFixProcessor"
1768
                name="Unresolved Import Quick Fix Processor">
1769
                <enablement>
1770
                   <with variable="project">
1771
		              <test property="org.eclipse.jdt.core.isInJavaProjectWithNature" value="org.eclipse.pde.PluginNature"/>
1772
                   </with>
1773
                </enablement>
1774
                <overrides id="org.eclipse.jdt.ui.text.correction.DefaultClasspathFixProcessor"/>
1775
                <overrides id="org.eclipse.jdt.junit.JUnitClasspathFixProcessor"/>
1776
          </classpathFixProcessor>
1777
       </extension>
1763
</plugin>
1778
</plugin>
(-)src/org/eclipse/pde/internal/ui/pderesources.properties (-1 / +6 lines)
Lines 1148-1154 Link Here
1148
1148
1149
Actions_Feature_OpenProjectWizardAction = &New Feature Project...
1149
Actions_Feature_OpenProjectWizardAction = &New Feature Project...
1150
Actions_Site_OpenProjectWizardAction = &New Update Site...
1150
Actions_Site_OpenProjectWizardAction = &New Update Site...
1151
1151
UnresolvedImportFixProcessor_1=Remove ''{0}'' from required bundles
1152
UnresolvedImportFixProcessor_2=Adds a bundle that exports the needed package to the list of required bundles for this project.
1153
UnresolvedImportFixProcessor_3=Add ''{0}'' to imported packages
1154
UnresolvedImportFixProcessor_4=Remove ''{0}'' from imported packages
1155
UnresolvedImportFixProcessor_5=Adds an import package dependency for this project.
1156
UnresolvedImportFixProcessor_0=Add ''{0}'' to required bundles
1152
UpdateClasspathJob_error_title = Update Classpaths
1157
UpdateClasspathJob_error_title = Update Classpaths
1153
UpdateClasspathJob_error_message = Updating failed. See log for details.
1158
UpdateClasspathJob_error_message = Updating failed. See log for details.
1154
UpdateClasspathResolution_label=Update the classpath and compliance settings
1159
UpdateClasspathResolution_label=Update the classpath and compliance settings
(-)src/org/eclipse/pde/internal/ui/PDEUIMessages.java (+7 lines)
Lines 1647-1652 Link Here
1647
	public static String Actions_Feature_OpenProjectWizardAction;
1647
	public static String Actions_Feature_OpenProjectWizardAction;
1648
	public static String Actions_Site_OpenProjectWizardAction;
1648
	public static String Actions_Site_OpenProjectWizardAction;
1649
1649
1650
	public static String UnresolvedImportFixProcessor_0;
1651
	public static String UnresolvedImportFixProcessor_1;
1652
	public static String UnresolvedImportFixProcessor_2;
1653
	public static String UnresolvedImportFixProcessor_3;
1654
	public static String UnresolvedImportFixProcessor_4;
1655
	public static String UnresolvedImportFixProcessor_5;
1656
1650
	public static String UpdateClasspathJob_error_title;
1657
	public static String UpdateClasspathJob_error_title;
1651
	public static String UpdateClasspathJob_error_message;
1658
	public static String UpdateClasspathJob_error_message;
1652
	public static String UpdateClasspathJob_task;
1659
	public static String UpdateClasspathJob_task;
(-)src/org/eclipse/pde/internal/ui/correction/java/UnresolvedImportFixProposal.java (+213 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.pde.internal.ui.correction.java;
12
13
import org.eclipse.core.resources.IProject;
14
import org.eclipse.core.runtime.CoreException;
15
import org.eclipse.core.runtime.IProgressMonitor;
16
import org.eclipse.core.runtime.OperationCanceledException;
17
import org.eclipse.core.runtime.Status;
18
import org.eclipse.jdt.ui.ISharedImages;
19
import org.eclipse.jdt.ui.JavaUI;
20
import org.eclipse.jdt.ui.text.java.ClasspathFixProcessor.ClasspathFixProposal;
21
import org.eclipse.ltk.core.refactoring.Change;
22
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
23
import org.eclipse.osgi.service.resolver.ExportPackageDescription;
24
import org.eclipse.pde.core.IBaseModel;
25
import org.eclipse.pde.core.plugin.IPluginModelBase;
26
import org.eclipse.pde.internal.ui.util.ModelModification;
27
import org.eclipse.pde.internal.ui.util.PDEModelUtility;
28
import org.eclipse.swt.graphics.Image;
29
30
/**
31
 * Abstract class defining a classpath fix proposal that will 
32
 * offer to fix an unresolved import by adding a dependency to
33
 * the plugin.  Creates a Change object that will add the dependency
34
 * when invoked.  When invoked, the Change object will also add an
35
 * undo change that will remove the dependency.  Extending classes
36
 * must implement handleDependencyChange to determine how the
37
 * dependency will be added (bundle requirement, package import, etc).
38
 * Two other abstract methods allow extending classes to define the
39
 * label and description associated with this proposal and it's changes.
40
 *  
41
 * @since 3.4
42
 * @see UnresolvedImportFixProcessor
43
 * @see UnresolvedImportDependencyChange
44
 */
45
public abstract class UnresolvedImportFixProposal extends ClasspathFixProposal{
46
		
47
	private IProject fProject;
48
	private ExportPackageDescription fDependency;
49
	
50
	/**
51
	 * Constructor
52
	 * @param project The project that needs the new required bundle
53
	 * @param packageDescription the package we want a dependency on
54
	 */
55
	/**
56
	 * Constructor
57
	 * @param project the project that will be modified to add the dependency
58
	 * @param packageDependency the package that must be added as a dependency
59
	 */
60
	public UnresolvedImportFixProposal(IProject project, ExportPackageDescription packageDependency) {
61
		fProject = project;
62
		fDependency = packageDependency;
63
	}
64
	
65
	/**
66
	 * Returns the label to use for the proposal and change.
67
	 * Label can be different if this is the undo change and
68
	 * the dependency is being removed rather than added.
69
	 * 
70
	 * @param isAdd whether the dependency is being added vs removed
71
	 * @return label to use for the proposal and change
72
	 */
73
	public abstract String getLabel(boolean isAdd);
74
	
75
	/**
76
	 * Return the description that will be displayed for this
77
	 * proposal in the 'Additional Information' area of the 
78
	 * quick fix popup.
79
	 * 
80
	 * @return description to use for this proposal
81
	 */
82
	public abstract String getDescription();
83
	
84
	/**
85
	 * Implementors must handle the addition or removal of the given package
86
	 * as a dependency for the given model in this method.
87
	 * 
88
	 * @param pm progress monitor to display progress as change takes place
89
	 * @param model model that will be changed to add/remove the dependency
90
	 * @param dependency the package to add/remove as a dependency
91
	 * @param isAdd whether the package is being added or removed
92
	 * @throws CoreException if there is a problem trying to change the dependency.
93
	 */
94
	public abstract void handleDependencyChange(IProgressMonitor pm, IPluginModelBase model, ExportPackageDescription dependency, boolean isAdd) throws CoreException;
95
96
	/* (non-Javadoc)
97
	 * @see org.eclipse.jdt.ui.text.java.ClasspathFixProcessor.ClasspathFixProposal#createChange(org.eclipse.core.runtime.IProgressMonitor)
98
	 */
99
	public Change createChange(IProgressMonitor monitor) throws CoreException {
100
		return new UnresolvedImportDependencyChange(fProject,fDependency, true);
101
	}
102
103
	/* (non-Javadoc)
104
	 * @see org.eclipse.jdt.ui.text.java.ClasspathFixProcessor.ClasspathFixProposal#getAdditionalProposalInfo()
105
	 */
106
	public String getAdditionalProposalInfo() {
107
		return getDescription();
108
	}
109
	
110
	/* (non-Javadoc)
111
	 * @see org.eclipse.jdt.ui.text.java.ClasspathFixProcessor.ClasspathFixProposal#getDisplayString()
112
	 */
113
	public String getDisplayString() {
114
		return getLabel(true);
115
	}
116
117
	/* (non-Javadoc)
118
	 * @see org.eclipse.jdt.ui.text.java.ClasspathFixProcessor.ClasspathFixProposal#getImage()
119
	 */
120
	public Image getImage() {
121
		return JavaUI.getSharedImages().getImage(ISharedImages.IMG_OBJS_LIBRARY);
122
	}
123
124
	/* (non-Javadoc)
125
	 * @see org.eclipse.jdt.ui.text.java.ClasspathFixProcessor.ClasspathFixProposal#getRelevance()
126
	 */
127
	public int getRelevance() {
128
		return 16;
129
	}
130
	
131
	/**
132
	 * @return the project this proposal will change with the new dependency
133
	 */
134
	public IProject getProject(){
135
		return fProject;
136
	}
137
	
138
	/**
139
	 * @return the package dependency this proposal is offering add
140
	 */
141
	public ExportPackageDescription getDependency(){
142
		return fDependency;
143
	}
144
145
	/**
146
	 * A Change object that will modify a plugin to add or remove
147
	 * a dependency on a package.
148
	 * @see UnresolvedImportFixProposal 
149
	 * @see UnresolvedImportFixProcessor
150
	 */
151
	private class UnresolvedImportDependencyChange extends Change{
152
153
		private IProject fBaseProject;
154
		private ExportPackageDescription fDependency;
155
		private boolean fIsAdd;
156
		
157
		/**
158
		 * Constructor
159
		 * @param project the project to change dependency on
160
		 * @param packageDescription the package dependency to change
161
		 * @param isAdd whether the dependency will be added or removed
162
		 */
163
		public UnresolvedImportDependencyChange(IProject project, ExportPackageDescription packageDescription, boolean isAdd) {
164
			fBaseProject = project;
165
			fDependency = packageDescription;
166
			fIsAdd= isAdd;
167
		}
168
		
169
		/* (non-Javadoc)
170
		 * @see org.eclipse.ltk.core.refactoring.Change#perform(org.eclipse.core.runtime.IProgressMonitor)
171
		 */
172
		public Change perform(IProgressMonitor pm) throws CoreException {
173
			ModelModification modelMod = new ModelModification(fBaseProject){
174
				protected void modifyModel(IBaseModel model, IProgressMonitor monitor) throws CoreException {
175
					if (model instanceof IPluginModelBase) {
176
						handleDependencyChange(monitor, (IPluginModelBase)model, fDependency, fIsAdd);
177
					}
178
				}
179
			};
180
			PDEModelUtility.modifyModel(modelMod, pm);
181
			// Return the undo action to do the opposite
182
			return new UnresolvedImportDependencyChange(fBaseProject, fDependency, !fIsAdd);
183
		}
184
	
185
		/* (non-Javadoc)
186
		 * @see org.eclipse.ltk.core.refactoring.Change#isValid(org.eclipse.core.runtime.IProgressMonitor)
187
		 */
188
		public RefactoringStatus isValid(IProgressMonitor pm) throws CoreException,	OperationCanceledException {
189
			return RefactoringStatus.create(Status.OK_STATUS);
190
		}
191
	
192
		/* (non-Javadoc)
193
		 * @see org.eclipse.ltk.core.refactoring.Change#initializeValidationData(org.eclipse.core.runtime.IProgressMonitor)
194
		 */
195
		public void initializeValidationData(IProgressMonitor pm) {
196
		}
197
	
198
		/* (non-Javadoc)
199
		 * @see org.eclipse.ltk.core.refactoring.Change#getName()
200
		 */
201
		public String getName() {
202
			return getLabel(fIsAdd);
203
		}
204
		
205
		/* (non-Javadoc)
206
		 * @see org.eclipse.ltk.core.refactoring.Change#getModifiedElement()
207
		 */
208
		public Object getModifiedElement() {
209
			return fBaseProject;
210
		}
211
	}
212
	
213
}
(-)src/org/eclipse/pde/internal/ui/correction/java/UnresolvedImportFixProcessor.java (+217 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.pde.internal.ui.correction.java;
12
13
import java.util.ArrayList;
14
import java.util.HashSet;
15
import java.util.Iterator;
16
import java.util.List;
17
import java.util.Set;
18
19
import org.eclipse.core.resources.IProject;
20
import org.eclipse.core.runtime.CoreException;
21
import org.eclipse.core.runtime.IProgressMonitor;
22
import org.eclipse.jdt.core.IJavaProject;
23
import org.eclipse.jdt.ui.text.java.ClasspathFixProcessor;
24
import org.eclipse.osgi.service.resolver.BundleDescription;
25
import org.eclipse.osgi.service.resolver.BundleSpecification;
26
import org.eclipse.osgi.service.resolver.ExportPackageDescription;
27
import org.eclipse.osgi.service.resolver.ImportPackageSpecification;
28
import org.eclipse.pde.core.plugin.IPluginImport;
29
import org.eclipse.pde.core.plugin.IPluginModelBase;
30
import org.eclipse.pde.core.plugin.PluginRegistry;
31
import org.eclipse.pde.internal.core.ICoreConstants;
32
import org.eclipse.pde.internal.core.PDECore;
33
import org.eclipse.pde.internal.core.bundle.BundlePluginBase;
34
import org.eclipse.pde.internal.core.converter.PluginConverter;
35
import org.eclipse.pde.internal.core.ibundle.IBundle;
36
import org.eclipse.pde.internal.core.ibundle.IBundlePluginModelBase;
37
import org.eclipse.pde.internal.core.ibundle.IManifestHeader;
38
import org.eclipse.pde.internal.core.text.bundle.Bundle;
39
import org.eclipse.pde.internal.core.text.bundle.ImportPackageHeader;
40
import org.eclipse.pde.internal.core.text.bundle.ImportPackageObject;
41
import org.eclipse.pde.internal.ui.PDEUIMessages;
42
import org.osgi.framework.Constants;
43
import org.osgi.framework.Version;
44
45
import com.ibm.icu.text.MessageFormat;
46
47
/**
48
 * Offers a classpath fix proposal if the broken import statement can be
49
 * fixed by adding a plugin dependency (required bundle or package import).
50
 * @since 3.4
51
 */
52
public class UnresolvedImportFixProcessor extends ClasspathFixProcessor {
53
54
	/* (non-Javadoc)
55
	 * @see org.eclipse.jdt.ui.text.java.ClasspathFixProcessor#getFixImportProposals(org.eclipse.jdt.core.IJavaProject, java.lang.String)
56
	 */
57
	public ClasspathFixProposal[] getFixImportProposals(IJavaProject project, String name) throws CoreException {
58
		int idx= name.lastIndexOf('.');
59
		String packageName= idx != -1 ? name.substring(0, idx) : null;
60
		String typeName= name.substring(idx + 1);
61
		if (typeName.length() == 1 && typeName.charAt(0) == '*') {
62
			typeName= null;
63
		}
64
		
65
		if (packageName != null){
66
			// Get the packages exported by all bundles, see if any can provide the required classes
67
			ExportPackageDescription[] knownPackages = PDECore.getDefault().getModelManager().getState().getState().getExportedPackages();
68
			Set validPackages = new HashSet();
69
			for (int i = 0; i < knownPackages.length; i++) {
70
				if (knownPackages[i].getName().equals(packageName)){
71
					validPackages.add(knownPackages[i]);
72
				}
73
			}
74
			
75
			List proposals = new ArrayList();
76
			Iterator validPackagesIter = validPackages.iterator();
77
			while (validPackagesIter.hasNext()) {
78
				ExportPackageDescription currentPackage = (ExportPackageDescription) validPackagesIter.next();
79
				addRequireBundleProposal(proposals, project.getProject(),currentPackage);
80
				addImportPackageProposal(proposals, project.getProject(),currentPackage);
81
			}
82
			
83
			return (ClasspathFixProposal[])proposals.toArray(new ClasspathFixProposal[proposals.size()]);
84
		}
85
		
86
		return new ClasspathFixProposal[0];
87
	}
88
	
89
	/**
90
	 * Helper method to create a proposal to add an require bundle dependency to the project
91
	 */
92
	private void addRequireBundleProposal(List proposalList, IProject project, ExportPackageDescription dependency){
93
		// Check if the bundle already exists
94
		boolean alreadyExists = false;
95
		BundleDescription description = PluginRegistry.findModel(project).getBundleDescription();
96
		BundleSpecification[] requiredBundles = description.getRequiredBundles();
97
		for (int i = 0; i < requiredBundles.length; i++) {
98
			if (requiredBundles[i].getName().equals(dependency.getExporter().getSymbolicName())){
99
				alreadyExists = true;
100
				break;
101
			}
102
		}
103
		if (!alreadyExists){
104
			proposalList.add(new UnresolvedImportFixProposal(project, dependency) {
105
			
106
				/* (non-Javadoc)
107
				 * @see org.eclipse.pde.internal.ui.correction.java.UnresolvedImportFixProposal#handleDependencyChange(org.eclipse.core.runtime.IProgressMonitor, org.eclipse.pde.internal.core.ibundle.IBundlePluginModelBase, org.eclipse.osgi.service.resolver.ExportPackageDescription, boolean)
108
				 */
109
				public void handleDependencyChange(IProgressMonitor pm,	IPluginModelBase model, ExportPackageDescription dependency, boolean isAdd) throws CoreException {
110
					IPluginImport pluginImport = model.getPluginFactory().createImport();
111
					pluginImport.setId(dependency.getExporter().getSymbolicName());
112
					if (isAdd) {
113
						model.getPluginBase().add(pluginImport);
114
					} else {
115
						model.getPluginBase().remove(pluginImport);
116
					}
117
				}
118
			
119
				/* (non-Javadoc)
120
				 * @see org.eclipse.pde.internal.ui.correction.java.UnresolvedImportFixProposal#getLabel(boolean)
121
				 */
122
				public String getLabel(boolean isAdd) {
123
					if (isAdd) {
124
						return MessageFormat.format(PDEUIMessages.UnresolvedImportFixProcessor_0,new Object[]{getDependency().getExporter().getName()});
125
					}
126
					return MessageFormat.format(PDEUIMessages.UnresolvedImportFixProcessor_1,new Object[]{getDependency().getExporter().getName()});
127
				}
128
			
129
				/* (non-Javadoc)
130
				 * @see org.eclipse.pde.internal.ui.correction.java.UnresolvedImportFixProposal#getDescription()
131
				 */
132
				public String getDescription() {
133
					return PDEUIMessages.UnresolvedImportFixProcessor_2;
134
				}
135
			});
136
		}
137
	}
138
	
139
	/**
140
	 * Helper method to create a proposal to add an import package dependency to the project
141
	 */
142
	private void addImportPackageProposal(List proposalList, IProject project, ExportPackageDescription dependency){
143
		// Check if the import package already exists
144
		boolean alreadyExists = false;
145
		IPluginModelBase base = PluginRegistry.findModel(project);
146
		if (!(base instanceof IBundlePluginModelBase)){
147
			// The model must be manifest based to add an import package entry
148
			return;
149
		}
150
		BundleDescription description = base.getBundleDescription();
151
		ImportPackageSpecification[] importedPackages = description.getImportPackages();
152
		for (int i = 0; i < importedPackages.length; i++) {
153
			if (importedPackages[i].getName().equals(dependency.getName())){
154
				alreadyExists = true;
155
				break;
156
			}
157
		}
158
		if (!alreadyExists){
159
			proposalList.add(new UnresolvedImportFixProposal(project, dependency) {
160
			
161
				/* (non-Javadoc)
162
				 * @see org.eclipse.pde.internal.ui.correction.java.UnresolvedImportFixProposal#handleDependencyChange(org.eclipse.core.runtime.IProgressMonitor, org.eclipse.pde.internal.core.ibundle.IBundlePluginModelBase, org.eclipse.osgi.service.resolver.ExportPackageDescription, boolean)
163
				 */
164
				public void handleDependencyChange(IProgressMonitor pm,	IPluginModelBase model, ExportPackageDescription dependency, boolean isAdd) throws CoreException {
165
					IBundle bundle = ((IBundlePluginModelBase)model).getBundleModel().getBundle();
166
					if (!(bundle instanceof Bundle)){
167
						return;
168
					}
169
					IManifestHeader mheader = bundle.getManifestHeader(Constants.IMPORT_PACKAGE);
170
					if (mheader == null) {
171
						bundle.setHeader(Constants.IMPORT_PACKAGE, new String());
172
						mheader = bundle.getManifestHeader(Constants.IMPORT_PACKAGE);
173
					}
174
					if (mheader instanceof ImportPackageHeader) {
175
						ImportPackageHeader header = (ImportPackageHeader) mheader;
176
						String versionAttr = (BundlePluginBase.getBundleManifestVersion(bundle) < 2) ? ICoreConstants.PACKAGE_SPECIFICATION_VERSION : Constants.VERSION_ATTRIBUTE;  
177
						ImportPackageObject obj = new ImportPackageObject(header, dependency, versionAttr);
178
						header.addPackage(obj);
179
					} else {
180
						StringBuffer buffer = new StringBuffer();
181
						String currentValue = (mheader != null) ? mheader.getValue() : null;
182
						if (currentValue != null){
183
							buffer.append(currentValue).append(PluginConverter.LIST_SEPARATOR);
184
						}
185
						if (dependency.getVersion().equals(Version.emptyVersion)){
186
							buffer.append(dependency.getName());
187
						} else {
188
							buffer.append(dependency.getName());
189
							buffer.append("; version=\""); //$NON-NLS-1$
190
							buffer.append(dependency.getVersion());
191
							buffer.append("\""); //$NON-NLS-1$
192
						}
193
						bundle.setHeader(Constants.IMPORT_PACKAGE, buffer.toString());
194
					}
195
				}
196
			
197
				/* (non-Javadoc)
198
				 * @see org.eclipse.pde.internal.ui.correction.java.UnresolvedImportFixProposal#getLabel(boolean)
199
				 */
200
				public String getLabel(boolean isAdd) {
201
					if (isAdd) {
202
						return MessageFormat.format(PDEUIMessages.UnresolvedImportFixProcessor_3,new Object[]{getDependency().getName()});
203
					}
204
					return MessageFormat.format(PDEUIMessages.UnresolvedImportFixProcessor_4,new Object[]{getDependency().getName()});
205
				}
206
			
207
				/* (non-Javadoc)
208
				 * @see org.eclipse.pde.internal.ui.correction.java.UnresolvedImportFixProposal#getDescription()
209
				 */
210
				public String getDescription() {
211
					return PDEUIMessages.UnresolvedImportFixProcessor_5;
212
				}
213
			
214
			});
215
		}
216
	}
217
}

Return to bug 88204