1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpeclipse.obfuscator.export;
14 import java.io.IOException;
15 import java.util.ArrayList;
16 import java.util.HashMap;
17 import java.util.Iterator;
18 import java.util.List;
20 import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
21 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
22 import net.sourceforge.phpeclipse.obfuscator.ObfuscatorIgnores;
23 import net.sourceforge.phpeclipse.obfuscator.ObfuscatorPass1Exporter;
24 import net.sourceforge.phpeclipse.obfuscator.ObfuscatorPass2Exporter;
25 import net.sourceforge.phpeclipse.ui.WebUI;
27 import org.eclipse.core.resources.IContainer;
28 import org.eclipse.core.resources.IFile;
29 import org.eclipse.core.resources.IProject;
30 import org.eclipse.core.resources.IResource;
31 import org.eclipse.core.runtime.CoreException;
32 import org.eclipse.core.runtime.IPath;
33 import org.eclipse.core.runtime.IProgressMonitor;
34 import org.eclipse.core.runtime.IStatus;
35 import org.eclipse.core.runtime.MultiStatus;
36 import org.eclipse.core.runtime.Path;
37 import org.eclipse.core.runtime.Status;
38 import org.eclipse.jface.operation.IRunnableWithProgress;
39 import org.eclipse.jface.operation.ModalContext;
40 import org.eclipse.jface.preference.IPreferenceStore;
41 import org.eclipse.ui.PlatformUI;
42 import org.eclipse.ui.dialogs.IOverwriteQuery;
45 * Operation for exporting the contents of a resource to the local file system.
48 class ObfuscatorExportOperation implements IRunnableWithProgress {
51 private IProgressMonitor fMonitor;
53 private ObfuscatorPass1Exporter fExporter1 = null;
55 private ObfuscatorPass2Exporter fExporter2 = null;
57 private HashMap fCurrentIdentifierMap = null;
59 private HashMap fProjectMap = null;
61 private String fCurrentProjectName = "";
63 private List fResourcesToExport;
65 private IOverwriteQuery fOverwriteCallback;
67 private IResource fResource;
69 private List errorTable = new ArrayList(1);
71 // The constants for the overwrite 3 state
72 private static final int OVERWRITE_NOT_SET = 0;
74 private static final int OVERWRITE_NONE = 1;
76 private static final int OVERWRITE_ALL = 2;
78 private int overwriteState = OVERWRITE_NOT_SET;
80 // private boolean createLeadupStructure = true;
81 private boolean createContainerDirectories = true;
84 * Create an instance of this class. Use this constructor if you wish to
85 * export specific resources without a common parent resource
87 // public ObfuscatorExportOperation(List resources, String destinationPath,
88 // IOverwriteQuery overwriteImplementor) {
91 // exporter1 = new ObfuscatorPass1Exporter(new Scanner(false, false),
93 // exporter2 = new ObfuscatorPass2Exporter(new Scanner(true, true),
95 // identifierMap = null;
97 // // Eliminate redundancies in list of resources being exported
98 // Iterator elementsEnum = resources.iterator();
99 // while (elementsEnum.hasNext()) {
100 // IResource currentResource = (IResource) elementsEnum.next();
101 // if (isDescendent(resources, currentResource))
102 // elementsEnum.remove(); //Remove currentResource
105 // resourcesToExport = resources;
106 // path = new Path(destinationPath);
107 // overwriteCallback = overwriteImplementor;
110 * Create an instance of this class. Use this constructor if you wish to
111 * recursively export a single resource
113 public ObfuscatorExportOperation(IResource res, String destinationPath,
114 IOverwriteQuery overwriteImplementor) {
118 fPath = new Path(destinationPath);
119 fOverwriteCallback = overwriteImplementor;
123 * Create an instance of this class. Use this constructor if you wish to
124 * export specific resources with a common parent resource (affects
125 * container directory creation)
127 public ObfuscatorExportOperation(IResource res, List resources,
128 String destinationPath, IOverwriteQuery overwriteImplementor) {
129 this(res, destinationPath, overwriteImplementor);
130 fResourcesToExport = resources;
134 * Add a new entry to the error table with the passed information
136 protected void addError(String message, Throwable e) {
137 errorTable.add(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 0,
142 * Answer the total number of file resources that exist at or below self in
143 * the resources hierarchy.
147 * org.eclipse.core.resources.IResource
149 protected int countChildrenOf(IResource resource) throws CoreException {
150 if (resource.getType() == IResource.FILE)
154 if (resource.isAccessible()) {
155 IResource[] children = ((IContainer) resource).members();
156 for (int i = 0; i < children.length; i++)
157 count += countChildrenOf(children[i]);
164 * Answer a boolean indicating the number of file resources that were
165 * specified for export
169 protected int countSelectedResources() throws CoreException {
171 Iterator resources = fResourcesToExport.iterator();
173 while (resources.hasNext())
174 result += countChildrenOf((IResource) resources.next());
180 * Create the directories required for exporting the passed resource, based
181 * upon its container hierarchy
184 * org.eclipse.core.resources.IResource
186 protected void createLeadupDirectoriesFor(IResource resource) {
187 IPath resourcePath = resource.getFullPath().removeLastSegments(1);
189 for (int i = 0; i < resourcePath.segmentCount(); i++) {
190 fPath = fPath.append(resourcePath.segment(i));
191 fExporter2.createFolder(fPath);
196 * Recursively export the previously-specified resource
198 protected void exportAllResources1() throws InterruptedException {
199 if (fResource.getType() == IResource.FILE) {
200 exportFile1((IFile) fResource, fPath);
203 setExporters(fResource);
204 exportChildren1(((IContainer) fResource).members(), fPath);
205 } catch (CoreException e) {
206 // not safe to show a dialog
207 // should never happen because the file system export wizard
209 // single resource chosen for export is both existent and
217 * Recursively export the previously-specified resource
219 protected void exportAllResources2() throws InterruptedException {
220 if (fResource.getType() == IResource.FILE) {
221 exportFile2((IFile) fResource, fPath);
224 setExporters(fResource);
225 exportChildren2(((IContainer) fResource).members(), fPath);
226 } catch (CoreException e) {
227 // not safe to show a dialog
228 // should never happen because the file system export wizard
230 // single resource chosen for export is both existent and
238 * Export all of the resources contained in the passed collection
241 * java.util.Enumeration
245 protected void exportChildren1(IResource[] children, IPath currentPath)
246 throws InterruptedException {
247 for (int i = 0; i < children.length; i++) {
248 IResource child = children[i];
249 if (!child.isAccessible())
252 if (child.getType() == IResource.FILE)
253 exportFile1((IFile) child, currentPath);
255 IPath destination = currentPath.append(child.getName());
256 fExporter1.createFolder(destination);
258 exportChildren1(((IContainer) child).members(), destination);
259 } catch (CoreException e) {
260 // not safe to show a dialog
261 // should never happen because:
262 // i. this method is called recursively iterating over the
263 // result of #members,
264 // which only answers existing children
265 // ii. there is an #isAccessible check done before #members
267 errorTable.add(e.getStatus());
274 * Export all of the resources contained in the passed collection
277 * java.util.Enumeration
281 protected void exportChildren2(IResource[] children, IPath currentPath)
282 throws InterruptedException {
283 for (int i = 0; i < children.length; i++) {
284 IResource child = children[i];
285 if (!child.isAccessible())
288 if (child.getType() == IResource.FILE)
289 exportFile2((IFile) child, currentPath);
291 IPath destination = currentPath.append(child.getName());
292 fExporter2.createFolder(destination);
294 exportChildren2(((IContainer) child).members(), destination);
295 } catch (CoreException e) {
296 // not safe to show a dialog
297 // should never happen because:
298 // i. this method is called recursively iterating over the
299 // result of #members,
300 // which only answers existing children
301 // ii. there is an #isAccessible check done before #members
303 errorTable.add(e.getStatus());
309 protected void exportFile1(IFile file, IPath location)
310 throws InterruptedException {
311 IPath fullPath = location.append(file.getName());
312 fMonitor.subTask(file.getFullPath().toString());
313 String properPathString = fullPath.toOSString();
314 File targetFile = new File(properPathString);
316 // if (targetFile.exists()) {
317 // if (!targetFile.canWrite()) {
318 // errorTable.add(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 0,
319 // ObfuscatorExportMessages.format("ObfuscatorTransfer.cannotOverwrite",
321 // new Object[] { targetFile.getAbsolutePath()}), null));
322 // monitor.worked(1);
326 // if (overwriteState == OVERWRITE_NONE)
329 // if (overwriteState != OVERWRITE_ALL) {
330 // String overwriteAnswer =
331 // overwriteCallback.queryOverwrite(properPathString);
333 // if (overwriteAnswer.equals(IOverwriteQuery.CANCEL))
334 // throw new InterruptedException();
336 // if (overwriteAnswer.equals(IOverwriteQuery.NO)) {
337 // monitor.worked(1);
341 // if (overwriteAnswer.equals(IOverwriteQuery.NO_ALL)) {
342 // monitor.worked(1);
343 // overwriteState = OVERWRITE_NONE;
347 // if (overwriteAnswer.equals(IOverwriteQuery.ALL))
348 // overwriteState = OVERWRITE_ALL;
354 fExporter1.write(file, fullPath);
355 } catch (IOException e) {
356 errorTable.add(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 0,
357 ObfuscatorExportMessages.format(
358 "ObfuscatorTransfer.errorExporting", //$NON-NLS-1$
359 new Object[] { fullPath, e.getMessage() }), e));
360 } catch (CoreException e) {
361 errorTable.add(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 0,
362 ObfuscatorExportMessages.format(
363 "ObfuscatorTransfer.errorExporting", //$NON-NLS-1$
364 new Object[] { fullPath, e.getMessage() }), e));
368 ModalContext.checkCanceled(fMonitor);
372 * Export the passed file to the specified location
375 * org.eclipse.core.resources.IFile
377 * org.eclipse.core.runtime.IPath
379 protected void exportFile2(IFile file, IPath location)
380 throws InterruptedException {
381 IPath fullPath = location.append(file.getName());
382 fMonitor.subTask(file.getFullPath().toString());
383 String properPathString = fullPath.toOSString();
384 File targetFile = new File(properPathString);
386 if (targetFile.exists()) {
387 if (!targetFile.canWrite()) {
388 errorTable.add(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID,
389 0, ObfuscatorExportMessages.format(
390 "ObfuscatorTransfer.cannotOverwrite", //$NON-NLS-1$
391 new Object[] { targetFile.getAbsolutePath() }),
397 if (overwriteState == OVERWRITE_NONE)
400 if (overwriteState != OVERWRITE_ALL) {
401 String overwriteAnswer = fOverwriteCallback
402 .queryOverwrite(properPathString);
404 if (overwriteAnswer.equals(IOverwriteQuery.CANCEL))
405 throw new InterruptedException();
407 if (overwriteAnswer.equals(IOverwriteQuery.NO)) {
412 if (overwriteAnswer.equals(IOverwriteQuery.NO_ALL)) {
414 overwriteState = OVERWRITE_NONE;
418 if (overwriteAnswer.equals(IOverwriteQuery.ALL))
419 overwriteState = OVERWRITE_ALL;
425 fExporter2.write(file, fullPath);
426 } catch (IOException e) {
427 errorTable.add(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 0,
428 ObfuscatorExportMessages.format(
429 "ObfuscatorTransfer.errorExporting", //$NON-NLS-1$
430 new Object[] { fullPath, e.getMessage() }), e));
431 } catch (CoreException e) {
432 errorTable.add(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 0,
433 ObfuscatorExportMessages.format(
434 "ObfuscatorTransfer.errorExporting", //$NON-NLS-1$
435 new Object[] { fullPath, e.getMessage() }), e));
439 ModalContext.checkCanceled(fMonitor);
442 protected void exportSpecifiedResources1() throws InterruptedException {
443 Iterator resources = fResourcesToExport.iterator();
444 IPath initPath = (IPath) fPath.clone();
446 while (resources.hasNext()) {
447 IResource currentResource = (IResource) resources.next();
448 if (!currentResource.isAccessible())
450 setExporters(currentResource);
453 if (fResource == null) {
454 // No root resource specified and creation of containment
456 // is required. Create containers from depth 2 onwards (ie.-
458 // child inclusive) for each resource being exported.
459 // if (createLeadupStructure)
460 // createLeadupDirectoriesFor(currentResource);
463 // Root resource specified. Must create containment directories
464 // from this point onwards for each resource being exported
465 IPath containersToCreate = currentResource.getFullPath()
466 .removeFirstSegments(
467 fResource.getFullPath().segmentCount())
468 .removeLastSegments(1);
470 for (int i = 0; i < containersToCreate.segmentCount(); i++) {
471 fPath = fPath.append(containersToCreate.segment(i));
472 fExporter1.createFolder(fPath);
476 if (currentResource.getType() == IResource.FILE)
477 exportFile1((IFile) currentResource, fPath);
479 if (createContainerDirectories) {
480 fPath = fPath.append(currentResource.getName());
481 fExporter1.createFolder(fPath);
485 exportChildren1(((IContainer) currentResource).members(),
487 } catch (CoreException e) {
488 // should never happen because #isAccessible is called
489 // before #members is invoked,
490 // which implicitly does an existence check
491 errorTable.add(e.getStatus());
498 * Export the resources contained in the previously-defined
499 * resourcesToExport collection
501 protected void exportSpecifiedResources2() throws InterruptedException {
502 Iterator resources = fResourcesToExport.iterator();
503 IPath initPath = (IPath) fPath.clone();
505 while (resources.hasNext()) {
506 IResource currentResource = (IResource) resources.next();
507 if (!currentResource.isAccessible())
509 setExporters(currentResource);
513 if (fResource == null) {
514 // No root resource specified and creation of containment
516 // is required. Create containers from depth 2 onwards (ie.-
518 // child inclusive) for each resource being exported.
519 // if (createLeadupStructure)
520 // createLeadupDirectoriesFor(currentResource);
523 // Root resource specified. Must create containment directories
524 // from this point onwards for each resource being exported
525 IPath containersToCreate = currentResource.getFullPath()
526 .removeFirstSegments(
527 fResource.getFullPath().segmentCount())
528 .removeLastSegments(1);
530 for (int i = 0; i < containersToCreate.segmentCount(); i++) {
531 fPath = fPath.append(containersToCreate.segment(i));
532 fExporter2.createFolder(fPath);
536 if (currentResource.getType() == IResource.FILE)
537 exportFile2((IFile) currentResource, fPath);
539 if (createContainerDirectories) {
540 fPath = fPath.append(currentResource.getName());
541 fExporter2.createFolder(fPath);
545 exportChildren2(((IContainer) currentResource).members(),
547 } catch (CoreException e) {
548 // should never happen because #isAccessible is called
549 // before #members is invoked,
550 // which implicitly does an existence check
551 errorTable.add(e.getStatus());
558 * Returns the status of the export operation. If there were any errors, the
559 * result is a status object containing individual status objects for each
560 * error. If there were no errors, the result is a status object with error
561 * code <code>OK</code>.
565 public IStatus getStatus() {
566 IStatus[] errors = new IStatus[errorTable.size()];
567 errorTable.toArray(errors);
568 return new MultiStatus(
569 PlatformUI.PLUGIN_ID,
572 ObfuscatorExportMessages
573 .getString("ObfuscatorExportOperation.problemsExporting"), //$NON-NLS-1$
578 * Answer a boolean indicating whether the passed child is a descendent of
579 * one or more members of the passed resources collection
585 * org.eclipse.core.resources.IResource
587 protected boolean isDescendent(List resources, IResource child) {
588 if (child.getType() == IResource.PROJECT)
591 IResource parent = child.getParent();
592 if (resources.contains(parent))
595 return isDescendent(resources, parent);
598 private void setExporters(IResource resource) {
599 if (fCurrentIdentifierMap == null) {
600 if (fProjectMap == null) {
601 fProjectMap = new HashMap();
603 createExporters(resource);
605 IProject project = resource.getProject();
606 if (!fCurrentProjectName.equals(project.getName())) {
607 HashMap temp = (HashMap) fProjectMap.get(project.getName());
609 fCurrentProjectName = project.getName();
610 fCurrentIdentifierMap = temp;
611 fExporter1 = new ObfuscatorPass1Exporter(new Scanner(false,
612 false), fCurrentIdentifierMap);
613 fExporter2 = new ObfuscatorPass2Exporter(new Scanner(true,
614 true), fCurrentIdentifierMap);
617 createExporters(resource);
622 private void createExporters(IResource resource) {
623 IProject project = resource.getProject();
624 IPreferenceStore store = WebUI.getDefault()
625 .getPreferenceStore();
626 ObfuscatorIgnores ignore = new ObfuscatorIgnores(project);
627 fCurrentIdentifierMap = ignore.getIdentifierMap();
628 fCurrentProjectName = project.getName();
629 fProjectMap.put(fCurrentProjectName, fCurrentIdentifierMap);
630 fExporter1 = new ObfuscatorPass1Exporter(new Scanner(false, false),
631 fCurrentIdentifierMap);
632 fExporter2 = new ObfuscatorPass2Exporter(new Scanner(true, true),
633 fCurrentIdentifierMap);
637 * Export the resources that were previously specified for export (or if a
638 * single resource was specified then export it recursively)
640 public void run(IProgressMonitor monitor) throws InterruptedException {
641 this.fMonitor = monitor;
642 final IPath tempPath = (IPath) fPath.clone();
643 if (fResource != null) {
644 setExporters(fResource);
645 // if (createLeadupStructure)
646 // createLeadupDirectoriesFor(resource);
648 if (createContainerDirectories
649 && fResource.getType() != IResource.FILE) {
650 // ensure it's a container
651 fPath = fPath.append(fResource.getName());
652 fExporter2.createFolder(fPath);
657 // reset variables for this run:
658 fCurrentIdentifierMap = null;
660 fCurrentProjectName = "";
662 // count number of files
663 int totalWork = IProgressMonitor.UNKNOWN;
665 if (fResourcesToExport == null) {
666 totalWork = countChildrenOf(fResource);
668 totalWork = countSelectedResources();
670 } catch (CoreException e) {
672 errorTable.add(e.getStatus());
676 ObfuscatorExportMessages
677 .getString("ObfuscatorTransfer.exportingTitle1"), totalWork); //$NON-NLS-1$
678 if (fResourcesToExport == null) {
679 exportAllResources1();
681 exportSpecifiedResources1();
685 // if (resourcesToExport == null)
686 // totalWork = countChildrenOf(resource);
688 // totalWork = countSelectedResources();
689 // } catch (CoreException e) {
690 // // Should not happen
691 // errorTable.add(e.getStatus());
698 ObfuscatorExportMessages
699 .getString("ObfuscatorTransfer.exportingTitle2"), totalWork); //$NON-NLS-1$
700 if (fResourcesToExport == null) {
701 exportAllResources2();
703 exportSpecifiedResources2();
711 * Set this boolean indicating whether a directory should be created for
712 * Folder resources that are explicitly passed for export
717 // public void setCreateContainerDirectories(boolean value) {
718 // createContainerDirectories = value;
721 * Set this boolean indicating whether each exported resource's complete
722 * path should include containment hierarchies as dictated by its parents
727 // public void setCreateLeadupStructure(boolean value) {
728 // createLeadupStructure = value;
731 * Set this boolean indicating whether exported resources should
732 * automatically overwrite existing files when a conflict occurs. If not
738 public void setOverwriteFiles(boolean value) {
740 overwriteState = OVERWRITE_ALL;