Class BundleArchive

java.lang.Object
org.apache.felix.framework.cache.BundleArchive

public class BundleArchive extends Object

This class is a logical abstraction for a bundle archive. This class, combined with BundleCache and concrete BundleRevision subclasses, implement the bundle cache for Felix. The bundle archive abstracts the actual bundle content into revisions and the revisions provide access to the actual bundle content. When a bundle is installed it has one revision associated with its content. Updating a bundle adds another revision for the updated content. Any number of revisions can be associated with a bundle archive. When the bundle (or framework) is refreshed, then all old revisions are purged and only the most recent revision is maintained.

The content associated with a revision can come in many forms, such as a standard JAR file or an exploded bundle directory. The bundle archive is responsible for creating all revision instances during invocations of the revise() method call. Internally, it determines the concrete type of revision type by examining the location string as an URL. Currently, it supports standard JAR files, referenced JAR files, and referenced directories. Examples of each type of URL are, respectively:

  • http://www.foo.com/bundle.jar
  • reference:file:/foo/bundle.jar
  • reference:file:/foo/bundle/

The "reference:" notation signifies that the resource should be used "in place", meaning that they will not be copied. For referenced JAR files, some resources may still be copied, such as embedded JAR files or native libraries, but for referenced exploded bundle directories, nothing will be copied. Currently, reference URLs can only refer to "file:" targets.

