lost.tok.export.SourceExportOperation.java Source code

Java tutorial

Introduction

Here is the source code for lost.tok.export.SourceExportOperation.java

Source

/* Tree of Knowledge - An information management Eclipse plugin
 * Copyright (C) 2007 Team Lost
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
 * Boston, MA  02110-1301, USA.
 */

package lost.tok.export;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import lost.tok.ToK;

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.osgi.util.NLS;
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
import org.eclipse.ui.internal.wizards.datatransfer.DataTransferMessages;
import org.eclipse.ui.internal.wizards.datatransfer.IFileExporter;

/**
 * Operation for exporting a resource and its children to a new .zip or .tar.gz
 * file.
 * 
 * @since 3.1
 */
public class SourceExportOperation implements IRunnableWithProgress {

    /** The create leadup structure. */
    private boolean createLeadupStructure = true;

    /** The destination filename. */
    private String destinationFilename;

    /** The error table. */
    private List<Status> errorTable = new ArrayList<Status>(1); // IStatus

    /** The exporter. */
    private IFileExporter exporter;

    /** The monitor. */
    private IProgressMonitor monitor;

    /** The resource. */
    private IResource resource;

    /** The resources to export. */
    private List resourcesToExport;

    /** The tok. */
    private ToK tok;

    /** The use compression. */
    private boolean useCompression = true;

    /**
     * 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
     * @param tok
     *            the tok
     */
    public SourceExportOperation(IResource res, List resources, String filename, ToK tok) {
        this(res, filename);
        this.tok = tok;
        resourcesToExport = resources;
    }

    /**
     * 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 SourceExportOperation(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 without a common parent resource
     * 
     * @param resources
     *            java.util.Vector
     * @param filename
     *            java.lang.String
     */
    public SourceExportOperation(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;
    }

    /**
     * Add a new entry to the error table with the passed information.
     * 
     * @param message
     *            the message
     * @param e
     *            the e
     */
    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.
     * 
     * @param checkResource
     *            org.eclipse.core.resources.IResource
     * 
     * @return int
     * 
     * @throws CoreException
     *             the core exception
     */
    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
     * 
     * @throws CoreException
     *             the core exception
     */
    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
     * 
     * @throws InterruptedException
     *             the interrupted exception
     */
    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 leadupDepth
     *            the number of resource levels to be included in the path
     *            including the resourse itself.
     * 
     * @throws InterruptedException
     *             the interrupted exception
     */
    protected void exportResource(IResource exportResource, int leadupDepth) throws InterruptedException {
        if (!exportResource.isAccessible()) {
            return;
        }

        if (exportResource.getType() == IResource.FILE) {
            writeFileToZip(exportResource, leadupDepth);
        } else {
            writeFolderToZip(exportResource, leadupDepth);

        }
    }

    /**
     * Export the resources contained in the previously-defined
     * resourcesToExport collection.
     * 
     * @throws InterruptedException
     *             the interrupted exception
     */
    protected void exportSpecifiedResources() throws InterruptedException {
        Iterator resources = resourcesToExport.iterator();

        while (resources.hasNext()) {
            IResource currentResource = (IResource) resources.next();
            exportResource(currentResource);
        }

        // finished with all the discussions
    }

    /**
     * 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.FileSystemExportOperation_problemsExporting, null);
    }

    /**
     * Initialize this operation.
     * 
     * @throws IOException
     *             Signals that an I/O exception has occurred.
     * 
     * @exception java.io.IOException
     */
    protected void initialize() throws IOException {
        exporter = new SourceZipFileExporter(destinationFilename, useCompression);
    }

    /**
     * Answer a boolean indicating whether the passed child is a descendent of
     * one or more members of the passed resources collection.
     * 
     * @param resources
     *            java.util.Vector
     * @param child
     *            org.eclipse.core.resources.IResource
     * 
     * @return boolean
     */
    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).
     * 
     * @param progressMonitor
     *            the progress monitor
     * 
     * @throws InvocationTargetException
     *             the invocation target exception
     * @throws InterruptedException
     *             the interrupted exception
     */
    public void run(IProgressMonitor progressMonitor) throws InvocationTargetException, InterruptedException {
        this.monitor = progressMonitor;

        try {
            initialize();
        } catch (IOException e) {
            throw new InvocationTargetException(e,
                    NLS.bind(DataTransferMessages.ZipExport_cannotOpen, e.getMessage()));
        }

        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.DataTransfer_exportingTitle, totalWork);
            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,
                        NLS.bind(DataTransferMessages.ZipExport_cannotClose, e.getMessage()));
            }
        } 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 exported resources should be
     * compressed (as opposed to simply being stored).
     * 
     * @param value
     *            boolean
     */
    public void setUseCompression(boolean value) {
        useCompression = value;
    }

    /**
     * Set this boolean indicating whether the file should be output in tar.gz
     * format rather than .zip format.
     * 
     * @param value
     *            boolean
     */
    public void setUseTarFormat(boolean value) {
    }

    /**
     * Write file to zip.
     * 
     * @param exportResource
     *            the export resource
     * @param leadupDepth
     *            the leadup depth
     * 
     * @throws InterruptedException
     *             the interrupted exception
     */
    private void writeFileToZip(IResource exportResource, int leadupDepth) throws InterruptedException {
        String destinationName;
        IPath fullPath = exportResource.getFullPath();
        if (createLeadupStructure) {
            destinationName = fullPath.makeRelative().toString();
        } else {
            destinationName = fullPath.removeFirstSegments(fullPath.segmentCount() - leadupDepth).toString();
        }
        monitor.subTask(destinationName);

        // Collect the names for fetching the links to the sources later

        try {
            exporter.write((IFile) exportResource, destinationName);
        } catch (IOException e) {
            addError(NLS.bind(DataTransferMessages.DataTransfer_errorExporting,
                    exportResource.getFullPath().makeRelative(), e.getMessage()), e);
        } catch (CoreException e) {
            addError(NLS.bind(DataTransferMessages.DataTransfer_errorExporting,
                    exportResource.getFullPath().makeRelative(), e.getMessage()), e);
        }

        monitor.worked(1);
        ModalContext.checkCanceled(monitor);
    }

    /**
     * Write folder to zip.
     * 
     * @param exportResource
     *            the export resource
     * @param leadupDepth
     *            the leadup depth
     * 
     * @throws InterruptedException
     *             the interrupted exception
     */
    private void writeFolderToZip(IResource exportResource, int leadupDepth) throws InterruptedException {
        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(NLS.bind(DataTransferMessages.DataTransfer_errorExporting, exportResource.getFullPath()), e);
        }

        for (int i = 0; i < children.length; i++) {
            exportResource(children[i], leadupDepth + 1);
        }
    }
}