blob: 99e8361297f8bd5fadd0cb26b8937ffa19710543 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2008 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.equinox.internal.frameworkadmin.utils;
import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.jar.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.equinox.internal.provisional.frameworkadmin.BundleInfo;
import org.eclipse.osgi.service.pluginconversion.PluginConversionException;
import org.eclipse.osgi.service.pluginconversion.PluginConverter;
import org.osgi.framework.Constants;
public class Utils {
private static final String PATH_SEP = "/"; //$NON-NLS-1$
private static final String[] EMPTY_STRING_ARRAY = new String[] {};
private static final String FILE_PROTOCOL = "file:"; //$NON-NLS-1$
private static final String FEATURE_MANIFEST = "feature.xml"; //$NON-NLS-1$
private static final String FRAGMENT_MANIFEST = "fragment.xml"; //$NON-NLS-1$
private static final String PLUGIN_MANIFEST = "plugin.xml"; //$NON-NLS-1$
/**
* Overwrite all properties of from to the properties of to. Return the result of to.
*
* @param to Properties whose keys and values of other Properties will be appended to.
* @param from Properties whose keys and values will be set to the other properties.
* @return Properties as a result of this method.
*/
public static Properties appendProperties(Properties to, Properties from) {
if (from != null) {
if (to == null)
to = new Properties();
// printoutProperties(System.out, "to", to);
// printoutProperties(System.out, "from", from);
for (Enumeration enumeration = from.keys(); enumeration.hasMoreElements();) {
String key = (String) enumeration.nextElement();
to.setProperty(key, from.getProperty(key));
}
}
// printoutProperties(System.out, "to", to);
return to;
}
//Return a dictionary representing a manifest. The data may result from plugin.xml conversion
private static Dictionary basicLoadManifest(File bundleLocation) {
InputStream manifestStream = null;
ZipFile jarFile = null;
try {
try {
String fileExtention = bundleLocation.getName();
fileExtention = fileExtention.substring(fileExtention.lastIndexOf('.') + 1);
// Handle a JAR'd bundle
if ("jar".equalsIgnoreCase(fileExtention) && bundleLocation.isFile()) { //$NON-NLS-1$
jarFile = new ZipFile(bundleLocation, ZipFile.OPEN_READ);
ZipEntry manifestEntry = jarFile.getEntry(JarFile.MANIFEST_NAME);
if (manifestEntry != null) {
manifestStream = jarFile.getInputStream(manifestEntry);
}
} else {
// we have a directory-based bundle
File bundleManifestFile = new File(bundleLocation, JarFile.MANIFEST_NAME);
if (bundleManifestFile.exists())
manifestStream = new BufferedInputStream(new FileInputStream(new File(bundleLocation, JarFile.MANIFEST_NAME)));
}
} catch (IOException e) {
//ignore
}
// we were unable to get an OSGi manifest file so try and convert an old-style manifest
if (manifestStream == null)
return convertPluginManifest(bundleLocation, true);
// It is not a manifest, but a plugin or a fragment
try {
Manifest m = new Manifest(manifestStream);
Dictionary manifest = manifestToProperties(m.getMainAttributes());
// add this check to handle the case were we read a non-OSGi manifest
if (manifest.get(Constants.BUNDLE_SYMBOLICNAME) == null)
return convertPluginManifest(bundleLocation, true);
return manifest;
} catch (IOException ioe) {
return null;
}
} finally {
try {
if (manifestStream != null)
manifestStream.close();
} catch (IOException e1) {
//Ignore
}
try {
if (jarFile != null)
jarFile.close();
} catch (IOException e2) {
//Ignore
}
}
}
public static void checkAbsoluteDir(File file, String dirName) throws IllegalArgumentException {
if (file == null)
throw new IllegalArgumentException(dirName + " is null");
if (!file.isAbsolute())
throw new IllegalArgumentException(dirName + " is not absolute path. file=" + file.getAbsolutePath());
if (!file.isDirectory())
throw new IllegalArgumentException(dirName + " is not directory. file=" + file.getAbsolutePath());
}
public static void checkAbsoluteFile(File file, String dirName) {//throws ManipulatorException {
if (file == null)
throw new IllegalArgumentException(dirName + " is null");
if (!file.isAbsolute())
throw new IllegalArgumentException(dirName + " is not absolute path. file=" + file.getAbsolutePath());
if (file.isDirectory())
throw new IllegalArgumentException(dirName + " is not file but directory");
}
public static URL checkFullUrl(URL url, String urlName) throws IllegalArgumentException {//throws ManipulatorException {
if (url == null)
throw new IllegalArgumentException(urlName + " is null");
if (!url.getProtocol().endsWith("file"))
return url;
File file = new File(url.getFile());
if (!file.isAbsolute())
throw new IllegalArgumentException(urlName + "(" + url + ") does not have absolute path");
if (file.getAbsolutePath().startsWith(PATH_SEP))
return url;
try {
return getUrl("file", null, PATH_SEP + file.getAbsolutePath());
} catch (MalformedURLException e) {
throw new IllegalArgumentException(urlName + "(" + "file:" + PATH_SEP + file.getAbsolutePath() + ") is not fully quallified");
}
}
public static void createParentDir(File file) throws IOException {
File parent = file.getParentFile();
if (parent == null)
return;
parent.mkdirs();
}
/**
* Deletes the given file recursively, adding failure info to
* the provided status object. The filePath is passed as a parameter
* to optimize java.io.File object creation.
*/
// Implementation taken from the Eclipse File sytem bundle class LocalFile.
// TODO consider putting back the progress and cancelation support.
private static boolean internalDelete(File target, String pathToDelete) {
//first try to delete - this should succeed for files and symbolic links to directories
if (target.delete() || !target.exists())
return true;
if (target.isDirectory()) {
String[] list = target.list();
if (list == null)
list = EMPTY_STRING_ARRAY;
int parentLength = pathToDelete.length();
boolean failedRecursive = false;
for (int i = 0, imax = list.length; i < imax; i++) {
//optimized creation of child path object
StringBuffer childBuffer = new StringBuffer(parentLength + list[i].length() + 1);
childBuffer.append(pathToDelete);
childBuffer.append(File.separatorChar);
childBuffer.append(list[i]);
String childName = childBuffer.toString();
// try best effort on all children so put logical OR at end
failedRecursive = !internalDelete(new java.io.File(childName), childName) || failedRecursive;
}
try {
// don't try to delete the root if one of the children failed
if (!failedRecursive && target.delete())
return true;
} catch (Exception e) {
// we caught a runtime exception so log it
return false;
}
}
// message = NLS.bind(Messages.couldnotDelete, target.getAbsolutePath());
return false;
}
public static void deleteDir(File target) throws IOException {
internalDelete(target, target.getAbsolutePath());
throw new IOException("Fail to delete Dir(" + target.getAbsolutePath() + ")");
}
/**
* First, it replaces File.seperator of relativePath to "/".
* If relativePath is in URL format, return its URL.
* Otherwise, create absolute URL based on the baseUrl.
*
* @param relativePath
* @param baseUrl
* @return URL
* @throws MalformedURLException
*/
public static URL formatUrl(String relativePath, URL baseUrl) throws MalformedURLException {//throws ManipulatorException {
relativePath = Utils.replaceAll(relativePath, File.separator, "/");
URL url = null;
try {
url = new URL(relativePath);
if (url.getProtocol().equals("file"))
if (!(new File(url.getFile())).isAbsolute())
url = getUrlInFull(relativePath, baseUrl);
return url;
} catch (MalformedURLException e) {
return getUrlInFull(relativePath, baseUrl);
}
}
public static BundleInfo[] getBundleInfosFromList(List list) {
if (list == null)
return new BundleInfo[0];
BundleInfo[] ret = new BundleInfo[list.size()];
list.toArray(ret);
return ret;
}
public static String[] getClauses(String header) {
StringTokenizer token = new StringTokenizer(header, ",");
List list = new LinkedList();
while (token.hasMoreTokens()) {
list.add(token.nextToken());
}
String[] ret = new String[list.size()];
list.toArray(ret);
return ret;
}
public static String[] getClausesManifestMainAttributes(String location, String name) {
return getClauses(getManifestMainAttributes(location, name));
}
public static String getManifestMainAttributes(String location, String name) {
Dictionary manifest = Utils.getOSGiManifest(location);
if (manifest == null)
throw new RuntimeException("Unable to locate bundle manifest: " + location);
return (String) manifest.get(name);
}
public static Dictionary getOSGiManifest(String location) {
if (location == null)
return null;
// if we have a file-based URL that doesn't end in ".jar" then...
if (location.startsWith(FILE_PROTOCOL) && !location.endsWith(".jar"))
return basicLoadManifest(new File(location.substring(FILE_PROTOCOL.length())));
try {
JarFile jar = null;
File file = null;
if (location.startsWith(FILE_PROTOCOL)) {
file = new File(location.substring(FILE_PROTOCOL.length()));
jar = new JarFile(file);
} else {
URL url = new URL("jar:" + location + "!/");
JarURLConnection jarConnection = (JarURLConnection) url.openConnection();
jar = jarConnection.getJarFile();
// todo should set this var if possible
// file = ;
}
try {
Manifest manifest = jar.getManifest();
// we might have an old-style plug-in so look for an old plug-in manifest
if (manifest == null) {
if (file == null)
return null;
// make sure we have something to convert
JarEntry entry = jar.getJarEntry(PLUGIN_MANIFEST);
if (entry == null)
entry = jar.getJarEntry(FRAGMENT_MANIFEST);
if (entry == null)
return null;
return convertPluginManifest(file, true);
}
Attributes attributes = manifest.getMainAttributes();
// if we have a JAR'd bundle that has a non-OSGi manifest file (like
// the ones produced by Ant, then try and convert the plugin.xml
if (attributes.getValue(Constants.BUNDLE_SYMBOLICNAME) == null) {
if (file == null)
return null;
return convertPluginManifest(file, true);
}
Dictionary result = new Hashtable();
for (Iterator iter = attributes.keySet().iterator(); iter.hasNext();) {
String key = iter.next().toString();
result.put(key, attributes.getValue(key));
}
return result;
} finally {
jar.close();
}
} catch (IOException e) {
if (System.getProperty("osgi.debug") != null) {
System.err.println("location=" + location);
e.printStackTrace();
}
}
return null;
}
/*
* Copied from BundleDescriptionFactory in the metadata generator.
*/
private static Dictionary convertPluginManifest(File bundleLocation, boolean logConversionException) {
PluginConverter converter;
try {
converter = org.eclipse.equinox.internal.frameworkadmin.utils.Activator.acquirePluginConverter();
if (converter == null) {
new RuntimeException("Unable to aquire PluginConverter service during generation for: " + bundleLocation).printStackTrace(); //$NON-NLS-1$
return null;
}
return converter.convertManifest(bundleLocation, false, null, true, null);
} catch (PluginConversionException convertException) {
// only log the exception if we had a plugin.xml or fragment.xml and we failed conversion
if (bundleLocation.getName().equals(FEATURE_MANIFEST))
return null;
if (!new File(bundleLocation, PLUGIN_MANIFEST).exists() && !new File(bundleLocation, FRAGMENT_MANIFEST).exists())
return null;
if (logConversionException) {
IStatus status = new Status(IStatus.WARNING, "org.eclipse.equinox.frameworkadmin", 0, "Error converting bundle manifest.", convertException);
System.out.println(status);
//TODO Need to find a way to get a logging service to log
}
return null;
}
}
public static String getPathFromClause(String clause) {
if (clause == null)
return null;
if (clause.indexOf(";") != -1)
clause = clause.substring(0, clause.indexOf(";"));
return clause.trim();
}
public static String getRelativePath(File target, File from) {
String targetPath = Utils.replaceAll(target.getAbsolutePath(), File.separator, PATH_SEP);
String fromPath = Utils.replaceAll(from.getAbsolutePath(), File.separator, PATH_SEP);
String[] targetTokens = Utils.getTokens(targetPath, PATH_SEP);
String[] fromTokens = Utils.getTokens(fromPath, PATH_SEP);
int index = -1;
for (int i = 0; i < fromTokens.length; i++)
if (fromTokens[i].equals(targetTokens[i]))
index = i;
else
break;
StringBuffer sb = new StringBuffer();
for (int i = index + 1; i < fromTokens.length; i++)
sb.append(".." + PATH_SEP);
for (int i = index + 1; i < targetTokens.length; i++)
if (i != targetTokens.length - 1)
sb.append(targetTokens[i] + PATH_SEP);
else
sb.append(targetTokens[i]);
return sb.toString();
}
public static String getRelativePath(URL target, URL from) throws IllegalArgumentException {
if (!target.getProtocol().equals(from.getProtocol()))
throw new IllegalArgumentException("Protocols of target(=" + target + ") and from(=" + from + ") does NOT equal");
if (target.getHost() != null && target.getHost().length() != 0) {
//System.out.println("target.getHost()=" + target.getHost());
if (from.getHost() != null && from.getHost().length() != 0) {
if (!target.getHost().equals(from.getHost()))
throw new IllegalArgumentException("Hosts of target(=" + target + ") and from(=" + from + ") does NOT equal");
if (target.getPort() != (from.getPort()))
throw new IllegalArgumentException("Ports of target(=" + target + ") and from(=" + from + ") does NOT equal");
} else
throw new IllegalArgumentException("While Host of target(=" + target + ") is set, Host of from is null.target.getHost()=" + target.getHost());
} else if (from.getHost() != null && from.getHost().length() != 0)
throw new IllegalArgumentException("While Host of from(=" + from + ") is set, Host of target is null");
String targetPath = target.getFile();
String fromPath = from.getFile();
String[] targetTokens = Utils.getTokens(targetPath, PATH_SEP);
String[] fromTokens = Utils.getTokens(fromPath, PATH_SEP);
int index = -1;
for (int i = 0; i < fromTokens.length; i++)
if (fromTokens[i].equals(targetTokens[i]))
index = i;
else
break;
StringBuffer sb = new StringBuffer();
for (int i = index + 1; i < fromTokens.length; i++)
sb.append(".." + PATH_SEP);
for (int i = index + 1; i < targetTokens.length; i++)
if (i != targetTokens.length - 1)
sb.append(targetTokens[i] + PATH_SEP);
else
sb.append(targetTokens[i]);
return sb.toString();
}
// public static URL getAbsoluteUrl(String relativePath, URL baseUrl) throws FwLauncherException {
// relativePath = Utils.replaceAll(relativePath, File.separator, "/");
// try {
// return new URL(baseUrl, relativePath);
// } catch (MalformedURLException e) {
// throw new FwLauncherException("Absolute URL cannot be created. \nrelativePath=" + relativePath + ",baseUrl=" + baseUrl, e, FwLauncherException.URL_FORMAT_ERROR);
// }
// }
// public static void setProperties(Properties to, Properties from, String key) {
// if (from != null) {
// String value = from.getProperty(key);
// if (value != null) {
// if (to != null)
// to = new Properties();
// to.setProperty(key, value);
// }
// }
// }
// public static int getIntProperties(Properties props, String key) {//throws ManipulatorException {
// if (props == null)
// throw new IllegalArgumentException("props == null");
// String value = null;
// try {
// value = props.getProperty(key);
// return Integer.parseInt(value);
// } catch (NumberFormatException nfe) {
// throw new ManipulatorException("key=" + key + ",value=" + value, nfe, ManipulatorException.OTHERS);
// }
// }
/**
* This method will be called for create a backup file.
*
* @param file target file
* @return File backup file whose filename consists of "hogehoge.yyyyMMddHHmmss.ext" or
* "hogehoge.yyyyMMddHHmmss".
*/
public static File getSimpleDataFormattedFile(File file) {
SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
String date = df.format(new Date());
String filename = file.getName();
int index = filename.lastIndexOf(".");
if (index != -1)
filename = filename.substring(0, index) + "." + date + "." + filename.substring(index + 1);
else
filename = filename + "." + date;
File dest = new File(file.getParentFile(), filename);
return dest;
}
public static String[] getTokens(String msg, String delim) {
return getTokens(msg, delim, false);
}
public static String[] getTokens(String msg, String delim, boolean returnDelims) {
StringTokenizer targetST = new StringTokenizer(msg, delim, returnDelims);
String[] tokens = new String[targetST.countTokens()];
ArrayList list = new ArrayList(targetST.countTokens());
while (targetST.hasMoreTokens()) {
list.add(targetST.nextToken());
}
list.toArray(tokens);
return tokens;
}
public static URL getUrl(String protocol, String host, String file) throws MalformedURLException {// throws ManipulatorException {
file = Utils.replaceAll(file, File.separator, "/");
return new URL(protocol, host, file);
}
public static URL getUrlInFull(String path, URL from) throws MalformedURLException {//throws ManipulatorException {
Utils.checkFullUrl(from, "from");
path = Utils.replaceAll(path, File.separator, "/");
//System.out.println("from.toExternalForm()=" + from.toExternalForm());
String fromSt = Utils.removeLastCh(from.toExternalForm(), '/');
//System.out.println("fromSt=" + fromSt);
if (path.startsWith("/")) {
String fileSt = from.getFile();
return new URL(fromSt.substring(0, fromSt.lastIndexOf(fileSt) - 1) + path);
}
return new URL(fromSt + "/" + path);
}
private static Properties manifestToProperties(Attributes d) {
Iterator iter = d.keySet().iterator();
Properties result = new Properties();
while (iter.hasNext()) {
Attributes.Name key = (Attributes.Name) iter.next();
result.put(key.toString(), d.get(key));
}
return result;
}
/**
* Just used for debug.
*
* @param ps printstream
* @param name name of properties
* @param props properties whose keys and values will be printed out.
*/
public static void printoutProperties(PrintStream ps, String name, Properties props) {
if (props == null || props.size() == 0) {
ps.println("Props(" + name + ") is empty");
return;
}
ps.println("Props(" + name + ")=");
for (Enumeration enumeration = props.keys(); enumeration.hasMoreElements();) {
String key = (String) enumeration.nextElement();
ps.print("\tkey=" + key);
ps.println("\tvalue=" + props.getProperty(key));
}
}
public static String removeLastCh(String target, char ch) {
while (target.charAt(target.length() - 1) == ch) {
target = target.substring(0, target.length() - 1);
}
return target;
}
public static String replaceAll(String st, String oldSt, String newSt) {
if (oldSt.equals(newSt))
return st;
int index = -1;
while ((index = st.indexOf(oldSt)) != -1) {
st = st.substring(0, index) + newSt + st.substring(index + oldSt.length());
}
return st;
}
public static String shrinkPath(String target) {
String targetPath = Utils.replaceAll(target, File.separator, PATH_SEP);
String[] targetTokens = Utils.getTokens(targetPath, PATH_SEP);
//String[] fromTokens = Utils.getTokens(fromPath, PATH_SEP);
for (int i = 0; i < targetTokens.length; i++)
if (targetTokens[i].equals("")) {
targetTokens[i] = null;
} else if (targetTokens[i].equals(".")) {
targetTokens[i] = null;
} else if (targetTokens[i].equals("..")) {
int id = i - 1;
while (targetTokens[id] == null) {
id--;
}
targetTokens[id] = null;
}
StringBuffer sb = new StringBuffer();
if (targetPath.startsWith(PATH_SEP))
sb.append(PATH_SEP);
for (int i = 0; i < targetTokens.length; i++)
if (targetTokens[i] != null)
sb.append(targetTokens[i] + PATH_SEP);
String ret = sb.toString();
if (!targetPath.endsWith(PATH_SEP))
ret = ret.substring(0, ret.lastIndexOf(PATH_SEP));
return ret;
}
/**
* Sort by increasing order of startlevels.
*
* @param bInfos array of BundleInfos to be sorted.
* @param initialBSL initial bundle start level to be used.
* @return sorted array of BundleInfos
*/
public static BundleInfo[] sortBundleInfos(BundleInfo[] bInfos, int initialBSL) {
SortedMap bslToList = new TreeMap();
for (int i = 0; i < bInfos.length; i++) {
Integer sL = new Integer(bInfos[i].getStartLevel());
if (sL.intValue() == BundleInfo.NO_LEVEL)
sL = new Integer(initialBSL);
List list = (List) bslToList.get(sL);
if (list == null) {
list = new LinkedList();
bslToList.put(sL, list);
}
list.add(bInfos[i]);
}
// bslToList is sorted by the key (StartLevel).
List bundleInfoList = new LinkedList();
for (Iterator ite = bslToList.keySet().iterator(); ite.hasNext();) {
Integer sL = (Integer) ite.next();
List list = (List) bslToList.get(sL);
for (Iterator ite2 = list.iterator(); ite2.hasNext();) {
BundleInfo bInfo = (BundleInfo) ite2.next();
bundleInfoList.add(bInfo);
}
}
return getBundleInfosFromList(bundleInfoList);
}
/**
* get String representing the given properties.
*
* @param name name of properties
* @param props properties whose keys and values will be printed out.
*/
public static String toStringProperties(String name, Properties props) {
if (props == null || props.size() == 0) {
return "Props(" + name + ") is empty\n";
}
StringBuffer sb = new StringBuffer();
sb.append("Props(" + name + ") is \n");
for (Enumeration enumeration = props.keys(); enumeration.hasMoreElements();) {
String key = (String) enumeration.nextElement();
sb.append("\tkey=" + key + "\tvalue=" + props.getProperty(key) + "\n");
}
return sb.toString();
}
public static void validateUrl(URL url) {//throws ManipulatorException {
try {//test
URLConnection connection = url.openConnection();
connection.connect();
} catch (IOException e) {
throw new IllegalArgumentException("URL(" + url + ") cannot be connected.");
}
}
}