See Also:
  • BundleCache
  • invalid reference
    org.apache.felix.framework.cache.BundleRevision
  • Field Details

    • FILE_PROTOCOL

      public static final transient String FILE_PROTOCOL
      See Also:
    • REFERENCE_PROTOCOL

      public static final transient String REFERENCE_PROTOCOL
      See Also:
    • INPUTSTREAM_PROTOCOL

      public static final transient String INPUTSTREAM_PROTOCOL
      See Also:
    • BUNDLE_INFO_FILE

      private static final transient String BUNDLE_INFO_FILE
      See Also:
    • REVISION_LOCATION_FILE

      private static final transient String REVISION_LOCATION_FILE
      See Also:
    • REVISION_DIRECTORY

      private static final transient String REVISION_DIRECTORY
      See Also:
    • DATA_DIRECTORY

      private static final transient String DATA_DIRECTORY
      See Also:
    • m_logger

      private final Logger m_logger
    • m_configMap

      private final Map m_configMap
    • m_zipFactory

      private final WeakZipFileFactory m_zipFactory
    • m_archiveRootDir

      private final File m_archiveRootDir
    • m_isSingleBundleFile

      private final boolean m_isSingleBundleFile
    • m_id

      private long m_id
    • m_originalLocation

      private String m_originalLocation
    • m_persistentState

      private int m_persistentState
    • m_startLevel

      private int m_startLevel
    • m_lastModified

      private long m_lastModified
    • m_refreshCount

      private long m_refreshCount
      The refresh count field is used when generating the bundle revision directory name where native libraries are extracted. This is necessary because Sun's JVM requires a one-to-one mapping between native libraries and class loaders where the native library is uniquely identified by its absolute path in the file system. This constraint creates a problem when a bundle is refreshed, because it gets a new class loader. Using the refresh counter to generate the name of the bundle revision directory resolves this problem because each time bundle is refresh, the native library will have a unique name. As a result of the unique name, the JVM will then reload the native library without a problem.
    • m_revisions

      private final SortedMap<Long,BundleArchiveRevision> m_revisions
    • BUNDLE_ID_FILE

      private static final transient String BUNDLE_ID_FILE
      See Also:
    • BUNDLE_LOCATION_FILE

      private static final transient String BUNDLE_LOCATION_FILE
      See Also:
    • BUNDLE_STATE_FILE

      private static final transient String BUNDLE_STATE_FILE
      See Also:
    • BUNDLE_START_LEVEL_FILE

      private static final transient String BUNDLE_START_LEVEL_FILE
      See Also:
    • BUNDLE_LASTMODIFIED_FILE

      private static final transient String BUNDLE_LASTMODIFIED_FILE
      See Also:
    • REFRESH_COUNTER_FILE

      private static final transient String REFRESH_COUNTER_FILE
      See Also:
    • ACTIVE_STATE

      private static final transient String ACTIVE_STATE
      See Also:
    • STARTING_STATE

      private static final transient String STARTING_STATE
      See Also:
    • INSTALLED_STATE

      private static final transient String INSTALLED_STATE
      See Also:
    • UNINSTALLED_STATE

      private static final transient String UNINSTALLED_STATE
      See Also:
  • Constructor Details

    • BundleArchive

      public BundleArchive(Logger logger, Map configMap, WeakZipFileFactory zipFactory, File archiveRootDir, long id, int startLevel, String location, InputStream is) throws Exception

      This constructor is used for creating new archives when a bundle is installed into the framework. Each archive receives a logger, a root directory, its associated bundle identifier, the associated bundle location string, and an input stream from which to read the bundle content. The root directory is where any required state can be stored. The input stream may be null, in which case the location is used as an URL to the bundle content.

      Parameters:
      logger - the logger to be used by the archive.
      archiveRootDir - the archive root directory for storing state.
      id - the bundle identifier associated with the archive.
      location - the bundle location string associated with the archive.
      is - input stream from which to read the bundle content.
      Throws:
      Exception - if any error occurs.
    • BundleArchive

      public BundleArchive(Logger logger, Map configMap, WeakZipFileFactory zipFactory, File archiveRootDir) throws Exception

      This constructor is called when an archive for a bundle is being reconstructed when the framework is restarted. Each archive receives a logger, a root directory, and its associated bundle identifier. The root directory is where any required state can be stored.

      Parameters:
      logger - the logger to be used by the archive.
      configMap - configMap for BundleArchive
      archiveRootDir - the archive root directory for storing state.
      Throws:
      Exception - if any error occurs.
  • Method Details

    • getId

      public long getId() throws Exception

      Returns the bundle identifier associated with this archive.

      Returns:
      the bundle identifier associated with this archive.
      Throws:
      Exception - if any error occurs.
    • getLocation

      public String getLocation() throws Exception

      Returns the location string associated with this archive.

      Returns:
      the location string associated with this archive.
      Throws:
      Exception - if any error occurs.
    • getPersistentState

      public int getPersistentState() throws Exception

      Returns the persistent state of this archive. The value returned is one of the following: Bundle.INSTALLED, Bundle.ACTIVE, or Bundle.UNINSTALLED.

      Returns:
      the persistent state of this archive.
      Throws:
      Exception - if any error occurs.
    • setPersistentState

      public void setPersistentState(int state) throws Exception

      Sets the persistent state of this archive. The value is one of the following: Bundle.INSTALLED, Bundle.ACTIVE, or Bundle.UNINSTALLED.

      Parameters:
      state - the persistent state value to set for this archive.
      Throws:
      Exception - if any error occurs.
    • getStartLevel

      public int getStartLevel() throws Exception

      Returns the start level of this archive.

      Returns:
      the start level of this archive.
      Throws:
      Exception - if any error occurs.
    • setStartLevel

      public void setStartLevel(int level) throws Exception

      Sets the the start level of this archive this archive.

      Parameters:
      level - the start level to set for this archive.
      Throws:
      Exception - if any error occurs.
    • getLastModified

      public long getLastModified() throws Exception

      Returns the last modification time of this archive.

      Returns:
      the last modification time of this archive.
      Throws:
      Exception - if any error occurs.
    • setLastModified

      public void setLastModified(long lastModified) throws Exception

      Sets the the last modification time of this archive.

      Parameters:
      lastModified - The time of the last modification to set for this archive. According to the OSGi specification this time is set each time a bundle is installed, updated or uninstalled.
      Throws:
      Exception - if any error occurs.
    • getRefreshCount

      private long getRefreshCount() throws Exception
      This utility method is used to retrieve the current refresh counter value for the bundle. This value is used when generating the bundle revision directory name where native libraries are extracted. This is necessary because Sun's JVM requires a one-to-one mapping between native libraries and class loaders where the native library is uniquely identified by its absolute path in the file system. This constraint creates a problem when a bundle is refreshed, because it gets a new class loader. Using the refresh counter to generate the name of the bundle revision directory resolves this problem because each time bundle is refresh, the native library will have a unique name. As a result of the unique name, the JVM will then reload the native library without a problem.
      Throws:
      Exception
    • setRefreshCount

      private void setRefreshCount(long count) throws Exception
      This utility method is used to retrieve the current refresh counter value for the bundle. This value is used when generating the bundle revision directory name where native libraries are extracted. This is necessary because Sun's JVM requires a one-to-one mapping between native libraries and class loaders where the native library is uniquely identified by its absolute path in the file system. This constraint creates a problem when a bundle is refreshed, because it gets a new class loader. Using the refresh counter to generate the name of the bundle revision directory resolves this problem because each time bundle is refresh, the native library will have a unique name. As a result of the unique name, the JVM will then reload the native library without a problem.
      Throws:
      Exception
    • getDataFile

      public File getDataFile(String fileName) throws Exception

      Returns a File object corresponding to the data file of the relative path of the specified string.

      Returns:
      a File object corresponding to the specified file name.
      Throws:
      Exception - if any error occurs.
    • getCurrentRevisionNumber

      public Long getCurrentRevisionNumber()

      Returns the current revision object for the archive.

      Returns:
      the current revision object for the archive.
    • getCurrentRevision

      public BundleArchiveRevision getCurrentRevision()

      Returns the current revision object for the archive.

      Returns:
      the current revision object for the archive.
    • isRemovalPending

      public boolean isRemovalPending()
    • revise

      public void revise(String location, InputStream is) throws Exception

      This method adds a revision to the archive using the associated location and input stream. If the input stream is null, then the location is used a URL to obtain an input stream.

      Parameters:
      location - the location string associated with the revision.
      is - the input stream from which to read the revision.
      Throws:
      Exception - if any error occurs.
    • reviseInternal

      private void reviseInternal(boolean isReload, Long revNum, String location, InputStream is) throws Exception
      Actually adds a revision to the bundle archive. This method is also used to reload cached bundles too. The revision is given the specified revision number and is read from the input stream if supplied or from the location URL if not.
      Parameters:
      isReload - if the bundle is being reloaded or not.
      revNum - the revision number of the revision.
      location - the location associated with the revision.
      is - the input stream from which to read the revision.
      Throws:
      Exception - if any error occurs.
    • rollbackRevise

      public boolean rollbackRevise() throws Exception

      This method undoes the previous revision to the archive; this method will remove the latest revision from the archive. This method is only called when there are problems during an update after the revision has been created, such as errors in the update bundle's manifest. This method can only be called if there is more than one revision, otherwise there is nothing to undo.

      Returns:
      true if the undo was a success false if there is no previous revision
      Throws:
      Exception - if any error occurs.
    • getRevisionLocation

      private String getRevisionLocation(Long revNum) throws Exception
      Throws:
      Exception
    • setRevisionLocation

      private void setRevisionLocation(String location, Long revNum) throws Exception
      Throws:
      Exception
    • close

      public void close()
    • closeAndDelete

      public void closeAndDelete()

      This method closes any revisions and deletes the bundle archive directory.

      Throws:
      Exception - if any error occurs.
    • purge

      public void purge() throws Exception

      This method removes all old revisions associated with the archive and keeps only the current revision.

      Throws:
      Exception - if any error occurs.
    • initialize

      private void initialize() throws Exception

      Initializes the bundle archive object by creating the archive root directory and saving the initial state.

      Throws:
      Exception - if any error occurs.
    • createRevisionFromLocation

      private BundleArchiveRevision createRevisionFromLocation(String location, InputStream is, Long revNum) throws Exception

      Creates a revision based on the location string and/or input stream.

      Returns:
      the location string associated with this archive.
      Throws:
      Exception
    • decode

      private static String decode(String s) throws UnsupportedEncodingException
      Throws:
      UnsupportedEncodingException
    • readBundleInfo

      private void readBundleInfo() throws Exception
      Throws:
      Exception
    • writeBundleInfo

      private void writeBundleInfo() throws Exception
      Throws:
      Exception
    • writeId

      private void writeId() throws Exception
      Throws:
      Exception
    • readId

      private long readId() throws Exception
      Throws:
      Exception
    • writeLocation

      private void writeLocation() throws Exception
      Throws:
      Exception
    • readLocation

      private String readLocation() throws Exception
      Throws:
      Exception
    • writePersistentState

      private void writePersistentState() throws Exception
      Throws:
      Exception
    • readPersistentState

      private int readPersistentState() throws Exception
      Throws:
      Exception
    • writeStartLevel

      private void writeStartLevel() throws Exception
      Throws:
      Exception
    • readStartLevel

      private int readStartLevel() throws Exception
      Throws:
      Exception
    • writeLastModified

      private void writeLastModified() throws Exception
      Throws:
      Exception
    • readLastModified

      private long readLastModified() throws Exception
      Throws:
      Exception
    • writeRefreshCount

      private void writeRefreshCount() throws Exception
      Throws:
      Exception
    • readRefreshCount

      private long readRefreshCount() throws Exception
      Throws:
      Exception