Package org.eclipse.osgi.internal.baseadaptor

Source Code of org.eclipse.osgi.internal.baseadaptor.BaseStorageHook

/*******************************************************************************
* Copyright (c) 2005, 2010 IBM Corporation and others.
* 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:
*     IBM Corporation - initial API and implementation
*     Rob Harrop - SpringSource Inc. (bug 253942)
*******************************************************************************/

package org.eclipse.osgi.internal.baseadaptor;

import java.io.*;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;
import org.eclipse.core.runtime.adaptor.LocationManager;
import org.eclipse.osgi.baseadaptor.BaseAdaptor;
import org.eclipse.osgi.baseadaptor.BaseData;
import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
import org.eclipse.osgi.baseadaptor.hooks.AdaptorHook;
import org.eclipse.osgi.baseadaptor.hooks.StorageHook;
import org.eclipse.osgi.framework.adaptor.*;
import org.eclipse.osgi.framework.debug.Debug;
import org.eclipse.osgi.framework.internal.core.*;
import org.eclipse.osgi.framework.internal.core.Constants;
import org.eclipse.osgi.framework.log.FrameworkLog;
import org.eclipse.osgi.framework.util.KeyedElement;
import org.eclipse.osgi.service.datalocation.Location;
import org.eclipse.osgi.util.ManifestElement;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.*;

public class BaseStorageHook implements StorageHook, AdaptorHook {
  public static final String KEY = BaseStorageHook.class.getName();
  public static final int HASHCODE = KEY.hashCode();
  public static final int DEL_BUNDLE_STORE = 0x01;
  public static final int DEL_GENERATION = 0x02;
  private static final int STORAGE_VERSION = 1;
  public static final String EXTERNAL_LIB_PREFIX = "external:"; //$NON-NLS-1$
  public static final String VARIABLE_DELIM_STRING = "$"; //$NON-NLS-1$
  public static final char VARIABLE_DELIM_CHAR = '$';
  public static String COMPOSITE_HEADER = "Equinox-CompositeBundle"; //$NON-NLS-1$
  public static String COMPOSITE_BUNDLE = "composite"; //$NON-NLS-1$
  public static String SURROGATE_BUNDLE = "surrogate"; //$NON-NLS-1$

  /** bundle's file name */
  private String fileName;
  /** native code paths for this BundleData */
  private String[] nativePaths;
  /** bundle generation */
  private int generation = 1;
  /** Is bundle a reference */
  private boolean reference;

  private BaseData bundleData;
  private BaseStorage storage;
  private File bundleStore;
  private File dataStore;

  public BaseStorageHook(BaseStorage storage) {
    this.storage = storage;
  }

  public int getStorageVersion() {
    return STORAGE_VERSION;
  }

  public StorageHook create(BaseData bundledata) throws BundleException {
    BaseStorageHook storageHook = new BaseStorageHook(storage);
    storageHook.bundleData = bundledata;
    return storageHook;
  }

  public void initialize(Dictionary manifest) throws BundleException {
    BaseStorageHook.loadManifest(bundleData, manifest);
  }

