| /******************************************************************************* |
| * Copyright (c) 2003, 2006 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - Initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jst.server.core; |
| |
| import java.io.*; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.zip.ZipEntry; |
| import java.util.zip.ZipOutputStream; |
| |
| import org.eclipse.core.resources.IContainer; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.runtime.*; |
| import org.eclipse.jst.server.core.internal.JavaServerPlugin; |
| import org.eclipse.jst.server.core.internal.Messages; |
| import org.eclipse.jst.server.core.internal.ProgressUtil; |
| import org.eclipse.jst.server.core.internal.Trace; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.wst.server.core.model.IModuleFile; |
| import org.eclipse.wst.server.core.model.IModuleFolder; |
| import org.eclipse.wst.server.core.model.IModuleResource; |
| import org.eclipse.wst.server.core.model.IModuleResourceDelta; |
| /** |
| * Utility class with an assortment of useful file methods. |
| * |
| * <p> |
| * <b>Note:</b> This class/interface is part of an interim API that is still under development and expected to |
| * change significantly before reaching stability. It is being made available at this early stage to solicit feedback |
| * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken |
| * (repeatedly) as the API evolves. |
| * </p> |
| * @plannedfor 2.0 |
| */ |
| public class PublishUtil { |
| // size of the buffer |
| private static final int BUFFER = 65536; |
| |
| // the buffer |
| private static byte[] buf = new byte[BUFFER]; |
| |
| private static final IStatus[] EMPTY_STATUS = new IStatus[0]; |
| |
| private static final File tempDir = JavaServerPlugin.getInstance().getStateLocation().toFile(); |
| |
| private static final String TEMPFILE_PREFIX = "tmp"; |
| |
| /** |
| * FileUtil cannot be created. Use static methods. |
| */ |
| private PublishUtil() { |
| super(); |
| } |
| |
| /** |
| * Copy a file from a to b. Closes the input stream after use. |
| * |
| * @param in java.io.InputStream |
| * @param to java.lang.String |
| * @deprecated Unused - will be removed. |
| * @return a status |
| */ |
| public static IStatus copyFile(InputStream in, String to) { |
| OutputStream out = null; |
| |
| try { |
| out = new FileOutputStream(to); |
| |
| int avail = in.read(buf); |
| while (avail > 0) { |
| out.write(buf, 0, avail); |
| avail = in.read(buf); |
| } |
| return Status.OK_STATUS; |
| } catch (Exception e) { |
| Trace.trace(Trace.SEVERE, "Error copying file", e); |
| return new Status(IStatus.ERROR, JavaServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCopyingFile, new String[] {to, e.getLocalizedMessage()}), e); |
| } finally { |
| try { |
| if (in != null) |
| in.close(); |
| } catch (Exception ex) { |
| // ignore |
| } |
| try { |
| if (out != null) |
| out.close(); |
| } catch (Exception ex) { |
| // ignore |
| } |
| } |
| } |
| |
| /** |
| * Smart copy the given module resources to the given path. |
| * |
| * @param resources |
| * @param path |
| * @param monitor a progress monitor, or <code>null</code> if progress |
| * reporting and cancellation are not desired |
| * @throws CoreException |
| * @deprecated This method only returns a single error in the case of failure. Use publishSmart() instead. |
| */ |
| public static void smartCopy(IModuleResource[] resources, IPath path, IProgressMonitor monitor) throws CoreException { |
| IStatus[] status = PublishUtil.publishSmart(resources, path, monitor); |
| if (status != null && status.length > 0) |
| throw new CoreException(status[0]); |
| } |
| |
| /** |
| * Handle a delta publish. |
| * |
| * @param kind |
| * @param path |
| * @param delta |
| * @throws CoreException |
| * @deprecated This method only returns a single error in the case of failure. Use publishDelta() instead. |
| */ |
| public static void handleDelta(int kind, IPath path, IModuleResourceDelta delta) throws CoreException { |
| IStatus[] status = PublishUtil.publishDelta(delta, path, null); |
| if (status != null && status.length > 0) |
| throw new CoreException(status[0]); |
| } |
| |
| /** |
| * |
| * @param path |
| * @param file |
| * @deprecated does not fail or return status if delete doesn't work |
| */ |
| protected static void deleteFile(IPath path, IModuleFile file) { |
| Trace.trace(Trace.PUBLISHING, "Deleting: " + file.getName() + " from " + path.toString()); |
| IPath path2 = path.append(file.getModuleRelativePath()).append(file.getName()); |
| path2.toFile().delete(); |
| } |
| |
| /** |
| * |
| * @param resources |
| * @param path |
| * @throws CoreException |
| * @deprecated This method only returns a single error in the case of failure. Use publishFull() instead |
| */ |
| public static void copy(IModuleResource[] resources, IPath path) throws CoreException { |
| IStatus[] status = PublishUtil.publishFull(resources, path, null); |
| if (status != null && status.length > 0) |
| throw new CoreException(status[0]); |
| } |
| |
| /** |
| * Creates a new zip file containing the given module resources. Deletes the existing file |
| * (and doesn't create a new one) if resources is null or empty. |
| * |
| * @param resources |
| * @param zipPath |
| * @throws CoreException |
| */ |
| public static void createZipFile(IModuleResource[] resources, IPath zipPath) throws CoreException { |
| IStatus[] status = PublishUtil.publishZip(resources, zipPath, null); |
| if (status != null && status.length > 0) |
| throw new CoreException(status[0]); |
| } |
| |
| /** |
| * Copy a file from a to b. Closes the input stream after use. |
| * |
| * @param in an input stream |
| * @param to a path to copy to. the directory must already exist |
| * @param ts timestamp |
| * @throws CoreException if anything goes wrong |
| */ |
| private static void copyFile(InputStream in, IPath to, long ts, IModuleFile mf) throws CoreException { |
| OutputStream out = null; |
| |
| File tempFile = null; |
| try { |
| File file = to.toFile(); |
| tempFile = File.createTempFile(TEMPFILE_PREFIX, "." + to.getFileExtension(), tempDir); |
| |
| out = new FileOutputStream(tempFile); |
| |
| int avail = in.read(buf); |
| while (avail > 0) { |
| out.write(buf, 0, avail); |
| avail = in.read(buf); |
| } |
| |
| out.close(); |
| out = null; |
| |
| moveTempFile(tempFile, file); |
| |
| if (ts != IResource.NULL_STAMP && ts != 0) |
| file.setLastModified(ts); |
| } catch (CoreException e) { |
| throw e; |
| } catch (Exception e) { |
| IPath path = mf.getModuleRelativePath().append(mf.getName()); |
| Trace.trace(Trace.SEVERE, "Error copying file: " + to.toOSString() + " to " + path.toOSString(), e); |
| throw new CoreException(new Status(IStatus.ERROR, JavaServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCopyingFile, path.toOSString(), e.getLocalizedMessage()), null)); |
| } finally { |
| if (tempFile != null && tempFile.exists()) |
| tempFile.deleteOnExit(); |
| try { |
| if (in != null) |
| in.close(); |
| } catch (Exception ex) { |
| // ignore |
| } |
| try { |
| if (out != null) |
| out.close(); |
| } catch (Exception ex) { |
| // ignore |
| } |
| } |
| } |
| |
| /** |
| * Utility method to recursively delete a directory. |
| * |
| * @param dir a directory |
| * @param monitor a progress monitor, or <code>null</code> if progress |
| * reporting and cancellation are not desired |
| * @return a possibly-empty array of error and warning status |
| */ |
| public static IStatus[] deleteDirectory(File dir, IProgressMonitor monitor) { |
| if (!dir.exists() || !dir.isDirectory()) |
| return new IStatus[] { new Status(IStatus.ERROR, JavaServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorNotADirectory, dir.getAbsolutePath()), null) }; |
| |
| List status = new ArrayList(2); |
| |
| try { |
| File[] files = dir.listFiles(); |
| int size = files.length; |
| monitor = ProgressUtil.getMonitorFor(monitor); |
| monitor.beginTask(NLS.bind(Messages.deletingTask, new String[] { dir.getAbsolutePath() }), size * 10); |
| |
| // cycle through files |
| boolean deleteCurrent = true; |
| for (int i = 0; i < size; i++) { |
| File current = files[i]; |
| if (current.isFile()) { |
| if (!current.delete()) { |
| status.add(new Status(IStatus.ERROR, JavaServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorDeleting, files[i].getAbsolutePath()), null)); |
| deleteCurrent = false; |
| } |
| monitor.worked(10); |
| } else if (current.isDirectory()) { |
| monitor.subTask(NLS.bind(Messages.deletingTask, new String[] {current.getAbsolutePath()})); |
| IStatus[] stat = deleteDirectory(current, ProgressUtil.getSubMonitorFor(monitor, 10)); |
| if (stat != null && stat.length > 0) { |
| deleteCurrent = false; |
| addArrayToList(status, stat); |
| } |
| } |
| } |
| if (deleteCurrent && !dir.delete()) |
| status.add(new Status(IStatus.ERROR, JavaServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorDeleting, dir.getAbsolutePath()), null)); |
| monitor.done(); |
| } catch (Exception e) { |
| Trace.trace(Trace.SEVERE, "Error deleting directory " + dir.getAbsolutePath(), e); |
| status.add(new Status(IStatus.ERROR, JavaServerPlugin.PLUGIN_ID, 0, e.getLocalizedMessage(), null)); |
| } |
| |
| IStatus[] stat = new IStatus[status.size()]; |
| status.toArray(stat); |
| return stat; |
| } |
| |
| /** |
| * Smart copy the given module resources to the given path. |
| * |
| * @param resources an array of module resources |
| * @param path an external path to copy to |
| * @param monitor a progress monitor, or <code>null</code> if progress |
| * reporting and cancellation are not desired |
| * @return a possibly-empty array of error and warning status |
| */ |
| public static IStatus[] publishSmart(IModuleResource[] resources, IPath path, IProgressMonitor monitor) { |
| if (resources == null) |
| return EMPTY_STATUS; |
| |
| monitor = ProgressUtil.getMonitorFor(monitor); |
| |
| List status = new ArrayList(2); |
| File toDir = path.toFile(); |
| int fromSize = resources.length; |
| String[] fromFileNames = new String[fromSize]; |
| for (int i = 0; i < fromSize; i++) |
| fromFileNames[i] = resources[i].getName(); |
| |
| // cache files and file names for performance |
| File[] toFiles = null; |
| String[] toFileNames = null; |
| |
| boolean foundExistingDir = false; |
| if (toDir.exists()) { |
| if (toDir.isDirectory()) { |
| foundExistingDir = true; |
| toFiles = toDir.listFiles(); |
| int toSize = toFiles.length; |
| toFileNames = new String[toSize]; |
| |
| // check if this exact file exists in the new directory |
| for (int i = 0; i < toSize; i++) { |
| toFileNames[i] = toFiles[i].getName(); |
| boolean isDir = toFiles[i].isDirectory(); |
| boolean found = false; |
| for (int j = 0; j < fromSize; j++) { |
| if (toFileNames[i].equals(fromFileNames[j]) && isDir == resources[j] instanceof IModuleFolder) |
| found = true; |
| } |
| |
| // delete file if it can't be found or isn't the correct type |
| if (!found) { |
| if (isDir) { |
| IStatus[] stat = deleteDirectory(toFiles[i], null); |
| addArrayToList(status, stat); |
| } else { |
| if (!toFiles[i].delete()) |
| status.add(new Status(IStatus.ERROR, JavaServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorDeleting, toFiles[i].getAbsolutePath()), null)); |
| } |
| toFiles[i] = null; |
| toFileNames[i] = null; |
| } |
| } |
| } else { //if (toDir.isFile()) |
| if (!toDir.delete()) { |
| status.add(new Status(IStatus.ERROR, JavaServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorDeleting, toDir.getAbsolutePath()), null)); |
| IStatus[] stat = new IStatus[status.size()]; |
| status.toArray(stat); |
| return stat; |
| } |
| } |
| } |
| if (!foundExistingDir && !toDir.mkdir()) { |
| status.add(new Status(IStatus.ERROR, JavaServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorMkdir, toDir.getAbsolutePath()), null)); |
| IStatus[] stat = new IStatus[status.size()]; |
| status.toArray(stat); |
| return stat; |
| } |
| |
| if (monitor.isCanceled()) |
| return new IStatus[] { Status.CANCEL_STATUS }; |
| |
| monitor.worked(50); |
| |
| // cycle through files and only copy when it doesn't exist |
| // or is newer |
| if (toFiles == null) |
| toFiles = toDir.listFiles(); |
| int toSize = 0; |
| if (toFiles != null) |
| toSize = toFiles.length; |
| |
| int dw = 0; |
| if (toSize > 0) |
| dw = 500 / toSize; |
| |
| // cache file names and last modified dates for performance |
| if (toFileNames == null) |
| toFileNames = new String[toSize]; |
| long[] toFileMod = new long[toSize]; |
| for (int i = 0; i < toSize; i++) { |
| if (toFiles[i] != null) { |
| if (toFileNames[i] != null) |
| toFileNames[i] = toFiles[i].getName(); |
| toFileMod[i] = toFiles[i].lastModified(); |
| } |
| } |
| |
| for (int i = 0; i < fromSize; i++) { |
| IModuleResource current = resources[i]; |
| String name = fromFileNames[i]; |
| boolean currentIsDir = current instanceof IModuleFolder; |
| |
| if (!currentIsDir) { |
| // check if this is a new or newer file |
| boolean copy = true; |
| IModuleFile mf = (IModuleFile) current; |
| |
| long mod = -1; |
| IFile file = (IFile) mf.getAdapter(IFile.class); |
| if (file != null) { |
| mod = file.getLocalTimeStamp(); |
| } else { |
| File file2 = (File) mf.getAdapter(File.class); |
| mod = file2.lastModified(); |
| } |
| |
| for (int j = 0; j < toSize; j++) { |
| if (name.equals(toFileNames[j]) && mod == toFileMod[j]) |
| copy = false; |
| } |
| |
| if (copy) { |
| try { |
| copyFile(mf, path.append(name)); |
| } catch (CoreException ce) { |
| status.add(ce.getStatus()); |
| } |
| } |
| monitor.worked(dw); |
| } else { //if (currentIsDir) { |
| IModuleFolder folder = (IModuleFolder) current; |
| IModuleResource[] children = folder.members(); |
| monitor.subTask(NLS.bind(Messages.copyingTask, new String[] {name, name})); |
| IStatus[] stat = publishSmart(children, path.append(name), ProgressUtil.getSubMonitorFor(monitor, dw)); |
| addArrayToList(status, stat); |
| } |
| } |
| if (monitor.isCanceled()) |
| return new IStatus[] { Status.CANCEL_STATUS }; |
| |
| monitor.worked(500 - dw * toSize); |
| monitor.done(); |
| |
| IStatus[] stat = new IStatus[status.size()]; |
| status.toArray(stat); |
| return stat; |
| } |
| |
| /** |
| * Handle a delta publish. |
| * |
| * @param delta a module resource delta |
| * @param path the path to publish to |
| * @param monitor a progress monitor, or <code>null</code> if progress |
| * reporting and cancellation are not desired |
| * @return a possibly-empty array of error and warning status |
| */ |
| public static IStatus[] publishDelta(IModuleResourceDelta[] delta, IPath path, IProgressMonitor monitor) { |
| if (delta == null) |
| return EMPTY_STATUS; |
| |
| monitor = ProgressUtil.getMonitorFor(monitor); |
| |
| List status = new ArrayList(2); |
| int size2 = delta.length; |
| for (int i = 0; i < size2; i++) { |
| IStatus[] stat = publishDelta(delta[i], path, monitor); |
| addArrayToList(status, stat); |
| } |
| |
| IStatus[] stat = new IStatus[status.size()]; |
| status.toArray(stat); |
| return stat; |
| } |
| |
| /** |
| * Handle a delta publish. |
| * |
| * @param delta a module resource delta |
| * @param path the path to publish to |
| * @param monitor a progress monitor, or <code>null</code> if progress |
| * reporting and cancellation are not desired |
| * @return a possibly-empty array of error and warning status |
| */ |
| public static IStatus[] publishDelta(IModuleResourceDelta delta, IPath path, IProgressMonitor monitor) { |
| List status = new ArrayList(2); |
| |
| IModuleResource resource = delta.getModuleResource(); |
| int kind2 = delta.getKind(); |
| |
| if (resource instanceof IModuleFile) { |
| IModuleFile file = (IModuleFile) resource; |
| try { |
| if (kind2 == IModuleResourceDelta.REMOVED) |
| deleteFile2(path, file); |
| else { |
| IPath path2 = path.append(file.getModuleRelativePath()).append(file.getName()); |
| File f = path2.toFile().getParentFile(); |
| if (!f.exists()) |
| f.mkdirs(); |
| |
| copyFile(file, path2); |
| } |
| } catch (CoreException ce) { |
| status.add(ce.getStatus()); |
| } |
| IStatus[] stat = new IStatus[status.size()]; |
| status.toArray(stat); |
| return stat; |
| } |
| |
| if (kind2 == IModuleResourceDelta.ADDED) { |
| IPath path2 = path.append(resource.getModuleRelativePath()).append(resource.getName()); |
| File file = path2.toFile(); |
| if (!file.exists() && !file.mkdirs()) { |
| status.add(new Status(IStatus.ERROR, JavaServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorMkdir, path2), null)); |
| IStatus[] stat = new IStatus[status.size()]; |
| status.toArray(stat); |
| return stat; |
| } |
| } |
| |
| IModuleResourceDelta[] childDeltas = delta.getAffectedChildren(); |
| int size = childDeltas.length; |
| for (int i = 0; i < size; i++) { |
| IStatus[] stat = publishDelta(childDeltas[i], path, monitor); |
| addArrayToList(status, stat); |
| } |
| |
| if (kind2 == IModuleResourceDelta.REMOVED) { |
| IPath path2 = path.append(resource.getModuleRelativePath()).append(resource.getName()); |
| File file = path2.toFile(); |
| if (file.exists() && !file.delete()) { |
| status.add(new Status(IStatus.ERROR, JavaServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorDeleting, path2), null)); |
| } |
| } |
| |
| IStatus[] stat = new IStatus[status.size()]; |
| status.toArray(stat); |
| return stat; |
| } |
| |
| private static void deleteFile2(IPath path, IModuleFile file) throws CoreException { |
| Trace.trace(Trace.PUBLISHING, "Deleting: " + file.getName() + " from " + path.toString()); |
| IPath path2 = path.append(file.getModuleRelativePath()).append(file.getName()); |
| if (path2.toFile().exists() && !path2.toFile().delete()) |
| throw new CoreException(new Status(IStatus.ERROR, JavaServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorDeleting, path2), null)); |
| } |
| |
| private static void copyFile(IModuleFile mf, IPath path) throws CoreException { |
| Trace.trace(Trace.PUBLISHING, "Copying: " + mf.getName() + " to " + path.toString()); |
| |
| IFile file = (IFile) mf.getAdapter(IFile.class); |
| if (file != null) |
| copyFile(file.getContents(), path, file.getLocalTimeStamp(), mf); |
| else { |
| File file2 = (File) mf.getAdapter(File.class); |
| InputStream in = null; |
| try { |
| in = new FileInputStream(file2); |
| } catch (IOException e) { |
| throw new CoreException(new Status(IStatus.ERROR, JavaServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorReading, file2.getAbsolutePath()), e)); |
| } |
| copyFile(in, path, file2.lastModified(), mf); |
| } |
| } |
| |
| /** |
| * Publish the given module resources to the given path. |
| * |
| * @param resources an array of module resources |
| * @param path a path to publish to |
| * @param monitor a progress monitor, or <code>null</code> if progress |
| * reporting and cancellation are not desired |
| * @return a possibly-empty array of error and warning status |
| */ |
| public static IStatus[] publishFull(IModuleResource[] resources, IPath path, IProgressMonitor monitor) { |
| if (resources == null) |
| return EMPTY_STATUS; |
| |
| monitor = ProgressUtil.getMonitorFor(monitor); |
| |
| List status = new ArrayList(2); |
| int size = resources.length; |
| for (int i = 0; i < size; i++) { |
| IStatus[] stat = copy(resources[i], path, monitor); |
| addArrayToList(status, stat); |
| } |
| |
| IStatus[] stat = new IStatus[status.size()]; |
| status.toArray(stat); |
| return stat; |
| } |
| |
| private static IStatus[] copy(IModuleResource resource, IPath path, IProgressMonitor monitor) { |
| String name = resource.getName(); |
| Trace.trace(Trace.PUBLISHING, "Copying: " + name + " to " + path.toString()); |
| List status = new ArrayList(2); |
| if (resource instanceof IModuleFolder) { |
| IModuleFolder folder = (IModuleFolder) resource; |
| IStatus[] stat = publishFull(folder.members(), path, monitor); |
| addArrayToList(status, stat); |
| } else { |
| IModuleFile mf = (IModuleFile) resource; |
| path = path.append(mf.getModuleRelativePath()).append(name); |
| File f = path.toFile().getParentFile(); |
| if (!f.exists()) |
| f.mkdirs(); |
| try { |
| copyFile(mf, path); |
| } catch (CoreException ce) { |
| status.add(ce.getStatus()); |
| } |
| } |
| IStatus[] stat = new IStatus[status.size()]; |
| status.toArray(stat); |
| return stat; |
| } |
| |
| /** |
| * Creates a new zip file containing the given module resources. Deletes the existing file |
| * (and doesn't create a new one) if resources is null or empty. |
| * |
| * @param resources an array of module resources |
| * @param path the path where the zip file should be created |
| * @param monitor a progress monitor, or <code>null</code> if progress |
| * reporting and cancellation are not desired |
| * @return a possibly-empty array of error and warning status |
| */ |
| public static IStatus[] publishZip(IModuleResource[] resources, IPath path, IProgressMonitor monitor) { |
| if (resources == null || resources.length == 0) { |
| // should also check if resources consists of all empty directories |
| File file = path.toFile(); |
| if (file.exists()) |
| file.delete(); |
| return EMPTY_STATUS; |
| } |
| |
| monitor = ProgressUtil.getMonitorFor(monitor); |
| |
| File tempFile = null; |
| try { |
| File file = path.toFile(); |
| tempFile = File.createTempFile(TEMPFILE_PREFIX, "." + path.getFileExtension(), tempDir); |
| |
| BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream(tempFile)); |
| ZipOutputStream zout = new ZipOutputStream(bout); |
| addZipEntries(zout, resources); |
| zout.close(); |
| |
| moveTempFile(tempFile, file); |
| } catch (CoreException e) { |
| return new IStatus[] { e.getStatus() }; |
| } catch (Exception e) { |
| Trace.trace(Trace.SEVERE, "Error zipping", e); |
| return new Status[] { new Status(IStatus.ERROR, JavaServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCreatingZipFile, path.lastSegment(), e.getLocalizedMessage()), e) }; |
| } finally { |
| if (tempFile != null && tempFile.exists()) |
| tempFile.deleteOnExit(); |
| } |
| return EMPTY_STATUS; |
| } |
| |
| private static void addZipEntries(ZipOutputStream zout, IModuleResource[] resources) throws Exception { |
| if (resources == null) |
| return; |
| |
| int size = resources.length; |
| for (int i = 0; i < size; i++) { |
| if (resources[i] instanceof IModuleFolder) { |
| IModuleFolder mf = (IModuleFolder) resources[i]; |
| IModuleResource[] res = mf.members(); |
| |
| IPath path = mf.getModuleRelativePath().append(mf.getName()); |
| String entryPath = path.toPortableString(); |
| if (!entryPath.endsWith("/")) |
| entryPath += '/'; |
| |
| ZipEntry ze = new ZipEntry(entryPath); |
| |
| long ts = 0; |
| IContainer folder = (IContainer) mf.getAdapter(IContainer.class); |
| if (folder != null) |
| ts = folder.getLocalTimeStamp(); |
| |
| if (ts != IResource.NULL_STAMP && ts != 0) |
| ze.setTime(ts); |
| |
| zout.putNextEntry(ze); |
| zout.closeEntry(); |
| |
| addZipEntries(zout, res); |
| continue; |
| } |
| |
| IModuleFile mf = (IModuleFile) resources[i]; |
| IPath path = mf.getModuleRelativePath().append(mf.getName()); |
| |
| ZipEntry ze = new ZipEntry(path.toPortableString()); |
| |
| InputStream in = null; |
| long ts = 0; |
| IFile file = (IFile) mf.getAdapter(IFile.class); |
| if (file != null) { |
| ts = file.getLocalTimeStamp(); |
| in = file.getContents(); |
| } else { |
| File file2 = (File) mf.getAdapter(File.class); |
| ts = file2.lastModified(); |
| in = new FileInputStream(file2); |
| } |
| |
| if (ts != IResource.NULL_STAMP && ts != 0) |
| ze.setTime(ts); |
| |
| zout.putNextEntry(ze); |
| |
| try { |
| int n = 0; |
| while (n > -1) { |
| n = in.read(buf); |
| if (n > 0) |
| zout.write(buf, 0, n); |
| } |
| } finally { |
| in.close(); |
| } |
| |
| zout.closeEntry(); |
| } |
| } |
| |
| /** |
| * Utility method to move a temp file into position by deleting the original and |
| * swapping in a new copy. |
| * |
| * @param tempFile |
| * @param file |
| * @throws CoreException |
| */ |
| private static void moveTempFile(File tempFile, File file) throws CoreException { |
| if (file.exists()) { |
| if (!safeDelete(file, 2)) { |
| // attempt to rewrite an existing file with the tempFile contents if |
| // the existing file can't be deleted to permit the move |
| try { |
| InputStream in = new FileInputStream(tempFile); |
| IStatus status = copyFile(in, file.getPath()); |
| if (!status.isOK()) { |
| MultiStatus status2 = new MultiStatus(JavaServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorDeleting, file.toString()), null); |
| status2.add(status); |
| throw new CoreException(status2); |
| } |
| return; |
| } catch (FileNotFoundException e) { |
| // shouldn't occur |
| } finally { |
| tempFile.delete(); |
| } |
| /*if (!safeDelete(file, 8)) { |
| tempFile.delete(); |
| throw new CoreException(new Status(IStatus.ERROR, JavaServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorDeleting, file.toString()), null)); |
| }*/ |
| } |
| } |
| if (!safeRename(tempFile, file, 10)) |
| throw new CoreException(new Status(IStatus.ERROR, JavaServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorRename, tempFile.toString()), null)); |
| } |
| |
| /** |
| * Safe delete. Tries to delete multiple times before giving up. |
| * |
| * @param f |
| * @return <code>true</code> if it succeeds, <code>false</code> otherwise |
| */ |
| private static boolean safeDelete(File f, int retrys) { |
| int count = 0; |
| while (count < retrys) { |
| if (!f.exists()) |
| return true; |
| |
| f.delete(); |
| |
| if (!f.exists()) |
| return true; |
| |
| count++; |
| // delay if we are going to try again |
| if (count < retrys) { |
| try { |
| Thread.sleep(100); |
| } catch (Exception e) { |
| // ignore |
| } |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Safe rename. Will try multiple times before giving up. |
| * |
| * @param from |
| * @param to |
| * @param retrys number of times to retry |
| * @return <code>true</code> if it succeeds, <code>false</code> otherwise |
| */ |
| private static boolean safeRename(File from, File to, int retrys) { |
| // make sure parent dir exists |
| File dir = to.getParentFile(); |
| if (dir != null && !dir.exists()) |
| dir.mkdirs(); |
| |
| int count = 0; |
| while (count < retrys) { |
| if (from.renameTo(to)) |
| return true; |
| |
| count++; |
| // delay if we are going to try again |
| if (count < retrys) { |
| try { |
| Thread.sleep(100); |
| } catch (Exception e) { |
| // ignore |
| } |
| } |
| } |
| return false; |
| } |
| |
| private static void addArrayToList(List list, IStatus[] a) { |
| if (list == null || a == null || a.length == 0) |
| return; |
| |
| int size = a.length; |
| for (int i = 0; i < size; i++) |
| list.add(a[i]); |
| } |
| } |