Source Code Cross Referenced for WorkspaceUndoUtil.java in  » IDE-Eclipse » ui-ide » org » eclipse » ui » ide » undo » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Eclipse » ui ide » org.eclipse.ui.ide.undo 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*******************************************************************************
002:         * Copyright (c) 2006, 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.ui.ide.undo;
011:
012:        import java.util.ArrayList;
013:        import java.util.List;
014:
015:        import org.eclipse.core.commands.operations.IUndoContext;
016:        import org.eclipse.core.commands.operations.ObjectUndoContext;
017:        import org.eclipse.core.resources.IContainer;
018:        import org.eclipse.core.resources.IFile;
019:        import org.eclipse.core.resources.IProject;
020:        import org.eclipse.core.resources.IResource;
021:        import org.eclipse.core.resources.IResourceStatus;
022:        import org.eclipse.core.resources.IWorkspace;
023:        import org.eclipse.core.resources.IWorkspaceRoot;
024:        import org.eclipse.core.resources.ResourcesPlugin;
025:        import org.eclipse.core.runtime.CoreException;
026:        import org.eclipse.core.runtime.IAdaptable;
027:        import org.eclipse.core.runtime.IPath;
028:        import org.eclipse.core.runtime.IProgressMonitor;
029:        import org.eclipse.core.runtime.IStatus;
030:        import org.eclipse.core.runtime.MultiStatus;
031:        import org.eclipse.core.runtime.NullProgressMonitor;
032:        import org.eclipse.core.runtime.OperationCanceledException;
033:        import org.eclipse.core.runtime.Status;
034:        import org.eclipse.core.runtime.SubProgressMonitor;
035:        import org.eclipse.jface.dialogs.IDialogConstants;
036:        import org.eclipse.jface.dialogs.MessageDialog;
037:        import org.eclipse.osgi.util.NLS;
038:        import org.eclipse.swt.widgets.Shell;
039:        import org.eclipse.ui.PlatformUI;
040:        import org.eclipse.ui.internal.WorkbenchPlugin;
041:        import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
042:        import org.eclipse.ui.internal.ide.undo.ContainerDescription;
043:        import org.eclipse.ui.internal.ide.undo.FileDescription;
044:        import org.eclipse.ui.internal.ide.undo.UndoMessages;
045:
046:        /**
047:         * WorkspaceUndoUtil defines common utility methods and constants used by
048:         * clients who create undoable workspace operations.
049:         * 
050:         * @since 3.3
051:         * 
052:         */
053:        public class WorkspaceUndoUtil {
054:
055:            private static ObjectUndoContext tasksUndoContext;
056:
057:            private static ObjectUndoContext bookmarksUndoContext;
058:
059:            /**
060:             * Return the undo context that should be used for workspace-wide operations
061:             * 
062:             * @return the undo context suitable for workspace-level operations.
063:             */
064:            public static IUndoContext getWorkspaceUndoContext() {
065:                return WorkbenchPlugin.getDefault().getOperationSupport()
066:                        .getUndoContext();
067:            }
068:
069:            /**
070:             * Return the undo context that should be used for operations involving
071:             * tasks.
072:             * 
073:             * @return the tasks undo context
074:             */
075:            public static IUndoContext getTasksUndoContext() {
076:                if (tasksUndoContext == null) {
077:                    tasksUndoContext = new ObjectUndoContext(new Object(),
078:                            "Tasks Context"); //$NON-NLS-1$
079:                    tasksUndoContext.addMatch(getWorkspaceUndoContext());
080:                }
081:                return tasksUndoContext;
082:            }
083:
084:            /**
085:             * Return the undo context that should be used for operations involving
086:             * bookmarks.
087:             * 
088:             * @return the bookmarks undo context
089:             */
090:            public static IUndoContext getBookmarksUndoContext() {
091:                if (bookmarksUndoContext == null) {
092:                    bookmarksUndoContext = new ObjectUndoContext(new Object(),
093:                            "Bookmarks Context"); //$NON-NLS-1$
094:                    bookmarksUndoContext.addMatch(getWorkspaceUndoContext());
095:                }
096:                return bookmarksUndoContext;
097:            }
098:
099:            /**
100:             * Make an <code>IAdaptable</code> that adapts to the specified shell,
101:             * suitable for passing for passing to any
102:             * {@link org.eclipse.core.commands.operations.IUndoableOperation} or
103:             * {@link org.eclipse.core.commands.operations.IOperationHistory} method
104:             * that requires an {@link org.eclipse.core.runtime.IAdaptable}
105:             * <code>uiInfo</code> parameter.
106:             * 
107:             * @param shell
108:             *            the shell that should be returned by the IAdaptable when asked
109:             *            to adapt a shell. If this parameter is <code>null</code>,
110:             *            the returned shell will also be <code>null</code>.
111:             * 
112:             * @return an IAdaptable that will return the specified shell.
113:             */
114:            public static IAdaptable getUIInfoAdapter(final Shell shell) {
115:                return new IAdaptable() {
116:                    public Object getAdapter(Class clazz) {
117:                        if (clazz == Shell.class) {
118:                            return shell;
119:                        }
120:                        return null;
121:                    }
122:                };
123:            }
124:
125:            private WorkspaceUndoUtil() {
126:                // should not construct
127:            }
128:
129:            /**
130:             * Delete all of the specified resources, returning resource descriptions
131:             * that can be used to restore them.
132:             * 
133:             * @param resourcesToDelete
134:             *            an array of resources to be deleted
135:             * @param monitor
136:             *            the progress monitor to use to show the operation's progress
137:             * @param uiInfo
138:             *            the IAdaptable (or <code>null</code>) provided by the
139:             *            caller in order to supply UI information for prompting the
140:             *            user if necessary. When this parameter is not
141:             *            <code>null</code>, it contains an adapter for the
142:             *            org.eclipse.swt.widgets.Shell.class
143:             * 
144:             * @param deleteContent
145:             *            a boolean indicating whether project content should be deleted
146:             *            when a project resource is to be deleted
147:             * @return an array of ResourceDescriptions that can be used to restore the
148:             *         deleted resources.
149:             * @throws CoreException
150:             *             propagates any CoreExceptions thrown from the resources API
151:             */
152:            static ResourceDescription[] delete(IResource[] resourcesToDelete,
153:                    IProgressMonitor monitor, IAdaptable uiInfo,
154:                    boolean deleteContent) throws CoreException {
155:                final List exceptions = new ArrayList();
156:                boolean forceOutOfSyncDelete = false;
157:                ResourceDescription[] returnedResourceDescriptions = new ResourceDescription[resourcesToDelete.length];
158:                monitor.beginTask("", resourcesToDelete.length); //$NON-NLS-1$
159:                monitor
160:                        .setTaskName(UndoMessages.AbstractResourcesOperation_DeleteResourcesProgress);
161:                try {
162:                    for (int i = 0; i < resourcesToDelete.length; ++i) {
163:                        if (monitor.isCanceled()) {
164:                            throw new OperationCanceledException();
165:                        }
166:                        IResource resource = resourcesToDelete[i];
167:                        try {
168:                            returnedResourceDescriptions[i] = delete(resource,
169:                                    new SubProgressMonitor(monitor, 1), uiInfo,
170:                                    forceOutOfSyncDelete, deleteContent);
171:                        } catch (CoreException e) {
172:                            if (resource.getType() == IResource.FILE) {
173:                                IStatus[] children = e.getStatus()
174:                                        .getChildren();
175:                                if (children.length == 1
176:                                        && children[0].getCode() == IResourceStatus.OUT_OF_SYNC_LOCAL) {
177:                                    int result = queryDeleteOutOfSync(resource,
178:                                            uiInfo);
179:
180:                                    if (result == IDialogConstants.YES_ID) {
181:                                        // retry the delete with a force out of sync
182:                                        delete(resource,
183:                                                new SubProgressMonitor(monitor,
184:                                                        1), uiInfo, true,
185:                                                deleteContent);
186:                                    } else if (result == IDialogConstants.YES_TO_ALL_ID) {
187:                                        // all future attempts should force out of
188:                                        // sync
189:                                        forceOutOfSyncDelete = true;
190:                                        delete(resource,
191:                                                new SubProgressMonitor(monitor,
192:                                                        1), uiInfo,
193:                                                forceOutOfSyncDelete,
194:                                                deleteContent);
195:                                    } else if (result == IDialogConstants.CANCEL_ID) {
196:                                        throw new OperationCanceledException();
197:                                    } else {
198:                                        exceptions.add(e);
199:                                    }
200:                                } else {
201:                                    exceptions.add(e);
202:                                }
203:                            } else {
204:                                exceptions.add(e);
205:                            }
206:                        }
207:                    }
208:                    IStatus result = createResult(exceptions);
209:                    if (!result.isOK()) {
210:                        throw new CoreException(result);
211:                    }
212:                } finally {
213:                    monitor.done();
214:                }
215:                return returnedResourceDescriptions;
216:            }
217:
218:            /**
219:             * Copies the resources to the given destination. This method can be called
220:             * recursively to merge folders during folder copy.
221:             * 
222:             * @param resources
223:             *            the resources to be copied
224:             * @param destination
225:             *            the destination path for the resources, relative to the
226:             *            workspace
227:             * @param resourcesAtDestination
228:             *            A list used to record the new copies.
229:             * @param monitor
230:             *            the progress monitor used to show progress
231:             * @param uiInfo
232:             *            the IAdaptable (or <code>null</code>) provided by the
233:             *            caller in order to supply UI information for prompting the
234:             *            user if necessary. When this parameter is not
235:             *            <code>null</code>, it contains an adapter for the
236:             *            org.eclipse.swt.widgets.Shell.class
237:             * @param pathIncludesName
238:             *            a boolean that indicates whether the specified path includes
239:             *            the resource's name at the destination. If this value is
240:             *            <code>true</code>, the destination will contain the desired
241:             *            name of the resource (usually only desired when only one
242:             *            resource is being copied). If this value is <code>false</code>,
243:             *            each resource's name will be appended to the destination.
244:             * @return an array of ResourceDescriptions describing any resources that
245:             *         were overwritten by the copy operation
246:             * @throws CoreException
247:             *             propagates any CoreExceptions thrown from the resources API
248:             */
249:            static ResourceDescription[] copy(IResource[] resources,
250:                    IPath destination, List resourcesAtDestination,
251:                    IProgressMonitor monitor, IAdaptable uiInfo,
252:                    boolean pathIncludesName) throws CoreException {
253:
254:                monitor.beginTask("", resources.length); //$NON-NLS-1$
255:                monitor
256:                        .setTaskName(UndoMessages.AbstractResourcesOperation_CopyingResourcesProgress);
257:                List overwrittenResources = new ArrayList();
258:                for (int i = 0; i < resources.length; i++) {
259:                    IResource source = resources[i];
260:                    IPath destinationPath;
261:                    if (pathIncludesName) {
262:                        destinationPath = destination;
263:                    } else {
264:                        destinationPath = destination.append(source.getName());
265:                    }
266:                    IWorkspaceRoot workspaceRoot = getWorkspaceRoot();
267:                    IResource existing = workspaceRoot
268:                            .findMember(destinationPath);
269:                    if (source.getType() == IResource.FOLDER
270:                            && existing != null) {
271:                        // The resource is a folder and it exists in the destination.
272:                        // Copy its children to the existing destination.
273:                        if (source.isLinked() == existing.isLinked()) {
274:                            IResource[] children = ((IContainer) source)
275:                                    .members();
276:                            ResourceDescription[] overwritten = copy(children,
277:                                    destinationPath, resourcesAtDestination,
278:                                    new SubProgressMonitor(monitor, 1), uiInfo,
279:                                    false);
280:                            // We don't record the copy since this recursive call will
281:                            // do so. Just record the overwrites.
282:                            for (int j = 0; j < overwritten.length; j++) {
283:                                overwrittenResources.add(overwritten[j]);
284:                            }
285:                        } else {
286:                            // delete the destination folder, copying a linked folder
287:                            // over an unlinked one or vice versa. Fixes bug 28772.
288:                            ResourceDescription[] deleted = delete(
289:                                    new IResource[] { existing },
290:                                    new SubProgressMonitor(monitor, 0), uiInfo,
291:                                    false);
292:                            source.copy(destinationPath, IResource.SHALLOW,
293:                                    new SubProgressMonitor(monitor, 1));
294:                            // Record the copy
295:                            resourcesAtDestination.add(getWorkspace().getRoot()
296:                                    .findMember(destinationPath));
297:                            for (int j = 0; j < deleted.length; j++) {
298:                                overwrittenResources.add(deleted[j]);
299:                            }
300:                        }
301:                    } else {
302:                        if (existing != null) {
303:                            if (source.isLinked() == existing.isLinked()) {
304:                                overwrittenResources
305:                                        .add(copyOverExistingResource(source,
306:                                                existing,
307:                                                new SubProgressMonitor(monitor,
308:                                                        1), uiInfo, false));
309:                                // Record the "copy"
310:                                resourcesAtDestination.add(existing);
311:                            } else {
312:                                // Copying a linked resource over unlinked or vice
313:                                // versa. Can't use setContents here. Fixes bug 28772.
314:                                ResourceDescription[] deleted = delete(
315:                                        new IResource[] { existing },
316:                                        new SubProgressMonitor(monitor, 0),
317:                                        uiInfo, false);
318:                                source.copy(destinationPath, IResource.SHALLOW,
319:                                        new SubProgressMonitor(monitor, 1));
320:                                // Record the copy
321:                                resourcesAtDestination.add(getWorkspace()
322:                                        .getRoot().findMember(destinationPath));
323:                                for (int j = 0; j < deleted.length; j++) {
324:                                    overwrittenResources.add(deleted[j]);
325:                                }
326:                            }
327:                        } else {
328:                            // no resources are being overwritten
329:                            // ensure the destination path exists
330:                            IPath parentPath = destination;
331:                            if (pathIncludesName) {
332:                                parentPath = destination.removeLastSegments(1);
333:                            }
334:                            IContainer generatedParent = generateContainers(parentPath);
335:                            source.copy(destinationPath, IResource.SHALLOW,
336:                                    new SubProgressMonitor(monitor, 1));
337:                            // Record the copy. If we had to generate a parent
338:                            // folder, that should be recorded as part of the copy
339:                            if (generatedParent == null) {
340:                                resourcesAtDestination.add(getWorkspace()
341:                                        .getRoot().findMember(destinationPath));
342:                            } else {
343:                                resourcesAtDestination.add(generatedParent);
344:                            }
345:                        }
346:
347:                        if (monitor.isCanceled()) {
348:                            throw new OperationCanceledException();
349:                        }
350:                    }
351:                }
352:                monitor.done();
353:                return (ResourceDescription[]) overwrittenResources
354:                        .toArray(new ResourceDescription[overwrittenResources
355:                                .size()]);
356:
357:            }
358:
359:            /**
360:             * Moves the resources to the given destination. This method can be called
361:             * recursively to merge folders during folder move.
362:             * 
363:             * @param resources
364:             *            the resources to be moved
365:             * @param destination
366:             *            the destination path for the resources, relative to the
367:             *            workspace
368:             * @param resourcesAtDestination
369:             *            A list used to record each moved resource.
370:             * @param reverseDestinations
371:             *            A list used to record each moved resource's original location
372:             * @param monitor
373:             *            the progress monitor used to show progress
374:             * @param uiInfo
375:             *            the IAdaptable (or <code>null</code>) provided by the
376:             *            caller in order to supply UI information for prompting the
377:             *            user if necessary. When this parameter is not
378:             *            <code>null</code>, it contains an adapter for the
379:             *            org.eclipse.swt.widgets.Shell.class
380:             * @param pathIncludesName
381:             *            a boolean that indicates whether the specified path includes
382:             *            the resource's name at the destination. If this value is
383:             *            <code>true</code>, the destination will contain the desired
384:             *            name of the resource (usually only desired when only one
385:             *            resource is being moved). If this value is <code>false</code>,
386:             *            each resource's name will be appended to the destination.
387:             * @return an array of ResourceDescriptions describing any resources that
388:             *         were overwritten by the move operation
389:             * @throws CoreException
390:             *             propagates any CoreExceptions thrown from the resources API
391:             */
392:            static ResourceDescription[] move(IResource[] resources,
393:                    IPath destination, List resourcesAtDestination,
394:                    List reverseDestinations, IProgressMonitor monitor,
395:                    IAdaptable uiInfo, boolean pathIncludesName)
396:                    throws CoreException {
397:
398:                monitor.beginTask("", resources.length); //$NON-NLS-1$
399:                monitor
400:                        .setTaskName(UndoMessages.AbstractResourcesOperation_MovingResources);
401:                List overwrittenResources = new ArrayList();
402:                for (int i = 0; i < resources.length; i++) {
403:                    IResource source = resources[i];
404:                    IPath destinationPath;
405:                    if (pathIncludesName) {
406:                        destinationPath = destination;
407:                    } else {
408:                        destinationPath = destination.append(source.getName());
409:                    }
410:                    IWorkspaceRoot workspaceRoot = getWorkspaceRoot();
411:                    IResource existing = workspaceRoot
412:                            .findMember(destinationPath);
413:                    if (source.getType() == IResource.FOLDER
414:                            && existing != null) {
415:                        // The resource is a folder and it exists in the destination.
416:                        // Move its children to the existing destination.
417:                        if (source.isLinked() == existing.isLinked()) {
418:                            IResource[] children = ((IContainer) source)
419:                                    .members();
420:                            ResourceDescription[] overwritten = move(children,
421:                                    destinationPath, resourcesAtDestination,
422:                                    reverseDestinations,
423:                                    new SubProgressMonitor(monitor, 1), uiInfo,
424:                                    false);
425:                            // We don't record the moved resources since the recursive
426:                            // call has done so. Just record the overwrites.
427:                            for (int j = 0; j < overwritten.length; j++) {
428:                                overwrittenResources.add(overwritten[j]);
429:                            }
430:                            // Delete the source. No need to record it since it
431:                            // will get moved back.
432:                            delete(source, monitor, uiInfo, false, false);
433:                        } else {
434:                            // delete the destination folder, moving a linked folder
435:                            // over an unlinked one or vice versa. Fixes bug 28772.
436:                            ResourceDescription[] deleted = delete(
437:                                    new IResource[] { existing },
438:                                    new SubProgressMonitor(monitor, 0), uiInfo,
439:                                    false);
440:                            // Record the original path
441:                            reverseDestinations.add(source.getFullPath());
442:                            source.move(destinationPath, IResource.SHALLOW
443:                                    | IResource.KEEP_HISTORY,
444:                                    new SubProgressMonitor(monitor, 1));
445:                            // Record the resource at its destination
446:                            resourcesAtDestination.add(getWorkspace().getRoot()
447:                                    .findMember(destinationPath));
448:                            for (int j = 0; j < deleted.length; j++) {
449:                                overwrittenResources.add(deleted[j]);
450:                            }
451:                        }
452:                    } else {
453:                        if (existing != null) {
454:                            if (source.isLinked() == existing.isLinked()) {
455:                                // Record the original path
456:                                reverseDestinations.add(source.getFullPath());
457:                                overwrittenResources
458:                                        .add(copyOverExistingResource(source,
459:                                                existing,
460:                                                new SubProgressMonitor(monitor,
461:                                                        1), uiInfo, true));
462:                                resourcesAtDestination.add(existing);
463:                            } else {
464:                                // Moving a linked resource over unlinked or vice
465:                                // versa. Can't use setContents here. Fixes bug 28772.
466:                                ResourceDescription[] deleted = delete(
467:                                        new IResource[] { existing },
468:                                        new SubProgressMonitor(monitor, 0),
469:                                        uiInfo, false);
470:                                reverseDestinations.add(source.getFullPath());
471:                                source.move(destinationPath, IResource.SHALLOW
472:                                        | IResource.KEEP_HISTORY,
473:                                        new SubProgressMonitor(monitor, 1));
474:                                // Record the resource at its destination
475:                                resourcesAtDestination.add(getWorkspace()
476:                                        .getRoot().findMember(destinationPath));
477:                                for (int j = 0; j < deleted.length; j++) {
478:                                    overwrittenResources.add(deleted[j]);
479:                                }
480:                            }
481:                        } else {
482:                            // No resources are being overwritten.
483:                            // First record the source path
484:                            reverseDestinations.add(source.getFullPath());
485:                            // ensure the destination path exists
486:                            IPath parentPath = destination;
487:                            if (pathIncludesName) {
488:                                parentPath = destination.removeLastSegments(1);
489:                            }
490:
491:                            IContainer generatedParent = generateContainers(parentPath);
492:                            source.move(destinationPath, IResource.SHALLOW
493:                                    | IResource.KEEP_HISTORY,
494:                                    new SubProgressMonitor(monitor, 1));
495:                            // Record the move. If we had to generate a parent
496:                            // folder, that should be recorded as part of the copy
497:                            if (generatedParent == null) {
498:                                resourcesAtDestination.add(getWorkspace()
499:                                        .getRoot().findMember(destinationPath));
500:                            } else {
501:                                resourcesAtDestination.add(generatedParent);
502:                            }
503:                        }
504:
505:                        if (monitor.isCanceled()) {
506:                            throw new OperationCanceledException();
507:                        }
508:                    }
509:                }
510:                monitor.done();
511:                return (ResourceDescription[]) overwrittenResources
512:                        .toArray(new ResourceDescription[overwrittenResources
513:                                .size()]);
514:
515:            }
516:
517:            /**
518:             * Recreate the resources from the specified resource descriptions.
519:             * 
520:             * @param resourcesToRecreate
521:             *            the ResourceDescriptions describing resources to be recreated
522:             * @param monitor
523:             *            the progress monitor used to show progress
524:             * @param uiInfo
525:             *            the IAdaptable (or <code>null</code>) provided by the
526:             *            caller in order to supply UI information for prompting the
527:             *            user if necessary. When this parameter is not
528:             *            <code>null</code>, it contains an adapter for the
529:             *            org.eclipse.swt.widgets.Shell.class
530:             * @return an array of resources that were created
531:             * @throws CoreException
532:             *             propagates any CoreExceptions thrown from the resources API
533:             */
534:            static IResource[] recreate(
535:                    ResourceDescription[] resourcesToRecreate,
536:                    IProgressMonitor monitor, IAdaptable uiInfo)
537:                    throws CoreException {
538:                final List exceptions = new ArrayList();
539:                IResource[] resourcesToReturn = new IResource[resourcesToRecreate.length];
540:                monitor.beginTask("", resourcesToRecreate.length); //$NON-NLS-1$
541:                monitor
542:                        .setTaskName(UndoMessages.AbstractResourcesOperation_CreateResourcesProgress);
543:                try {
544:                    for (int i = 0; i < resourcesToRecreate.length; ++i) {
545:                        if (monitor.isCanceled()) {
546:                            throw new OperationCanceledException();
547:                        }
548:                        try {
549:                            resourcesToReturn[i] = resourcesToRecreate[i]
550:                                    .createResource(new SubProgressMonitor(
551:                                            monitor, 1));
552:                        } catch (CoreException e) {
553:                            exceptions.add(e);
554:                        }
555:                    }
556:                    IStatus result = WorkspaceUndoUtil.createResult(exceptions);
557:                    if (!result.isOK()) {
558:                        throw new CoreException(result);
559:                    }
560:                } finally {
561:                    monitor.done();
562:                }
563:                return resourcesToReturn;
564:            }
565:
566:            /**
567:             * Delete the specified resources, returning a resource description that can
568:             * be used to restore it.
569:             * 
570:             * @param resourceToDelete
571:             *            the resource to be deleted
572:             * @param monitor
573:             *            the progress monitor to use to show the operation's progress
574:             * @param uiInfo
575:             *            the IAdaptable (or <code>null</code>) provided by the
576:             *            caller in order to supply UI information for prompting the
577:             *            user if necessary. When this parameter is not
578:             *            <code>null</code>, it contains an adapter for the
579:             *            org.eclipse.swt.widgets.Shell.class
580:             * @param forceOutOfSyncDelete
581:             *            a boolean indicating whether a resource should be deleted even
582:             *            if it is out of sync with the file system
583:             * @param deleteContent
584:             *            a boolean indicating whether project content should be deleted
585:             *            when a project resource is to be deleted
586:             * @return a ResourceDescription that can be used to restore the deleted
587:             *         resource.
588:             * @throws CoreException
589:             *             propagates any CoreExceptions thrown from the resources API
590:             */
591:            static ResourceDescription delete(IResource resourceToDelete,
592:                    IProgressMonitor monitor, IAdaptable uiInfo,
593:                    boolean forceOutOfSyncDelete, boolean deleteContent)
594:                    throws CoreException {
595:                ResourceDescription resourceDescription = ResourceDescription
596:                        .fromResource(resourceToDelete);
597:                if (resourceToDelete.getType() == IResource.PROJECT) {
598:                    // it is a project
599:                    monitor
600:                            .setTaskName(UndoMessages.AbstractResourcesOperation_DeleteResourcesProgress);
601:                    IProject project = (IProject) resourceToDelete;
602:                    project
603:                            .delete(deleteContent, forceOutOfSyncDelete,
604:                                    monitor);
605:                } else {
606:                    // if it's not a project, just delete it
607:                    monitor.beginTask("", 2); //$NON-NLS-1$
608:                    monitor
609:                            .setTaskName(UndoMessages.AbstractResourcesOperation_DeleteResourcesProgress);
610:                    int updateFlags;
611:                    if (forceOutOfSyncDelete) {
612:                        updateFlags = IResource.KEEP_HISTORY | IResource.FORCE;
613:                    } else {
614:                        updateFlags = IResource.KEEP_HISTORY;
615:                    }
616:                    resourceToDelete.delete(updateFlags,
617:                            new SubProgressMonitor(monitor, 1));
618:                    resourceDescription.recordStateFromHistory(
619:                            resourceToDelete,
620:                            new SubProgressMonitor(monitor, 1));
621:                    monitor.done();
622:                }
623:
624:                return resourceDescription;
625:            }
626:
627:            /*
628:             * Copy the content of the specified resource to the existing resource,
629:             * returning a ResourceDescription that can be used to restore the original
630:             * content. Do nothing if the resources are not files.
631:             */
632:            private static ResourceDescription copyOverExistingResource(
633:                    IResource source, IResource existing,
634:                    IProgressMonitor monitor, IAdaptable uiInfo,
635:                    boolean deleteSourceFile) throws CoreException {
636:                if (!(source instanceof  IFile && existing instanceof  IFile)) {
637:                    return null;
638:                }
639:                IFile file = (IFile) source;
640:                IFile existingFile = (IFile) existing;
641:                monitor
642:                        .beginTask(
643:                                UndoMessages.AbstractResourcesOperation_CopyingResourcesProgress,
644:                                3);
645:                if (file != null && existingFile != null) {
646:                    if (validateEdit(file, existingFile, getShell(uiInfo))) {
647:                        // Remember the state of the existing file so it can be
648:                        // restored.
649:                        FileDescription fileDescription = new FileDescription(
650:                                existingFile);
651:                        // Reset the contents to that of the file being moved
652:                        existingFile.setContents(file.getContents(),
653:                                IResource.KEEP_HISTORY, new SubProgressMonitor(
654:                                        monitor, 1));
655:                        fileDescription.recordStateFromHistory(existingFile,
656:                                new SubProgressMonitor(monitor, 1));
657:                        // Now delete the source file if requested
658:                        // We don't need to remember anything about it, because
659:                        // any undo involving this operation will move the original
660:                        // content back to it.
661:                        if (deleteSourceFile) {
662:                            file.delete(IResource.KEEP_HISTORY,
663:                                    new SubProgressMonitor(monitor, 1));
664:                        }
665:                        monitor.done();
666:                        return fileDescription;
667:                    }
668:                }
669:                monitor.done();
670:                return null;
671:            }
672:
673:            /*
674:             * Check for existence of the specified path and generate any containers
675:             * that do not yet exist. Return any generated containers, or null if no
676:             * container had to be generated.
677:             */
678:            private static IContainer generateContainers(IPath path)
679:                    throws CoreException {
680:                IResource container;
681:                if (path.segmentCount() == 0) {
682:                    // nothing to generate
683:                    return null;
684:                }
685:                container = getWorkspaceRoot().findMember(path);
686:                // Nothing to generate because container exists
687:                if (container != null) {
688:                    return null;
689:                }
690:
691:                // Now make a non-existent handle representing the desired container
692:                if (path.segmentCount() == 1) {
693:                    container = ResourcesPlugin.getWorkspace().getRoot()
694:                            .getProject(path.segment(0));
695:                } else {
696:                    container = ResourcesPlugin.getWorkspace().getRoot()
697:                            .getFolder(path);
698:                }
699:                ContainerDescription containerDescription = ContainerDescription
700:                        .fromContainer((IContainer) container);
701:                container = containerDescription.createResourceHandle();
702:                containerDescription.createExistentResourceFromHandle(
703:                        container, new NullProgressMonitor());
704:                return (IContainer) container;
705:            }
706:
707:            /*
708:             * Ask the user whether the given resource should be deleted despite being
709:             * out of sync with the file system.
710:             * 
711:             * Return one of the IDialogConstants constants indicating which of the Yes,
712:             * Yes to All, No, Cancel options has been selected by the user.
713:             */
714:            private static int queryDeleteOutOfSync(IResource resource,
715:                    IAdaptable uiInfo) {
716:                Shell shell = getShell(uiInfo);
717:                final MessageDialog dialog = new MessageDialog(
718:                        shell,
719:                        UndoMessages.AbstractResourcesOperation_deletionMessageTitle,
720:                        null,
721:                        NLS
722:                                .bind(
723:                                        UndoMessages.AbstractResourcesOperation_outOfSyncQuestion,
724:                                        resource.getName()),
725:                        MessageDialog.QUESTION, new String[] {
726:                                IDialogConstants.YES_LABEL,
727:                                IDialogConstants.YES_TO_ALL_LABEL,
728:                                IDialogConstants.NO_LABEL,
729:                                IDialogConstants.CANCEL_LABEL }, 0);
730:                shell.getDisplay().syncExec(new Runnable() {
731:                    public void run() {
732:                        dialog.open();
733:                    }
734:                });
735:                int result = dialog.getReturnCode();
736:                if (result == 0) {
737:                    return IDialogConstants.YES_ID;
738:                }
739:                if (result == 1) {
740:                    return IDialogConstants.YES_TO_ALL_ID;
741:                }
742:                if (result == 2) {
743:                    return IDialogConstants.NO_ID;
744:                }
745:                return IDialogConstants.CANCEL_ID;
746:            }
747:
748:            /*
749:             * Creates and return a result status appropriate for the given list of
750:             * exceptions.
751:             */
752:            private static IStatus createResult(List exceptions) {
753:                if (exceptions.isEmpty()) {
754:                    return Status.OK_STATUS;
755:                }
756:                final int exceptionCount = exceptions.size();
757:                if (exceptionCount == 1) {
758:                    return ((CoreException) exceptions.get(0)).getStatus();
759:                }
760:                CoreException[] children = (CoreException[]) exceptions
761:                        .toArray(new CoreException[exceptionCount]);
762:                boolean outOfSync = false;
763:                for (int i = 0; i < children.length; i++) {
764:                    if (children[i].getStatus().getCode() == IResourceStatus.OUT_OF_SYNC_LOCAL) {
765:                        outOfSync = true;
766:                        break;
767:                    }
768:                }
769:                String title = outOfSync ? UndoMessages.AbstractResourcesOperation_outOfSyncError
770:                        : UndoMessages.AbstractResourcesOperation_deletionExceptionMessage;
771:                final MultiStatus multi = new MultiStatus(
772:                        IDEWorkbenchPlugin.IDE_WORKBENCH, 0, title, null);
773:                for (int i = 0; i < exceptionCount; i++) {
774:                    CoreException exception = children[i];
775:                    IStatus status = exception.getStatus();
776:                    multi.add(new Status(status.getSeverity(), status
777:                            .getPlugin(), status.getCode(),
778:                            status.getMessage(), exception));
779:                }
780:                return multi;
781:            }
782:
783:            /*
784:             * Return the workspace.
785:             */
786:            private static IWorkspace getWorkspace() {
787:                return ResourcesPlugin.getWorkspace();
788:            }
789:
790:            /*
791:             * Return the workspace root.
792:             */
793:            private static IWorkspaceRoot getWorkspaceRoot() {
794:                return getWorkspace().getRoot();
795:            }
796:
797:            /*
798:             * Validate the destination file if it is read-only and additionally the
799:             * source file if both are read-only. Returns true if both files could be
800:             * made writeable.
801:             */
802:            private static boolean validateEdit(IFile source,
803:                    IFile destination, Shell shell) {
804:                if (destination.isReadOnly()) {
805:                    IWorkspace workspace = WorkspaceUndoUtil.getWorkspace();
806:                    IStatus status;
807:                    if (source.isReadOnly()) {
808:                        status = workspace.validateEdit(new IFile[] { source,
809:                                destination }, shell);
810:                    } else {
811:                        status = workspace.validateEdit(
812:                                new IFile[] { destination }, shell);
813:                    }
814:                    return status.isOK();
815:                }
816:                return true;
817:            }
818:
819:            /**
820:             * Return the shell described by the specified adaptable, or the active
821:             * shell if no shell has been specified in the adaptable.
822:             * 
823:             * @param uiInfo
824:             *            the IAdaptable (or <code>null</code>) provided by the
825:             *            caller in order to supply UI information for prompting the
826:             *            user if necessary. When this parameter is not
827:             *            <code>null</code>, it contains an adapter for the
828:             *            org.eclipse.swt.widgets.Shell.class
829:             * 
830:             * @return the Shell that can be used to show information
831:             */
832:            public static Shell getShell(IAdaptable uiInfo) {
833:                if (uiInfo != null) {
834:                    Shell shell = (Shell) uiInfo.getAdapter(Shell.class);
835:                    if (shell != null) {
836:                        return shell;
837:                    }
838:                }
839:                return PlatformUI.getWorkbench().getActiveWorkbenchWindow()
840:                        .getShell();
841:            }
842:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.