  static void loadManifest(BaseData target, Dictionary manifest) throws BundleException {
    try {
      target.setVersion(Version.parseVersion((String) manifest.get(Constants.BUNDLE_VERSION)));
    } catch (IllegalArgumentException e) {
      target.setVersion(new InvalidVersion((String) manifest.get(Constants.BUNDLE_VERSION)));
    }
    ManifestElement[] bsnHeader = ManifestElement.parseHeader(Constants.BUNDLE_SYMBOLICNAME, (String) manifest.get(Constants.BUNDLE_SYMBOLICNAME));
    int bundleType = 0;
    if (bsnHeader != null) {
      target.setSymbolicName(bsnHeader[0].getValue());
      String singleton = bsnHeader[0].getDirective(Constants.SINGLETON_DIRECTIVE);
      if (singleton == null)
        singleton = bsnHeader[0].getAttribute(Constants.SINGLETON_DIRECTIVE);
      if ("true".equals(singleton)) //$NON-NLS-1$
        bundleType |= BundleData.TYPE_SINGLETON;
    }
    // check that the classpath is valid
    String classpath = (String) manifest.get(Constants.BUNDLE_CLASSPATH);
    ManifestElement.parseHeader(Constants.BUNDLE_CLASSPATH, classpath);
    target.setClassPathString(classpath);
    target.setActivator((String) manifest.get(Constants.BUNDLE_ACTIVATOR));
    String host = (String) manifest.get(Constants.FRAGMENT_HOST);
    if (host != null) {
      bundleType |= BundleData.TYPE_FRAGMENT;
      ManifestElement[] hostElement = ManifestElement.parseHeader(Constants.FRAGMENT_HOST, host);
      if (Constants.getInternalSymbolicName().equals(hostElement[0].getValue()) || Constants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(hostElement[0].getValue())) {
        String extensionType = hostElement[0].getDirective("extension"); //$NON-NLS-1$
        if (extensionType == null || extensionType.equals("framework")) //$NON-NLS-1$
          bundleType |= BundleData.TYPE_FRAMEWORK_EXTENSION;
        else if (extensionType.equals("bootclasspath")) //$NON-NLS-1$
          bundleType |= BundleData.TYPE_BOOTCLASSPATH_EXTENSION;
        else if (extensionType.equals("extclasspath")) //$NON-NLS-1$
          bundleType |= BundleData.TYPE_EXTCLASSPATH_EXTENSION;
      }
    } else {
      String composite = (String) manifest.get(COMPOSITE_HEADER);
      if (composite != null) {
        if (COMPOSITE_BUNDLE.equals(composite))
          bundleType |= BundleData.TYPE_COMPOSITEBUNDLE;
        else
          bundleType |= BundleData.TYPE_SURROGATEBUNDLE;
      }
    }
    target.setType(bundleType);
    target.setExecutionEnvironment((String) manifest.get(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT));
    target.setDynamicImports((String) manifest.get(Constants.DYNAMICIMPORT_PACKAGE));
  }

  public StorageHook load(BaseData target, DataInputStream in) throws IOException {
    target.setLocation(AdaptorUtil.readString(in, false));
    target.setSymbolicName(AdaptorUtil.readString(in, false));
    target.setVersion(AdaptorUtil.loadVersion(in));
    target.setActivator(AdaptorUtil.readString(in, false));
    target.setClassPathString(AdaptorUtil.readString(in, false));
    target.setExecutionEnvironment(AdaptorUtil.readString(in, false));
    target.setDynamicImports(AdaptorUtil.readString(in, false));
    target.setStartLevel(in.readInt());
    target.setStatus(in.readInt());
    target.setType(in.readInt());
    target.setLastModified(in.readLong());
    target.setDirty(false); // make sure to reset the dirty bit;

    BaseStorageHook storageHook = new BaseStorageHook(storage);
    storageHook.bundleData = target;
    storageHook.generation = in.readInt();
    storageHook.reference = in.readBoolean();
    storageHook.setFileName(getAbsolute(storageHook.reference, AdaptorUtil.readString(in, false)));
    int nativePathCount = in.readInt();
    storageHook.nativePaths = nativePathCount > 0 ? new String[nativePathCount] : null;
    for (int i = 0; i < nativePathCount; i++)
      storageHook.nativePaths[i] = in.readUTF();
    return storageHook;
  }

  private String getAbsolute(boolean isReference, String path) {
    if (!isReference)
      return path;
    // fileName for bundles installed with reference URLs is stored relative to the install location
    File storedPath = new File(path);
    if (!storedPath.isAbsolute())
      // make sure it has the absolute location instead
      return new FilePath(storage.getInstallPath() + path).toString();
    return path;
  }

  public void save(DataOutputStream out) throws IOException {
    if (bundleData == null)
      throw new IllegalStateException();
    AdaptorUtil.writeStringOrNull(out, bundleData.getLocation());
    AdaptorUtil.writeStringOrNull(out, bundleData.getSymbolicName());
    AdaptorUtil.writeStringOrNull(out, bundleData.getVersion().toString());
    AdaptorUtil.writeStringOrNull(out, bundleData.getActivator());
    AdaptorUtil.writeStringOrNull(out, bundleData.getClassPathString());
    AdaptorUtil.writeStringOrNull(out, bundleData.getExecutionEnvironment());
    AdaptorUtil.writeStringOrNull(out, bundleData.getDynamicImports());
    StorageHook[] hooks = bundleData.getStorageHooks();
    boolean forgetStartLevel = false;
    for (int i = 0; i < hooks.length && !forgetStartLevel; i++)
      forgetStartLevel = hooks[i].forgetStartLevelChange(bundleData.getStartLevel());
    out.writeInt(!forgetStartLevel ? bundleData.getStartLevel() : 1);
    boolean forgetStatus = false;
    // see if we should forget the persistently started flag
    for (int i = 0; i < hooks.length && !forgetStatus; i++)
      forgetStatus = hooks[i].forgetStatusChange(bundleData.getStatus());
    out.writeInt(!forgetStatus ? bundleData.getStatus() : (~Constants.BUNDLE_STARTED) & bundleData.getStatus());
    out.writeInt(bundleData.getType());
    out.writeLong(bundleData.getLastModified());

    out.writeInt(getGeneration());
    out.writeBoolean(isReference());
    String storedFileName = isReference() ? new FilePath(storage.getInstallPath()).makeRelative(new FilePath(getFileName())) : getFileName();
    AdaptorUtil.writeStringOrNull(out, storedFileName);
    if (nativePaths == null)
      out.writeInt(0);
    else {
      out.writeInt(nativePaths.length);
      for (int i = 0; i < nativePaths.length; i++)
        out.writeUTF(nativePaths[i]);
    }

  }

