Package org.eclipse.osgi.internal.resolver

Source Code of org.eclipse.osgi.internal.resolver.StateImpl

/*******************************************************************************
* Copyright (c) 2003, 2007 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
*******************************************************************************/
package org.eclipse.osgi.internal.resolver;

import java.util.*;

import org.eclipse.osgi.framework.debug.Debug;
import org.eclipse.osgi.framework.debug.FrameworkDebugOptions;
import org.eclipse.osgi.framework.internal.core.Constants;
import org.eclipse.osgi.framework.internal.core.FilterImpl;
import org.eclipse.osgi.framework.util.*;
import org.eclipse.osgi.internal.baseadaptor.StateManager;
import org.eclipse.osgi.service.resolver.*;
import org.eclipse.osgi.util.ManifestElement;
import org.osgi.framework.*;

public abstract class StateImpl implements State {
  public static final String[] PROPS = {"osgi.os", "osgi.ws", "osgi.nl", "osgi.arch", Constants.OSGI_FRAMEWORK_SYSTEM_PACKAGES, Constants.OSGI_RESOLVER_MODE, Constants.FRAMEWORK_EXECUTIONENVIRONMENT, "osgi.resolveOptional", "osgi.genericAliases"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
  transient private Resolver resolver;
  transient private StateDeltaImpl changes;
  transient private boolean resolving = false;
  transient private HashSet removalPendings = new HashSet();
  private boolean resolved = true;
  private long timeStamp = System.currentTimeMillis();
  private KeyedHashSet bundleDescriptions = new KeyedHashSet(false);
  private HashMap resolverErrors = new HashMap();
  private StateObjectFactory factory;
  private KeyedHashSet resolvedBundles = new KeyedHashSet();
  boolean fullyLoaded = false;
  private boolean dynamicCacheChanged = false;
  // only used for lazy loading of BundleDescriptions
  private StateReader reader;
  private Dictionary[] platformProperties = {new Hashtable(PROPS.length)}; // Dictionary here because of Filter API
  private long highestBundleId = -1;
  private HashSet platformPropertyKeys = new HashSet(PROPS.length);

  private static long cumulativeTime;

  // to prevent extra-package instantiation
  protected StateImpl() {
    // always add the default platform property keys.
    addPlatformPropertyKeys(PROPS);
  }

  public boolean addBundle(BundleDescription description) {
    if (!basicAddBundle(description))
      return false;
    String platformFilter = description.getPlatformFilter();
    if (platformFilter != null) {
      try {
        // add any new platform filter propery keys this bundle is using
        FilterImpl filter = (FilterImpl) FrameworkUtil.createFilter(platformFilter);
        addPlatformPropertyKeys(filter.getAttributes());
      } catch (InvalidSyntaxException e) {
        // ignore this is handled in another place
      }
    }
    resolved = false;
    getDelta().recordBundleAdded((BundleDescriptionImpl) description);
    if (Constants.getInternalSymbolicName().equals(description.getSymbolicName()))
      resetSystemExports();
    if (resolver != null)
      resolver.bundleAdded(description);
    updateTimeStamp();
    return true;
  }

  public boolean updateBundle(BundleDescription newDescription) {
    BundleDescriptionImpl existing = (BundleDescriptionImpl) bundleDescriptions.get((BundleDescriptionImpl) newDescription);
    if (existing == null)
      return false;
    if (!bundleDescriptions.remove(existing))
      return false;
    resolvedBundles.remove(existing);
    existing.setStateBit(BundleDescriptionImpl.REMOVAL_PENDING, true);
    if (!basicAddBundle(newDescription))
      return false;
    resolved = false;
    getDelta().recordBundleUpdated((BundleDescriptionImpl) newDescription);
    if (Constants.getInternalSymbolicName().equals(newDescription.getSymbolicName()))
      resetSystemExports();
    if (resolver != null) {
      boolean pending = existing.getDependents().length > 0;
      resolver.bundleUpdated(newDescription, existing, pending);
      if (pending) {
        getDelta().recordBundleRemovalPending(existing);
        removalPendings.add(existing);
      } else {
        // an existing bundle has been updated with no dependents it can safely be unresolved now
        synchronized (this) {
          try {
            resolving = true;
            resolverErrors.remove(existing);
            resolveBundle(existing, false, null, null, null, null);
          } finally {
            resolving = false;
          }
        }
      }
    }
    updateTimeStamp();
    return true;
  }

  public BundleDescription removeBundle(long bundleId) {
    BundleDescription toRemove = getBundle(bundleId);
    if (toRemove == null || !removeBundle(toRemove))
      return null;
    return toRemove;
  }

  public boolean removeBundle(BundleDescription toRemove) {
    if (!bundleDescriptions.remove((KeyedElement) toRemove))
      return false;
    resolvedBundles.remove((KeyedElement) toRemove);
    resolved = false;
    getDelta().recordBundleRemoved((BundleDescriptionImpl) toRemove);
    ((BundleDescriptionImpl) toRemove).setStateBit(BundleDescriptionImpl.REMOVAL_PENDING, true);
    if (resolver != null) {
      boolean pending = toRemove.getDependents().length > 0;
      resolver.bundleRemoved(toRemove, pending);
      if (pending) {
        getDelta().recordBundleRemovalPending((BundleDescriptionImpl) toRemove);
        removalPendings.add(toRemove);
      } else {
        // a bundle has been removed with no dependents it can safely be unresolved now
        synchronized (this) {
          try {
            resolving = true;
            resolverErrors.remove(toRemove);
            resolveBundle(toRemove, false, null, null, null, null);
          } finally {
            resolving = false;
          }
        }
      }
    }
    updateTimeStamp();
    return true;
  }

  public StateDelta getChanges() {
    return getDelta();
  }

  private StateDeltaImpl getDelta() {
    if (changes == null)
      changes = new StateDeltaImpl(this);
    return changes;
  }

  public BundleDescription[] getBundles(String symbolicName) {
    if (Constants.OSGI_SYSTEM_BUNDLE.equals(symbolicName))
      symbolicName = Constants.getInternalSymbolicName();
    final List bundles = new ArrayList();
    for (Iterator iter = bundleDescriptions.iterator(); iter.hasNext();) {
      BundleDescription bundle = (BundleDescription) iter.next();
      if (symbolicName.equals(bundle.getSymbolicName()))
        bundles.add(bundle);
    }
    return (BundleDescription[]) bundles.toArray(new BundleDescription[bundles.size()]);
  }

  public BundleDescription[] getBundles() {
    return (BundleDescription[]) bundleDescriptions.elements(new BundleDescription[bundleDescriptions.size()]);
  }

  public BundleDescription getBundle(long id) {
    BundleDescription result = (BundleDescription) bundleDescriptions.getByKey(new Long(id));
    if (result != null)
      return result;
    // need to look in removal pending bundles;
    for (Iterator iter = removalPendings.iterator(); iter.hasNext();) {
      BundleDescription removedBundle = (BundleDescription) iter.next();
      if (removedBundle.getBundleId() == id) // just return the first matching id
        return removedBundle;
    }
    return null;
  }

  public BundleDescription getBundle(String name, Version version) {
    BundleDescription[] allBundles = getBundles(name);
    if (allBundles.length == 1)
      return version == null || allBundles[0].getVersion().equals(version) ? allBundles[0] : null;

    if (allBundles.length == 0)
      return null;

    BundleDescription unresolvedFound = null;
    BundleDescription resolvedFound = null;
    for (int i = 0; i < allBundles.length; i++) {
      BundleDescription current = allBundles[i];
      BundleDescription base;

      if (current.isResolved())
        base = resolvedFound;
      else
        base = unresolvedFound;

      if (version == null || current.getVersion().equals(version)) {
        if (base != null && (base.getVersion().compareTo(current.getVersion()) <= 0 || base.getBundleId() > current.getBundleId())) {
          if (base == resolvedFound)
            resolvedFound = current;
          else
            unresolvedFound = current;
        } else {
          if (current.isResolved())
            resolvedFound = current;
          else
            unresolvedFound = current;
        }

      }
    }
    if (resolvedFound != null)
      return resolvedFound;

    return unresolvedFound;
  }

  public long getTimeStamp() {
    return timeStamp;
  }

  public boolean isResolved() {
    return resolved || isEmpty();
  }

  public void resolveConstraint(VersionConstraint constraint, BaseDescription supplier) {
    ((VersionConstraintImpl) constraint).setSupplier(supplier);
  }

  public synchronized void resolveBundle(BundleDescription bundle, boolean status, BundleDescription[] hosts, ExportPackageDescription[] selectedExports, BundleDescription[] resolvedRequires, ExportPackageDescription[] resolvedImports) {
    if (!resolving)
      throw new IllegalStateException(); // TODO need error message here!
    BundleDescriptionImpl modifiable = (BundleDescriptionImpl) bundle;
    // must record the change before setting the resolve state to
    // accurately record if a change has happened.
    getDelta().recordBundleResolved(modifiable, status);
    // force the new resolution data to stay in memory; we will not read this from disk anymore
    modifiable.setLazyLoaded(false);
    modifiable.setStateBit(BundleDescriptionImpl.RESOLVED, status);
    if (status) {
      resolverErrors.remove(modifiable);
      resolvedBundles.add(modifiable);
    } else {
      // remove the bundle from the resolved pool
      resolvedBundles.remove(modifiable);
      modifiable.removeDependencies();
    }
    // to support develoment mode we will resolveConstraints even if the resolve status == false
    // we only do this if the resolved constraints are not null
    if (selectedExports == null || resolvedRequires == null || resolvedImports == null)
      unresolveConstraints(modifiable);
    else
      resolveConstraints(modifiable, hosts, selectedExports, resolvedRequires, resolvedImports);
  }

  public synchronized void removeBundleComplete(BundleDescription bundle) {
    if (!resolving)
      throw new IllegalStateException(); // TODO need error message here!
    getDelta().recordBundleRemovalComplete((BundleDescriptionImpl) bundle);
    removalPendings.remove(bundle);
  }

  private void resolveConstraints(BundleDescriptionImpl bundle, BundleDescription[] hosts, ExportPackageDescription[] selectedExports, BundleDescription[] resolvedRequires, ExportPackageDescription[] resolvedImports) {
    HostSpecificationImpl hostSpec = (HostSpecificationImpl) bundle.getHost();
    if (hostSpec != null) {
      if (hosts != null) {
        hostSpec.setHosts(hosts);
        for (int i = 0; i < hosts.length; i++)
          ((BundleDescriptionImpl) hosts[i]).addDependency(bundle, true);
      }
    }

    bundle.setSelectedExports(selectedExports);
    bundle.setResolvedRequires(resolvedRequires);
    bundle.setResolvedImports(resolvedImports);

    bundle.addDependencies(hosts, true);
    bundle.addDependencies(resolvedRequires, true);
    bundle.addDependencies(resolvedImports, true);
    // add dependecies for generics
    GenericSpecification[] genericRequires = bundle.getGenericRequires();
    if (genericRequires.length > 0) {
      ArrayList genericSuppliers = new ArrayList(genericRequires.length);
      for (int i = 0; i < genericRequires.length; i++) {
        GenericDescription[] suppliers = genericRequires[i].getSuppliers();
        if (suppliers != null)
          for (int j = 0; j < suppliers.length; j++)
            genericSuppliers.add(suppliers[j]);
      }
      bundle.addDependencies((BaseDescription[]) genericSuppliers.toArray(new BaseDescription[genericSuppliers.size()]), true);
    }
  }

  private void unresolveConstraints(BundleDescriptionImpl bundle) {
    HostSpecificationImpl host = (HostSpecificationImpl) bundle.getHost();
    if (host != null)
      host.setHosts(null);

    bundle.setSelectedExports(null);
    bundle.setResolvedImports(null);
    bundle.setResolvedRequires(null);

    // remove suppliers for generics
    GenericSpecification[] genericRequires = bundle.getGenericRequires();
    if (genericRequires.length > 0)
      for (int i = 0; i < genericRequires.length; i++)
        ((GenericSpecificationImpl) genericRequires[i]).setSupplers(null);
    bundle.removeDependencies();
  }

  private synchronized StateDelta resolve(boolean incremental, BundleDescription[] reResolve) {
    try {
      resolving = true;
      if (resolver == null)
        throw new IllegalStateException("no resolver set"); //$NON-NLS-1$
      fullyLoad();
      long start = 0;
      if (StateManager.DEBUG_PLATFORM_ADMIN_RESOLVER)
        start = System.currentTimeMillis();
      if (!incremental) {
        resolved = false;
        reResolve = getBundles();
        // need to get any removal pendings before flushing
        if (removalPendings.size() > 0) {
          BundleDescription[] removed = getRemovalPendings();
          reResolve = mergeBundles(reResolve, removed);
        }
        flush(reResolve);
      }
      if (resolved && reResolve == null)
        return new StateDeltaImpl(this);
      if (removalPendings.size() > 0) {
        BundleDescription[] removed = getRemovalPendings();
        reResolve = mergeBundles(reResolve, removed);
      }
      // use the Headers class to handle ignoring case while matching keys (bug 180817)
      Headers[] tmpPlatformProperties = new Headers[platformProperties.length];
      for (int i = 0; i < platformProperties.length; i++) {
        tmpPlatformProperties[i] = new Headers(platformProperties[i].size());
        for (Enumeration keys = platformProperties[i].keys(); keys.hasMoreElements();) {
          Object key = keys.nextElement();
          tmpPlatformProperties[i].put(key, platformProperties[i].get(key));
        }
      }
      resolver.resolve(reResolve, tmpPlatformProperties);
      resolved = removalPendings.size() == 0;

      StateDelta savedChanges = changes == null ? new StateDeltaImpl(this) : changes;
      changes = new StateDeltaImpl(this);

      if (StateManager.DEBUG_PLATFORM_ADMIN_RESOLVER) {
        long time = System.currentTimeMillis() - start;
        Debug.println("Time spent resolving: " + time); //$NON-NLS-1$
        cumulativeTime = cumulativeTime + time;
        FrameworkDebugOptions.getDefault().setOption("org.eclipse.core.runtime.adaptor/resolver/timing/value", Long.toString(cumulativeTime)); //$NON-NLS-1$
      }
      if (savedChanges.getChanges().length > 0)
        updateTimeStamp();
      return savedChanges;
    } finally {
      resolving = false;
    }
  }

  private BundleDescription[] mergeBundles(BundleDescription[] reResolve, BundleDescription[] removed) {
    if (reResolve == null)
      return removed; // just return all the removed bundles
    if (reResolve.length == 0)
      return reResolve; // if reResolve length==0 then we want to prevent pending removal
    // merge in all removal pending bundles that are not already in the list
    ArrayList result = new ArrayList(reResolve.length + removed.length);
    for (int i = 0; i < reResolve.length; i++)
      result.add(reResolve[i]);
    for (int i = 0; i < removed.length; i++) {
      boolean found = false;
      for (int j = 0; j < reResolve.length; j++) {
        if (removed[i] == reResolve[j]) {
          found = true;
          break;
        }
      }
      if (!found)
        result.add(removed[i]);
    }
    return (BundleDescription[]) result.toArray(new BundleDescription[result.size()]);
  }

  private void flush(BundleDescription[] bundles) {
    resolver.flush();
    resolved = false;
    resolverErrors.clear();
    if (resolvedBundles.isEmpty())
      return;
    for (int i = 0; i < bundles.length; i++) {
      resolveBundle(bundles[i], false, null, null, null, null);
    }
    resolvedBundles.clear();
  }

  public StateDelta resolve() {
    return resolve(true, null);
  }

  public StateDelta resolve(boolean incremental) {
    return resolve(incremental, null);
  }

  public StateDelta resolve(BundleDescription[] reResolve) {
    return resolve(true, reResolve);
  }

  public void setOverrides(Object value) {
    throw new UnsupportedOperationException();
  }

  public BundleDescription[] getResolvedBundles() {
    return (BundleDescription[]) resolvedBundles.elements(new BundleDescription[resolvedBundles.size()]);
  }

  public boolean isEmpty() {
    return bundleDescriptions.isEmpty();
  }

  void setResolved(boolean resolved) {
    this.resolved = resolved;
  }

  boolean basicAddBundle(BundleDescription description) {
    ((BundleDescriptionImpl) description).setContainingState(this);
    ((BundleDescriptionImpl) description).setStateBit(BundleDescriptionImpl.REMOVAL_PENDING, false);
    if (bundleDescriptions.add((BundleDescriptionImpl) description)) {
      if (description.getBundleId() > getHighestBundleId())
        highestBundleId = description.getBundleId();
      return true;
    }
    return false;
  }

  void addResolvedBundle(BundleDescriptionImpl resolvedBundle) {
    resolvedBundles.add(resolvedBundle);
  }

  public ExportPackageDescription[] getExportedPackages() {
    fullyLoad();
    final List allExportedPackages = new ArrayList();
    for (Iterator iter = resolvedBundles.iterator(); iter.hasNext();) {
      BundleDescription bundle = (BundleDescription) iter.next();
      ExportPackageDescription[] bundlePackages = bundle.getSelectedExports();
      if (bundlePackages == null)
        continue;
      for (int i = 0; i < bundlePackages.length; i++)
        allExportedPackages.add(bundlePackages[i]);
    }
    for (Iterator iter = removalPendings.iterator(); iter.hasNext();) {
      BundleDescription bundle = (BundleDescription) iter.next();
      ExportPackageDescription[] bundlePackages = bundle.getSelectedExports();
      if (bundlePackages == null)
        continue;
      for (int i = 0; i < bundlePackages.length; i++)
        allExportedPackages.add(bundlePackages[i]);
    }
    return (ExportPackageDescription[]) allExportedPackages.toArray(new ExportPackageDescription[allExportedPackages.size()]);
  }

  BundleDescription[] getFragments(final BundleDescription host) {
    final List fragments = new ArrayList();
    for (Iterator iter = bundleDescriptions.iterator(); iter.hasNext();) {
      BundleDescription bundle = (BundleDescription) iter.next();
      HostSpecification hostSpec = bundle.getHost();

      if (hostSpec != null) {
        BundleDescription[] hosts = hostSpec.getHosts();
        if (hosts != null)
          for (int i = 0; i < hosts.length; i++)
            if (hosts[i] == host) {
              fragments.add(bundle);
              break;
            }
      }
    }
    return (BundleDescription[]) fragments.toArray(new BundleDescription[fragments.size()]);
  }

  public void setTimeStamp(long newTimeStamp) {
    timeStamp = newTimeStamp;
  }

  private void updateTimeStamp() {
    if (getTimeStamp() == Long.MAX_VALUE)
      setTimeStamp(0);
    setTimeStamp(getTimeStamp() + 1);
  }

  public StateObjectFactory getFactory() {
    return factory;
  }

  void setFactory(StateObjectFactory factory) {
    this.factory = factory;
  }

  public BundleDescription getBundleByLocation(String location) {
    for (Iterator i = bundleDescriptions.iterator(); i.hasNext();) {
      BundleDescription current = (BundleDescription) i.next();
      if (location.equals(current.getLocation()))
        return current;
    }
    return null;
  }

  public Resolver getResolver() {
    return resolver;
  }

  public void setResolver(Resolver newResolver) {
    if (resolver == newResolver)
      return;
    if (resolver != null) {
      Resolver oldResolver = resolver;
      resolver = null;
      oldResolver.setState(null);
    }
    resolver = newResolver;
    if (resolver == null)
      return;
    resolver.setState(this);
  }

  public boolean setPlatformProperties(Dictionary platformProperties) {
    return setPlatformProperties(new Dictionary[] {platformProperties});
  }

  public boolean setPlatformProperties(Dictionary[] platformProperties) {
    return setPlatformProperties(platformProperties, true);
  }

  synchronized boolean setPlatformProperties(Dictionary[] platformProperties, boolean resetSystemExports) {
    if (platformProperties.length == 0)
      throw new IllegalArgumentException();
    // copy the properties for our use internally
    Dictionary[] newPlatformProperties = new Dictionary[platformProperties.length];
    for (int i = 0; i < platformProperties.length; i++) {
      newPlatformProperties[i] = new Hashtable(platformProperties[i].size());
      synchronized (platformProperties[i]) {
        for (Enumeration keys = platformProperties[i].keys(); keys.hasMoreElements();) {
          Object key = keys.nextElement();
          newPlatformProperties[i].put(key, platformProperties[i].get(key));
        }
      }
    }
    boolean result = false;
    if (this.platformProperties.length != newPlatformProperties.length) {
      result = true;
    } else {
      // we need to see if any of the existing filter prop keys have changed
      String[] keys = getPlatformPropertyKeys();
      for (int i = 0; i < newPlatformProperties.length && !result; i++)
        result |= changedProps(this.platformProperties[i], newPlatformProperties[i], keys);
    }
    // always do a complete replacement of the properties in case new bundles are added that uses new filter props
    this.platformProperties = newPlatformProperties;
    if (resetSystemExports && result)
      resetSystemExports();
    return result;
  }

  private void resetSystemExports() {
    BundleDescription[] systemBundles = getBundles(Constants.getInternalSymbolicName());
    if (systemBundles.length > 0) {
      BundleDescriptionImpl systemBundle = (BundleDescriptionImpl) systemBundles[0];
      ExportPackageDescription[] exports = systemBundle.getExportPackages();
      ArrayList newExports = new ArrayList(exports.length);
      for (int i = 0; i < exports.length; i++)
        if (((Integer) exports[i].getDirective(ExportPackageDescriptionImpl.EQUINOX_EE)).intValue() < 0)
          newExports.add(exports[i]);
      addSystemExports(newExports);
      systemBundle.setExportPackages((ExportPackageDescription[]) newExports.toArray(new ExportPackageDescription[newExports.size()]));
    }
  }

  private void addSystemExports(ArrayList exports) {
    for (int i = 0; i < platformProperties.length; i++)
      try {
        ManifestElement[] elements = ManifestElement.parseHeader(Constants.EXPORT_PACKAGE, (String) platformProperties[i].get(Constants.OSGI_FRAMEWORK_SYSTEM_PACKAGES));
        if (elements == null)
          continue;
        // we can pass false for strict mode here because we never want to mark the system exports as internal.
        ExportPackageDescription[] systemExports = StateBuilder.createExportPackages(elements, null, null, null, 2, false);
        Integer profInx = new Integer(i);
        for (int j = 0; j < systemExports.length; j++) {
          ((ExportPackageDescriptionImpl) systemExports[j]).setDirective(ExportPackageDescriptionImpl.EQUINOX_EE, profInx);
          exports.add(systemExports[j]);
        }
      } catch (BundleException e) {
        // TODO consider throwing this...
      }
  }

  public Dictionary[] getPlatformProperties() {
    return platformProperties;
  }

  private boolean checkProp(Object origObj, Object newObj) {
    if ((origObj == null && newObj != null) || (origObj != null && newObj == null))
      return true;
    if (origObj == null)
      return false;
    if (origObj.getClass() != newObj.getClass())
      return true;
    if (origObj instanceof String)
      return !origObj.equals(newObj);
    String[] origProps = (String[]) origObj;
    String[] newProps = (String[]) newObj;
    if (origProps.length != newProps.length)
      return true;
    for (int i = 0; i < origProps.length; i++) {
      if (!origProps[i].equals(newProps[i]))
        return true;
    }
    return false;
  }

  private boolean changedProps(Dictionary origProps, Dictionary newProps, String[] keys) {
    for (int i = 0; i < keys.length; i++) {
      Object origProp = origProps.get(keys[i]);
      Object newProp = newProps.get(keys[i]);
      if (checkProp(origProp, newProp))
        return true;
    }
    return false;
  }

  public BundleDescription[] getRemovalPendings() {
    return (BundleDescription[]) removalPendings.toArray(new BundleDescription[removalPendings.size()]);
  }

  public synchronized ExportPackageDescription linkDynamicImport(BundleDescription importingBundle, String requestedPackage) {
    if (resolver == null)
      throw new IllegalStateException("no resolver set"); //$NON-NLS-1$
    BundleDescriptionImpl importer = (BundleDescriptionImpl) importingBundle;
    if (importer.getDynamicStamp(requestedPackage) == getTimeStamp())
      return null;
    try {
      resolving = true;
      fullyLoad();
      // ask the resolver to resolve our dynamic import
      ExportPackageDescriptionImpl result = (ExportPackageDescriptionImpl) resolver.resolveDynamicImport(importingBundle, requestedPackage);
      if (result == null)
        importer.setDynamicStamp(requestedPackage, new Long(getTimeStamp()));
      else {
        importer.setDynamicStamp(requestedPackage, null); // remove any cached timestamp
        // need to add the result to the list of resolved imports
        importer.addDynamicResolvedImport(result);
      }
      setDynamicCacheChanged(true);
      return result;
    } finally {
      resolving = false;
    }
  }

  void setReader(StateReader reader) {
    this.reader = reader;
  }

  StateReader getReader() {
    return reader;
  }

  public void fullyLoad() {
    if (reader == null)
      return;
    synchronized (reader) {
      if (fullyLoaded == true)
        return;
      if (reader.isLazyLoaded())
        reader.fullyLoad();
      fullyLoaded = true;
    }
  }

  public void unloadLazyData(long expireTime) {
    // make sure no other thread is trying to unload or load
    synchronized (reader) {
      if (reader.getAccessedFlag()) {
        reader.setAccessedFlag(false); // reset accessed flag
        return;
      }
      fullyLoaded = false;
      BundleDescription[] bundles = getBundles();
      for (int i = 0; i < bundles.length; i++)
        ((BundleDescriptionImpl) bundles[i]).unload();
    }
  }

  public ExportPackageDescription[] getSystemPackages() {
    ArrayList result = new ArrayList();
    BundleDescription[] systemBundles = getBundles(Constants.getInternalSymbolicName());
    if (systemBundles.length > 0) {
      BundleDescriptionImpl systemBundle = (BundleDescriptionImpl) systemBundles[0];
      ExportPackageDescription[] exports = systemBundle.getExportPackages();
      for (int i = 0; i < exports.length; i++)
        if (((Integer) exports[i].getDirective(ExportPackageDescriptionImpl.EQUINOX_EE)).intValue() >= 0)
          result.add(exports[i]);
    }
    return (ExportPackageDescription[]) result.toArray(new ExportPackageDescription[result.size()]);
  }

  boolean inStrictMode() {
    return Constants.STRICT_MODE.equals(getPlatformProperties()[0].get(Constants.OSGI_RESOLVER_MODE));
  }

  public synchronized ResolverError[] getResolverErrors(BundleDescription bundle) {
    if (bundle.isResolved())
      return new ResolverError[0];
    ArrayList result = (ArrayList) resolverErrors.get(bundle);
    return result == null ? new ResolverError[0] : (ResolverError[]) result.toArray(new ResolverError[result.size()]);
  }

  public synchronized void addResolverError(BundleDescription bundle, int type, String data, VersionConstraint unsatisfied) {
    if (!resolving)
      throw new IllegalStateException(); // TODO need error message here!
    ArrayList errors = (ArrayList) resolverErrors.get(bundle);
    if (errors == null) {
      errors = new ArrayList(1);
      resolverErrors.put(bundle, errors);
    }
    errors.add(new ResolverErrorImpl((BundleDescriptionImpl) bundle, type, data, unsatisfied));
  }

  public synchronized void removeResolverErrors(BundleDescription bundle) {
    if (!resolving)
      throw new IllegalStateException(); // TODO need error message here!
    resolverErrors.remove(bundle);
  }

  public boolean dynamicCacheChanged() {
    return dynamicCacheChanged;
  }

  void setDynamicCacheChanged(boolean dynamicCacheChanged) {
    this.dynamicCacheChanged = dynamicCacheChanged;
  }

  public StateHelper getStateHelper() {
    return StateHelperImpl.getInstance();
  }

  void addPlatformPropertyKeys(String[] keys) {
    synchronized (platformPropertyKeys) {
      for (int i = 0; i < keys.length; i++)
        if (!platformPropertyKeys.contains(keys[i]))
          platformPropertyKeys.add(keys[i]);
    }
  }

  String[] getPlatformPropertyKeys() {
    synchronized (platformPropertyKeys) {
      return (String[]) platformPropertyKeys.toArray(new String[platformPropertyKeys.size()]);
    }
  }

  public long getHighestBundleId() {
    return highestBundleId;
  }

}
TOP

Related Classes of org.eclipse.osgi.internal.resolver.StateImpl

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.