blob: a47cd0c7741093f51dadfe993a6312dcd7a57622 [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.osgi.framework.internal.defaultadaptor;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;
import org.eclipse.osgi.framework.adaptor.*;
import org.eclipse.osgi.framework.adaptor.core.AbstractFrameworkAdaptor;
import org.eclipse.osgi.framework.debug.Debug;
import org.eclipse.osgi.framework.internal.core.Constants;
import org.eclipse.osgi.framework.util.Headers;
import org.eclipse.osgi.internal.resolver.StateManager;
import org.eclipse.osgi.service.resolver.*;
import org.eclipse.osgi.service.resolver.BundleDescription;
import org.eclipse.osgi.service.resolver.State;
import org.osgi.framework.*;
/**
* //TODO Add comment here
*/
public class DefaultAdaptor extends AbstractFrameworkAdaptor
{
protected static final String METADATA_ADAPTOR_NEXTID = "METADATA_ADAPTOR_NEXTID";
protected static final String METADATA_ADAPTOR_IBSL = "METADATA_ADAPTOR_IBSL";
/** directory containing installed bundles */
protected File bundleRootDir;
/** String containing bundle dir */
protected String bundledir = null;
/** name of a bundles data directory */
protected String dataDirName = "data";
protected boolean reset = false;
/** The MetaData for the default adaptor */
protected MetaData metadata;
/** Dictionary containing permission data */
protected PermissionStorage permissionStore;
/** next available bundle id */
protected long nextId = 1;
/** Development ClassPath entries */
protected String[] devCP;
/** Name of the Adaptor manifest file */
protected final String ADAPTOR_MANIFEST = "/META-INF/ADAPTOR.MF";
/** This adaptor's manifest file */
protected Headers manifest=null;
protected AdaptorElementFactory elementFactory = null;
/** The State Manager */
protected StateManager stateManager;
/**
* Constructor for DefaultAdaptor. This constructor parses the arguments passed
* and remembers them for later when initialize is called.
* <p>No blank spaces should be used in the arguments to the DefaultAdaptor.
* The options that DefaultAdaptor recognizes and handles are:
* <ul>
* <li><b>bundledir=<i>directory name</i></b>If a directory name is specified, the adaptor should initialize
* to store bundles in that directory. This arg should be enclosed in "" if it contains the ":"
* character (example "bundledir=c:\mydir").
* <li><b>reset</b>Resets the bundle storage by deleting the bundledir
* </ul>
* Any other arguments are ignored.
*
* @param An array of strings containing arguments.
* This object cannot be used until initialize is called.
*
*/
public DefaultAdaptor(String[] args)
{
if (args != null)
{
for (int i = 0; i < args.length; i++)
{
String arg = args[i];
if (arg.equalsIgnoreCase("reset"))
{
reset = true;
}
else if (arg.indexOf("=") != -1)
{
StringTokenizer tok = new StringTokenizer(args[i], "=");
if (tok.countTokens() == 2)
{
String key = tok.nextToken();
if (key.equalsIgnoreCase("bundledir"))
{
// save file name for initializeStorage to use
bundledir = tok.nextToken();
}
}
}
}
}
}
public void initialize(EventPublisher eventPublisher)
{
super.initialize(eventPublisher);
getBundleDir();
readAdaptorManifest();
stateManager = createStateManager();
}
/**
* Creates the StateManager for the adaptor
* @return the StateManager.
*/
protected StateManager createStateManager(){
stateManager = new StateManager(bundleRootDir);
State systemState = stateManager.getSystemState();
if (systemState != null)
return stateManager;
systemState = stateManager.createSystemState();
Vector installedBundles = getInstalledBundles();
if (installedBundles == null)
return stateManager;
StateObjectFactory factory = stateManager.getFactory();
for (Iterator iter = installedBundles.iterator(); iter.hasNext(); ) {
BundleData toAdd = (BundleData) iter.next();
try {
Dictionary manifest = toAdd.getManifest();
BundleDescription newDescription = factory.createBundleDescription(manifest, toAdd.getLocation(),toAdd.getBundleID());
systemState.addBundle(newDescription);
} catch (BundleException be) {
// just ignore bundle datas with invalid manifests
}
}
// we need the state resolved
systemState.resolve();
return stateManager;
}
/**
* Get the directory to store the bundles in. Bundledir can be set in 3 different ways.
* Priority is:
* 1 - OSGI Launcher command line -adaptor argument
* 2 - System property org.eclipse.osgi.framework.defaultadaptor.bundledir - could be specified with -D when launching
* 3 - osgi.properties - org.eclipse.osgi.framework.defaultadaptor.bundledir property
*
* Bundledir will be stored back to adaptor properties which
* the framework will copy into the System properties.
*/
protected void getBundleDir()
{
/* if bundledir was not set by the constructor from the -adaptor cmd line arg */
if (bundledir == null)
{
/* check the system properties */
bundledir = System.getProperty("org.eclipse.osgi.framework.defaultadaptor.bundledir");
if (bundledir == null)
{
/* check the osgi.properties file, but default to "bundles" */
bundledir = properties.getProperty("org.eclipse.osgi.framework.defaultadaptor.bundledir", "bundles");
}
}
/* store bundledir back into adaptor properties for others to see */
properties.put("org.eclipse.osgi.framework.defaultadaptor.bundledir", bundledir);
bundleRootDir = new File(bundledir);
}
/**
* Reads and initializes the adaptor BundleManifest object. The
* BundleManifest is used by the getExportPackages() and getExportServices()
* methods of the adpator.
*/
protected void readAdaptorManifest() {
InputStream in = getClass().getResourceAsStream(ADAPTOR_MANIFEST);
if (Debug.DEBUG && Debug.DEBUG_GENERAL) {
if (in == null) {
Debug.println("Unable to find adaptor bundle manifest " + ADAPTOR_MANIFEST);
}
}
try {
manifest = Headers.parseManifest(in);
} catch (BundleException e) {
Debug.println("Unable to read adaptor bundle manifest " + ADAPTOR_MANIFEST);
}
}
/**
* Initialize the persistent storage.
*
* <p>This method initializes the bundle persistent storage
* area.
* If a dir was specified in the -adaptor command line option, then it
* is used. If not,
* if the property
* <i>org.eclipse.osgi.framework.defaultadaptor.bundledir</i> is specifed, its value
* will be used as the name of the bundle directory
* instead of <tt>./bundles</tt>.
* If reset was specified on the -adaptor command line option,
* then the storage will be cleared.
*
* @throws IOException If an error occurs initializing the storage.
*/
public void initializeStorage() throws IOException
{
boolean makedir = false;
if (bundleRootDir.exists())
{
if (reset)
{
makedir = true;
if (!rm(bundleRootDir))
{
if (Debug.DEBUG && Debug.DEBUG_GENERAL)
{
Debug.println("Could not remove directory: " + bundleRootDir.getPath());
}
}
}
else
{
if (!bundleRootDir.isDirectory())
{
if (Debug.DEBUG && Debug.DEBUG_GENERAL)
{
Debug.println("Exists but not a directory: " + bundleRootDir.getPath());
}
throw new IOException(AdaptorMsg.formatter.getString("ADAPTOR_STORAGE_EXCEPTION"));
}
}
}
else
{
makedir = true;
}
if (makedir)
{
if (!bundleRootDir.mkdirs())
{
if (Debug.DEBUG && Debug.DEBUG_GENERAL)
{
Debug.println("Unable to create directory: " + bundleRootDir.getPath());
}
throw new IOException(AdaptorMsg.formatter.getString("ADAPTOR_STORAGE_EXCEPTION"));
}
}
metadata = new MetaData(getMetaDataFile(), "Framework metadata");
metadata.load();
nextId = metadata.getLong(METADATA_ADAPTOR_NEXTID, 1);
initialBundleStartLevel = metadata.getInt(METADATA_ADAPTOR_IBSL,1);
}
protected File getMetaDataFile(){
return new File(bundleRootDir, ".framework");
}
/**
* This method cleans up storage in the specified directory and
* any subdirectories.
*
* @param directory The directory to clean.
* @param depth The remaining depth. When depth is zero, this
* method will not recurse any deeper
* @see #compactStorage
*/
private void compact(File directory)
{
if (Debug.DEBUG && Debug.DEBUG_GENERAL)
{
Debug.println("compact(" + directory.getPath() + ")");
}
String list[] = directory.list();
if (list != null)
{
int len = list.length;
for (int i = 0; i < len; i++)
{
if (dataDirName.equals(list[i]))
{
continue; /* do not examine the bundles data dir. */
}
File target = new File(directory, list[i]);
/* if the file is a directory */
if (target.isDirectory())
{
File delete = new File(target, ".delete");
/* and the directory is marked for delete */
if (delete.exists())
{
/* if rm fails to delete the directory *
* and .delete was removed
*/
if (!rm(target) && !delete.exists())
{
try
{
/* recreate .delete */
FileOutputStream out = new FileOutputStream(delete);
out.close();
}
catch (IOException e)
{
if (Debug.DEBUG && Debug.DEBUG_GENERAL)
{
Debug.println("Unable to write " + delete.getPath() + ": " + e.getMessage());
}
}
}
}
else
{
compact(target); /* descend into directory */
}
}
}
}
}
/**
* Clean up the persistent storage.
*
* <p>Cleans up any deferred deletions in persistent storage.
*
*/
public void compactStorage()
{
compact(bundleRootDir);
}
/**
* @see org.eclipse.osgi.framework.adaptor.FrameworkAdaptor#getInstalledBundles()
*/
public Vector getInstalledBundles()
{
String list[] = bundleRootDir.list();
if (list == null) {
return null;
}
int len = list.length;
Vector bundleDatas = new Vector(len << 1, 10);
/* create bundle objects for all installed bundles. */
for (int i = 0; i < len; i++)
{
try
{
DefaultBundleData data;
try
{
data = (DefaultBundleData)getElementFactory().getBundleData(this);
data.initializeExistingBundle(list[i]);
}
catch (NumberFormatException e)
{
continue; /* the directory is not a bundle id */
}
if (Debug.DEBUG && Debug.DEBUG_GENERAL)
{
Debug.println("BundleData created: " + data);
}
bundleDatas.addElement(data);
}
catch (IOException e)
{
if (Debug.DEBUG && Debug.DEBUG_GENERAL)
{
Debug.println("Unable to open Bundle[" + list[i] + "]: " + e.getMessage());
Debug.printStackTrace(e);
}
}
}
return (bundleDatas);
}
/**
* Prepare to install a bundle from a URLConnection.
* <p>To complete the install,
* begin and then commit
* must be called on the returned <code>BundleOperation</code> object.
* If either of these methods throw a BundleException
* or some other error occurs,
* then undo must be called on the <code>BundleOperation</code> object
* to undo the change to persistent storage.
*
* @param location Bundle location.
* @param source URLConnection from which the bundle may be read.
* Any InputStreams returned from the source
* (URLConnections.getInputStream) must be closed by the
* <code>BundleOperation</code> object.
* @return BundleOperation object to be used to complete the install.
*/
public BundleOperation installBundle(final String location, final URLConnection source)
{
return (new BundleOperation()
{
private DefaultBundleData data;
/**
* Begin the operation on the bundle (install, update, uninstall).
*
* @return BundleData object for the target bundle.
* @throws BundleException If a failure occured modifiying peristent storage.
*/
public org.eclipse.osgi.framework.adaptor.BundleData begin() throws BundleException
{
long id;
try
{
/*
* Open InputStream first to trigger prereq installs, if any,
* before allocating bundle id.
*/
InputStream in = source.getInputStream();
try
{
try
{
id = getNextBundleId();
metadata.save();
}
catch (IOException e)
{
throw new BundleException(AdaptorMsg.formatter.getString("ADAPTOR_STORAGE_EXCEPTION"), e);
}
if (in instanceof ReferenceInputStream)
{
URL reference = ((ReferenceInputStream) in).getReference();
if (!"file".equals(reference.getProtocol()))
{
throw new BundleException(
AdaptorMsg.formatter.getString("ADAPTOR_URL_CREATE_EXCEPTION", reference));
}
data = (DefaultBundleData)getElementFactory().getBundleData(DefaultAdaptor.this);
data.initializeReferencedBundle(id, location, reference.getPath());
}
else
{
data = (DefaultBundleData)getElementFactory().getBundleData(DefaultAdaptor.this);
data.initializeNewBundle(id, location, in);
}
}
finally
{
try
{
in.close();
}
catch (IOException e)
{
}
}
}
catch (IOException ioe)
{
throw new BundleException(AdaptorMsg.formatter.getString("BUNDLE_READ_EXCEPTION"), ioe);
}
return (data);
}
public void undo()
{
if (data != null)
{
try
{
data.close();
}
catch (IOException e)
{
if (Debug.DEBUG && Debug.DEBUG_GENERAL)
{
Debug.println("Unable to close " + data + ": " + e.getMessage());
}
}
}
if (data != null)
{
File bundleDir = data.getBundleDir();
if (!rm(bundleDir))
{
/* mark this bundle to be deleted to ensure it is fully cleaned up
* on next restart.
*/
File delete = new File(bundleDir, ".delete");
if (!delete.exists())
{
try
{
/* create .delete */
FileOutputStream out = new FileOutputStream(delete);
out.close();
}
catch (IOException e)
{
if (Debug.DEBUG && Debug.DEBUG_GENERAL)
{
Debug.println("Unable to write " + delete.getPath() + ": " + e.getMessage());
}
}
}
}
}
}
public void commit(boolean postpone) throws BundleException
{
try
{
data.save();
}
catch (IOException e)
{
throw new BundleException(AdaptorMsg.formatter.getString("ADAPTOR_STORAGE_EXCEPTION"), e);
}
BundleDescription bundleDescription = stateManager.getFactory().createBundleDescription(data.getManifest(), data.getLocation(),data.getBundleID());
stateManager.getSystemState().addBundle(bundleDescription);
}
});
}
/**
* Prepare to update a bundle from a URLConnection.
* <p>To complete the update,
* modify and then commit
* will be called on the returned BundleStorage object.
* If either of these methods throw a BundleException
* or some other error occurs,
* then undo will be called on the BundleStorage object
* to undo the change to persistent storage.
*
* @param bundle Bundle to update.
* @param source URLConnection from which the bundle may be read.
* @return BundleOperation object to be used to complete the update.
*/
public BundleOperation updateBundle(
final org.eclipse.osgi.framework.adaptor.BundleData bundledata,
final URLConnection source)
{
return (new BundleOperation()
{
private DefaultBundleData data;
private DefaultBundleData newData;
/**
* Perform the change to persistent storage.
*
* @return Bundle object for the target bundle.
*/
public org.eclipse.osgi.framework.adaptor.BundleData begin() throws BundleException
{
this.data = (DefaultBundleData) bundledata;
try
{
InputStream in = source.getInputStream();
try
{
if (in instanceof ReferenceInputStream)
{
URL reference = ((ReferenceInputStream) in).getReference();
if (!"file".equals(reference.getProtocol()))
{
throw new BundleException(
AdaptorMsg.formatter.getString("ADAPTOR_URL_CREATE_EXCEPTION", reference));
}
// check to make sure we are not just trying to update to the same
// directory reference. This would be a no-op.
String path = reference.getPath();
if (path.equals(data.getName())){
throw new BundleException(
AdaptorMsg.formatter.getString("ADAPTOR_SAME_REF_UPDATE",reference));
}
try
{
newData = data.nextGeneration(reference.getPath());
}
catch (IOException e)
{
throw new BundleException(
AdaptorMsg.formatter.getString("ADAPTOR_STORAGE_EXCEPTION"),
e);
}
File bundleGenerationDir = newData.getGenerationDir();
if (!bundleGenerationDir.exists())
{
throw new BundleException(
AdaptorMsg.formatter.getString(
"ADAPTOR_DIRECTORY_CREATE_EXCEPTION",
bundleGenerationDir.getPath()));
}
newData.bundleFile = BundleFile.createBundleFile(newData.file, newData);
}
else
{
try
{
newData = data.nextGeneration();
}
catch (IOException e)
{
throw new BundleException(
AdaptorMsg.formatter.getString("ADAPTOR_STORAGE_EXCEPTION"),
e);
}
File bundleGenerationDir = newData.getGenerationDir();
if (!bundleGenerationDir.exists())
{
throw new BundleException(
AdaptorMsg.formatter.getString(
"ADAPTOR_DIRECTORY_CREATE_EXCEPTION",
bundleGenerationDir.getPath()));
}
File file = newData.getBundleFile();
readFile(in, file);
newData.bundleFile = BundleFile.createBundleFile(file, newData);
}
}
finally
{
try
{
in.close();
}
catch (IOException ee)
{
}
}
newData.loadFromManifest();
}
catch (IOException e)
{
throw new BundleException(AdaptorMsg.formatter.getString("BUNDLE_READ_EXCEPTION"), e);
}
return (newData);
}
/**
* Commit the change to persistent storage.
*
* @param postpone If true, the bundle's persistent
* storage cannot be immediately reclaimed.
* @throws BundleException If a failure occured modifiying peristent storage.
*/
public void commit(boolean postpone) throws BundleException
{
try
{
newData.save();
}
catch (IOException e)
{
throw new BundleException(AdaptorMsg.formatter.getString("ADAPTOR_STORAGE_EXCEPTION"), e);
}
long bundleId = newData.getBundleID();
State systemState = stateManager.getSystemState();
systemState.removeBundle(bundleId);
BundleDescription newDescription = stateManager.getFactory().createBundleDescription(newData.getManifest(), newData.getLocation(),bundleId);
systemState.addBundle(newDescription);
File originalGenerationDir = data.getGenerationDir();
if (postpone || !rm(originalGenerationDir))
{
/* mark this bundle to be deleted to ensure it is fully cleaned up
* on next restart.
*/
File delete = new File(originalGenerationDir, ".delete");
if (!delete.exists())
{
try
{
/* create .delete */
FileOutputStream out = new FileOutputStream(delete);
out.close();
}
catch (IOException e)
{
if (Debug.DEBUG && Debug.DEBUG_GENERAL)
{
Debug.println("Unable to write " + delete.getPath() + ": " + e.getMessage());
}
eventPublisher.publishFrameworkEvent(FrameworkEvent.ERROR, data.getBundle(), e);
}
}
}
}
/**
* Undo the change to persistent storage.
*
* @throws BundleException If a failure occured modifiying peristent storage.
*/
public void undo() throws BundleException
{
/*if (bundleFile != null)
{
bundleFile.close();
} */
if (newData != null)
{
File nextGenerationDir = newData.getGenerationDir();
if (!rm(nextGenerationDir)) /* delete downloaded bundle */
{
/* mark this bundle to be deleted to ensure it is fully cleaned up
* on next restart.
*/
File delete = new File(nextGenerationDir, ".delete");
if (!delete.exists())
{
try
{
/* create .delete */
FileOutputStream out = new FileOutputStream(delete);
out.close();
}
catch (IOException e)
{
if (Debug.DEBUG && Debug.DEBUG_GENERAL)
{
Debug.println("Unable to write " + delete.getPath() + ": " + e.getMessage());
}
}
}
}
}
}
});
}
/**
* Prepare to uninstall a bundle.
* <p>To complete the uninstall,
* modify and then commit
* will be called on the returned BundleStorage object.
* If either of these methods throw a BundleException
* or some other error occurs,
* then undo will be called on the BundleStorage object
* to undo the change to persistent storage.
*
* @param bundle BundleData to uninstall.
* @return BundleOperation object to be used to complete the uninstall.
*/
public BundleOperation uninstallBundle(final org.eclipse.osgi.framework.adaptor.BundleData bundledata)
{
return (new BundleOperation()
{
private DefaultBundleData data;
/**
* Perform the change to persistent storage.
*
* @return Bundle object for the target bundle.
* @throws BundleException If a failure occured modifiying peristent storage.
*/
public org.eclipse.osgi.framework.adaptor.BundleData begin() throws BundleException
{
this.data = (DefaultBundleData) bundledata;
return (bundledata);
}
/**
* Commit the change to persistent storage.
*
* @param postpone If true, the bundle's persistent
* storage cannot be immediately reclaimed.
* @throws BundleException If a failure occured modifiying peristent storage.
*/
public void commit(boolean postpone) throws BundleException
{
File bundleDir = data.getBundleDir();
if (postpone || !rm(bundleDir))
{
/* mark this bundle to be deleted to ensure it is fully cleaned up
* on next restart.
*/
File delete = new File(bundleDir, ".delete");
if (!delete.exists())
{
try
{
/* create .delete */
FileOutputStream out = new FileOutputStream(delete);
out.close();
}
catch (IOException e)
{
if (Debug.DEBUG && Debug.DEBUG_GENERAL)
{
Debug.println("Unable to write " + delete.getPath() + ": " + e.getMessage());
}
}
}
}
stateManager.getSystemState().removeBundle(data.getBundleID());
}
/**
* Undo the change to persistent storage.
*
* @throws BundleException If a failure occured modifiying peristent storage.
*/
public void undo() throws BundleException
{
}
});
}
/**
* Returns the PermissionStorage object which will be used to
* to manage the permission data.
*
* <p>The PermissionStorage object will store permission data
* in the "permdata" subdirectory of the bundle storage directory
* assigned by <tt>initializeStorage</tt>.
*
* @return The PermissionStorage object for the DefaultAdaptor.
*/
public org.eclipse.osgi.framework.adaptor.PermissionStorage getPermissionStorage() throws IOException
{
if (permissionStore == null)
{
synchronized (this)
{
if (permissionStore == null)
{
permissionStore = new PermissionStorage(this);
}
}
}
return permissionStore;
}
public void frameworkStart(BundleContext context) throws BundleException{
super.frameworkStart(context);
// Check the osgi.dev property to see if dev classpath entries have been defined.
String osgiDev = context.getProperty("osgi.dev");
if (osgiDev != null) {
// Add each dev classpath entry
Vector devClassPath = new Vector(6);
StringTokenizer st = new StringTokenizer(osgiDev,",");
while (st.hasMoreTokens()) {
String tok = st.nextToken();
if (!tok.equals("")) {
devClassPath.addElement(tok);
}
}
devCP = new String[devClassPath.size()];
devClassPath.toArray(devCP);
}
State state = stateManager.getSystemState();
BundleDescription systemBundle = state.getBundle(0);
if (systemBundle == null || !systemBundle.isResolved())
// this would be a bug in the framework
throw new IllegalStateException();
}
public void frameworkStop(BundleContext context) throws BundleException {
try {
stateManager.shutdown();
} catch (IOException e) {
throw new BundleException(null, e);
}
super.frameworkStop(context);
}
/**
* Register a service object.
*
*/
protected ServiceRegistration register(String name, Object service, Bundle bundle)
{
Hashtable properties = new Hashtable(7);
Dictionary headers = bundle.getHeaders();
properties.put(Constants.SERVICE_VENDOR, headers.get(Constants.BUNDLE_VENDOR));
properties.put(Constants.SERVICE_RANKING, new Integer(Integer.MAX_VALUE));
properties.put(Constants.SERVICE_PID, bundle.getBundleId() + "." + service.getClass().getName());
return context.registerService(name, service, properties);
}
/**
* This function performs the equivalent of "rm -r" on a file or directory.
*
* @param file file or directory to delete
* @return false is the specified files still exists, true otherwise.
*/
protected boolean rm(File file)
{
if (file.exists())
{
if (file.isDirectory())
{
String list[] = file.list();
int len = list.length;
for (int i = 0; i < len; i++)
{
// we are doing a lot of garbage collecting here
rm(new File(file, list[i]));
}
}
if (Debug.DEBUG && Debug.DEBUG_GENERAL)
{
if (file.isDirectory())
{
Debug.println("rmdir " + file.getPath());
}
else
{
Debug.println("rm " + file.getPath());
}
}
boolean success = file.delete();
if (Debug.DEBUG && Debug.DEBUG_GENERAL)
{
if (!success)
{
Debug.println(" rm failed!!");
}
}
return (success);
}
else
{
return (true);
}
}
public void setInitialBundleStartLevel(int value) {
super.setInitialBundleStartLevel(value);
metadata.setInt(METADATA_ADAPTOR_IBSL,value);
try {
metadata.save();
} catch (IOException e) {
eventPublisher.publishFrameworkEvent(FrameworkEvent.ERROR, context.getBundle(), e);
}
}
/**
* Map a location string into a bundle name.
* This methods treats the location string as a URL.
*
* @param location bundle location string.
* @return bundle name.
*/
public String mapLocationToName(String location)
{
int end = location.indexOf('?', 0); /* "?" query */
if (end == -1)
{
end = location.indexOf('#', 0); /* "#" fragment */
if (end == -1)
{
end = location.length();
}
}
int begin = location.replace('\\', '/').lastIndexOf('/', end);
int colon = location.lastIndexOf(':', end);
if (colon > begin)
{
begin = colon;
}
return (location.substring(begin + 1, end));
}
/**
* Return the next valid, unused bundle id.
*
* @return Next valid, unused bundle id.
* @throws IOException If there are no more unused bundle ids.
*/
protected synchronized long getNextBundleId() throws IOException
{
while (nextId < Long.MAX_VALUE)
{
long id = nextId;
nextId++;
metadata.setLong(METADATA_ADAPTOR_NEXTID, nextId);
File bundleDir = new File(bundleRootDir, String.valueOf(id));
if (bundleDir.exists())
{
continue;
}
return (id);
}
throw new IOException(AdaptorMsg.formatter.getString("ADAPTOR_STORAGE_EXCEPTION"));
}
/**
* Read a file from an InputStream and write it to the file system.
*
* @param is InputStream from which to read.
* @param file output file to create.
* @exception IOException
*/
public static void readFile(InputStream in, File file) throws IOException
{
FileOutputStream fos = null;
try
{
fos = new FileOutputStream(file);
byte buffer[] = new byte[1024];
int count;
while ((count = in.read(buffer, 0, buffer.length)) > 0)
{
fos.write(buffer, 0, count);
}
fos.close();
fos = null;
in.close();
in = null;
}
catch (IOException e)
{
// close open streams
if (fos != null)
{
try
{
fos.close();
}
catch (IOException ee)
{
}
}
if (in != null)
{
try
{
in.close();
}
catch (IOException ee)
{
}
}
if (Debug.DEBUG && Debug.DEBUG_GENERAL)
{
Debug.println("Unable to read file");
Debug.printStackTrace(e);
}
throw e;
}
}
/* (non-Javadoc)
* @see org.eclipse.osgi.framework.adaptor.FrameworkAdaptor#getExportPackages()
*/
public String getExportPackages() {
if (manifest == null)
return null;
return (String)manifest.get(Constants.EXPORT_PACKAGE);
}
/* (non-Javadoc)
* @see org.eclipse.osgi.framework.adaptor.FrameworkAdaptor#getExportServices()
*/
public String getExportServices() {
if (manifest == null)
return null;
return (String)manifest.get(Constants.EXPORT_SERVICE);
}
public AdaptorElementFactory getElementFactory() {
if (elementFactory == null)
elementFactory = new AdaptorElementFactory();
return elementFactory;
}
public IBundleStats getBundleStats(){
return null;
}
// TODO need to clean this up. get state, statemanger, platform admin etc all need to be harmonized
public State getState() {
return stateManager.getSystemState();
}
public StateManager getStateManager() {
return stateManager;
}
public PlatformAdmin getPlatformAdmin() {
return PlatformAdmin.getInstance();
}
}