  public int getKeyHashCode() {
    return HASHCODE;
  }

  public boolean compare(KeyedElement other) {
    return other.getKey() == KEY;
  }

  public Object getKey() {
    return KEY;
  }

  public String getFileName() {
    return fileName;
  }

  public int getGeneration() {
    return generation;
  }

  public String[] getNativePaths() {
    return nativePaths;
  }

  public void installNativePaths(String[] installPaths) throws BundleException {
    validateNativePaths(installPaths);
    this.nativePaths = installPaths;
  }

  public void validateNativePaths(String[] nativePaths) throws BundleException {
    for (int i = 0; i < nativePaths.length; i++) {
      if (nativePaths[i].startsWith(EXTERNAL_LIB_PREFIX)) {
        String path = substituteVars(nativePaths[i].substring(EXTERNAL_LIB_PREFIX.length()));
        File nativeFile = new File(path);
        if (!nativeFile.exists())
          throw new BundleException(NLS.bind(AdaptorMsg.BUNDLE_NATIVECODE_EXCEPTION, nativeFile.getAbsolutePath()), BundleException.NATIVECODE_ERROR);
        continue; // continue to next path
      }
      // ensure the file exists in the bundle; it will get extracted later on demand
      BundleEntry nativeEntry = bundleData.getBundleFile().getEntry(nativePaths[i]);
      if (nativeEntry == null)
        throw new BundleException(NLS.bind(AdaptorMsg.BUNDLE_NATIVECODE_EXCEPTION, nativePaths[i]), BundleException.NATIVECODE_ERROR);
    }
  }

  public boolean isReference() {
    return reference;
  }

  public File getBundleStore() {
    if (bundleStore == null)
      bundleStore = new File(storage.getBundleStoreRoot(), String.valueOf(bundleData.getBundleID()));
    return bundleStore;
  }

  public File getDataFile(String path) {
    // lazily initialize dirData to prevent early access to configuration location
    if (dataStore == null)
      dataStore = new File(getBundleStore(), BaseStorage.DATA_DIR_NAME);
    if (path != null && !dataStore.exists() && (storage.isReadOnly() || !dataStore.mkdirs()))
      if (Debug.DEBUG && Debug.DEBUG_GENERAL)
        Debug.println("Unable to create bundle data directory: " + dataStore.getPath()); //$NON-NLS-1$
    return path == null ? dataStore : new File(dataStore, path);
  }

  void delete(boolean postpone, int type) throws IOException {
    File delete = null;
    switch (type) {
      case DEL_GENERATION :
        delete = getGenerationDir();
        break;
      case DEL_BUNDLE_STORE :
        delete = getBundleStore();
        break;
    }
    if (delete != null && delete.exists() && (postpone || !AdaptorUtil.rm(delete))) {
      /* create .delete */
      FileOutputStream out = new FileOutputStream(new File(delete, BaseStorage.DELETE_FLAG));
      out.close();
    }
  }

  File getGenerationDir() {
    return new File(getBundleStore(), String.valueOf(getGeneration()));
  }

  File getParentGenerationDir() {
    Location parentConfiguration = null;
    Location currentConfiguration = LocationManager.getConfigurationLocation();
    if (currentConfiguration != null && (parentConfiguration = currentConfiguration.getParentLocation()) != null)
      return new File(parentConfiguration.getURL().getFile(), FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME + '/' + LocationManager.BUNDLES_DIR + '/' + bundleData.getBundleID() + '/' + getGeneration());
    return null;
  }

  File createGenerationDir() {
    File generationDir = getGenerationDir();
    if (!generationDir.exists() && (storage.isReadOnly() || !generationDir.mkdirs()))
      if (Debug.DEBUG && Debug.DEBUG_GENERAL)
        Debug.println("Unable to create bundle generation directory: " + generationDir.getPath()); //$NON-NLS-1$
    return generationDir;
  }

