Modify bundle cache to use a single file to record bundle state
if a configuration property is set. (FELIX-2654)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1022172 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/Felix.java b/framework/src/main/java/org/apache/felix/framework/Felix.java
index 62ac4ab..ec2a57a 100644
--- a/framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -2461,7 +2461,7 @@
try
{
// Add the bundle to the cache.
- ba = m_cache.create(id, location, is);
+ ba = m_cache.create(id, getInitialBundleStartLevel(), location, is);
}
catch (Exception ex)
{
@@ -2577,15 +2577,6 @@
}
}
- // If the bundle is new, then set its start level; existing
- // bundles already have their start level set.
- if (isNew)
- {
- // This will persistently set the bundle's start level.
- bundle.setStartLevel(getInitialBundleStartLevel());
- bundle.setLastModified(System.currentTimeMillis());
- }
-
// Acquire global lock.
boolean locked = acquireGlobalLock();
if (!locked)
diff --git a/framework/src/main/java/org/apache/felix/framework/cache/BundleArchive.java b/framework/src/main/java/org/apache/felix/framework/cache/BundleArchive.java
index e46d7e7..fc8e0cf 100644
--- a/framework/src/main/java/org/apache/felix/framework/cache/BundleArchive.java
+++ b/framework/src/main/java/org/apache/felix/framework/cache/BundleArchive.java
@@ -67,32 +67,38 @@
public static final transient String REFERENCE_PROTOCOL = "reference:";
public static final transient String INPUTSTREAM_PROTOCOL = "inputstream:";
- private static final transient String BUNDLE_ID_FILE = "bundle.id";
- private static final transient String BUNDLE_LOCATION_FILE = "bundle.location";
+ private static final transient String BUNDLE_INFO_FILE = "bundle.info";
private static final transient String REVISION_LOCATION_FILE = "revision.location";
- private static final transient String BUNDLE_STATE_FILE = "bundle.state";
- private static final transient String BUNDLE_START_LEVEL_FILE = "bundle.startlevel";
- private static final transient String REFRESH_COUNTER_FILE = "refresh.counter";
- private static final transient String BUNDLE_LASTMODIFIED_FILE = "bundle.lastmodified";
private static final transient String REVISION_DIRECTORY = "version";
private static final transient String DATA_DIRECTORY = "data";
- private static final transient String ACTIVE_STATE = "active";
- private static final transient String STARTING_STATE = "starting";
- private static final transient String INSTALLED_STATE = "installed";
- private static final transient String UNINSTALLED_STATE = "uninstalled";
private final Logger m_logger;
private final Map m_configMap;
- private long m_id = -1;
private final File m_archiveRootDir;
+ private final boolean m_isSingleBundleFile;
+
+ private long m_id = -1;
private String m_originalLocation = null;
private int m_persistentState = -1;
private int m_startLevel = -1;
private long m_lastModified = -1;
- private BundleRevision[] m_revisions = null;
+ /**
+ * 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.
+ **/
private long m_refreshCount = -1;
+ private BundleRevision[] m_revisions = null;
+
/**
* <p>
* This constructor is only used by the system bundle archive implementation
@@ -104,6 +110,9 @@
m_logger = null;
m_configMap = null;
m_archiveRootDir = null;
+
+ String s = (String) m_configMap.get(BundleCache.CACHE_SINGLEBUNDLEFILE_PROP);
+ m_isSingleBundleFile = (s == null) || (!s.equalsIgnoreCase("true")) ? false : true;
}
/**
@@ -124,7 +133,7 @@
* @throws Exception if any error occurs.
**/
public BundleArchive(Logger logger, Map configMap, File archiveRootDir, long id,
- String location, InputStream is) throws Exception
+ int startLevel, String location, InputStream is) throws Exception
{
m_logger = logger;
m_configMap = configMap;
@@ -136,6 +145,13 @@
"Bundle ID cannot be less than or equal to zero.");
}
m_originalLocation = location;
+ m_persistentState = Bundle.INSTALLED;
+ m_startLevel = startLevel;
+ m_lastModified = System.currentTimeMillis();
+ m_refreshCount = 0;
+
+ String s = (String) m_configMap.get(BundleCache.CACHE_SINGLEBUNDLEFILE_PROP);
+ m_isSingleBundleFile = (s == null) || (!s.equalsIgnoreCase("true")) ? false : true;
// Save state.
initialize();
@@ -163,6 +179,14 @@
m_configMap = configMap;
m_archiveRootDir = archiveRootDir;
+ String s = (String) m_configMap.get(BundleCache.CACHE_SINGLEBUNDLEFILE_PROP);
+ m_isSingleBundleFile = (s == null) || (!s.equalsIgnoreCase("true")) ? false : true;
+
+ if (m_isSingleBundleFile)
+ {
+ readBundleInfo();
+ }
+
// Add a revision for each one that already exists in the file
// system. The file system might contain more than one revision
// if the bundle was updated in a previous session, but the
@@ -214,34 +238,8 @@
{
if (m_id <= 0)
{
- // Read bundle location.
- InputStream is = null;
- BufferedReader br = null;
- try
- {
- is = BundleCache.getSecureAction()
- .getFileInputStream(new File(m_archiveRootDir, BUNDLE_ID_FILE));
- br = new BufferedReader(new InputStreamReader(is));
- m_id = Long.parseLong(br.readLine());
- }
- catch (FileNotFoundException ex)
- {
- // HACK: Get the bundle identifier from the archive root directory
- // name, which is of the form "bundle<id>" where <id> is the bundle
- // identifier numbers. This is a hack to deal with old archives that
- // did not save their bundle identifier, but instead had it passed
- // into them. Eventually, this can be removed.
- m_id = Long.parseLong(
- m_archiveRootDir.getName().substring(
- BundleCache.BUNDLE_DIR_PREFIX.length()));
- }
- finally
- {
- if (br != null) br.close();
- if (is != null) is.close();
- }
+ m_id = readId();
}
-
return m_id;
}
@@ -256,21 +254,7 @@
{
if (m_originalLocation == null)
{
- // Read bundle location.
- InputStream is = null;
- BufferedReader br = null;
- try
- {
- is = BundleCache.getSecureAction()
- .getFileInputStream(new File(m_archiveRootDir, BUNDLE_LOCATION_FILE));
- br = new BufferedReader(new InputStreamReader(is));
- m_originalLocation = br.readLine();
- }
- finally
- {
- if (br != null) br.close();
- if (is != null) is.close();
- }
+ m_originalLocation = readLocation();
}
return m_originalLocation;
}
@@ -288,49 +272,7 @@
{
if (m_persistentState < 0)
{
- // Get bundle state file.
- File stateFile = new File(m_archiveRootDir, BUNDLE_STATE_FILE);
-
- // If the state file doesn't exist, then
- // assume the bundle was installed.
- if (!BundleCache.getSecureAction().fileExists(stateFile))
- {
- m_persistentState = Bundle.INSTALLED;
- }
- else
- {
- // Read the bundle state.
- InputStream is = null;
- BufferedReader br = null;
- try
- {
- is = BundleCache.getSecureAction()
- .getFileInputStream(stateFile);
- br = new BufferedReader(new InputStreamReader(is));
- String s = br.readLine();
- if ((s != null) && s.equals(ACTIVE_STATE))
- {
- m_persistentState = Bundle.ACTIVE;
- }
- else if ((s != null) && s.equals(STARTING_STATE))
- {
- m_persistentState = Bundle.STARTING;
- }
- else if ((s != null) && s.equals(UNINSTALLED_STATE))
- {
- m_persistentState = Bundle.UNINSTALLED;
- }
- else
- {
- m_persistentState = Bundle.INSTALLED;
- }
- }
- finally
- {
- if (br != null) br.close();
- if (is != null) is.close();
- }
- }
+ m_persistentState = readPersistentState();
}
return m_persistentState;
}
@@ -346,46 +288,16 @@
**/
public synchronized void setPersistentState(int state) throws Exception
{
- // Write the bundle state.
- OutputStream os = null;
- BufferedWriter bw = null;
if (m_persistentState != state)
{
- try
+ m_persistentState = state;
+ if (m_isSingleBundleFile)
{
- os = BundleCache.getSecureAction()
- .getFileOutputStream(new File(m_archiveRootDir, BUNDLE_STATE_FILE));
- bw = new BufferedWriter(new OutputStreamWriter(os));
- String s = null;
- switch (state)
- {
- case Bundle.ACTIVE:
- s = ACTIVE_STATE;
- break;
- case Bundle.STARTING:
- s = STARTING_STATE;
- break;
- case Bundle.UNINSTALLED:
- s = UNINSTALLED_STATE;
- break;
- default:
- s = INSTALLED_STATE;
- break;
- }
- bw.write(s, 0, s.length());
- m_persistentState = state;
+ writeBundleInfo();
}
- catch (IOException ex)
+ else
{
- m_logger.log(
- Logger.LOG_ERROR,
- getClass().getName() + ": Unable to record state - " + ex);
- throw ex;
- }
- finally
- {
- if (bw != null) bw.close();
- if (os != null) os.close();
+ writePersistentState();
}
}
}
@@ -401,33 +313,7 @@
{
if (m_startLevel < 0)
{
- // Get bundle start level file.
- File levelFile = new File(m_archiveRootDir, BUNDLE_START_LEVEL_FILE);
-
- // If the start level file doesn't exist, then
- // return an error.
- if (!BundleCache.getSecureAction().fileExists(levelFile))
- {
- m_startLevel = -1;
- }
- else
- {
- // Read the bundle start level.
- InputStream is = null;
- BufferedReader br= null;
- try
- {
- is = BundleCache.getSecureAction()
- .getFileInputStream(levelFile);
- br = new BufferedReader(new InputStreamReader(is));
- m_startLevel = Integer.parseInt(br.readLine());
- }
- finally
- {
- if (br != null) br.close();
- if (is != null) is.close();
- }
- }
+ m_startLevel = readStartLevel();
}
return m_startLevel;
}
@@ -441,29 +327,17 @@
**/
public synchronized void setStartLevel(int level) throws Exception
{
- // Write the bundle start level.
- OutputStream os = null;
- BufferedWriter bw = null;
- try
+ if (m_startLevel != level)
{
- os = BundleCache.getSecureAction()
- .getFileOutputStream(new File(m_archiveRootDir, BUNDLE_START_LEVEL_FILE));
- bw = new BufferedWriter(new OutputStreamWriter(os));
- String s = Integer.toString(level);
- bw.write(s, 0, s.length());
m_startLevel = level;
- }
- catch (IOException ex)
- {
- m_logger.log(
- Logger.LOG_ERROR,
- getClass().getName() + ": Unable to record start level - " + ex);
- throw ex;
- }
- finally
- {
- if (bw != null) bw.close();
- if (os != null) os.close();
+ if (m_isSingleBundleFile)
+ {
+ writeBundleInfo();
+ }
+ else
+ {
+ writeStartLevel();
+ }
}
}
@@ -478,32 +352,7 @@
{
if (m_lastModified < 0)
{
- // Get bundle last modification time file.
- File lastModFile = new File(m_archiveRootDir, BUNDLE_LASTMODIFIED_FILE);
-
- // If the last modification file doesn't exist, then
- // return an error.
- if (!BundleCache.getSecureAction().fileExists(lastModFile))
- {
- m_lastModified = 0;
- }
- else
- {
- // Read the bundle start level.
- InputStream is = null;
- BufferedReader br= null;
- try
- {
- is = BundleCache.getSecureAction().getFileInputStream(lastModFile);
- br = new BufferedReader(new InputStreamReader(is));
- m_lastModified = Long.parseLong(br.readLine());
- }
- finally
- {
- if (br != null) br.close();
- if (is != null) is.close();
- }
- }
+ m_lastModified = readLastModified();
}
return m_lastModified;
}
@@ -520,29 +369,73 @@
**/
public synchronized void setLastModified(long lastModified) throws Exception
{
- // Write the bundle last modification time.
- OutputStream os = null;
- BufferedWriter bw = null;
- try
+ if (m_lastModified != lastModified)
{
- os = BundleCache.getSecureAction()
- .getFileOutputStream(new File(m_archiveRootDir, BUNDLE_LASTMODIFIED_FILE));
- bw = new BufferedWriter(new OutputStreamWriter(os));
- String s = Long.toString(lastModified);
- bw.write(s, 0, s.length());
m_lastModified = lastModified;
+ if (m_isSingleBundleFile)
+ {
+ writeBundleInfo();
+ }
+ else
+ {
+ writeLastModified();
+ }
}
- catch (IOException ex)
+ }
+
+ /**
+ * 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.
+ **/
+ private long getRefreshCount() throws Exception
+ {
+ // If the refresh counter is not yet initialized, do so now.
+ if (m_refreshCount < 0)
{
- m_logger.log(
- Logger.LOG_ERROR,
- getClass().getName() + ": Unable to record last modification time - " + ex);
- throw ex;
+ m_refreshCount = readRefreshCount();
}
- finally
+
+ return m_refreshCount;
+ }
+
+ /**
+ * 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.
+ **/
+ private void setRefreshCount(long count)
+ throws Exception
+ {
+ if (m_refreshCount != count)
{
- if (bw != null) bw.close();
- if (os != null) os.close();
+ m_refreshCount = count;
+ if (m_isSingleBundleFile)
+ {
+ writeBundleInfo();
+ }
+ else
+ {
+ writeRefreshCount();
+ }
}
}
@@ -860,19 +753,17 @@
throw new IOException("Unable to create archive directory.");
}
- // Save id.
- os = BundleCache.getSecureAction()
- .getFileOutputStream(new File(m_archiveRootDir, BUNDLE_ID_FILE));
- bw = new BufferedWriter(new OutputStreamWriter(os));
- bw.write(Long.toString(m_id), 0, Long.toString(m_id).length());
- bw.close();
- os.close();
-
- // Save location string.
- os = BundleCache.getSecureAction()
- .getFileOutputStream(new File(m_archiveRootDir, BUNDLE_LOCATION_FILE));
- bw = new BufferedWriter(new OutputStreamWriter(os));
- bw.write(m_originalLocation, 0, m_originalLocation.length());
+ if (m_isSingleBundleFile)
+ {
+ writeBundleInfo();
+ }
+ else
+ {
+ writeId();
+ writeLocation();
+ writePersistentState();
+ writeStartLevel();
+ }
}
finally
{
@@ -1011,96 +902,92 @@
return result.toString();
}
-
- /**
- * 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.
- **/
- private long getRefreshCount() throws Exception
+ private void readBundleInfo() throws Exception
{
- // If the refresh counter is not yet initialized, do so now.
- if (m_refreshCount < 0)
+ File infoFile = new File(m_archiveRootDir, BUNDLE_INFO_FILE);
+
+ // Read the bundle start level.
+ InputStream is = null;
+ BufferedReader br= null;
+ try
{
- // Get refresh counter file.
- File counterFile = new File(m_archiveRootDir, REFRESH_COUNTER_FILE);
+ is = BundleCache.getSecureAction()
+ .getFileInputStream(infoFile);
+ br = new BufferedReader(new InputStreamReader(is));
- // If the refresh counter file doesn't exist, then
- // assume the counter is at zero.
- if (!BundleCache.getSecureAction().fileExists(counterFile))
- {
- m_refreshCount = 0;
- }
- else
- {
- // Read the bundle refresh counter.
- InputStream is = null;
- BufferedReader br = null;
- try
- {
- is = BundleCache.getSecureAction()
- .getFileInputStream(counterFile);
- br = new BufferedReader(new InputStreamReader(is));
- long counter = Long.parseLong(br.readLine());
- return counter;
- }
- finally
- {
- if (br != null) br.close();
- if (is != null) is.close();
- }
- }
+ // Read id.
+ m_id = Long.parseLong(br.readLine());
+ // Read location.
+ m_originalLocation = br.readLine();
+ // Read state.
+ m_persistentState = Integer.parseInt(br.readLine());
+ // Read start level.
+ m_startLevel = Integer.parseInt(br.readLine());
+ // Read last modified.
+ m_lastModified = Long.parseLong(br.readLine());
+ // Read refresh count.
+ m_refreshCount = Long.parseLong(br.readLine());
}
-
- return m_refreshCount;
+ catch (FileNotFoundException ex)
+ {
+ // If there wasn't an info file, then maybe this is an old-style
+ // bundle cache, so try to read the files individually. We can
+ // delete this eventually.
+ m_id = readId();
+ m_originalLocation = readLocation();
+ m_persistentState = readPersistentState();
+ m_startLevel = readStartLevel();
+ m_lastModified = readLastModified();
+ m_refreshCount = readRefreshCount();
+ }
+ finally
+ {
+ if (br != null) br.close();
+ if (is != null) is.close();
+ }
}
- /**
- * 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.
- **/
- private void setRefreshCount(long counter)
- throws Exception
+ private void writeBundleInfo() throws Exception
{
- // Get refresh counter file.
- File counterFile = new File(m_archiveRootDir, REFRESH_COUNTER_FILE);
-
- // Write the refresh counter.
+ // Write the bundle start level.
OutputStream os = null;
BufferedWriter bw = null;
try
{
os = BundleCache.getSecureAction()
- .getFileOutputStream(counterFile);
+ .getFileOutputStream(new File(m_archiveRootDir, BUNDLE_INFO_FILE));
bw = new BufferedWriter(new OutputStreamWriter(os));
- String s = Long.toString(counter);
+
+ // Write id.
+ String s = Long.toString(m_id);
bw.write(s, 0, s.length());
- m_refreshCount = counter;
+ bw.newLine();
+ // Write location.
+ s = (m_originalLocation == null) ? "" : m_originalLocation;
+ bw.write(s, 0, s.length());
+ bw.newLine();
+ // Write state.
+ s = Integer.toString(m_persistentState);
+ bw.write(s, 0, s.length());
+ bw.newLine();
+ // Write start level.
+ s = Integer.toString(m_startLevel);
+ bw.write(s, 0, s.length());
+ bw.newLine();
+ // Write last modified.
+ s = Long.toString(m_lastModified);
+ bw.write(s, 0, s.length());
+ bw.newLine();
+ // Write refresh count.
+ s = Long.toString(m_refreshCount);
+ bw.write(s, 0, s.length());
+ bw.newLine();
}
catch (IOException ex)
{
m_logger.log(
Logger.LOG_ERROR,
- getClass().getName() + ": Unable to write refresh counter: " + ex);
+ getClass().getName() + ": Unable to cache bundle info - " + ex);
throw ex;
}
finally
@@ -1109,4 +996,347 @@
if (os != null) os.close();
}
}
+
+ //
+ // Deprecated bundle cache format to be deleted eventually.
+ //
+
+ private static final transient String BUNDLE_ID_FILE = "bundle.id";
+ private static final transient String BUNDLE_LOCATION_FILE = "bundle.location";
+ private static final transient String BUNDLE_STATE_FILE = "bundle.state";
+ private static final transient String BUNDLE_START_LEVEL_FILE = "bundle.startlevel";
+ private static final transient String BUNDLE_LASTMODIFIED_FILE = "bundle.lastmodified";
+ private static final transient String REFRESH_COUNTER_FILE = "refresh.counter";
+
+ private void writeId() throws Exception
+ {
+ OutputStream os = BundleCache.getSecureAction()
+ .getFileOutputStream(new File(m_archiveRootDir, BUNDLE_ID_FILE));
+ BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
+ bw.write(Long.toString(m_id), 0, Long.toString(m_id).length());
+ bw.close();
+ os.close();
+ }
+
+ private long readId() throws Exception
+ {
+ long id;
+
+ InputStream is = null;
+ BufferedReader br = null;
+ try
+ {
+ is = BundleCache.getSecureAction()
+ .getFileInputStream(new File(m_archiveRootDir, BUNDLE_ID_FILE));
+ br = new BufferedReader(new InputStreamReader(is));
+ id = Long.parseLong(br.readLine());
+ }
+ catch (FileNotFoundException ex)
+ {
+ // HACK: Get the bundle identifier from the archive root directory
+ // name, which is of the form "bundle<id>" where <id> is the bundle
+ // identifier numbers. This is a hack to deal with old archives that
+ // did not save their bundle identifier, but instead had it passed
+ // into them. Eventually, this can be removed.
+ id = Long.parseLong(
+ m_archiveRootDir.getName().substring(
+ BundleCache.BUNDLE_DIR_PREFIX.length()));
+ }
+ finally
+ {
+ if (br != null) br.close();
+ if (is != null) is.close();
+ }
+
+ return id;
+ }
+
+ private void writeLocation() throws Exception
+ {
+ OutputStream os = BundleCache.getSecureAction()
+ .getFileOutputStream(new File(m_archiveRootDir, BUNDLE_LOCATION_FILE));
+ BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
+ bw.write(m_originalLocation, 0, m_originalLocation.length());
+ bw.close();
+ os.close();
+ }
+
+ private String readLocation() throws Exception
+ {
+ InputStream is = null;
+ BufferedReader br = null;
+ try
+ {
+ is = BundleCache.getSecureAction()
+ .getFileInputStream(new File(m_archiveRootDir, BUNDLE_LOCATION_FILE));
+ br = new BufferedReader(new InputStreamReader(is));
+ return br.readLine();
+ }
+ finally
+ {
+ if (br != null) br.close();
+ if (is != null) is.close();
+ }
+ }
+
+ private static final transient String ACTIVE_STATE = "active";
+ private static final transient String STARTING_STATE = "starting";
+ private static final transient String INSTALLED_STATE = "installed";
+ private static final transient String UNINSTALLED_STATE = "uninstalled";
+
+ private void writePersistentState() throws Exception
+ {
+ OutputStream os = null;
+ BufferedWriter bw = null;
+ try
+ {
+ os = BundleCache.getSecureAction()
+ .getFileOutputStream(new File(m_archiveRootDir, BUNDLE_STATE_FILE));
+ bw = new BufferedWriter(new OutputStreamWriter(os));
+ String s = null;
+ switch (m_persistentState)
+ {
+ case Bundle.ACTIVE:
+ s = ACTIVE_STATE;
+ break;
+ case Bundle.STARTING:
+ s = STARTING_STATE;
+ break;
+ case Bundle.UNINSTALLED:
+ s = UNINSTALLED_STATE;
+ break;
+ default:
+ s = INSTALLED_STATE;
+ break;
+ }
+ bw.write(s, 0, s.length());
+ }
+ catch (IOException ex)
+ {
+ m_logger.log(
+ Logger.LOG_ERROR,
+ getClass().getName() + ": Unable to record state - " + ex);
+ throw ex;
+ }
+ finally
+ {
+ if (bw != null) bw.close();
+ if (os != null) os.close();
+ }
+ }
+
+ private int readPersistentState() throws Exception
+ {
+ int state = Bundle.INSTALLED;
+
+ // Get bundle state file.
+ File stateFile = new File(m_archiveRootDir, BUNDLE_STATE_FILE);
+
+ // If the state file doesn't exist, then
+ // assume the bundle was installed.
+ if (BundleCache.getSecureAction().fileExists(stateFile))
+ {
+ // Read the bundle state.
+ InputStream is = null;
+ BufferedReader br = null;
+ try
+ {
+ is = BundleCache.getSecureAction()
+ .getFileInputStream(stateFile);
+ br = new BufferedReader(new InputStreamReader(is));
+ String s = br.readLine();
+ if ((s != null) && s.equals(ACTIVE_STATE))
+ {
+ state = Bundle.ACTIVE;
+ }
+ else if ((s != null) && s.equals(STARTING_STATE))
+ {
+ state = Bundle.STARTING;
+ }
+ else if ((s != null) && s.equals(UNINSTALLED_STATE))
+ {
+ state = Bundle.UNINSTALLED;
+ }
+ else
+ {
+ state = Bundle.INSTALLED;
+ }
+ }
+ catch (Exception ex)
+ {
+ state = Bundle.INSTALLED;
+ }
+ finally
+ {
+ if (br != null) br.close();
+ if (is != null) is.close();
+ }
+ }
+
+ return state;
+ }
+
+ private void writeStartLevel() throws Exception
+ {
+ OutputStream os = null;
+ BufferedWriter bw = null;
+ try
+ {
+ os = BundleCache.getSecureAction()
+ .getFileOutputStream(new File(m_archiveRootDir, BUNDLE_START_LEVEL_FILE));
+ bw = new BufferedWriter(new OutputStreamWriter(os));
+ String s = Integer.toString(m_startLevel);
+ bw.write(s, 0, s.length());
+ }
+ catch (IOException ex)
+ {
+ m_logger.log(
+ Logger.LOG_ERROR,
+ getClass().getName() + ": Unable to record start level - " + ex);
+ throw ex;
+ }
+ finally
+ {
+ if (bw != null) bw.close();
+ if (os != null) os.close();
+ }
+ }
+
+ private int readStartLevel() throws Exception
+ {
+ int level = -1;
+
+ // Get bundle start level file.
+ File levelFile = new File(m_archiveRootDir, BUNDLE_START_LEVEL_FILE);
+
+ // If the start level file doesn't exist, then
+ // return an error.
+ if (!BundleCache.getSecureAction().fileExists(levelFile))
+ {
+ level = -1;
+ }
+ else
+ {
+ // Read the bundle start level.
+ InputStream is = null;
+ BufferedReader br= null;
+ try
+ {
+ is = BundleCache.getSecureAction()
+ .getFileInputStream(levelFile);
+ br = new BufferedReader(new InputStreamReader(is));
+ level = Integer.parseInt(br.readLine());
+ }
+ finally
+ {
+ if (br != null) br.close();
+ if (is != null) is.close();
+ }
+ }
+ return level;
+ }
+
+ private void writeLastModified() throws Exception
+ {
+ OutputStream os = null;
+ BufferedWriter bw = null;
+ try
+ {
+ os = BundleCache.getSecureAction()
+ .getFileOutputStream(new File(m_archiveRootDir, BUNDLE_LASTMODIFIED_FILE));
+ bw = new BufferedWriter(new OutputStreamWriter(os));
+ String s = Long.toString(m_lastModified);
+ bw.write(s, 0, s.length());
+ }
+ catch (IOException ex)
+ {
+ m_logger.log(
+ Logger.LOG_ERROR,
+ getClass().getName() + ": Unable to record start level - " + ex);
+ throw ex;
+ }
+ finally
+ {
+ if (bw != null) bw.close();
+ if (os != null) os.close();
+ }
+ }
+
+ private long readLastModified() throws Exception
+ {
+ long last = 0;
+
+ InputStream is = null;
+ BufferedReader br = null;
+ try
+ {
+ is = BundleCache.getSecureAction()
+ .getFileInputStream(new File(m_archiveRootDir, BUNDLE_LASTMODIFIED_FILE));
+ br = new BufferedReader(new InputStreamReader(is));
+ last = Long.parseLong(br.readLine());
+ }
+ catch (Exception ex)
+ {
+ last = 0;
+ }
+ finally
+ {
+ if (br != null) br.close();
+ if (is != null) is.close();
+ }
+
+ return last;
+ }
+
+ private void writeRefreshCount() throws Exception
+ {
+ OutputStream os = null;
+ BufferedWriter bw = null;
+ try
+ {
+ os = BundleCache.getSecureAction()
+ .getFileOutputStream(new File(m_archiveRootDir, REFRESH_COUNTER_FILE));
+ bw = new BufferedWriter(new OutputStreamWriter(os));
+ String s = Long.toString(m_refreshCount);
+ bw.write(s, 0, s.length());
+ }
+ catch (IOException ex)
+ {
+ m_logger.log(
+ Logger.LOG_ERROR,
+ getClass().getName() + ": Unable to write refresh count: " + ex);
+ throw ex;
+ }
+ finally
+ {
+ if (bw != null) bw.close();
+ if (os != null) os.close();
+ }
+ }
+
+ private long readRefreshCount() throws Exception
+ {
+ long count = 0;
+
+ InputStream is = null;
+ BufferedReader br = null;
+ try
+ {
+ is = BundleCache.getSecureAction()
+ .getFileInputStream(new File(m_archiveRootDir, REFRESH_COUNTER_FILE));
+ br = new BufferedReader(new InputStreamReader(is));
+ count = Long.parseLong(br.readLine());
+ }
+ catch (Exception ex)
+ {
+ count = 0;
+ }
+ finally
+ {
+ if (br != null) br.close();
+ if (is != null) is.close();
+ }
+
+ return count;
+ }
}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/cache/BundleCache.java b/framework/src/main/java/org/apache/felix/framework/cache/BundleCache.java
index 92a5be0..a9d5ad6 100644
--- a/framework/src/main/java/org/apache/felix/framework/cache/BundleCache.java
+++ b/framework/src/main/java/org/apache/felix/framework/cache/BundleCache.java
@@ -66,6 +66,8 @@
{
public static final String CACHE_BUFSIZE_PROP = "felix.cache.bufsize";
public static final String CACHE_ROOTDIR_PROP = "felix.cache.rootdir";
+ // TODO: CACHE - Remove this once we migrate the cache format.
+ public static final String CACHE_SINGLEBUNDLEFILE_PROP = "felix.cache.singlebundlefile";
protected static transient int BUFSIZE = 4096;
protected static transient final String CACHE_DIR_NAME = "felix-cache";
@@ -154,7 +156,7 @@
archiveList.toArray(new BundleArchive[archiveList.size()]);
}
- public BundleArchive create(long id, String location, InputStream is)
+ public BundleArchive create(long id, int startLevel, String location, InputStream is)
throws Exception
{
File cacheDir = determineCacheDir(m_configMap);
@@ -167,7 +169,8 @@
{
// Create the archive and add it to the list of archives.
BundleArchive ba =
- new BundleArchive(m_logger, m_configMap, archiveRootDir, id, location, is);
+ new BundleArchive(
+ m_logger, m_configMap, archiveRootDir, id, startLevel, location, is);
return ba;
}
catch (Exception ex)