001: /*******************************************************************************
002: * Copyright (c) 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.ui.text.correction;
011:
012: import java.util.ArrayList;
013: import java.util.Arrays;
014: import java.util.Collection;
015: import java.util.Collections;
016: import java.util.Comparator;
017: import java.util.HashSet;
018: import java.util.List;
019:
020: import org.eclipse.core.runtime.CoreException;
021: import org.eclipse.core.runtime.IConfigurationElement;
022: import org.eclipse.core.runtime.ISafeRunnable;
023: import org.eclipse.core.runtime.IStatus;
024: import org.eclipse.core.runtime.MultiStatus;
025: import org.eclipse.core.runtime.Platform;
026: import org.eclipse.core.runtime.SafeRunner;
027: import org.eclipse.core.runtime.Status;
028:
029: import org.eclipse.core.expressions.EvaluationContext;
030: import org.eclipse.core.expressions.EvaluationResult;
031: import org.eclipse.core.expressions.Expression;
032: import org.eclipse.core.expressions.ExpressionConverter;
033: import org.eclipse.core.expressions.ExpressionTagNames;
034:
035: import org.eclipse.jdt.core.IJavaProject;
036: import org.eclipse.jdt.core.JavaCore;
037:
038: import org.eclipse.jdt.ui.JavaUI;
039: import org.eclipse.jdt.ui.text.java.ClasspathFixProcessor;
040: import org.eclipse.jdt.ui.text.java.ClasspathFixProcessor.ClasspathFixProposal;
041:
042: import org.eclipse.jdt.internal.ui.JavaPlugin;
043: import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
044:
045: public final class ClasspathFixProcessorDescriptor {
046:
047: private static final String ATT_EXTENSION = "classpathFixProcessors"; //$NON-NLS-1$
048:
049: private static final String ID = "id"; //$NON-NLS-1$
050: private static final String CLASS = "class"; //$NON-NLS-1$
051:
052: private static final String OVERRIDES = "overrides"; //$NON-NLS-1$
053:
054: private static ClasspathFixProcessorDescriptor[] fgContributedClasspathFixProcessors;
055:
056: private final IConfigurationElement fConfigurationElement;
057: private ClasspathFixProcessor fProcessorInstance;
058: private List fOverriddenIds;
059: private Boolean fStatus;
060:
061: public ClasspathFixProcessorDescriptor(IConfigurationElement element) {
062: fConfigurationElement = element;
063: fProcessorInstance = null;
064: fStatus = null; // undefined
065: if (fConfigurationElement
066: .getChildren(ExpressionTagNames.ENABLEMENT).length == 0) {
067: fStatus = Boolean.TRUE;
068: }
069: IConfigurationElement[] children = fConfigurationElement
070: .getChildren(OVERRIDES);
071: if (children.length > 0) {
072: fOverriddenIds = new ArrayList(children.length);
073: for (int i = 0; i < children.length; i++) {
074: fOverriddenIds.add(children[i].getAttribute(ID));
075: }
076: } else {
077: fOverriddenIds = Collections.EMPTY_LIST;
078: }
079: }
080:
081: public String getID() {
082: return fConfigurationElement.getAttribute(ID);
083: }
084:
085: public Collection/*String*/getOverridenIds() {
086: return fOverriddenIds;
087: }
088:
089: public IStatus checkSyntax() {
090: IConfigurationElement[] children = fConfigurationElement
091: .getChildren(ExpressionTagNames.ENABLEMENT);
092: if (children.length > 1) {
093: return new StatusInfo(
094: IStatus.ERROR,
095: "Only one < enablement > element allowed. Disabling " + getID()); //$NON-NLS-1$
096: }
097: return new StatusInfo(IStatus.OK,
098: "Syntactically correct classpath fix processor"); //$NON-NLS-1$
099: }
100:
101: public boolean matches(IJavaProject javaProject) {
102: if (fStatus != null) {
103: return fStatus.booleanValue();
104: }
105:
106: IConfigurationElement[] children = fConfigurationElement
107: .getChildren(ExpressionTagNames.ENABLEMENT);
108: if (children.length == 1) {
109: try {
110: ExpressionConverter parser = ExpressionConverter
111: .getDefault();
112: Expression expression = parser.perform(children[0]);
113: EvaluationContext evalContext = new EvaluationContext(
114: null, javaProject);
115: evalContext.addVariable("project", javaProject); //$NON-NLS-1$
116: evalContext
117: .addVariable(
118: "sourceLevel", javaProject.getOption(JavaCore.COMPILER_SOURCE, true)); //$NON-NLS-1$
119: return expression.evaluate(evalContext) == EvaluationResult.TRUE;
120: } catch (CoreException e) {
121: JavaPlugin.log(e);
122: }
123: return false;
124: }
125: fStatus = Boolean.FALSE;
126: return false;
127: }
128:
129: public ClasspathFixProcessor getProcessor(IJavaProject project) {
130: if (matches(project)) {
131: if (fProcessorInstance == null) {
132: try {
133: Object extension = fConfigurationElement
134: .createExecutableExtension(CLASS);
135: if (extension instanceof ClasspathFixProcessor) {
136: fProcessorInstance = (ClasspathFixProcessor) extension;
137: } else {
138: String message = "Invalid extension to " + ATT_EXTENSION //$NON-NLS-1$
139: + ". Must extends ClasspathFixProcessor: " + getID(); //$NON-NLS-1$
140: JavaPlugin.log(new Status(IStatus.ERROR,
141: JavaUI.ID_PLUGIN, message));
142: fStatus = Boolean.FALSE;
143: return null;
144: }
145: } catch (CoreException e) {
146: JavaPlugin.log(e);
147: fStatus = Boolean.FALSE;
148: return null;
149: }
150: }
151: return fProcessorInstance;
152: }
153: return null;
154: }
155:
156: private static ClasspathFixProcessorDescriptor[] getCorrectionProcessors() {
157: if (fgContributedClasspathFixProcessors == null) {
158: IConfigurationElement[] elements = Platform
159: .getExtensionRegistry()
160: .getConfigurationElementsFor(JavaUI.ID_PLUGIN,
161: ATT_EXTENSION);
162: ArrayList res = new ArrayList(elements.length);
163:
164: for (int i = 0; i < elements.length; i++) {
165: ClasspathFixProcessorDescriptor desc = new ClasspathFixProcessorDescriptor(
166: elements[i]);
167: IStatus status = desc.checkSyntax();
168: if (status.isOK()) {
169: res.add(desc);
170: } else {
171: JavaPlugin.log(status);
172: }
173: }
174: fgContributedClasspathFixProcessors = (ClasspathFixProcessorDescriptor[]) res
175: .toArray(new ClasspathFixProcessorDescriptor[res
176: .size()]);
177: Arrays.sort(fgContributedClasspathFixProcessors,
178: new Comparator() {
179: public int compare(Object o1, Object o2) {
180: ClasspathFixProcessorDescriptor d1 = (ClasspathFixProcessorDescriptor) o1;
181: ClasspathFixProcessorDescriptor d2 = (ClasspathFixProcessorDescriptor) o2;
182: if (d1.getOverridenIds().contains(
183: d2.getID())) {
184: return -1;
185: }
186: if (d2.getOverridenIds().contains(
187: d1.getID())) {
188: return 1;
189: }
190: return 0;
191: }
192: });
193: }
194: return fgContributedClasspathFixProcessors;
195: }
196:
197: public static ClasspathFixProposal[] getProposals(
198: final IJavaProject project, final String missingType,
199: final MultiStatus status) {
200: final ArrayList proposals = new ArrayList();
201:
202: final HashSet overriddenIds = new HashSet();
203: ClasspathFixProcessorDescriptor[] correctionProcessors = getCorrectionProcessors();
204: for (int i = 0; i < correctionProcessors.length; i++) {
205: final ClasspathFixProcessorDescriptor curr = correctionProcessors[i];
206: if (!overriddenIds.contains(curr.getID())) {
207: SafeRunner.run(new ISafeRunnable() {
208: public void run() throws Exception {
209: ClasspathFixProcessor processor = curr
210: .getProcessor(project);
211: if (processor != null) {
212: ClasspathFixProposal[] fixProposals = processor
213: .getFixImportProposals(project,
214: missingType);
215: if (fixProposals != null) {
216: for (int k = 0; k < fixProposals.length; k++) {
217: proposals.add(fixProposals[k]);
218: }
219: overriddenIds.addAll(curr
220: .getOverridenIds());
221: }
222: }
223: }
224:
225: public void handleException(Throwable exception) {
226: if (status != null) {
227: status
228: .merge(new Status(
229: IStatus.ERROR,
230: JavaUI.ID_PLUGIN,
231: IStatus.ERROR,
232: CorrectionMessages.ClasspathFixProcessorDescriptor_error_processing_processors,
233: exception));
234: }
235: }
236: });
237: }
238: }
239: return (ClasspathFixProposal[]) proposals
240: .toArray(new ClasspathFixProposal[proposals.size()]);
241: }
242: }
|