blob: 456dd67d8d78307f493b57311cf79000eae92fb0 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2007 IBM Corporation.
* 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:
* <a href="mailto:masquill@us.ibm.com>Mike Squillace</a> - initial API and implementation
*******************************************************************************/
package org.eclipse.actf.util.resources;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Dictionary;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.actf.core.config.Version;
import org.eclipse.actf.util.Utils;
import org.eclipse.actf.util.logging.IReporter;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.osgi.service.datalocation.Location;
import org.osgi.framework.Bundle;
/**
* an implementation for locating resources within the Eclipse framework.
*
* @author <a href="mailto:masquill@us.ibm.com>Mike Squillace</a>
*
*/
public class EclipseResourceLocator extends DefaultResourceLocator
{
private List _bundles = new LinkedList();
/**
* used to identify the bundles in which resources are to be found. Each bundle in
* Eclipse has its own class loader and we leave it to the platform to choose the class loader to be used. Thus, calling this method means that a <code>ClassLoader</code>
* should not be passed to <code>getResourceAsStream</code>. Also, not all methods for finding resources in bundles
* use <code>ClassLoader</code> objects.
*
* @param bundle - the name of the bundle (i.e. plug-in) that is to be searched for a resource
*/
public void registerBundleName (String bundle) {
_bundles.add(bundle);
}
/**
* {@inheritDoc}
* Note that resources are located in the context of bundles in Eclipse.
* @see #setBundle(String)
*/
public InputStream getResourceAsStream (String id, ClassLoader loader) {
return getResourceAsStream(id, null, null, loader);
}
public InputStream getResourceAsStream (String id, String base,
String ext, ClassLoader loader) {
return loader != null
? super.getResourceAsStream(id, base, ext, loader)
: getResourceAsStream(id, base, ext);
}
private InputStream getResourceAsStream (String id, String base, String ext) {
InputStream stream = null;
for (Iterator iter = _bundles.listIterator(); iter.hasNext() & stream == null; ){
String bundleName = (String) iter.next();
stream = getResourceAsStream(id, base, ext, bundleName);
}
return stream;
}
public InputStream getResourceAsStream (String id, String base,
String ext, String bundleName) {
InputStream stream = null; //Stream to be returned.
String relativePath = getRelativePath(base, id, ext);
IPath pathToFile = null;
if (bundleName != null) {
pathToFile = getPathToFile(bundleName, relativePath);
}
if (pathToFile != null) {
try {
stream = new FileInputStream(pathToFile.toFile());
Utils.println(Utils.ALL, "Created stream for file - " + relativePath + " using bundle " + bundleName);
}catch (FileNotFoundException e) {
//Don't need to report anything in this catch , the result of the call to
//getPathToFile will have already made sure that this file exists.
}
} else {
Utils.println(Utils.ALL, "unable to create stream for file - " + relativePath + " using bundle " + bundleName);
}
return stream;
}
private String getRelativePath (String base, String fileName, String ext) {
String relativePath = null;
//First, build the relative file path that we want to look for.
if (base == null) {
//If we have a base of null, default to using the resources directory
base = IResourceLocator.DEFAULT_ACTF_RESOURCES_DIR;
}
if (ext != null) {
//The passed extension is not null, use it.
relativePath = base + File.separator + fileName + "." + ext;
}else {
//Null for an extension means we default to using .properties
relativePath = base + File.separator + fileName + ".properties";
}
return relativePath;
}
/**
* {@inheritDoc}
* <p>Search Algorithm is:</p>
* <p><ol>
* <li>Search through the registered ClassLoaders for the resource
* <li>Search through the registered Bundles for the resource
* <li>Test if the name is actually a Bundle
* </ol></p>
*/
public URL getResource (String name) {
URL result = super.getResource(name);
// If we didn't find the resource in any of the registered ClassLoaders
// Search through the bundle list to see if the resource is in a bundle
if ( result == null ) {
IPath ipath = null;
for (Iterator iter = _bundles.listIterator(); iter.hasNext() & ipath == null; ){
String bundleName = (String) iter.next();
if ( bundleName.equals(name)) {
ipath = getPathToBundle( name );
} else {
ipath = getPathToFile(bundleName, name);
}
}
// If the resource was not in any of the registered bundles
// Check to see if the resource is a bundle name
if ( ipath == null ) {
ipath = getPathToBundle( name );
}
// If we found the resource then create a URL to return
if ( ipath != null ) {
try {
result = ipath.toFile().toURL();
} catch (MalformedURLException e) {
}
}
}
return result;
}
/**
* {@inheritDoc}
* Note: You may also pass a bundle name to this method to obtain a bundle path
*/
public String getPath ( String name ) {
String result = null;
URL url = getResource( name );
result = convertToFileURL( url );
return result;
}
/**
* {@inheritDoc}
*/
public String[] getPaths( String name ) {
String[] result = null;
URL[] urls = getResources( name );
if ( urls != null ) {
result = new String[urls.length];
for( int i=0; i < urls.length; i++ ) {
result[i] = convertToFileURL( urls[i]);
}
}
return result;
}
private String convertToFileURL( URL url ) {
String result = null;
if ( url != null ) {
try {
URL fileUrl = FileLocator.toFileURL(url);
result = fileUrl.getFile().substring(1); // remove "file:/"
} catch( IOException e) {
result = null;
}
}
return result;
}
public IPath getPathToFile (String bundleName, String relativePath) {
Path absolutePath = null;
if (bundleName != null && bundleName.length() > 0) {
Bundle bundle = Platform.getBundle(bundleName);
if (bundle != null) {
Path relativeFilePath = new Path(relativePath);
URL pathUrl = Platform.find(bundle, relativeFilePath);
if (pathUrl == null) {
// look in resources directory
relativeFilePath = new Path(DEFAULT_ACTF_RESOURCES_DIR + "/" + relativePath);
pathUrl = Platform.find(bundle, relativeFilePath);
}
if (pathUrl != null) {
try {
pathUrl = Platform.resolve(pathUrl);
absolutePath = new Path(new File(pathUrl.getFile()).getAbsolutePath());
Utils.println(IReporter.DETAIL,
"getPathToFile(), absolute path to " + relativePath + " = " + absolutePath.toString());
}catch (IOException ioe) {
Utils.println(IReporter.SYSTEM_NONFATAL, ioe);
}
}
}
}
return absolutePath;
}
private IPath getPathToBundle (String bundleName) {
IPath absolutePath = null;
if (bundleName == null || bundleName.length() == 0) { return absolutePath; }
Version eclipseVersion = getEclipseVersion();
Bundle bundle = Platform.getBundle(bundleName);
if (bundle != null) {
// In Eclipse 3.1 the bundle location is always relative. To get the
// absolute path we
// need start with the path of the Eclipse installation, append the
// relative path
// to the bundle and let the Path class resolve the path segments to
// for the canonical
// path.
// In Eclipse 3.0 the bundle locations are always absolute.
if ((eclipseVersion.getMajor() == 3)
&& (eclipseVersion.getMinor() == 0)) {
absolutePath = new Path("");
}else {
absolutePath = new Path(getEclipseInstallPath());
}
// The bundle location always begins with "update@" and ends with
// the relative bundle location.
// We have to strip off the "update@" before we append it to the
// path.
String[] bundlePaths = bundle.getLocation().split("@");
absolutePath = absolutePath.append(bundlePaths[1]);
if ((eclipseVersion.getMajor() == 3)
&& (eclipseVersion.getMinor() == 0)) {
IPath path = absolutePath.makeAbsolute();
// String [] segments = path.segments();
// for ( int i=0; i<path.segmentCount(); i++) {
// ConfigUtils.logDebug("\tsegment [" + i + "] - " +
// segments[i]);
// }
File file = path.toFile();
absolutePath = new Path(file.getPath());
}
Utils.println(
IReporter.DETAIL,
"getPathToBundle(), path to bundle "
+ bundleName + " = " + absolutePath.toString());
}
return absolutePath;
}
private Version getEclipseVersion () {
Version eclipseVersion = null;
Bundle platformBundle = Platform.getBundle("org.eclipse.platform");
Dictionary platformDict = platformBundle.getHeaders();
if (!platformDict.isEmpty()) {
String version = (String) platformDict.get(Version.bundleVersionKey);
eclipseVersion = new Version(version);
}else {
eclipseVersion = new Version("0.0.0");
}
Utils.println(
IReporter.DETAIL,
"getEclipseVersion(), Eclipse version - "
+ eclipseVersion.toString());
return eclipseVersion;
}
private String getEclipseInstallPath () {
String filePath = "";
try {
// The following code returns the Eclipse installation path.
// The URL.getPath() method returns the path in the form of
// /d:/eclipse.
// We want to strip off the preceeding "/" and an easy way to do it
// is to convert it to a Path and return the string representation.
Location installLocation = Platform.getInstallLocation();
URL url = installLocation.getURL();
Path absolutePath = new Path(new File(url.getFile()).getAbsolutePath());
filePath = absolutePath.toString();
}catch (Exception e) {
Utils.println(IReporter.SYSTEM_NONFATAL, e.getMessage(), e);
}
Utils.println(
IReporter.DETAIL,
"getEclipseInstallPath(), Eclipse installation path - " + filePath);
return filePath;
}
}