X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/obfuscator/export/ObfuscatorExportOperation.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/obfuscator/export/ObfuscatorExportOperation.java new file mode 100644 index 0000000..f8e50dc --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/obfuscator/export/ObfuscatorExportOperation.java @@ -0,0 +1,640 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package net.sourceforge.phpeclipse.obfuscator.export; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +import net.sourceforge.phpdt.internal.compiler.parser.Scanner; +import net.sourceforge.phpeclipse.PHPeclipsePlugin; +import net.sourceforge.phpeclipse.obfuscator.ObfuscatorIgnores; +import net.sourceforge.phpeclipse.obfuscator.ObfuscatorPass1Exporter; +import net.sourceforge.phpeclipse.obfuscator.ObfuscatorPass2Exporter; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.MultiStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.operation.ModalContext; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.dialogs.IOverwriteQuery; + + +/** + * Operation for exporting the contents of a resource to the local file system. + */ +/*package*/ +class ObfuscatorExportOperation implements IRunnableWithProgress { + private IPath fPath; + private IProgressMonitor fMonitor; + private ObfuscatorPass1Exporter fExporter1 = null; + private ObfuscatorPass2Exporter fExporter2 = null; + private HashMap fCurrentIdentifierMap = null; + private HashMap fProjectMap = null; + private String fCurrentProjectName = ""; + + private List fResourcesToExport; + private IOverwriteQuery fOverwriteCallback; + private IResource fResource; + private List errorTable = new ArrayList(1); + + //The constants for the overwrite 3 state + private static final int OVERWRITE_NOT_SET = 0; + private static final int OVERWRITE_NONE = 1; + private static final int OVERWRITE_ALL = 2; + private int overwriteState = OVERWRITE_NOT_SET; + + // private boolean createLeadupStructure = true; + private boolean createContainerDirectories = true; + /** + * Create an instance of this class. Use this constructor if you wish to + * export specific resources without a common parent resource + */ + // public ObfuscatorExportOperation(List resources, String destinationPath, IOverwriteQuery overwriteImplementor) { + // super(); + // + // exporter1 = new ObfuscatorPass1Exporter(new Scanner(false, false), identifierMap); + // exporter2 = new ObfuscatorPass2Exporter(new Scanner(true, true), identifierMap); + // identifierMap = null; + // + // // Eliminate redundancies in list of resources being exported + // Iterator elementsEnum = resources.iterator(); + // while (elementsEnum.hasNext()) { + // IResource currentResource = (IResource) elementsEnum.next(); + // if (isDescendent(resources, currentResource)) + // elementsEnum.remove(); //Remove currentResource + // } + // + // resourcesToExport = resources; + // path = new Path(destinationPath); + // overwriteCallback = overwriteImplementor; + // } + /** + * Create an instance of this class. Use this constructor if you wish to + * recursively export a single resource + */ + public ObfuscatorExportOperation(IResource res, String destinationPath, IOverwriteQuery overwriteImplementor) { + super(); + + fResource = res; + fPath = new Path(destinationPath); + fOverwriteCallback = overwriteImplementor; + } + /** + * Create an instance of this class. Use this constructor if you wish to + * export specific resources with a common parent resource (affects container + * directory creation) + */ + public ObfuscatorExportOperation(IResource res, List resources, String destinationPath, IOverwriteQuery overwriteImplementor) { + this(res, destinationPath, overwriteImplementor); + fResourcesToExport = resources; + } + /** + * Add a new entry to the error table with the passed information + */ + protected void addError(String message, Throwable e) { + errorTable.add(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 0, message, e)); + } + /** + * Answer the total number of file resources that exist at or below self in the + * resources hierarchy. + * + * @return int + * @param resource org.eclipse.core.resources.IResource + */ + protected int countChildrenOf(IResource resource) throws CoreException { + if (resource.getType() == IResource.FILE) + return 1; + + int count = 0; + if (resource.isAccessible()) { + IResource[] children = ((IContainer) resource).members(); + for (int i = 0; i < children.length; i++) + count += countChildrenOf(children[i]); + } + + return count; + } + /** + * Answer a boolean indicating the number of file resources that were + * specified for export + * + * @return int + */ + protected int countSelectedResources() throws CoreException { + int result = 0; + Iterator resources = fResourcesToExport.iterator(); + + while (resources.hasNext()) + result += countChildrenOf((IResource) resources.next()); + + return result; + } + /** + * Create the directories required for exporting the passed resource, + * based upon its container hierarchy + * + * @param resource org.eclipse.core.resources.IResource + */ + protected void createLeadupDirectoriesFor(IResource resource) { + IPath resourcePath = resource.getFullPath().removeLastSegments(1); + + for (int i = 0; i < resourcePath.segmentCount(); i++) { + fPath = fPath.append(resourcePath.segment(i)); + fExporter2.createFolder(fPath); + } + } + /** + * Recursively export the previously-specified resource + */ + protected void exportAllResources1() throws InterruptedException { + if (fResource.getType() == IResource.FILE) { + exportFile1((IFile) fResource, fPath); + } else { + try { + setExporters(fResource); + exportChildren1(((IContainer) fResource).members(), fPath); + } catch (CoreException e) { + // not safe to show a dialog + // should never happen because the file system export wizard ensures that the + // single resource chosen for export is both existent and accessible + errorTable.add(e); + } + } + } + /** + * Recursively export the previously-specified resource + */ + protected void exportAllResources2() throws InterruptedException { + if (fResource.getType() == IResource.FILE) { + exportFile2((IFile) fResource, fPath); + } else { + try { + setExporters(fResource); + exportChildren2(((IContainer) fResource).members(), fPath); + } catch (CoreException e) { + // not safe to show a dialog + // should never happen because the file system export wizard ensures that the + // single resource chosen for export is both existent and accessible + errorTable.add(e); + } + } + } + /** + * Export all of the resources contained in the passed collection + * + * @param children java.util.Enumeration + * @param currentPath IPath + */ + protected void exportChildren1(IResource[] children, IPath currentPath) throws InterruptedException { + for (int i = 0; i < children.length; i++) { + IResource child = children[i]; + if (!child.isAccessible()) + continue; + + if (child.getType() == IResource.FILE) + exportFile1((IFile) child, currentPath); + else { + IPath destination = currentPath.append(child.getName()); + fExporter1.createFolder(destination); + try { + exportChildren1(((IContainer) child).members(), destination); + } catch (CoreException e) { + // not safe to show a dialog + // should never happen because: + // i. this method is called recursively iterating over the result of #members, + // which only answers existing children + // ii. there is an #isAccessible check done before #members is invoked + errorTable.add(e.getStatus()); + } + } + } + } + + /** + * Export all of the resources contained in the passed collection + * + * @param children java.util.Enumeration + * @param currentPath IPath + */ + protected void exportChildren2(IResource[] children, IPath currentPath) throws InterruptedException { + for (int i = 0; i < children.length; i++) { + IResource child = children[i]; + if (!child.isAccessible()) + continue; + + if (child.getType() == IResource.FILE) + exportFile2((IFile) child, currentPath); + else { + IPath destination = currentPath.append(child.getName()); + fExporter2.createFolder(destination); + try { + exportChildren2(((IContainer) child).members(), destination); + } catch (CoreException e) { + // not safe to show a dialog + // should never happen because: + // i. this method is called recursively iterating over the result of #members, + // which only answers existing children + // ii. there is an #isAccessible check done before #members is invoked + errorTable.add(e.getStatus()); + } + } + } + } + + protected void exportFile1(IFile file, IPath location) throws InterruptedException { + IPath fullPath = location.append(file.getName()); + fMonitor.subTask(file.getFullPath().toString()); + String properPathString = fullPath.toOSString(); + File targetFile = new File(properPathString); + + // if (targetFile.exists()) { + // if (!targetFile.canWrite()) { + // errorTable.add(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 0, ObfuscatorExportMessages.format("ObfuscatorTransfer.cannotOverwrite", //$NON-NLS-1$ + // new Object[] { targetFile.getAbsolutePath()}), null)); + // monitor.worked(1); + // return; + // } + // + // if (overwriteState == OVERWRITE_NONE) + // return; + // + // if (overwriteState != OVERWRITE_ALL) { + // String overwriteAnswer = overwriteCallback.queryOverwrite(properPathString); + // + // if (overwriteAnswer.equals(IOverwriteQuery.CANCEL)) + // throw new InterruptedException(); + // + // if (overwriteAnswer.equals(IOverwriteQuery.NO)) { + // monitor.worked(1); + // return; + // } + // + // if (overwriteAnswer.equals(IOverwriteQuery.NO_ALL)) { + // monitor.worked(1); + // overwriteState = OVERWRITE_NONE; + // return; + // } + // + // if (overwriteAnswer.equals(IOverwriteQuery.ALL)) + // overwriteState = OVERWRITE_ALL; + // } + // } + + try { + setExporters(file); + fExporter1.write(file, fullPath); + } catch (IOException e) { + errorTable.add(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 0, ObfuscatorExportMessages.format("ObfuscatorTransfer.errorExporting", //$NON-NLS-1$ + new Object[] { fullPath, e.getMessage()}), e)); + } catch (CoreException e) { + errorTable.add(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 0, ObfuscatorExportMessages.format("ObfuscatorTransfer.errorExporting", //$NON-NLS-1$ + new Object[] { fullPath, e.getMessage()}), e)); + } + + fMonitor.worked(1); + ModalContext.checkCanceled(fMonitor); + } + /** + * Export the passed file to the specified location + * + * @param file org.eclipse.core.resources.IFile + * @param location org.eclipse.core.runtime.IPath + */ + protected void exportFile2(IFile file, IPath location) throws InterruptedException { + IPath fullPath = location.append(file.getName()); + fMonitor.subTask(file.getFullPath().toString()); + String properPathString = fullPath.toOSString(); + File targetFile = new File(properPathString); + + if (targetFile.exists()) { + if (!targetFile.canWrite()) { + errorTable.add(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 0, ObfuscatorExportMessages.format("ObfuscatorTransfer.cannotOverwrite", //$NON-NLS-1$ + new Object[] { targetFile.getAbsolutePath()}), null)); + fMonitor.worked(1); + return; + } + + if (overwriteState == OVERWRITE_NONE) + return; + + if (overwriteState != OVERWRITE_ALL) { + String overwriteAnswer = fOverwriteCallback.queryOverwrite(properPathString); + + if (overwriteAnswer.equals(IOverwriteQuery.CANCEL)) + throw new InterruptedException(); + + if (overwriteAnswer.equals(IOverwriteQuery.NO)) { + fMonitor.worked(1); + return; + } + + if (overwriteAnswer.equals(IOverwriteQuery.NO_ALL)) { + fMonitor.worked(1); + overwriteState = OVERWRITE_NONE; + return; + } + + if (overwriteAnswer.equals(IOverwriteQuery.ALL)) + overwriteState = OVERWRITE_ALL; + } + } + + try { + setExporters(file); + fExporter2.write(file, fullPath); + } catch (IOException e) { + errorTable.add(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 0, ObfuscatorExportMessages.format("ObfuscatorTransfer.errorExporting", //$NON-NLS-1$ + new Object[] { fullPath, e.getMessage()}), e)); + } catch (CoreException e) { + errorTable.add(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 0, ObfuscatorExportMessages.format("ObfuscatorTransfer.errorExporting", //$NON-NLS-1$ + new Object[] { fullPath, e.getMessage()}), e)); + } + + fMonitor.worked(1); + ModalContext.checkCanceled(fMonitor); + } + + protected void exportSpecifiedResources1() throws InterruptedException { + Iterator resources = fResourcesToExport.iterator(); + IPath initPath = (IPath) fPath.clone(); + + while (resources.hasNext()) { + IResource currentResource = (IResource) resources.next(); + if (!currentResource.isAccessible()) + continue; + setExporters(currentResource); + fPath = initPath; + + if (fResource == null) { + // No root resource specified and creation of containment directories + // is required. Create containers from depth 2 onwards (ie.- project's + // child inclusive) for each resource being exported. + // if (createLeadupStructure) + // createLeadupDirectoriesFor(currentResource); + + } else { + // Root resource specified. Must create containment directories + // from this point onwards for each resource being exported + IPath containersToCreate = + currentResource.getFullPath().removeFirstSegments(fResource.getFullPath().segmentCount()).removeLastSegments(1); + + for (int i = 0; i < containersToCreate.segmentCount(); i++) { + fPath = fPath.append(containersToCreate.segment(i)); + fExporter1.createFolder(fPath); + } + } + + if (currentResource.getType() == IResource.FILE) + exportFile1((IFile) currentResource, fPath); + else { + if (createContainerDirectories) { + fPath = fPath.append(currentResource.getName()); + fExporter1.createFolder(fPath); + } + + try { + exportChildren1(((IContainer) currentResource).members(), fPath); + } catch (CoreException e) { + // should never happen because #isAccessible is called before #members is invoked, + // which implicitly does an existence check + errorTable.add(e.getStatus()); + } + } + } + } + /** + * Export the resources contained in the previously-defined + * resourcesToExport collection + */ + protected void exportSpecifiedResources2() throws InterruptedException { + Iterator resources = fResourcesToExport.iterator(); + IPath initPath = (IPath) fPath.clone(); + + while (resources.hasNext()) { + IResource currentResource = (IResource) resources.next(); + if (!currentResource.isAccessible()) + continue; + setExporters(currentResource); + + fPath = initPath; + + if (fResource == null) { + // No root resource specified and creation of containment directories + // is required. Create containers from depth 2 onwards (ie.- project's + // child inclusive) for each resource being exported. + // if (createLeadupStructure) + // createLeadupDirectoriesFor(currentResource); + + } else { + // Root resource specified. Must create containment directories + // from this point onwards for each resource being exported + IPath containersToCreate = + currentResource.getFullPath().removeFirstSegments(fResource.getFullPath().segmentCount()).removeLastSegments(1); + + for (int i = 0; i < containersToCreate.segmentCount(); i++) { + fPath = fPath.append(containersToCreate.segment(i)); + fExporter2.createFolder(fPath); + } + } + + if (currentResource.getType() == IResource.FILE) + exportFile2((IFile) currentResource, fPath); + else { + if (createContainerDirectories) { + fPath = fPath.append(currentResource.getName()); + fExporter2.createFolder(fPath); + } + + try { + exportChildren2(((IContainer) currentResource).members(), fPath); + } catch (CoreException e) { + // should never happen because #isAccessible is called before #members is invoked, + // which implicitly does an existence check + errorTable.add(e.getStatus()); + } + } + } + } + /** + * Returns the status of the export operation. + * If there were any errors, the result is a status object containing + * individual status objects for each error. + * If there were no errors, the result is a status object with error code OK. + * + * @return the status + */ + public IStatus getStatus() { + IStatus[] errors = new IStatus[errorTable.size()]; + errorTable.toArray(errors); + return new MultiStatus(PlatformUI.PLUGIN_ID, IStatus.OK, errors, ObfuscatorExportMessages.getString("ObfuscatorExportOperation.problemsExporting"), //$NON-NLS-1$ + null); + } + /** + * Answer a boolean indicating whether the passed child is a descendent + * of one or more members of the passed resources collection + * + * @return boolean + * @param resources java.util.List + * @param child org.eclipse.core.resources.IResource + */ + protected boolean isDescendent(List resources, IResource child) { + if (child.getType() == IResource.PROJECT) + return false; + + IResource parent = child.getParent(); + if (resources.contains(parent)) + return true; + + return isDescendent(resources, parent); + } + + private void setExporters(IResource resource) { + if (fCurrentIdentifierMap == null) { + if (fProjectMap == null) { + fProjectMap = new HashMap(); + } + createExporters(resource); + } else { + IProject project = resource.getProject(); + if (!fCurrentProjectName.equals(project.getName())) { + HashMap temp = (HashMap) fProjectMap.get(project.getName()); + if (temp != null) { + fCurrentProjectName = project.getName(); + fCurrentIdentifierMap = temp; + fExporter1 = new ObfuscatorPass1Exporter(new Scanner(false, false), fCurrentIdentifierMap); + fExporter2 = new ObfuscatorPass2Exporter(new Scanner(true, true), fCurrentIdentifierMap); + return; + } + createExporters(resource); + } + } + } + + private void createExporters(IResource resource) { + IProject project = resource.getProject(); + IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore(); + ObfuscatorIgnores ignore = new ObfuscatorIgnores(project); + fCurrentIdentifierMap = ignore.getIdentifierMap(); + fCurrentProjectName = project.getName(); + fProjectMap.put(fCurrentProjectName, fCurrentIdentifierMap); + fExporter1 = new ObfuscatorPass1Exporter(new Scanner(false, false), fCurrentIdentifierMap); + fExporter2 = new ObfuscatorPass2Exporter(new Scanner(true, true), fCurrentIdentifierMap); + } + /** + * Export the resources that were previously specified for export + * (or if a single resource was specified then export it recursively) + */ + public void run(IProgressMonitor monitor) throws InterruptedException { + this.fMonitor = monitor; + final IPath tempPath = (IPath) fPath.clone(); + if (fResource != null) { + setExporters(fResource); + // if (createLeadupStructure) + // createLeadupDirectoriesFor(resource); + + if (createContainerDirectories && fResource.getType() != IResource.FILE) { + // ensure it's a container + fPath = fPath.append(fResource.getName()); + fExporter2.createFolder(fPath); + } + } + + try { + // reset variables for this run: + fCurrentIdentifierMap = null; + fProjectMap = null; + fCurrentProjectName = ""; + + // count number of files + int totalWork = IProgressMonitor.UNKNOWN; + try { + if (fResourcesToExport == null) { + totalWork = countChildrenOf(fResource); + } else { + totalWork = countSelectedResources(); + } + } catch (CoreException e) { + // Should not happen + errorTable.add(e.getStatus()); + } + monitor.beginTask(ObfuscatorExportMessages.getString("ObfuscatorTransfer.exportingTitle1"), totalWork); //$NON-NLS-1$ + if (fResourcesToExport == null) { + exportAllResources1(); + } else { + exportSpecifiedResources1(); + } + + // try { + // if (resourcesToExport == null) + // totalWork = countChildrenOf(resource); + // else + // totalWork = countSelectedResources(); + // } catch (CoreException e) { + // // Should not happen + // errorTable.add(e.getStatus()); + // } + + // reset path: + fPath = tempPath; + monitor.beginTask(ObfuscatorExportMessages.getString("ObfuscatorTransfer.exportingTitle2"), totalWork); //$NON-NLS-1$ + if (fResourcesToExport == null) { + exportAllResources2(); + } else { + exportSpecifiedResources2(); + } + } finally { + monitor.done(); + } + } + /** + * Set this boolean indicating whether a directory should be created for + * Folder resources that are explicitly passed for export + * + * @param value boolean + */ + // public void setCreateContainerDirectories(boolean value) { + // createContainerDirectories = value; + // } + /** + * Set this boolean indicating whether each exported resource's complete path should + * include containment hierarchies as dictated by its parents + * + * @param value boolean + */ + // public void setCreateLeadupStructure(boolean value) { + // createLeadupStructure = value; + // } + /** + * Set this boolean indicating whether exported resources should automatically + * overwrite existing files when a conflict occurs. If not + * query the user. + * + * @param value boolean + */ + public void setOverwriteFiles(boolean value) { + if (value) + overwriteState = OVERWRITE_ALL; + } +}