Applied patch (FELIX-31) to implement Bundle.getLastModified() in a persistent
way; the previous implementation was not persistent.


git-svn-id: https://svn.apache.org/repos/asf/incubator/felix/trunk@449715 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleInfo.java b/framework/src/main/java/org/apache/felix/framework/BundleInfo.java
index ea22e8e..cfd82ba 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleInfo.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleInfo.java
@@ -31,7 +31,6 @@
     private BundleArchive m_archive = null;
     private IModule[] m_modules = null;
     private int m_state = 0;
-    private long m_modified = 0;
     private BundleActivator m_activator = null;
     private BundleContext m_context = null;
     // Indicates whether the bundle is stale, meaning that it has
@@ -215,12 +214,33 @@
 
     public long getLastModified()
     {
-        return m_modified;
+        try
+        {
+            return m_archive.getLastModified();
+        }
+        catch (Exception ex)
+        {
+            m_logger.log(
+                Logger.LOG_ERROR,
+                "Error reading last modification time from bundle archive.",
+                ex);
+            return 0;
+        }
     }
 
     public void setLastModified(long l)
     {
-        m_modified = l;
+        try
+        {
+            m_archive.setLastModified(l);
+        }
+        catch (Exception ex)
+        {
+            m_logger.log(
+                Logger.LOG_ERROR,
+                "Error writing last modification time to bundle archive.",
+                ex);
+        }
     }
 
     public int getPersistentState()
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 f3b5122..676d900 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
@@ -78,6 +78,7 @@
     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_ACTIVATOR_FILE = "bundle.activator";
+    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";
@@ -91,6 +92,7 @@
     private String m_currentLocation = null;
     private int m_persistentState = -1;
     private int m_startLevel = -1;
+    private long m_lastModified = -1;
     private BundleRevision[] m_revisions = null;
     private Collection m_trustedCaCerts = null;
 
@@ -476,6 +478,85 @@
 
     /**
      * <p>
+     * Returns the last modification time of this archive.
+     * </p>
+     * @return the last modification time of this archive.
+     * @throws Exception if any error occurs.
+    **/
+    public synchronized long getLastModified() throws Exception
+    {
+        if (m_lastModified >= 0)
+        {
+            return m_lastModified;
+        }
+ 
+        // 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))
+        {
+            return 0;
+        }
+
+        // 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());
+            return m_lastModified;
+        }
+        finally
+        {
+            if (br != null) br.close();
+            if (is != null) is.close();
+        }
+    }
+
+    /**
+     * <p>
+     * Sets the the last modification time of this archive.
+     * </p>
+     * @param 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.
+    **/
+    public synchronized void setLastModified(long lastModified) throws Exception
+    {
+        // Write the bundle last modification time.
+        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(lastModified);
+            bw.write(s, 0, s.length());
+            m_lastModified = lastModified;
+        }
+        catch (IOException ex)
+        {
+            m_logger.log(
+                Logger.LOG_ERROR,
+                getClass().getName() + ": Unable to record last modification time - " + ex);
+            throw ex;
+        }
+        finally
+        {
+            if (bw != null) bw.close();
+            if (os != null) os.close();
+        }
+    }
+
+    /**
+     * <p>
      * Returns a <tt>File</tt> object corresponding to the data file
      * of the relative path of the specified string.
      * </p>