]>
Commit | Line | Data |
---|---|---|
1b2798f6 EK |
1 | /******************************************************************************* |
2 | * Copyright (c) 2005, 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 | * Sergey Prigogin <eclipse.sprigogin@gmail.com> - [refactoring] Provide a way to implement refactorings that depend on resources that have to be explicitly released - https://bugs.eclipse.org/347599 | |
11 | *******************************************************************************/ | |
12 | package org.eclipse.jdt.internal.ui.refactoring.binary; | |
13 | ||
14 | import java.net.URI; | |
15 | import java.util.ArrayList; | |
16 | import java.util.Arrays; | |
17 | import java.util.Collection; | |
18 | import java.util.HashSet; | |
19 | import java.util.List; | |
20 | import java.util.Map; | |
21 | import java.util.jar.JarFile; | |
22 | ||
23 | import org.eclipse.core.filesystem.EFS; | |
24 | import org.eclipse.core.filesystem.IFileStore; | |
25 | import org.eclipse.core.filesystem.URIUtil; | |
26 | ||
27 | import org.eclipse.core.runtime.Assert; | |
28 | import org.eclipse.core.runtime.CoreException; | |
29 | import org.eclipse.core.runtime.IAdaptable; | |
30 | import org.eclipse.core.runtime.IPath; | |
31 | import org.eclipse.core.runtime.IProgressMonitor; | |
32 | import org.eclipse.core.runtime.SubProgressMonitor; | |
33 | ||
34 | import org.eclipse.core.resources.IFolder; | |
35 | import org.eclipse.core.resources.IResource; | |
36 | import org.eclipse.core.resources.IWorkspaceRoot; | |
37 | import org.eclipse.core.resources.IWorkspaceRunnable; | |
38 | import org.eclipse.core.resources.ResourcesPlugin; | |
39 | ||
40 | import org.eclipse.ltk.core.refactoring.Change; | |
41 | import org.eclipse.ltk.core.refactoring.Refactoring; | |
42 | import org.eclipse.ltk.core.refactoring.RefactoringContext; | |
43 | import org.eclipse.ltk.core.refactoring.RefactoringContribution; | |
44 | import org.eclipse.ltk.core.refactoring.RefactoringCore; | |
45 | import org.eclipse.ltk.core.refactoring.RefactoringDescriptor; | |
46 | import org.eclipse.ltk.core.refactoring.RefactoringDescriptorProxy; | |
47 | import org.eclipse.ltk.core.refactoring.RefactoringStatus; | |
48 | import org.eclipse.ltk.core.refactoring.RefactoringStatusContext; | |
49 | import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry; | |
50 | import org.eclipse.ltk.core.refactoring.history.RefactoringHistory; | |
51 | import org.eclipse.ltk.ui.refactoring.history.RefactoringHistoryWizard; | |
52 | ||
53 | import org.eclipse.jdt.core.IClasspathEntry; | |
54 | import org.eclipse.jdt.core.ICompilationUnit; | |
55 | import org.eclipse.jdt.core.IJavaElement; | |
56 | import org.eclipse.jdt.core.IJavaModel; | |
57 | import org.eclipse.jdt.core.IJavaProject; | |
58 | import org.eclipse.jdt.core.IPackageFragment; | |
59 | import org.eclipse.jdt.core.IPackageFragmentRoot; | |
60 | import org.eclipse.jdt.core.JavaCore; | |
61 | import org.eclipse.jdt.core.JavaModelException; | |
62 | import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor; | |
63 | ||
64 | import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptorUtil; | |
65 | import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages; | |
66 | import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext; | |
67 | import org.eclipse.jdt.internal.corext.refactoring.binary.SourceCreationOperation; | |
68 | import org.eclipse.jdt.internal.corext.refactoring.binary.StubCreationOperation; | |
69 | import org.eclipse.jdt.internal.corext.util.JavaModelUtil; | |
70 | import org.eclipse.jdt.internal.corext.util.Messages; | |
71 | ||
72 | import org.eclipse.jdt.ui.JavaElementLabels; | |
73 | ||
74 | import org.eclipse.jdt.internal.ui.JavaPlugin; | |
75 | import org.eclipse.jdt.internal.ui.jarimport.JarImportMessages; | |
76 | import org.eclipse.jdt.internal.ui.util.CoreUtility; | |
77 | ||
78 | /** | |
79 | * Partial implementation of a refactoring history wizard which creates stubs | |
80 | * from a binary package fragment root while refactoring. | |
81 | * | |
82 | * @since 3.2 | |
83 | */ | |
84 | public abstract class BinaryRefactoringHistoryWizard extends RefactoringHistoryWizard { | |
85 | ||
86 | /** The meta-inf fragment */ | |
87 | private static final String META_INF_FRAGMENT= JarFile.MANIFEST_NAME.substring(0, JarFile.MANIFEST_NAME.indexOf('/')); | |
88 | ||
89 | /** The temporary linked source folder */ | |
90 | private static final String SOURCE_FOLDER= ".src"; //$NON-NLS-1$ | |
91 | ||
92 | /** The temporary stubs folder */ | |
93 | private static final String STUB_FOLDER= ".stubs"; //$NON-NLS-1$ | |
94 | ||
95 | /** | |
96 | * Updates the new classpath with exclusion patterns for the specified path. | |
97 | * | |
98 | * @param entries | |
99 | * the classpath entries | |
100 | * @param path | |
101 | * the path | |
102 | */ | |
103 | private static void addExclusionPatterns(final List<IClasspathEntry> entries, final IPath path) { | |
104 | for (int index= 0; index < entries.size(); index++) { | |
105 | final IClasspathEntry entry= entries.get(index); | |
106 | if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE && entry.getPath().isPrefixOf(path)) { | |
107 | final IPath[] patterns= entry.getExclusionPatterns(); | |
108 | if (!JavaModelUtil.isExcludedPath(path, patterns)) { | |
109 | final IPath[] filters= new IPath[patterns.length + 1]; | |
110 | System.arraycopy(patterns, 0, filters, 0, patterns.length); | |
111 | filters[patterns.length]= path.removeFirstSegments(entry.getPath().segmentCount()).addTrailingSeparator(); | |
112 | entries.set(index, JavaCore.newSourceEntry(entry.getPath(), filters, entry.getOutputLocation())); | |
113 | } | |
114 | } | |
115 | } | |
116 | } | |
117 | ||
118 | /** | |
119 | * Checks whether the archive referenced by the package fragment root is not | |
120 | * shared with multiple java projects in the workspace. | |
121 | * | |
122 | * @param root | |
123 | * the package fragment root | |
124 | * @param monitor | |
125 | * the progress monitor to use | |
126 | * @return the status of the operation | |
127 | */ | |
128 | private static RefactoringStatus checkPackageFragmentRoots(final IPackageFragmentRoot root, final IProgressMonitor monitor) { | |
129 | final RefactoringStatus status= new RefactoringStatus(); | |
130 | try { | |
131 | monitor.beginTask(JarImportMessages.JarImportWizard_prepare_import, 100); | |
132 | final IWorkspaceRoot workspace= ResourcesPlugin.getWorkspace().getRoot(); | |
133 | if (workspace != null) { | |
134 | final IJavaModel model= JavaCore.create(workspace); | |
135 | if (model != null) { | |
136 | try { | |
137 | final URI uri= getLocationURI(root.getRawClasspathEntry()); | |
138 | if (uri != null) { | |
139 | final IJavaProject[] projects= model.getJavaProjects(); | |
140 | final IProgressMonitor subMonitor= new SubProgressMonitor(monitor, 100, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL); | |
141 | try { | |
142 | subMonitor.beginTask(JarImportMessages.JarImportWizard_prepare_import, projects.length * 100); | |
143 | for (int index= 0; index < projects.length; index++) { | |
144 | final IPackageFragmentRoot[] roots= projects[index].getPackageFragmentRoots(); | |
145 | final IProgressMonitor subsubMonitor= new SubProgressMonitor(subMonitor, 100, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL); | |
146 | try { | |
147 | subsubMonitor.beginTask(JarImportMessages.JarImportWizard_prepare_import, roots.length); | |
148 | for (int offset= 0; offset < roots.length; offset++) { | |
149 | final IPackageFragmentRoot current= roots[offset]; | |
150 | if (!current.equals(root) && current.getKind() == IPackageFragmentRoot.K_BINARY) { | |
151 | final IClasspathEntry entry= current.getRawClasspathEntry(); | |
152 | if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) { | |
153 | final URI location= getLocationURI(entry); | |
154 | if (uri.equals(location)) | |
155 | status.addFatalError(Messages.format(JarImportMessages.JarImportWizard_error_shared_jar, new String[] { JavaElementLabels.getElementLabel(current.getJavaProject(), JavaElementLabels.ALL_DEFAULT) })); | |
156 | } | |
157 | } | |
158 | subsubMonitor.worked(1); | |
159 | } | |
160 | } finally { | |
161 | subsubMonitor.done(); | |
162 | } | |
163 | } | |
164 | } finally { | |
165 | subMonitor.done(); | |
166 | } | |
167 | } | |
168 | } catch (CoreException exception) { | |
169 | status.addError(exception.getLocalizedMessage()); | |
170 | } | |
171 | } | |
172 | } | |
173 | } finally { | |
174 | monitor.done(); | |
175 | } | |
176 | return status; | |
177 | } | |
178 | ||
179 | /** | |
180 | * Configures the classpath of the project before refactoring. | |
181 | * | |
182 | * @param project | |
183 | * the java project | |
184 | * @param root | |
185 | * the package fragment root to refactor | |
186 | * @param folder | |
187 | * the temporary source folder | |
188 | * @param monitor | |
189 | * the progress monitor to use | |
190 | * @throws IllegalStateException | |
191 | * if the plugin state location does not exist | |
192 | * @throws CoreException | |
193 | * if an error occurs while configuring the class path | |
194 | */ | |
195 | private static void configureClasspath(final IJavaProject project, final IPackageFragmentRoot root, final IFolder folder, final IProgressMonitor monitor) throws IllegalStateException, CoreException { | |
196 | try { | |
197 | monitor.beginTask(JarImportMessages.JarImportWizard_prepare_import, 200); | |
198 | final IClasspathEntry entry= root.getRawClasspathEntry(); | |
199 | final IClasspathEntry[] entries= project.getRawClasspath(); | |
200 | final List<IClasspathEntry> list= new ArrayList<IClasspathEntry>(); | |
201 | list.addAll(Arrays.asList(entries)); | |
202 | final IFileStore store= EFS.getLocalFileSystem().getStore(JavaPlugin.getDefault().getStateLocation().append(STUB_FOLDER).append(project.getElementName())); | |
203 | if (store.fetchInfo(EFS.NONE, new SubProgressMonitor(monitor, 25, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)).exists()) | |
204 | store.delete(EFS.NONE, new SubProgressMonitor(monitor, 25, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)); | |
205 | store.mkdir(EFS.NONE, new SubProgressMonitor(monitor, 25, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)); | |
206 | folder.createLink(store.toURI(), IResource.NONE, new SubProgressMonitor(monitor, 25, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)); | |
207 | addExclusionPatterns(list, folder.getFullPath()); | |
208 | for (int index= 0; index < entries.length; index++) { | |
209 | if (entries[index].equals(entry)) | |
210 | list.add(index, JavaCore.newSourceEntry(folder.getFullPath())); | |
211 | } | |
212 | project.setRawClasspath(list.toArray(new IClasspathEntry[list.size()]), false, new SubProgressMonitor(monitor, 100, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)); | |
213 | } finally { | |
214 | monitor.done(); | |
215 | } | |
216 | } | |
217 | ||
218 | /** | |
219 | * Returns the location URI of the classpath entry | |
220 | * | |
221 | * @param entry | |
222 | * the classpath entry | |
223 | * @return the location URI | |
224 | */ | |
225 | public static URI getLocationURI(final IClasspathEntry entry) { | |
226 | IPath path= null; | |
227 | if (entry.getEntryKind() == IClasspathEntry.CPE_VARIABLE) | |
228 | path= JavaCore.getResolvedVariablePath(entry.getPath()); | |
229 | else | |
230 | path= entry.getPath(); | |
231 | final IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot(); | |
232 | URI location= null; | |
233 | if (root.exists(path)) { | |
234 | location= root.getFile(path).getRawLocationURI(); | |
235 | } else | |
236 | location= URIUtil.toURI(path); | |
237 | return location; | |
238 | } | |
239 | ||
240 | /** Is auto build enabled? */ | |
241 | private boolean fAutoBuild= true; | |
242 | ||
243 | /** Has the wizard been cancelled? */ | |
244 | protected boolean fCancelled= false; | |
245 | ||
246 | /** The java project or <code>null</code> */ | |
247 | protected IJavaProject fJavaProject= null; | |
248 | ||
249 | /** | |
250 | * The packages which already have been processed (element type: | |
251 | * <IPackageFragment>) | |
252 | */ | |
253 | private final Collection<IJavaElement> fProcessedFragments= new HashSet<IJavaElement>(); | |
254 | ||
255 | /** The temporary source folder, or <code>null</code> */ | |
256 | private IFolder fSourceFolder= null; | |
257 | ||
258 | /** | |
259 | * Creates a new stub refactoring history wizard. | |
260 | * | |
261 | * @param overview | |
262 | * <code>true</code> to show an overview of the refactorings, | |
263 | * <code>false</code> otherwise | |
264 | * @param caption | |
265 | * the wizard caption | |
266 | * @param title | |
267 | * the wizard title | |
268 | * @param description | |
269 | * the wizard description | |
270 | */ | |
271 | protected BinaryRefactoringHistoryWizard(final boolean overview, final String caption, final String title, final String description) { | |
272 | super(overview, caption, title, description); | |
273 | } | |
274 | ||
275 | /** | |
276 | * Creates a new stub refactoring history wizard. | |
277 | * | |
278 | * @param caption | |
279 | * the wizard caption | |
280 | * @param title | |
281 | * the wizard title | |
282 | * @param description | |
283 | * the wizard description | |
284 | */ | |
285 | protected BinaryRefactoringHistoryWizard(final String caption, final String title, final String description) { | |
286 | super(caption, title, description); | |
287 | } | |
288 | ||
289 | /** | |
290 | * {@inheritDoc} | |
291 | */ | |
292 | @Override | |
293 | protected RefactoringStatus aboutToPerformHistory(final IProgressMonitor monitor) { | |
294 | final RefactoringStatus status= new RefactoringStatus(); | |
295 | try { | |
296 | fJavaProject= null; | |
297 | fSourceFolder= null; | |
298 | fProcessedFragments.clear(); | |
299 | monitor.beginTask(JarImportMessages.JarImportWizard_prepare_import, 520); | |
300 | status.merge(super.aboutToPerformHistory(new SubProgressMonitor(monitor, 10, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL))); | |
301 | if (!status.hasFatalError()) { | |
302 | final IPackageFragmentRoot root= getPackageFragmentRoot(); | |
303 | if (root != null) { | |
304 | status.merge(checkPackageFragmentRoots(root, new SubProgressMonitor(monitor, 90, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL))); | |
305 | if (!status.hasFatalError()) { | |
306 | status.merge(checkSourceAttachmentRefactorings(new SubProgressMonitor(monitor, 20, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL))); | |
307 | if (!status.hasFatalError()) { | |
308 | final IJavaProject project= root.getJavaProject(); | |
309 | if (project != null) { | |
310 | final IFolder folder= project.getProject().getFolder(SOURCE_FOLDER + String.valueOf(System.currentTimeMillis())); | |
311 | try { | |
312 | fAutoBuild= CoreUtility.setAutoBuilding(false); | |
313 | final RefactoringHistory history= getRefactoringHistory(); | |
314 | if (history != null && !history.isEmpty()) | |
315 | configureClasspath(project, root, folder, new SubProgressMonitor(monitor, 300, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)); | |
316 | } catch (CoreException exception) { | |
317 | status.merge(RefactoringStatus.createFatalErrorStatus(exception.getLocalizedMessage())); | |
318 | try { | |
319 | project.setRawClasspath(project.readRawClasspath(), false, new SubProgressMonitor(monitor, 100, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)); | |
320 | } catch (CoreException throwable) { | |
321 | JavaPlugin.log(throwable); | |
322 | } | |
323 | } finally { | |
324 | if (!status.hasFatalError()) { | |
325 | fJavaProject= project; | |
326 | fSourceFolder= folder; | |
327 | } | |
328 | } | |
329 | } | |
330 | } | |
331 | } | |
332 | } | |
333 | } | |
334 | } finally { | |
335 | monitor.done(); | |
336 | } | |
337 | return status; | |
338 | } | |
339 | ||
340 | /** | |
341 | * {@inheritDoc} | |
342 | */ | |
343 | @Override | |
344 | protected RefactoringStatus aboutToPerformRefactoring(final Refactoring refactoring, final RefactoringDescriptor descriptor, final IProgressMonitor monitor) { | |
345 | final RefactoringStatus status= new RefactoringStatus(); | |
346 | try { | |
347 | // nothing to do | |
348 | } finally { | |
349 | monitor.done(); | |
350 | } | |
351 | return status; | |
352 | } | |
353 | ||
354 | /** | |
355 | * Can this wizard use the source attachment of the package fragment root if | |
356 | * necessary? | |
357 | * | |
358 | * @return <code>true</code> to use the source attachment, | |
359 | * <code>false</code> otherwise | |
360 | */ | |
361 | protected boolean canUseSourceAttachment() { | |
362 | final IPackageFragmentRoot root= getPackageFragmentRoot(); | |
363 | if (root != null) { | |
364 | try { | |
365 | return root.getSourceAttachmentPath() != null; | |
366 | } catch (JavaModelException exception) { | |
367 | JavaPlugin.log(exception); | |
368 | } | |
369 | } | |
370 | return false; | |
371 | } | |
372 | ||
373 | /** | |
374 | * Checks whether there are any refactorings to be executed which need a | |
375 | * source attachment, but none exists. | |
376 | * | |
377 | * @param monitor | |
378 | * the progress monitor | |
379 | * @return a status describing the outcome of the check | |
380 | */ | |
381 | protected RefactoringStatus checkSourceAttachmentRefactorings(final IProgressMonitor monitor) { | |
382 | final RefactoringStatus status= new RefactoringStatus(); | |
383 | try { | |
384 | if (!canUseSourceAttachment()) { | |
385 | final RefactoringDescriptorProxy[] proxies= getRefactoringHistory().getDescriptors(); | |
386 | monitor.beginTask(JarImportMessages.JarImportWizard_prepare_import, proxies.length * 100); | |
387 | for (int index= 0; index < proxies.length; index++) { | |
388 | final RefactoringDescriptor descriptor= proxies[index].requestDescriptor(new SubProgressMonitor(monitor, 100, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)); | |
389 | if (descriptor != null) { | |
390 | final int flags= descriptor.getFlags(); | |
391 | if ((flags & JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT) != 0) | |
392 | status.merge(RefactoringStatus.createFatalErrorStatus(Messages.format(JarImportMessages.BinaryRefactoringHistoryWizard_error_missing_source_attachment, descriptor.getDescription()))); | |
393 | } | |
394 | } | |
395 | } else | |
396 | monitor.beginTask(JarImportMessages.JarImportWizard_prepare_import, 1); | |
397 | } finally { | |
398 | monitor.done(); | |
399 | } | |
400 | return status; | |
401 | } | |
402 | ||
403 | /** | |
404 | * Creates the necessary source code for the refactoring. | |
405 | * | |
406 | * @param monitor | |
407 | * the progress monitor to use | |
408 | * @return | |
409 | * the resulting status | |
410 | */ | |
411 | private RefactoringStatus createNecessarySourceCode(final IProgressMonitor monitor) { | |
412 | final RefactoringStatus status= new RefactoringStatus(); | |
413 | try { | |
414 | monitor.beginTask(JarImportMessages.JarImportWizard_prepare_import, 240); | |
415 | final IPackageFragmentRoot root= getPackageFragmentRoot(); | |
416 | if (root != null && fSourceFolder != null && fJavaProject != null) { | |
417 | try { | |
418 | final SubProgressMonitor subMonitor= new SubProgressMonitor(monitor, 40, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL); | |
419 | final IJavaElement[] elements= root.getChildren(); | |
420 | final List<IPackageFragment> list= new ArrayList<IPackageFragment>(elements.length); | |
421 | try { | |
422 | subMonitor.beginTask(JarImportMessages.JarImportWizard_prepare_import, elements.length); | |
423 | for (int index= 0; index < elements.length; index++) { | |
424 | final IJavaElement element= elements[index]; | |
425 | if (!fProcessedFragments.contains(element) && !element.getElementName().equals(META_INF_FRAGMENT)) | |
426 | list.add((IPackageFragment) element); | |
427 | subMonitor.worked(1); | |
428 | } | |
429 | } finally { | |
430 | subMonitor.done(); | |
431 | } | |
432 | if (!list.isEmpty()) { | |
433 | fProcessedFragments.addAll(list); | |
434 | final URI uri= fSourceFolder.getRawLocationURI(); | |
435 | if (uri != null) { | |
436 | final IPackageFragmentRoot sourceFolder= fJavaProject.getPackageFragmentRoot(fSourceFolder); | |
437 | IWorkspaceRunnable runnable= null; | |
438 | if (canUseSourceAttachment()) { | |
439 | runnable= new SourceCreationOperation(uri, list) { | |
440 | ||
441 | private IPackageFragment fFragment= null; | |
442 | ||
443 | @Override | |
444 | protected final void createCompilationUnit(final IFileStore store, final String name, final String content, final IProgressMonitor pm) throws CoreException { | |
445 | fFragment.createCompilationUnit(name, content, true, pm); | |
446 | } | |
447 | ||
448 | @Override | |
449 | protected final void createPackageFragment(final IFileStore store, final String name, final IProgressMonitor pm) throws CoreException { | |
450 | fFragment= sourceFolder.createPackageFragment(name, true, pm); | |
451 | } | |
452 | }; | |
453 | } else { | |
454 | runnable= new StubCreationOperation(uri, list, true) { | |
455 | ||
456 | private IPackageFragment fFragment= null; | |
457 | ||
458 | @Override | |
459 | protected final void createCompilationUnit(final IFileStore store, final String name, final String content, final IProgressMonitor pm) throws CoreException { | |
460 | fFragment.createCompilationUnit(name, content, true, pm); | |
461 | } | |
462 | ||
463 | @Override | |
464 | protected final void createPackageFragment(final IFileStore store, final String name, final IProgressMonitor pm) throws CoreException { | |
465 | fFragment= sourceFolder.createPackageFragment(name, true, pm); | |
466 | } | |
467 | }; | |
468 | } | |
469 | try { | |
470 | runnable.run(new SubProgressMonitor(monitor, 150, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)); | |
471 | } finally { | |
472 | fSourceFolder.refreshLocal(IResource.DEPTH_INFINITE, new SubProgressMonitor(monitor, 50, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)); | |
473 | } | |
474 | } | |
475 | } | |
476 | } catch (CoreException exception) { | |
477 | status.addFatalError(exception.getLocalizedMessage()); | |
478 | } | |
479 | } | |
480 | } finally { | |
481 | monitor.done(); | |
482 | } | |
483 | return status; | |
484 | } | |
485 | ||
486 | /** | |
487 | * {@inheritDoc} | |
488 | */ | |
489 | @Override | |
490 | protected RefactoringContext createRefactoringContext(RefactoringDescriptor descriptor, RefactoringStatus status, IProgressMonitor monitor) throws CoreException { | |
491 | Assert.isNotNull(descriptor); | |
492 | ||
493 | createNecessarySourceCode(monitor); | |
494 | ||
495 | if (descriptor instanceof JavaRefactoringDescriptor) { | |
496 | JavaRefactoringDescriptor javaDescriptor= (JavaRefactoringDescriptor) descriptor; | |
497 | RefactoringContribution contribution= RefactoringCore.getRefactoringContribution(javaDescriptor.getID()); | |
498 | ||
499 | Map<String, String> map= contribution.retrieveArgumentMap(descriptor); | |
500 | if (fJavaProject == null) { | |
501 | status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments)); | |
502 | return null; | |
503 | } | |
504 | ||
505 | String name= fJavaProject.getElementName(); | |
506 | ||
507 | String handle= map.get(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT); | |
508 | if (handle != null && handle.length() > 0) | |
509 | map.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT, getTransformedHandle(name, handle)); | |
510 | ||
511 | int count= 1; | |
512 | String attribute= JavaRefactoringDescriptorUtil.ATTRIBUTE_ELEMENT + count; | |
513 | while ((handle= map.get(attribute)) != null) { | |
514 | if (handle.length() > 0) | |
515 | map.put(attribute, getTransformedHandle(name, handle)); | |
516 | count++; | |
517 | attribute= JavaRefactoringDescriptorUtil.ATTRIBUTE_ELEMENT + count; | |
518 | } | |
519 | ||
520 | // create adapted descriptor | |
521 | try { | |
522 | descriptor= contribution.createDescriptor(descriptor.getID(), name, descriptor.getDescription(), descriptor.getComment(), map, descriptor.getFlags()); | |
523 | } catch (IllegalArgumentException e) { | |
524 | status.merge(RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments)); | |
525 | return null; | |
526 | } | |
527 | } | |
528 | return descriptor.createRefactoringContext(status); | |
529 | } | |
530 | ||
531 | /** | |
532 | * Deconfigures the classpath after all refactoring have been performed. | |
533 | * | |
534 | * @param entries | |
535 | * the classpath entries to reset the project to | |
536 | * @param monitor | |
537 | * the progress monitor to use | |
538 | * @return <code>true</code> if the classpath has been changed, | |
539 | * <code>false</code> otherwise | |
540 | * @throws CoreException | |
541 | * if an error occurs while deconfiguring the classpath | |
542 | */ | |
543 | protected boolean deconfigureClasspath(IClasspathEntry[] entries, IProgressMonitor monitor) throws CoreException { | |
544 | return false; | |
545 | } | |
546 | ||
547 | /** | |
548 | * Deconfigures the classpath of the project after refactoring. | |
549 | * | |
550 | * @param monitor | |
551 | * the progress monitor to use | |
552 | * @throws CoreException | |
553 | * if an error occurs while deconfiguring the classpath | |
554 | */ | |
555 | private void deconfigureClasspath(final IProgressMonitor monitor) throws CoreException { | |
556 | try { | |
557 | monitor.beginTask(JarImportMessages.JarImportWizard_cleanup_import, 300); | |
558 | if (fJavaProject != null) { | |
559 | final IClasspathEntry[] entries= fJavaProject.readRawClasspath(); | |
560 | final boolean changed= deconfigureClasspath(entries, new SubProgressMonitor(monitor, 100, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)); | |
561 | final RefactoringHistory history= getRefactoringHistory(); | |
562 | final boolean valid= history != null && !history.isEmpty(); | |
563 | if (valid) | |
564 | RefactoringCore.getUndoManager().flush(); | |
565 | if (valid || changed) | |
566 | fJavaProject.setRawClasspath(entries, changed, new SubProgressMonitor(monitor, 60, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)); | |
567 | } | |
568 | if (fSourceFolder != null) { | |
569 | final IFileStore store= EFS.getStore(fSourceFolder.getRawLocationURI()); | |
570 | if (store.fetchInfo(EFS.NONE, new SubProgressMonitor(monitor, 10, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)).exists()) | |
571 | store.delete(EFS.NONE, new SubProgressMonitor(monitor, 10, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)); | |
572 | fSourceFolder.delete(true, false, new SubProgressMonitor(monitor, 10, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)); | |
573 | fSourceFolder.clearHistory(new SubProgressMonitor(monitor, 10, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)); | |
574 | fSourceFolder= null; | |
575 | } | |
576 | if (fJavaProject != null) { | |
577 | try { | |
578 | fJavaProject.getResource().refreshLocal(IResource.DEPTH_INFINITE, new SubProgressMonitor(monitor, 100, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)); | |
579 | } catch (CoreException exception) { | |
580 | JavaPlugin.log(exception); | |
581 | } | |
582 | } | |
583 | } finally { | |
584 | fJavaProject= null; | |
585 | monitor.done(); | |
586 | } | |
587 | } | |
588 | ||
589 | /** | |
590 | * Returns the package fragment root to stub. | |
591 | * | |
592 | * @return the package fragment root to stub, or <code>null</code> | |
593 | */ | |
594 | protected abstract IPackageFragmentRoot getPackageFragmentRoot(); | |
595 | ||
596 | /** | |
597 | * Returns the refactoring history to perform. | |
598 | * | |
599 | * @return the refactoring history to perform, or the empty history | |
600 | */ | |
601 | protected abstract RefactoringHistory getRefactoringHistory(); | |
602 | ||
603 | /** | |
604 | * Returns the transformed handle corresponding to the specified input | |
605 | * handle. | |
606 | * | |
607 | * @param project | |
608 | * the project, or <code>null</code> for the workspace | |
609 | * @param handle | |
610 | * the handle to transform | |
611 | * @return the transformed handle, or the original one if nothing needed to | |
612 | * be transformed | |
613 | */ | |
614 | private String getTransformedHandle(final String project, final String handle) { | |
615 | if (fSourceFolder != null) { | |
616 | final IJavaElement target= JavaCore.create(fSourceFolder); | |
617 | if (target instanceof IPackageFragmentRoot) { | |
618 | final IPackageFragmentRoot extended= (IPackageFragmentRoot) target; | |
619 | String sourceIdentifier= null; | |
620 | final IJavaElement element= JavaRefactoringDescriptorUtil.handleToElement(project, handle, false); | |
621 | if (element != null) { | |
622 | final IPackageFragmentRoot root= (IPackageFragmentRoot) element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); | |
623 | if (root != null) | |
624 | sourceIdentifier= root.getHandleIdentifier(); | |
625 | else { | |
626 | final IJavaProject javaProject= element.getJavaProject(); | |
627 | if (javaProject != null) | |
628 | sourceIdentifier= javaProject.getHandleIdentifier(); | |
629 | } | |
630 | if (sourceIdentifier != null) { | |
631 | final IJavaElement result= JavaCore.create(extended.getHandleIdentifier() + element.getHandleIdentifier().substring(sourceIdentifier.length())); | |
632 | if (result != null) | |
633 | return JavaRefactoringDescriptorUtil.elementToHandle(project, result); | |
634 | } | |
635 | } | |
636 | } | |
637 | } | |
638 | return handle; | |
639 | } | |
640 | ||
641 | /** | |
642 | * {@inheritDoc} | |
643 | */ | |
644 | @Override | |
645 | protected RefactoringStatus historyPerformed(final IProgressMonitor monitor) { | |
646 | try { | |
647 | monitor.beginTask(JarImportMessages.JarImportWizard_cleanup_import, 100); | |
648 | final RefactoringStatus status= super.historyPerformed(new SubProgressMonitor(monitor, 10, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)); | |
649 | if (!status.hasFatalError()) { | |
650 | try { | |
651 | deconfigureClasspath(new SubProgressMonitor(monitor, 90, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)); | |
652 | } catch (CoreException exception) { | |
653 | status.addError(exception.getLocalizedMessage()); | |
654 | } finally { | |
655 | try { | |
656 | CoreUtility.setAutoBuilding(fAutoBuild); | |
657 | } catch (CoreException exception) { | |
658 | JavaPlugin.log(exception); | |
659 | } | |
660 | } | |
661 | } | |
662 | return status; | |
663 | } finally { | |
664 | monitor.done(); | |
665 | } | |
666 | } | |
667 | ||
668 | /** | |
669 | * {@inheritDoc} | |
670 | */ | |
671 | @Override | |
672 | public boolean performCancel() { | |
673 | fCancelled= true; | |
674 | return super.performCancel(); | |
675 | } | |
676 | ||
677 | /** | |
678 | * {@inheritDoc} | |
679 | */ | |
680 | @Override | |
681 | protected RefactoringStatus refactoringPerformed(final Refactoring refactoring, final IProgressMonitor monitor) { | |
682 | try { | |
683 | monitor.beginTask("", 120); //$NON-NLS-1$ | |
684 | final RefactoringStatus status= super.refactoringPerformed(refactoring, new SubProgressMonitor(monitor, 100, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)); | |
685 | if (!status.hasFatalError()) { | |
686 | if (fSourceFolder != null) { | |
687 | try { | |
688 | fSourceFolder.refreshLocal(IResource.DEPTH_INFINITE, new SubProgressMonitor(monitor, 100, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)); | |
689 | } catch (CoreException exception) { | |
690 | JavaPlugin.log(exception); | |
691 | } | |
692 | } | |
693 | } | |
694 | return status; | |
695 | } finally { | |
696 | monitor.done(); | |
697 | } | |
698 | } | |
699 | ||
700 | /** | |
701 | * {@inheritDoc} | |
702 | */ | |
703 | @Override | |
704 | protected boolean selectPreviewChange(final Change change) { | |
705 | if (fSourceFolder != null) { | |
706 | final IPath source= fSourceFolder.getFullPath(); | |
707 | final Object element= change.getModifiedElement(); | |
708 | if (element instanceof IAdaptable) { | |
709 | final IAdaptable adaptable= (IAdaptable) element; | |
710 | final IResource resource= (IResource) adaptable.getAdapter(IResource.class); | |
711 | if (resource != null && source.isPrefixOf(resource.getFullPath())) | |
712 | return false; | |
713 | } | |
714 | } | |
715 | return super.selectPreviewChange(change); | |
716 | } | |
717 | ||
718 | /** | |
719 | * {@inheritDoc} | |
720 | */ | |
721 | @Override | |
722 | protected boolean selectStatusEntry(final RefactoringStatusEntry entry) { | |
723 | if (fSourceFolder != null) { | |
724 | final IPath source= fSourceFolder.getFullPath(); | |
725 | final RefactoringStatusContext context= entry.getContext(); | |
726 | if (context instanceof JavaStatusContext) { | |
727 | final JavaStatusContext extended= (JavaStatusContext) context; | |
728 | final ICompilationUnit unit= extended.getCompilationUnit(); | |
729 | if (unit != null) { | |
730 | final IResource resource= unit.getResource(); | |
731 | if (resource != null && source.isPrefixOf(resource.getFullPath())) | |
732 | return false; | |
733 | } | |
734 | } | |
735 | } | |
736 | return super.selectStatusEntry(entry); | |
737 | } | |
738 | } |