blob: e7878e904b5444f1cd71c459a491ef57ad6df88c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2019 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* 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.JarFile;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.eclipse.core.runtime.URIUtil;
import org.eclipse.equinox.frameworkadmin.BundleInfo;
import org.eclipse.osgi.util.ManifestElement;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
public class Utils {
private static final String FILE_SCHEME = "file"; //$NON-NLS-1$
private static final String PATH_SEP = "/"; //$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<Object> 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<String, String> basicLoadManifest(File bundleLocation) {
InputStream manifestStream = null;
ZipFile jarFile = null;
try {
try {
// Handle a JAR'd bundle
if (bundleLocation.isFile()) {
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 null;
try {
Map<String, String> manifest = ManifestElement.parseBundleManifest(manifestStream, null);
// add this check to handle the case were we read a non-OSGi manifest
if (manifest.get(Constants.BUNDLE_SYMBOLICNAME) == null)
return null;
return manifestToProperties(manifest);
} catch (IOException | BundleException 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"); //$NON-NLS-1$
if (!file.isAbsolute())
throw new IllegalArgumentException(dirName + " is not absolute path. file=" + file.getAbsolutePath()); //$NON-NLS-1$
if (!file.isDirectory())
throw new IllegalArgumentException(dirName + " is not directory. file=" + file.getAbsolutePath()); //$NON-NLS-1$
}
public static void checkAbsoluteFile(File file, String dirName) {// throws ManipulatorException {
if (file == null)
throw new IllegalArgumentException(dirName + " is null"); //$NON-NLS-1$
if (!file.isAbsolute())
throw new IllegalArgumentException(dirName + " is not absolute path. file=" + file.getAbsolutePath()); //$NON-NLS-1$
if (file.isDirectory())
throw new IllegalArgumentException(dirName + " is not file but directory"); //$NON-NLS-1$
}
public static URL checkFullUrl(URL url, String urlName) throws IllegalArgumentException {// throws
// ManipulatorException
// {
if (url == null)
throw new IllegalArgumentException(urlName + " is null"); //$NON-NLS-1$
if (!url.getProtocol().endsWith("file")) //$NON-NLS-1$
return url;
File file = new File(url.getFile());
if (!file.isAbsolute())
throw new IllegalArgumentException(urlName + "(" + url + ") does not have absolute path"); //$NON-NLS-1$ //$NON-NLS-2$
if (file.getAbsolutePath().startsWith(PATH_SEP))
return url;
try {
return getUrl("file", null, PATH_SEP + file.getAbsolutePath()); //$NON-NLS-1$
} catch (MalformedURLException e) {
throw new IllegalArgumentException(
urlName + "(" + "file:" + PATH_SEP + file.getAbsolutePath() + ") is not fully quallified"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
}
public static boolean createParentDir(File file) {
File parent = file.getParentFile();
if (parent == null)
return false;
if (parent.exists())
return true;
return parent.mkdirs();
}
public static BundleInfo[] getBundleInfosFromList(List<BundleInfo> 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, ","); //$NON-NLS-1$
List<String> 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(URI location, String name) {
return getClauses(getManifestMainAttributes(location, name));
}
public static String getManifestMainAttributes(URI location, String name) {
Dictionary<String, String> manifest = Utils.getOSGiManifest(location);
if (manifest == null)
throw new RuntimeException("Unable to locate bundle manifest: " + location); //$NON-NLS-1$
return manifest.get(name);
}
public static Dictionary<String, String> getOSGiManifest(URI location) {
if (location == null)
return null;
// if we have a file-based URL that doesn't end in ".jar" then...
if (FILE_SCHEME.equals(location.getScheme()))
return basicLoadManifest(URIUtil.toFile(location));
try {
URL url = new URL("jar:" + location.toString() + "!/"); //$NON-NLS-1$//$NON-NLS-2$
JarURLConnection jarConnection = (JarURLConnection) url.openConnection();
try (ZipFile jar = jarConnection.getJarFile()) {
ZipEntry entry = jar.getEntry(JarFile.MANIFEST_NAME);
if (entry == null)
return null;
Map<String, String> manifest = ManifestElement.parseBundleManifest(jar.getInputStream(entry), null);
// 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 (manifest.get(Constants.BUNDLE_SYMBOLICNAME) == null) {
return null;
}
return manifestToProperties(manifest);
} catch (BundleException e) {
return null;
}
} catch (IOException e) {
if (System.getProperty("osgi.debug") != null) { //$NON-NLS-1$
System.err.println("location=" + location); //$NON-NLS-1$
e.printStackTrace();
}
}
return null;
}
public static String getPathFromClause(String clause) {
if (clause == null)
return null;
if (clause.indexOf(";") != -1) //$NON-NLS-1$
clause = clause.substring(0, clause.indexOf(";")); //$NON-NLS-1$
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;
StringBuilder sb = new StringBuilder();
for (int i = index + 1; i < fromTokens.length; i++)
sb.append(".." + PATH_SEP); //$NON-NLS-1$
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();
}
/**
* 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"); //$NON-NLS-1$
String date = df.format(new Date());
String filename = file.getName();
int index = filename.lastIndexOf("."); //$NON-NLS-1$
if (index != -1)
filename = filename.substring(0, index) + "." + date + "." + filename.substring(index + 1); //$NON-NLS-1$ //$NON-NLS-2$
else
filename = filename + "." + date; //$NON-NLS-1$
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<String> 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, "/"); //$NON-NLS-1$
return new URL(protocol, host, file);
}
public static URL getUrlInFull(String path, URL from) throws MalformedURLException {// throws ManipulatorException
Utils.checkFullUrl(from, "from"); //$NON-NLS-1$
path = Utils.replaceAll(path, File.separator, "/"); //$NON-NLS-1$
// System.out.println("from.toExternalForm()=" + from.toExternalForm());
String fromSt = Utils.removeLastCh(from.toExternalForm(), '/');
// System.out.println("fromSt=" + fromSt);
if (path.startsWith("/")) { //$NON-NLS-1$
String fileSt = from.getFile();
return new URL(fromSt.substring(0, fromSt.lastIndexOf(fileSt) - 1) + path);
}
return new URL(fromSt + "/" + path); //$NON-NLS-1$
}
private static Dictionary<String, String> manifestToProperties(Map<String, String> d) {
Dictionary<String, String> result = new Hashtable<>();
for (String key : d.keySet()) {
result.put(key, 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"); //$NON-NLS-1$ //$NON-NLS-2$
return;
}
ps.println("Props(" + name + ")="); //$NON-NLS-1$ //$NON-NLS-2$
for (Enumeration<Object> enumeration = props.keys(); enumeration.hasMoreElements();) {
String key = (String) enumeration.nextElement();
ps.print("\tkey=" + key); //$NON-NLS-1$
ps.println("\tvalue=" + props.getProperty(key)); //$NON-NLS-1$
}
}
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;
}
/**
* 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<Integer, List<BundleInfo>> bslToList = new TreeMap<>();
for (BundleInfo bInfo : bInfos) {
Integer sL = Integer.valueOf(bInfo.getStartLevel());
if (sL.intValue() == BundleInfo.NO_LEVEL)
sL = Integer.valueOf(initialBSL);
List<BundleInfo> list = bslToList.get(sL);
if (list == null) {
list = new LinkedList<>();
bslToList.put(sL, list);
}
list.add(bInfo);
}
// bslToList is sorted by the key (StartLevel).
List<BundleInfo> bundleInfoList = new LinkedList<>();
for (Integer sL : bslToList.keySet()) {
List<BundleInfo> list = bslToList.get(sL);
for (BundleInfo bInfo : list) {
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"; //$NON-NLS-1$ //$NON-NLS-2$
}
StringBuilder sb = new StringBuilder();
sb.append("Props(" + name + ") is \n"); //$NON-NLS-1$ //$NON-NLS-2$
for (Enumeration<Object> enumeration = props.keys(); enumeration.hasMoreElements();) {
String key = (String) enumeration.nextElement();
sb.append("\tkey=" + key + "\tvalue=" + props.getProperty(key) + "\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return sb.toString();
}
}