]> git.uio.no Git - ifi-stolz-refaktor.git/blob - case-study/jdt-before/core extension/org/eclipse/jdt/internal/corext/fix/CleanUpRegistry.java
d3e696bd9b4a3c02967a652a388ac89065a569fa
[ifi-stolz-refaktor.git] / case-study / jdt-before / core extension / org / eclipse / jdt / internal / corext / fix / CleanUpRegistry.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2011 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.jdt.internal.corext.fix;
12
13 import java.util.ArrayList;
14 import java.util.Arrays;
15 import java.util.Comparator;
16 import java.util.Set;
17
18 import com.ibm.icu.text.Collator;
19
20 import org.eclipse.swt.SWT;
21 import org.eclipse.swt.layout.GridData;
22 import org.eclipse.swt.layout.GridLayout;
23 import org.eclipse.swt.widgets.Composite;
24 import org.eclipse.swt.widgets.Text;
25
26 import org.eclipse.core.runtime.CoreException;
27 import org.eclipse.core.runtime.IConfigurationElement;
28 import org.eclipse.core.runtime.IExtensionPoint;
29 import org.eclipse.core.runtime.ISafeRunnable;
30 import org.eclipse.core.runtime.IStatus;
31 import org.eclipse.core.runtime.Platform;
32 import org.eclipse.core.runtime.SafeRunner;
33 import org.eclipse.core.runtime.Status;
34
35 import org.eclipse.jface.util.SafeRunnable;
36
37 import org.eclipse.jdt.internal.corext.util.Messages;
38
39 import org.eclipse.jdt.ui.cleanup.CleanUpOptions;
40 import org.eclipse.jdt.ui.cleanup.ICleanUp;
41 import org.eclipse.jdt.ui.cleanup.ICleanUpConfigurationUI;
42 import org.eclipse.jdt.ui.cleanup.ICleanUpOptionsInitializer;
43
44 import org.eclipse.jdt.internal.ui.IJavaStatusConstants;
45 import org.eclipse.jdt.internal.ui.JavaPlugin;
46 import org.eclipse.jdt.internal.ui.fix.MapCleanUpOptions;
47 import org.eclipse.jdt.internal.ui.preferences.cleanup.CleanUpTabPage;
48 import org.eclipse.jdt.internal.ui.preferences.cleanup.ContributedCleanUpTabPage;
49
50 /**
51  * The clean up registry provides a set of clean ups and there corresponding UI representatives.
52  * 
53  * @since 3.4
54  */
55 public class CleanUpRegistry {
56
57         private static final class ErrorPage implements ICleanUpConfigurationUI {
58
59                 private final Exception fException;
60
61                 private ErrorPage(Exception e) {
62                         fException= e;
63                 }
64
65                 public Composite createContents(Composite parent) {
66                         Composite result= new Composite(parent, SWT.NONE);
67                         result.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
68                         result.setLayout(new GridLayout(1, false));
69
70                         Text text= new Text(result, SWT.MULTI | SWT.BORDER | SWT.READ_ONLY);
71                         text.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
72                         text.setText(Messages.format(FixMessages.CleanUpRegistry_ErrorTabPage_description, fException.getLocalizedMessage()));
73
74                         return result;
75                 }
76
77                 public int getCleanUpCount() {
78                         return 0;
79                 }
80
81                 public String getPreview() {
82                         return FixMessages.CleanUpRegistry_ErrorTabPage_preview;
83                 }
84
85                 public int getSelectedCleanUpCount() {
86                         return 0;
87                 }
88
89                 public void setOptions(CleanUpOptions options) {
90                 }
91         }
92
93         public static class CleanUpTabPageDescriptor {
94
95                 private static final String ATTRIBUTE_ID_CLASS= "class"; //$NON-NLS-1$
96                 private static final String ATTRIBUTE_ID_NAME= "name"; //$NON-NLS-1$
97                 private static final String ATTRIBUTE_NAME_KIND= "cleanUpKind"; //$NON-NLS-1$
98                 
99                 private final String fName;
100                 private final IConfigurationElement fElement;
101                 private int fKind;
102
103                 /**
104                  * @param element the configuration element
105                  */
106                 public CleanUpTabPageDescriptor(IConfigurationElement element) {
107                         fElement= element;
108                         fName= element.getAttribute(ATTRIBUTE_ID_NAME);
109                         String kind= fElement.getAttribute(ATTRIBUTE_NAME_KIND);
110                         fKind= getCleanUpKind(kind);
111                         if (fKind == -1)
112                                 JavaPlugin.logErrorMessage(Messages.format(FixMessages.CleanUpRegistry_WrongKindForConfigurationUI_error, new String[] { fName, element.getContributor().getName(),
113                                                 kind }));
114                 }
115
116                 /**
117                  * @return the name of the tab
118                  */
119                 public String getName() {
120                         return fName;
121                 }
122
123                 /**
124                  * @return the kind of clean up
125                  */
126                 public int getKind() {
127                         return fKind;
128                 }
129
130                 /**
131                  * @return new instance of a tab page
132                  */
133                 public CleanUpTabPage createTabPage() {
134                         try {
135                                 ICleanUpConfigurationUI page= (ICleanUpConfigurationUI)fElement.createExecutableExtension(ATTRIBUTE_ID_CLASS);
136                                 if (page instanceof CleanUpTabPage)
137                                         return (CleanUpTabPage)page;
138
139                                 return new ContributedCleanUpTabPage(page);
140                         } catch (final CoreException e) {
141                                 JavaPlugin.log(e);
142                                 return new ContributedCleanUpTabPage(new ErrorPage(e));
143                         }
144                 }
145         }
146
147         private static class CleanUpDescriptor {
148
149                 private static final String ATTRIBUTE_ID_CLASS= "class"; //$NON-NLS-1$
150                 private static final String ATTRIBURE_ID_RUNAFTER= "runAfter"; //$NON-NLS-1$
151                 private static final String ATTRIBUTE_ID_ID= "id"; //$NON-NLS-1$
152
153                 private final IConfigurationElement fElement;
154                 private final String fId;
155                 private final String fRunAfter;
156
157                 /**
158                  * @param element the configuration element
159                  */
160                 public CleanUpDescriptor(IConfigurationElement element) {
161                         fElement= element;
162                         fId= element.getAttribute(ATTRIBUTE_ID_ID);
163                         fRunAfter= element.getAttribute(ATTRIBURE_ID_RUNAFTER);
164                 }
165
166                 /**
167                  * @return the unique id of this clean up
168                  */
169                 public String getId() {
170                         return fId;
171                 }
172
173                 /**
174                  * @return the id of the clean up which must run before this clean up or
175                  *         <strong>null</strong> if none specified
176                  */
177                 public String getRunAfter() {
178                         return fRunAfter;
179                 }
180
181                 /**
182                  * @return the clean up or <code>null</code> if the clean up could not be instantiated
183                  */
184                 public ICleanUp createCleanUp() {
185                         try {
186                                 return (ICleanUp)fElement.createExecutableExtension(ATTRIBUTE_ID_CLASS);
187                         } catch (CoreException e) {
188                                 String msg= Messages.format(FixMessages.CleanUpRegistry_cleanUpCreation_error, new String[] { fElement.getAttribute(ATTRIBUTE_ID_ID), fElement.getContributor().getName() });
189                                 JavaPlugin.logErrorStatus(msg, e.getStatus());
190                                 return null;
191                         }
192                 }
193         }
194
195         private static final class CleanUpInitializerDescriptor {
196
197                 private static final String ATTRIBUTE_NAME_CLASS= "class"; //$NON-NLS-1$
198                 private static final String ATTRIBUTE_NAME_KIND= "cleanUpKind"; //$NON-NLS-1$
199
200                 private final IConfigurationElement fElement;
201
202                 private final int fKind;
203
204                 private ICleanUpOptionsInitializer fOptionsProvider;
205
206                 public CleanUpInitializerDescriptor(IConfigurationElement element) {
207                         fElement= element;
208                         String kind= fElement.getAttribute(ATTRIBUTE_NAME_KIND);
209                         fKind= getCleanUpKind(kind);
210                         if (fKind == -1)
211                                 JavaPlugin.logErrorMessage(Messages.format(FixMessages.CleanUpRegistry_UnknownInitializerKind_errorMessage, new String[] { element.getContributor().getName(), kind }));
212                 }
213
214                 public int getKind() {
215                         return fKind;
216                 }
217
218                 public ICleanUpOptionsInitializer getOptionsInitializer() {
219                         if (fOptionsProvider == null) {
220                                 try {
221                                         fOptionsProvider= (ICleanUpOptionsInitializer)fElement.createExecutableExtension(ATTRIBUTE_NAME_CLASS);
222                                 } catch (CoreException e) {
223                                         JavaPlugin.log(e);
224                                         fOptionsProvider= new ICleanUpOptionsInitializer() {
225                                                 public void setDefaultOptions(CleanUpOptions options) {
226                                                 }
227                                         };
228                                 }
229                         }
230                         return fOptionsProvider;
231                 }
232         }
233         
234         private static final String EXTENSION_POINT_NAME= "cleanUps"; //$NON-NLS-1$
235         private static final String CLEAN_UP_CONFIGURATION_ELEMENT_NAME= "cleanUp"; //$NON-NLS-1$
236         private static final String TABPAGE_CONFIGURATION_ELEMENT_NAME= "cleanUpConfigurationUI"; //$NON-NLS-1$
237
238         private static final String CLEAN_UP_INITIALIZER_CONFIGURATION_ELEMENT_NAME= "cleanUpOptionsInitializer"; //$NON-NLS-1$
239         private static final String ATTRIBUTE_KIND_TYPE_SAVE_ACTION= "saveAction"; //$NON-NLS-1$
240         private static final String ATTRIBUTE_KIND_TYPE_CLEAN_UP= "cleanUp"; //$NON-NLS-1$
241
242         private CleanUpDescriptor[] fCleanUpDescriptors;
243         private CleanUpTabPageDescriptor[] fPageDescriptors;
244
245         private CleanUpInitializerDescriptor[] fCleanUpInitializerDescriptors;
246
247         /**
248          * Creates and returns the registered clean ups that don't fail upon creation.
249          * 
250          * @return an array of clean ups
251          */
252         public synchronized ICleanUp[] createCleanUps() {
253                 return createCleanUps(null);
254         }
255
256         /**
257          * Creates and returns the registered clean ups that don't fail upon creation.
258          * 
259          * @param ids the ids of the clean ups to create, or <code>null</code> to create all
260          * @return an array of clean ups
261          * @since 3.5
262          */
263         public synchronized ICleanUp[] createCleanUps(Set<String> ids) {
264                 ensureCleanUpsRegistered();
265                 ArrayList<ICleanUp> result= new ArrayList<ICleanUp>(fCleanUpDescriptors.length);
266                 for (int i= 0; i < fCleanUpDescriptors.length; i++) {
267                         if (ids == null || ids.contains(fCleanUpDescriptors[i].getId())) {
268                                 ICleanUp cleanUp= fCleanUpDescriptors[i].createCleanUp();
269                                 if (cleanUp != null)
270                                         result.add(cleanUp);
271                         }
272                 }
273                 return result.toArray(new ICleanUp[result.size()]);
274         }
275
276         /**
277          * @param kind the kind of clean up for which to retrieve the configuratin pages
278          * 
279          * @return set of clean up tab page descriptors
280          * 
281          * @see CleanUpConstants#DEFAULT_CLEAN_UP_OPTIONS
282          * @see CleanUpConstants#DEFAULT_SAVE_ACTION_OPTIONS
283          */
284         public synchronized CleanUpTabPageDescriptor[] getCleanUpTabPageDescriptors(int kind) {
285                 ensurePagesRegistered();
286
287                 ArrayList<CleanUpTabPageDescriptor> result= new ArrayList<CleanUpTabPageDescriptor>();
288                 for (int i= 0; i < fPageDescriptors.length; i++) {
289                         if (fPageDescriptors[i].getKind() == kind)
290                                 result.add(fPageDescriptors[i]);
291                 }
292                 return result.toArray(new CleanUpTabPageDescriptor[result.size()]);
293         }
294
295         /**
296          * Returns the default options for the specified clean up kind.
297          * 
298          * @param kind the kind of clean up for which to retrieve the options
299          * @return the default options
300          * 
301          * @see CleanUpConstants#DEFAULT_CLEAN_UP_OPTIONS
302          * @see CleanUpConstants#DEFAULT_SAVE_ACTION_OPTIONS
303          */
304         public MapCleanUpOptions getDefaultOptions(int kind) {
305                 ensureCleanUpInitializersRegistered();
306
307                 CleanUpOptions options= new CleanUpOptions();
308                 for (int i= 0; i < fCleanUpInitializerDescriptors.length; i++) {
309                         CleanUpInitializerDescriptor descriptor= fCleanUpInitializerDescriptors[i];
310                         if (descriptor.getKind() == kind) {
311                                 descriptor.getOptionsInitializer().setDefaultOptions(options);
312                         }
313                 }
314                 MapCleanUpOptions mapCleanUpOptions= new MapCleanUpOptions();
315                 mapCleanUpOptions.addAll(options);
316                 return mapCleanUpOptions;
317         }
318
319         private synchronized void ensureCleanUpsRegistered() {
320                 if (fCleanUpDescriptors != null)
321                         return;
322
323
324                 final ArrayList<CleanUpDescriptor> descriptors= new ArrayList<CleanUpDescriptor>();
325
326                 IExtensionPoint point= Platform.getExtensionRegistry().getExtensionPoint(JavaPlugin.getPluginId(), EXTENSION_POINT_NAME);
327                 IConfigurationElement[] elements= point.getConfigurationElements();
328                 for (int i= 0; i < elements.length; i++) {
329                         IConfigurationElement element= elements[i];
330
331                         if (CLEAN_UP_CONFIGURATION_ELEMENT_NAME.equals(element.getName())) {
332                                 descriptors.add(new CleanUpDescriptor(element));
333                         }
334                 }
335
336
337                 // Make sure we filter those who fail or misbehave
338                 for (int i= 0; i < descriptors.size(); i++) {
339                         final CleanUpDescriptor cleanUpDescriptor= descriptors.get(i);
340                         final boolean disable[]= new boolean[1];
341                         ISafeRunnable runnable= new SafeRunnable() {
342                                 
343                                 public void run() throws Exception {
344                                         ICleanUp cleanUp= cleanUpDescriptor.createCleanUp();
345                                         if (cleanUp == null)
346                                                 disable[0]= true;
347                                         else {
348                                                 cleanUp.setOptions(new CleanUpOptions());
349                                                 String[] enbledSteps= cleanUp.getStepDescriptions();
350                                                 if (enbledSteps != null && enbledSteps.length > 0) {
351                                                         JavaPlugin.logErrorMessage(
352                                                                         Messages.format(FixMessages.CleanUpRegistry_cleanUpAlwaysEnabled_error, new String[] { cleanUpDescriptor.getId(),
353                                                                         cleanUpDescriptor.fElement.getContributor().getName() }));
354                                                         disable[0]= true;
355                                                 }
356                                         }
357                                 }
358                                 @Override
359                                 public void handleException(Throwable t) {
360                                         disable[0]= true;
361                                         String message= Messages.format(FixMessages.CleanUpRegistry_cleanUpCreation_error, new String[] { cleanUpDescriptor.getId(),
362                                                         cleanUpDescriptor.fElement.getContributor().getName() });
363                                         IStatus status= new Status(IStatus.ERROR, JavaPlugin.getPluginId(), IJavaStatusConstants.INTERNAL_ERROR, message, t);
364                                         JavaPlugin.log(status);
365                                 }
366
367                         };
368                         SafeRunner.run(runnable);
369                         if (disable[0])
370                                 descriptors.remove(i--);
371                 }
372
373                 fCleanUpDescriptors= descriptors.toArray(new CleanUpDescriptor[descriptors.size()]);
374                 sort(fCleanUpDescriptors);
375
376         }
377
378         private static void sort(CleanUpDescriptor[] data) {
379                 int lastSwapI= -1;
380                 int lastSwapJ= -1;
381                 mainLoop: for (int i= 0; i < data.length; i++) {
382                         String runAfter= data[i].getRunAfter();
383                         if (runAfter == null)
384                                 continue;
385                         int jStart= i + 1;
386                         for (int j= jStart; j < data.length; j++) {
387                                 String jID= data[j].getId();
388                                 if (runAfter.equals(jID)) {
389                                         if (lastSwapI == i && j >= lastSwapJ) {
390                                                 JavaPlugin.logErrorMessage("Problem reading cleanUps extensions: cannot satisfy rule for '" + data[i].getId() + "' to runAfter '" + runAfter + "'");   //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
391                                                 continue mainLoop;
392                                         }
393                                         lastSwapI= i;
394                                         lastSwapJ= j;
395                                         swap(data, i, j);
396                                         i--;
397                                         continue mainLoop;
398                                 }
399                         }
400                         for (int j= 0; j < jStart; j++) {
401                                 String jID= data[j].getId();
402                                 if (runAfter.equals(jID))
403                                         continue mainLoop;
404                         }
405                         JavaPlugin.logErrorMessage("Problem reading cleanUps extensions: cannot satisfy rule for '" + data[i].getId() + "' to runAfter '" + runAfter + "' because the runAfter clean up does not exist."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
406                 }
407         }
408
409         private static void swap(CleanUpDescriptor[] data, int i, int j) {
410                 CleanUpDescriptor o= data[i];
411                 data[i]= data[j];
412                 data[j]= o;
413         }
414
415         private synchronized void ensurePagesRegistered() {
416                 if (fPageDescriptors != null)
417                         return;
418                 
419                 ArrayList<CleanUpTabPageDescriptor> result= new ArrayList<CleanUpTabPageDescriptor>();
420
421                 IExtensionPoint point= Platform.getExtensionRegistry().getExtensionPoint(JavaPlugin.getPluginId(), EXTENSION_POINT_NAME);
422                 IConfigurationElement[] elements= point.getConfigurationElements();
423                 for (int i= 0; i < elements.length; i++) {
424                         IConfigurationElement element= elements[i];
425
426                         if (TABPAGE_CONFIGURATION_ELEMENT_NAME.equals(element.getName())) {
427                                 result.add(new CleanUpTabPageDescriptor(element));
428                         }
429                 }
430
431                 fPageDescriptors= result.toArray(new CleanUpTabPageDescriptor[result.size()]);
432                 Arrays.sort(fPageDescriptors, new Comparator<CleanUpTabPageDescriptor>() {
433                         public int compare(CleanUpTabPageDescriptor o1, CleanUpTabPageDescriptor o2) {
434                                 String name1= o1.getName();
435                                 String name2= o2.getName();
436                                 return Collator.getInstance().compare(name1.replaceAll("&", ""), name2.replaceAll("&", "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
437                         }
438                 });
439         }
440
441         private synchronized void ensureCleanUpInitializersRegistered() {
442                 if (fCleanUpInitializerDescriptors != null)
443                         return;
444
445                 ArrayList<CleanUpInitializerDescriptor> result= new ArrayList<CleanUpInitializerDescriptor>();
446
447                 IExtensionPoint point= Platform.getExtensionRegistry().getExtensionPoint(JavaPlugin.getPluginId(), EXTENSION_POINT_NAME);
448                 IConfigurationElement[] elements= point.getConfigurationElements();
449                 for (int i= 0; i < elements.length; i++) {
450                         IConfigurationElement element= elements[i];
451
452                         if (CLEAN_UP_INITIALIZER_CONFIGURATION_ELEMENT_NAME.equals(element.getName())) {
453                                 result.add(new CleanUpInitializerDescriptor(element));
454                         }
455                 }
456
457                 fCleanUpInitializerDescriptors= result.toArray(new CleanUpInitializerDescriptor[result.size()]);
458         }
459
460         private static int getCleanUpKind(String kind) {
461                 if (kind.equals(ATTRIBUTE_KIND_TYPE_CLEAN_UP)) {
462                         return CleanUpConstants.DEFAULT_CLEAN_UP_OPTIONS;
463                 } else if (kind.equals(ATTRIBUTE_KIND_TYPE_SAVE_ACTION)) {
464                         return CleanUpConstants.DEFAULT_SAVE_ACTION_OPTIONS;
465                 } else {
466                         return -1;
467                 }
468         }
469
470 }