blob: 074397536f574eda2c850d3d7b72e233b97cfb86 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004 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.adaptor.core;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.Properties;
import org.eclipse.osgi.framework.adaptor.BundleData;
import org.eclipse.osgi.framework.adaptor.EventPublisher;
import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
import org.eclipse.osgi.framework.adaptor.BundleWatcher;
import org.eclipse.osgi.framework.debug.Debug;
import org.eclipse.osgi.framework.internal.core.Constants;
import org.eclipse.osgi.framework.util.Headers;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
/**
* An abstract FrameworkAdaptor class that has default implementations that most
* FrameworkAdaptor implementations can use.
*/
public abstract class AbstractFrameworkAdaptor implements FrameworkAdaptor {
/** Name of the Adaptor manifest file */
protected final String ADAPTOR_MANIFEST = "ADAPTOR.MF";
protected EventPublisher eventPublisher;
/**
* The ServiceRegistry object for this FrameworkAdaptor.
*/
protected ServiceRegistryImpl serviceRegistry;
/**
* The Properties object for this FrameworkAdaptor
*/
protected Properties properties;
/**
* The System Bundle's BundleContext.
*/
protected BundleContext context; //TODO Rename to systemBundleContext
/**
* The initial bundle start level.
*/
protected int initialBundleStartLevel = 1;
/** This adaptor's manifest file */
protected Headers manifest = null;
/**
* The BundleClassLoader parent to use when creating BundleClassLoaders.
* The behavior of the ParentClassLoader will load classes
* from the boot strap classloader.
*/
protected static ClassLoader bundleClassLoaderParent = new ParentClassLoader();
/**
* Initializes the ServiceRegistry, loads the properties for this
* FrameworkAdaptor and initializes all the Vector and Hashtable capacity,
* increment and factor values.
* @see org.eclipse.osgi.framework.adaptor.FrameworkAdaptor#initialize()
*/
public void initialize(EventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
serviceRegistry = new ServiceRegistryImpl();
serviceRegistry.initialize();
loadProperties();
readAdaptorManifest();
}
/**
* @see org.eclipse.osgi.framework.adaptor.FrameworkAdaptor#getProperties()
*/
public Properties getProperties() {
return properties;
}
/**
* @see org.eclipse.osgi.framework.adaptor.FrameworkAdaptor#mapLocationToURLConnection(String)
*/
public URLConnection mapLocationToURLConnection(String location) throws BundleException {
try {
return (new URL(location).openConnection());
} catch (IOException e) {
throw new BundleException(AdaptorMsg.formatter.getString("ADAPTOR_URL_CREATE_EXCEPTION", location), e);
}
}
/**
* Always returns -1 to indicate that this operation is not supported by this
* FrameworkAdaptor. Extending classes should override this method if
* they support this operation.
* @see org.eclipse.osgi.framework.adaptor.FrameworkAdaptor#getTotalFreeSpace()
*/
public long getTotalFreeSpace() throws IOException {
return -1;
}
/**
* @see org.eclipse.osgi.framework.adaptor.FrameworkAdaptor#getServiceRegistry()
*/
public org.eclipse.osgi.framework.adaptor.ServiceRegistry getServiceRegistry() {
return serviceRegistry;
}
/**
* @see org.eclipse.osgi.framework.adaptor.FrameworkAdaptor#frameworkStart(org.osgi.framework.BundleContext)
*/
public void frameworkStart(BundleContext context) throws BundleException {
this.context = context;
BundleResourceHandler.setContext(context);
}
/**
* @see org.eclipse.osgi.framework.adaptor.FrameworkAdaptor#frameworkStop(org.osgi.framework.BundleContext)
*/
public void frameworkStop(BundleContext context) throws BundleException {
this.context = null;
BundleResourceHandler.setContext(null);
}
/**
* @see org.eclipse.osgi.framework.adaptor.FrameworkAdaptor#frameworkStopping()
*/
public void frameworkStopping() {
}
/**
* @see org.eclipse.osgi.framework.adaptor.FrameworkAdaptor#getExportPackages()
*/
public String getExportPackages() {
if (manifest == null)
return null;
return (String) manifest.get(Constants.EXPORT_PACKAGE);
}
/**
* @see org.eclipse.osgi.framework.adaptor.FrameworkAdaptor#getExportServices()
*/
public String getExportServices() {
if (manifest == null)
return null;
return (String) manifest.get(Constants.EXPORT_SERVICE);
}
public String getProvidePackages() {
if (manifest == null)
return null;
return (String) manifest.get(Constants.PROVIDE_PACKAGE);
}
/**
* Returns the EventPublisher for this FrameworkAdaptor.
* @return The EventPublisher.
*/
public EventPublisher getEventPublisher() {
return eventPublisher;
}
public int getInitialBundleStartLevel() {
return initialBundleStartLevel;
}
public void setInitialBundleStartLevel(int value) {
initialBundleStartLevel = value;
}
public BundleWatcher getBundleStats() {
return null;
}
/**
* This method locates and reads the osgi.properties file.
* If the system property <i>org.eclipse.osgi.framework.internal.core.properties</i> is specifed, its value
* will be used as the name of the file instead of
* <tt>osgi.properties</tt>. There are 3 places to look for these properties. These
* 3 places are searched in the following order, stopping when the properties are found.
*
* <ol>
* <li>Look for a file in the file system
* <li>Look for a resource in the FrameworkAdaptor's package
* </ol>
*/
protected void loadProperties() {
properties = new Properties();
String resource = System.getProperty(Constants.OSGI_PROPERTIES, Constants.DEFAULT_OSGI_PROPERTIES);
try {
InputStream in = null;
File file = new File(resource);
if (file.exists()) {
in = new FileInputStream(file);
}
if (in == null) {
in = getClass().getResourceAsStream(resource);
}
if (in != null) {
try {
properties.load(new BufferedInputStream(in));
} finally {
try {
in.close();
} catch (IOException ee) {
}
}
} else {
if (Debug.DEBUG && Debug.DEBUG_GENERAL)
Debug.println("Skipping osgi.properties: " + resource);
}
} catch (IOException e) {
if (Debug.DEBUG && Debug.DEBUG_GENERAL) {
Debug.println("Unable to load osgi.properties: " + e.getMessage());
}
}
}
/**
* 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 = null;
// walk up the class hierarchy until we find the ADAPTOR_MANIFEST.
Class adaptorClazz = getClass();
while (in == null && AbstractFrameworkAdaptor.class.isAssignableFrom(adaptorClazz)) {
in = adaptorClazz.getResourceAsStream(ADAPTOR_MANIFEST);
adaptorClazz = adaptorClazz.getSuperclass();
}
if (in == null) {
if (Debug.DEBUG && Debug.DEBUG_GENERAL) {
Debug.println("Unable to find adaptor bundle manifest " + ADAPTOR_MANIFEST);
}
manifest = new Headers(new Properties());
return;
}
try {
manifest = Headers.parseManifest(in);
} catch (BundleException e) {
Debug.println("Unable to read adaptor bundle manifest " + ADAPTOR_MANIFEST);
}
}
public BundleData createSystemBundleData() throws BundleException {
return new SystemBundleData(this);
}
abstract public AdaptorElementFactory getElementFactory();
/**
* Does a recursive copy of one directory to another.
* @param inDir input directory to copy.
* @param outDir output directory to copy to.
* @throws IOException if any error occurs during the copy.
*/
public static void copyDir(File inDir, File outDir) throws IOException {
String[] files = inDir.list();
if (files != null && files.length > 0) {
outDir.mkdir();
for (int i = 0; i < files.length; i++) {
File inFile = new File(inDir, files[i]);
File outFile = new File(outDir, files[i]);
if (inFile.isDirectory()) {
copyDir(inFile, outFile);
} else {
InputStream in = new FileInputStream(inFile);
readFile(in, outFile);
}
}
}
}
/**
* 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;
}
}
public ClassLoader getBundleClassLoaderParent() {
return bundleClassLoaderParent;
}
/**
* Empty parent classloader. This is used by default as the BundleClassLoader
* parent.
*/
protected static class ParentClassLoader extends ClassLoader {
protected ParentClassLoader() {
super(null);
}
}
}