| /******************************************************************************* |
| * 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 org.eclipse.ui.wizards.datatransfer; |
| |
| import java.io.IOException; |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.core.resources.IContainer; |
| import org.eclipse.core.resources.IFile; |
| 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.Status; |
| import org.eclipse.jface.operation.IRunnableWithProgress; |
| import org.eclipse.jface.operation.ModalContext; |
| import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin; |
| |
| /** |
| * Operation for exporting a resource and its children to a new .zip file |
| */ |
| /*package*/ |
| class ZipFileExportOperation implements IRunnableWithProgress { |
| private ZipFileExporter exporter; |
| |
| private String destinationFilename; |
| |
| private IProgressMonitor monitor; |
| |
| private List resourcesToExport; |
| |
| private IResource resource; |
| |
| private List errorTable = new ArrayList(1); //IStatus |
| |
| private boolean useCompression = true; |
| |
| private boolean createLeadupStructure = true; |
| |
| private boolean generateManifestFile = false; |
| |
| /** |
| * Create an instance of this class. Use this constructor if you wish to |
| * export specific resources without a common parent resource |
| * |
| * @param resources java.util.Vector |
| * @param filename java.lang.String |
| */ |
| public ZipFileExportOperation(List resources, String filename) { |
| super(); |
| |
| // 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(); //Removes currentResource; |
| } |
| |
| resourcesToExport = resources; |
| destinationFilename = filename; |
| } |
| |
| /** |
| * Create an instance of this class. Use this constructor if you wish |
| * to recursively export a single resource. |
| * |
| * @param res org.eclipse.core.resources.IResource; |
| * @param filename java.lang.String |
| */ |
| public ZipFileExportOperation(IResource res, String filename) { |
| super(); |
| resource = res; |
| destinationFilename = filename; |
| } |
| |
| /** |
| * 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) |
| * |
| * @param res org.eclipse.core.resources.IResource |
| * @param resources java.util.Vector |
| * @param filename java.lang.String |
| */ |
| public ZipFileExportOperation(IResource res, List resources, String filename) { |
| this(res, filename); |
| resourcesToExport = 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, |
| IDEWorkbenchPlugin.IDE_WORKBENCH, 0, message, e)); |
| } |
| |
| /** |
| * Answer the total number of file resources that exist at or below self |
| * in the resources hierarchy. |
| * |
| * @return int |
| * @param checkResource org.eclipse.core.resources.IResource |
| */ |
| protected int countChildrenOf(IResource checkResource) throws CoreException { |
| if (checkResource.getType() == IResource.FILE) |
| return 1; |
| |
| int count = 0; |
| if (checkResource.isAccessible()) { |
| IResource[] children = ((IContainer) checkResource).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 = resourcesToExport.iterator(); |
| while (resources.hasNext()) |
| result += countChildrenOf((IResource) resources.next()); |
| |
| return result; |
| } |
| |
| /** |
| * Export the passed resource to the destination .zip. Export with |
| * no path leadup |
| * |
| * @param exportResource org.eclipse.core.resources.IResource |
| */ |
| protected void exportResource(IResource exportResource) |
| throws InterruptedException { |
| exportResource(exportResource, 1); |
| } |
| |
| /** |
| * Export the passed resource to the destination .zip |
| * |
| * @param exportResource org.eclipse.core.resources.IResource |
| * @param depth - the number of resource levels to be included in |
| * the path including the resourse itself. |
| */ |
| protected void exportResource(IResource exportResource, int leadupDepth) |
| throws InterruptedException { |
| if (!exportResource.isAccessible()) |
| return; |
| |
| if (exportResource.getType() == IResource.FILE) { |
| String destinationName; |
| IPath fullPath = exportResource.getFullPath(); |
| if (createLeadupStructure) |
| destinationName = fullPath.makeRelative().toString(); |
| else |
| destinationName = fullPath.removeFirstSegments( |
| fullPath.segmentCount() - leadupDepth).toString(); |
| monitor.subTask(destinationName); |
| |
| try { |
| exporter.write((IFile) exportResource, destinationName); |
| } catch (IOException e) { |
| addError(DataTransferMessages.format( |
| "DataTransfer.errorExporting", //$NON-NLS-1$ |
| new Object[] { |
| exportResource.getFullPath().makeRelative(), |
| e.getMessage() }), e); |
| } catch (CoreException e) { |
| addError(DataTransferMessages.format( |
| "DataTransfer.errorExporting", //$NON-NLS-1$ |
| new Object[] { |
| exportResource.getFullPath().makeRelative(), |
| e.getMessage() }), e); |
| } |
| |
| monitor.worked(1); |
| ModalContext.checkCanceled(monitor); |
| } else { |
| IResource[] children = null; |
| |
| try { |
| children = ((IContainer) exportResource).members(); |
| } catch (CoreException e) { |
| // this should never happen because an #isAccessible check is done before #members is invoked |
| addError( |
| DataTransferMessages |
| .format( |
| "DataTransfer.errorExporting", new Object[] { exportResource.getFullPath() }), e); //$NON-NLS-1$ |
| } |
| |
| for (int i = 0; i < children.length; i++) |
| exportResource(children[i], leadupDepth + 1); |
| |
| } |
| } |
| |
| /** |
| * Export the resources contained in the previously-defined |
| * resourcesToExport collection |
| */ |
| protected void exportSpecifiedResources() throws InterruptedException { |
| Iterator resources = resourcesToExport.iterator(); |
| |
| while (resources.hasNext()) { |
| IResource currentResource = (IResource) resources.next(); |
| exportResource(currentResource); |
| } |
| } |
| |
| /** |
| * Answer the error table |
| * |
| * @return Vector of IStatus |
| */ |
| public List getResult() { |
| return errorTable; |
| } |
| |
| /** |
| * Returns the status of the 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 <code>OK</code>. |
| * |
| * @return the status |
| */ |
| public IStatus getStatus() { |
| IStatus[] errors = new IStatus[errorTable.size()]; |
| errorTable.toArray(errors); |
| return new MultiStatus( |
| IDEWorkbenchPlugin.IDE_WORKBENCH, |
| IStatus.OK, |
| errors, |
| DataTransferMessages |
| .getString("FileSystemExportOperation.problemsExporting"), //$NON-NLS-1$ |
| null); |
| } |
| |
| /** |
| * Initialize this operation |
| * |
| * @exception java.io.IOException |
| */ |
| protected void initialize() throws IOException { |
| exporter = new ZipFileExporter(destinationFilename, useCompression, |
| generateManifestFile); |
| |
| } |
| |
| /** |
| * 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.Vector |
| * @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); |
| } |
| |
| /** |
| * Export the resources that were previously specified for export |
| * (or if a single resource was specified then export it recursively) |
| */ |
| public void run(IProgressMonitor progressMonitor) |
| throws InvocationTargetException, InterruptedException { |
| this.monitor = progressMonitor; |
| |
| try { |
| initialize(); |
| } catch (IOException e) { |
| throw new InvocationTargetException(e, DataTransferMessages.format( |
| "ZipExport.cannotOpen", new Object[] { e.getMessage() })); //$NON-NLS-1$ |
| } |
| |
| try { |
| // ie.- a single resource for recursive export was specified |
| int totalWork = IProgressMonitor.UNKNOWN; |
| try { |
| if (resourcesToExport == null) |
| totalWork = countChildrenOf(resource); |
| else |
| totalWork = countSelectedResources(); |
| } catch (CoreException e) { |
| // Should not happen |
| } |
| monitor.beginTask(DataTransferMessages |
| .getString("DataTransfer.exportingTitle"), totalWork); //$NON-NLS-1$ |
| if (resourcesToExport == null) { |
| exportResource(resource); |
| } else { |
| // ie.- a list of specific resources to export was specified |
| exportSpecifiedResources(); |
| } |
| |
| try { |
| exporter.finished(); |
| } catch (IOException e) { |
| throw new InvocationTargetException( |
| e, |
| DataTransferMessages |
| .format( |
| "ZipExport.cannotClose", new Object[] { e.getMessage() })); //$NON-NLS-1$ |
| } |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * Set this boolean indicating whether each exported resource's 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 a manifest.mf file based upon |
| * the exported contents should be created and included in the final |
| * archive |
| * |
| * @param value boolean |
| */ |
| public void setGenerateManifestFile(boolean value) { |
| generateManifestFile = value; |
| } |
| |
| /** |
| * Set this boolean indicating whether exported resources should |
| * be compressed (as opposed to simply being stored) |
| * |
| * @param value boolean |
| */ |
| public void setUseCompression(boolean value) { |
| useCompression = value; |
| } |
| } |