  public void setReference(boolean reference) {
    this.reference = reference;
  }

  public void setFileName(String fileName) {
    this.fileName = fileName;
    // This is only done for PDE source lookup (bug 126517)
    this.bundleData.setFileName(fileName);
  }

  public void copy(StorageHook storageHook) {
    if (!(storageHook instanceof BaseStorageHook))
      throw new IllegalArgumentException();
    BaseStorageHook hook = (BaseStorageHook) storageHook;
    bundleStore = hook.bundleStore;
    dataStore = hook.dataStore;
    generation = hook.generation + 1;
    // fileName and reference will be set by update
  }

  public void validate() throws IllegalArgumentException {
    // do nothing
  }

  public Dictionary getManifest(boolean firstLoad) throws BundleException {
    // do nothing
    return null;
  }

  public boolean forgetStatusChange(int status) {
    // do nothing
    return false;
  }

  public boolean forgetStartLevelChange(int startlevel) {
    // do nothing
    return false;
  }

  public void initialize(BaseAdaptor adaptor) {
    // do nothing
  }

  public void frameworkStart(BundleContext context) throws BundleException {
    // do nothing
  }

  public void frameworkStop(BundleContext context) throws BundleException {
    // do nothing
  }

  public void frameworkStopping(BundleContext context) {
    // do nothing
  }

  public void addProperties(Properties properties) {
    // do nothing
  }

  public URLConnection mapLocationToURLConnection(String location) throws IOException {
    // take into account that initial@ is special (bug 268563)
    if (location.startsWith("initial@")) { //$NON-NLS-1$
      location = location.substring(8);
      return new URL(location).openConnection();
    }
    // see if this is an existing location
    Bundle[] bundles = storage.getAdaptor().getContext().getBundles();
    AbstractBundle bundle = null;
    for (int i = 0; i < bundles.length && bundle == null; i++)
      if (location.equals(bundles[i].getLocation()))
        bundle = (AbstractBundle) bundles[i];
    if (bundle == null)
      return null;
    BaseData data = (BaseData) bundle.getBundleData();
    BaseStorageHook hook = (BaseStorageHook) data.getStorageHook(BaseStorageHook.KEY);
    return hook.isReference() ? new URL("reference:file:" + hook.getFileName()).openConnection() : null; //$NON-NLS-1$
  }

  public void handleRuntimeError(Throwable error) {
    // do nothing
  }

  public FrameworkLog createFrameworkLog() {
    // do nothing
    return null;
  }

  public BaseStorage getStorage() {
    return storage;
  }

  public static String substituteVars(String path) {
    StringBuffer buf = new StringBuffer(path.length());
    StringTokenizer st = new StringTokenizer(path, VARIABLE_DELIM_STRING, true);
    boolean varStarted = false; // indicates we are processing a var subtitute
    String var = null; // the current var key
    while (st.hasMoreElements()) {
      String tok = st.nextToken();
      if (VARIABLE_DELIM_STRING.equals(tok)) {
        if (!varStarted) {
          varStarted = true; // we found the start of a var
          var = ""; //$NON-NLS-1$
        } else {
          // we have found the end of a var
          String prop = null;
          // get the value of the var from system properties
          if (var != null && var.length() > 0)
            prop = FrameworkProperties.getProperty(var);
          if (prop == null) {
            try {
              // try using the System.getenv method if it exists (bug 126921)
              Method getenv = System.class.getMethod("getenv", new Class[] {String.class}); //$NON-NLS-1$
              prop = (String) getenv.invoke(null, new Object[] {var});
            } catch (Throwable t) {
              // do nothing;
              // on 1.4 VMs this throws an error
              // on J2ME this method does not exist
            }
          }
          if (prop != null)
            // found a value; use it
            buf.append(prop);
          else
            // could not find a value append the var name w/o delims
            buf.append(var == null ? "" : var); //$NON-NLS-1$
          varStarted = false;
          var = null;
        }
      } else {
        if (!varStarted)
          buf.append(tok); // the token is not part of a var
        else
          var = tok; // the token is the var key; save the key to process when we find the end token
      }
    }
    if (var != null)
      // found a case of $var at the end of the path with no trailing $; just append it as is.
      buf.append(VARIABLE_DELIM_CHAR).append(var);
    return buf.toString();
  }
}
TOP

Related Classes of org.eclipse.osgi.internal.baseadaptor.BaseStorageHook

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.