blob: 81827f07d28c2065405c0422b6744eca569d9759 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.core.internal.runtime;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Map;
import org.eclipse.core.internal.boot.PlatformURLHandler;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.osgi.framework.Bundle;
//TODO Add a comment
//TODO Remove the deadcode (WS_JAR_VARIANTS / OS / JAR and the methods)
public class FindSupport {
private static String[] WS_JAR_VARIANTS = buildWSVariants();
private static String[] OS_JAR_VARIANTS = buildOSVariants();
private static String[] NL_JAR_VARIANTS = buildNLVariants(InternalPlatform.getDefault().getNL());
private static String[] JAR_VARIANTS = buildVanillaVariants();
private static String[] buildWSVariants() {
ArrayList result = new ArrayList();
result.add("ws/" + InternalPlatform.getDefault().getWS()); //$NON-NLS-1$
result.add(""); //$NON-NLS-1$
return (String[]) result.toArray(new String[result.size()]);
}
private static String[] buildVanillaVariants() {
return new String[] {""}; //$NON-NLS-1$
}
private static String[] buildOSVariants() {
ArrayList result = new ArrayList();
result.add("os/" + InternalPlatform.getDefault().getOS() + "/" + InternalPlatform.getDefault().getOSArch()); //$NON-NLS-1$ //$NON-NLS-2$
result.add("os/" + InternalPlatform.getDefault().getOS()); //$NON-NLS-1$
result.add(""); //$NON-NLS-1$
return (String[]) result.toArray(new String[result.size()]);
}
private static String[] buildNLVariants(String nl) {
ArrayList result = new ArrayList();
IPath base = new Path("nl"); //$NON-NLS-1$
IPath path = new Path(nl.replace('_', '/'));
while (path.segmentCount() > 0) {
result.add(base.append(path).toString());
// for backwards compatibility only, don't replace the slashes
if (path.segmentCount() > 1)
result.add(base.append(path.toString().replace('/', '_')).toString());
path = path.removeLastSegments(1);
}
return (String[]) result.toArray(new String[result.size()]);
}
/**
* Returns a URL for the given path. Returns <code>null</code> if the URL
* could not be computed or created.
*
* TODO fix these comments
* @param path file path relative to plug-in installation location
* @param override map of override substitution arguments to be used for
* any $arg$ path elements. The map keys correspond to the substitution
* arguments (eg. "$nl$" or "$os$"). The resulting
* values must be of type java.lang.String. If the map is <code>null</code>,
* or does not contain the required substitution argument, the default
* is used.
* @return a URL for the given path or <code>null</code>
*
*/
private String getFileFromURL(URL target) {
String protocol = target.getProtocol();
if (protocol.equals(PlatformURLHandler.FILE))
return target.getFile();
if (protocol.equals(PlatformURLHandler.JAR)) {
// strip off the jar separator at the end of the url then do a recursive call
// to interpret the sub URL.
String file = target.getFile();
file = file.substring(0, file.length() - PlatformURLHandler.JAR_SEPARATOR.length());
try {
return getFileFromURL(new URL(file));
} catch (MalformedURLException e) {
}
}
return null;
}
public static URL find(Bundle bundle, IPath path) {
return find(bundle, path, null);
}
/**
* See doc on @link Platform#find(Bundle, IPath) Platform#find(Bundle, IPath)
*/
public static URL find(Bundle b, IPath path, Map override) {
if (path == null)
return null;
URL result = null;
// Check for the empty or root case first
if (path.isEmpty() || path.isRoot()) {
// Watch for the root case. It will produce a new
// URL which is only the root directory (and not the
// root of this plugin).
result = findInPlugin(b, Path.EMPTY);
if (result == null)
result = findInFragments(b, Path.EMPTY);
return result;
}
// Now check for paths without variable substitution
String first = path.segment(0);
if (first.charAt(0) != '$') {
result = findInPlugin(b, path);
if (result == null)
result = findInFragments(b, path);
return result;
}
// Worry about variable substitution
IPath rest = path.removeFirstSegments(1);
if (first.equalsIgnoreCase("$nl$")) //$NON-NLS-1$
return findNL(b, rest, override);
if (first.equalsIgnoreCase("$os$")) //$NON-NLS-1$
return findOS(b, rest, override);
if (first.equalsIgnoreCase("$ws$")) //$NON-NLS-1$
return findWS(b, rest, override);
if (first.equalsIgnoreCase("$files$")) //$NON-NLS-1$
return null;
return null;
}
private static URL findOS(Bundle b, IPath path, Map override) {
String os = null;
if (override != null)
try {
// check for override
os = (String) override.get("$os$"); //$NON-NLS-1$
} catch (ClassCastException e) {
// just in case
}
if (os == null)
// use default
os = InternalPlatform.getDefault().getOS();
if (os.length() == 0)
return null;
// Now do the same for osarch
String osArch = null;
if (override != null)
try {
// check for override
osArch = (String) override.get("$arch$"); //$NON-NLS-1$
} catch (ClassCastException e) {
// just in case
}
if (osArch == null)
// use default
osArch = InternalPlatform.getDefault().getOSArch();
if (osArch.length() == 0)
return null;
URL result = null;
IPath base = new Path("os").append(os).append(osArch); //$NON-NLS-1$
// Keep doing this until all you have left is "os" as a path
while (base.segmentCount() != 1) {
IPath filePath = base.append(path);
result = findInPlugin(b, filePath);
if (result != null)
return result;
result = findInFragments(b, filePath);
if (result != null)
return result;
base = base.removeLastSegments(1);
}
// If we get to this point, we haven't found it yet.
// Look in the plugin and fragment root directories
result = findInPlugin(b, path);
if (result != null)
return result;
return findInFragments(b, path);
}
private static URL findWS(Bundle b, IPath path, Map override) {
String ws = null;
if (override != null)
try {
// check for override
ws = (String) override.get("$ws$"); //$NON-NLS-1$
} catch (ClassCastException e) {
// just in case
}
if (ws == null)
// use default
ws = InternalPlatform.getDefault().getWS();
IPath filePath = new Path("ws").append(ws).append(path); //$NON-NLS-1$
// We know that there is only one segment to the ws path
// e.g. ws/win32
URL result = findInPlugin(b, filePath);
if (result != null)
return result;
result = findInFragments(b, filePath);
if (result != null)
return result;
// If we get to this point, we haven't found it yet.
// Look in the plugin and fragment root directories
result = findInPlugin(b, path);
if (result != null)
return result;
return findInFragments(b, path);
}
private static URL findNL(Bundle b, IPath path, Map override) {
String nl = null;
String[] nlVariants = null;
if (override != null)
try {
// check for override
nl = (String) override.get("$nl$"); //$NON-NLS-1$
} catch (ClassCastException e) {
// just in case
}
nlVariants = nl == null ? NL_JAR_VARIANTS : buildNLVariants(nl);
if (nl != null && nl.length() == 0)
return null;
URL result = null;
for (int i = 0; i < nlVariants.length; i++) {
IPath filePath = new Path(nlVariants[i]).append(path);
result = findInPlugin(b, filePath);
if (result != null)
return result;
result = findInFragments(b, filePath);
if (result != null)
return result;
}
// If we get to this point, we haven't found it yet.
// Look in the plugin and fragment root directories
result = findInPlugin(b, path);
if (result != null)
return result;
return findInFragments(b, path);
}
private static URL findInPlugin(Bundle b, IPath filePath) {
return b.getEntry(filePath.toString());
}
private static URL findInFragments(Bundle b, IPath filePath) {
Bundle[] fragments = InternalPlatform.getDefault().getFragments(b);
if (fragments == null)
return null;
URL fileURL = null;
int i = 0;
while (i < fragments.length && fileURL == null) {
fileURL = fragments[i].getEntry(filePath.toString());
i++;
}
return fileURL;
}
/**
* Returns an input stream for the specified file. The file path
* must be specified relative to this plug-in's installation location.
* Optionally, the platform searches for the correct localized version
* of the specified file using the users current locale, and Java
* naming convention for localized resource files (locale suffix appended
* to the specified file extension).
* <p>
* The caller must close the returned stream when done.
* </p>
*
* @param bundle the bundle to search
* @param file path relative to plug-in installation location
* @param localized <code>true</code> for the localized version
* of the file, and <code>false</code> for the file exactly
* as specified
* @return an input stream
* @exception IOException if the given path cannot be found in the given bundle
*/
public static final InputStream openStream(Bundle bundle, IPath file, boolean localized) throws IOException {
URL url = null;
if (!localized) {
url = findInPlugin(bundle, file);
if (url == null)
url = findInFragments(bundle, file);
} else {
url = FindSupport.find(bundle, file);
}
if (url != null)
return url.openStream();
throw new IOException("Cannot find " + file.toString()); //$NON-NLS-1$
}
}