/******************************************************************************* * Copyright (c) 2000, 2010 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.update.core; import java.io.*; import java.text.DateFormat; import java.util.Date; import java.util.HashMap; import java.util.Locale; import java.util.Map; import org.eclipse.core.runtime.*; import org.eclipse.update.core.model.*; import org.eclipse.update.internal.core.*; /** * This class is a collection of utility functions that can be * used for install processing * <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> * @deprecated The org.eclipse.update component has been replaced by Equinox p2. * This API will be deleted in a future release. See bug 311590 for details. */ public class Utilities { private static Map entryMap; private static final DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.getDefault()); private static long tmpseed = (new Date()).getTime(); private static String dirRoot = null; /** * Returns a new working directory (in temporary space). Ensures * the directory exists. Any directory levels that had to be created * are marked for deletion on exit. * * @return working directory * @exception IOException * @since 2.0 */ public static synchronized File createWorkingDirectory() throws IOException { if (dirRoot == null) { dirRoot = System.getProperty("java.io.tmpdir"); //$NON-NLS-1$ // in Linux, returns '/tmp', we must add '/' if (!dirRoot.endsWith(File.separator)) dirRoot += File.separator; // on Unix/Linux, the temp dir is shared by many users, so we need to ensure // that the top working directory is different for each user if (!Platform.getOS().equals("win32")) { //$NON-NLS-1$ String home = System.getProperty("user.home"); //$NON-NLS-1$ home = Integer.toString(home.hashCode()); dirRoot += home + File.separator; } dirRoot += "eclipse" + File.separator + ".update" + File.separator + Long.toString(tmpseed) + File.separator; //$NON-NLS-1$ //$NON-NLS-2$ } String tmpName = dirRoot + Long.toString(++tmpseed) + File.separator; File tmpDir = new File(tmpName); verifyPath(tmpDir, false); if (!tmpDir.exists()) throw new FileNotFoundException(tmpName); return tmpDir; } /** * Create a new working file. The file is marked for deletion on exit. * * @see #lookupLocalFile(String) * @param tmpDir directory location for new file. Any missing directory * levels are created (and marked for deletion on exit) * @param name optional file name, or <code>null</code>. If name is not * specified, a temporary name is generated. * @return created working file * @exception IOException * @since 2.0 */ public static synchronized File createLocalFile(File tmpDir, String name) throws IOException { // create the local file File temp; String filePath; if (name != null) { // create file with specified name filePath = name.replace('/', File.separatorChar); if (filePath.startsWith(File.separator)) filePath = filePath.substring(1); temp = new File(tmpDir, filePath); } else { // create file with temp name temp = File.createTempFile("eclipse", null, tmpDir); //$NON-NLS-1$ } temp.deleteOnExit(); verifyPath(temp, true); return temp; } /** * The file is associated with a lookup key. * @param key optional lookup key, or <code>null</code>. * @param temp the local working file * @since 2.0.2 */ public synchronized static void mapLocalFile(String key, File temp) { // create file association if (key != null) { if (entryMap == null) entryMap = new HashMap(); entryMap.put(key, temp); } } /** * Returns a previously cached local file (in temporary area) matching the * specified key. * * @param key lookup key * @return cached file, or <code>null</code>. * @since 2.0 */ public static synchronized File lookupLocalFile(String key) { if (entryMap == null) return null; return (File) entryMap.get(key); } /** * Flushes all the keys from the local file map. * Reinitialize the cache. * * @since 2.1 */ public synchronized static void flushLocalFile() { entryMap = null; } /** * Removes the specified key from the local file map. The file is * not actually deleted until VM termination. * * @param key lookup key * @since 2.0 */ public static synchronized void removeLocalFile(String key) { if (entryMap != null) entryMap.remove(key); } /** * Copies specified input stream to the output stream. Neither stream * is closed as part of this operation. * * @param is input stream * @param os output stream * @param monitor progress monitor * @exception IOException * @exception InstallAbortedException * @since 2.0 */ public static void copy(InputStream is, OutputStream os, InstallMonitor monitor) throws IOException, InstallAbortedException { long offset = UpdateManagerUtils.copy(is, os, monitor, 0); if (offset != -1) { if (monitor != null && monitor.isCanceled()) { String msg = Messages.Feature_InstallationCancelled; throw new InstallAbortedException(msg, null); } else { throw new IOException(); } } } /** * Creates a CoreException from some other exception. * The type of the CoreException is <code>IStatus.ERROR</code> * If the exception passed as a parameter is also a CoreException, * the new CoreException will contain all the status of the passed * CoreException. * * @see IStatus#ERROR * @param s exception string * @param code the code reported * @param e actual exception being reported * @return a CoreException * @since 2.0 */ public static CoreException newCoreException(String s, int code, Throwable e) { String id = UpdateCore.getPlugin().getBundle().getSymbolicName(); // check the case of a multistatus IStatus status; if (e instanceof FeatureDownloadException) return (FeatureDownloadException)e; else if (e instanceof CoreException) { if (s == null) s = ""; //$NON-NLS-1$ status = new MultiStatus(id, code, s, e); IStatus childrenStatus = ((CoreException) e).getStatus(); ((MultiStatus) status).add(childrenStatus); ((MultiStatus) status).addAll(childrenStatus); } else { StringBuffer completeString = new StringBuffer(""); //$NON-NLS-1$ if (s != null) completeString.append(s); if (e != null) { completeString.append(" ["); //$NON-NLS-1$ String msg = e.getLocalizedMessage(); completeString.append(msg!=null?msg:e.toString()); completeString.append("]"); //$NON-NLS-1$ } status = new Status(IStatus.ERROR, id, code, completeString.toString(), e); } CoreException ce = new CoreException(status); if ( e instanceof FatalIOException) { ce = new CoreExceptionWithRootCause(status); ((CoreExceptionWithRootCause)ce).setRootException(e); } /* for when we move to 1.5 if ( e instanceof CoreException) { ce.initCause(e.getCause()); } else { ce.initCause(e); } if (e != null) ce.setStackTrace(e.getStackTrace());*/ return ce; } /** * Creates a CoreException from some other exception. * The type of the CoreException is <code>IStatus.ERROR</code> * If the exception passed as a parameter is also a CoreException, * the new CoreException will contain all the status of the passed * CoreException. * * @see IStatus#ERROR * @param s exception string * @param e actual exception being reported * @return a CoreException * @since 2.0 */ public static CoreException newCoreException(String s, Throwable e) { return newCoreException(s, IStatus.OK, e); } /** * Creates a CoreException from two other CoreException * * @param s overall exception string * @param s1 string for first detailed exception * @param s2 string for second detailed exception * @param e1 first detailed exception * @param e2 second detailed exception * @return a CoreException with multi-status * @since 2.0 */ public static CoreException newCoreException(String s, String s1, String s2, CoreException e1, CoreException e2) { String id = UpdateCore.getPlugin().getBundle().getSymbolicName(); if (s == null) s = ""; //$NON-NLS-1$ IStatus childStatus1 = e1.getStatus(); IStatus childStatus2 = e2.getStatus(); int code = (childStatus1.getCode() == childStatus2.getCode()) ? childStatus1.getCode() : IStatus.OK; MultiStatus multi = new MultiStatus(id, code, s, null); multi.add(childStatus1); multi.addAll(childStatus1); multi.add(childStatus2); multi.addAll(childStatus2); return new CoreException(multi); } /** * Formats a Date based on the default Locale * If teh Date is <code>null</code> returns an empty String * * @param date the Date to format * @return the formatted Date as a String * @since 2.0 */ public static String format(Date date) { if (date == null) return ""; //$NON-NLS-1$ return dateFormat.format(date); } /** * Perform shutdown processing for temporary file handling. * This method is called when platform is shutting down. * It is not intended to be called at any other time under * normal circumstances. A side-effect of calling this method * is that the contents of the temporary directory managed * by this class are deleted. * * @since 2.0 */ public static void shutdown() { if (dirRoot == null) return; File temp = new File(dirRoot); // temp directory root for this run cleanupTemp(temp); temp.delete(); } private static void cleanupTemp(File root) { File[] files = root.listFiles(); for (int i = 0; files != null && i < files.length; i++) { if (files[i].isDirectory()) cleanupTemp(files[i]); files[i].delete(); } } private static void verifyPath(File path, boolean isFile) { // if we are expecting a file back off 1 path element if (isFile) { if (path.getAbsolutePath().endsWith(File.separator)) { // make sure this is a file path = path.getParentFile(); isFile = false; } } // already exists ... just return if (path.exists()) return; // does not exist ... ensure parent exists File parent = path.getParentFile(); verifyPath(parent, false); // ensure directories are made. Mark files or directories for deletion if (!isFile) path.mkdir(); path.deleteOnExit(); } }