Fix bundle refreshing of native libraries. (FELIX-2990)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1134338 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 105e6cb..ab9a644 100644
--- a/framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -2663,7 +2663,10 @@
// due to an error or system crash.
try
{
- ba.purge();
+ if (ba.isRemovalPending())
+ {
+ ba.purge();
+ }
}
catch (Exception ex)
{
@@ -3572,6 +3575,9 @@
// resolved exporters of the package.
if (cap.getNamespace().equals(BundleRevision.PACKAGE_NAMESPACE))
{
+// TODO: OSGi R4.3 - We can probably do this in a more efficient way once
+// BundleWiring.getCapabilities() returns the proper result. We probably
+// Won't even need this method.
String pkgName = (String)
cap.getAttributes().get(BundleCapabilityImpl.PACKAGE_ATTR);
Map<String, Object> attrs = new HashMap<String, Object>(1);
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 af26209..4f0d6bf 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
@@ -25,6 +25,7 @@
import java.util.TreeMap;
import org.apache.felix.framework.Logger;
import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
/**
* <p>
@@ -490,15 +491,9 @@
return (m_revisions.isEmpty()) ? null : m_revisions.get(m_revisions.lastKey());
}
- /**
- * <p>
- * Returns the revision object for the specified revision.
- * </p>
- * @return the revision object for the specified revision.
- **/
- public synchronized BundleRevision getRevision(Long l)
+ public synchronized boolean isRemovalPending()
{
- return m_revisions.get(l);
+ return (m_revisions.size() > 1);
}
/**
@@ -700,21 +695,24 @@
**/
public synchronized void purge() throws Exception
{
- if (m_revisions.size() > 1)
+ // Remember current revision number.
+ Long currentRevNum = getCurrentRevisionNumber();
+
+ // Record whether the current revision has native libraries, which
+ // we'll use later to determine if we need to rename its directory.
+ boolean hasNativeLibs = getCurrentRevision().getManifestHeader()
+ .containsKey(Constants.BUNDLE_NATIVECODE);
+
+ // Close all revisions and then delete all but the current revision.
+ // We don't delete it the current revision, because we want to rename it
+ // to the new refresh level.
+ close();
+
+ // Delete all old revisions.
+ long refreshCount = getRefreshCount();
+ for (Long revNum : m_revisions.keySet())
{
- // Close the revisions and then delete all but the current revision.
- // We don't delete it the current revision, because we want to rename it
- // to the new refresh level.
- close();
-
- // Remove the current revision from the revision map so it doesn't
- // get deleted.
- Long currentRevNum = m_revisions.lastKey();
- m_revisions.remove(currentRevNum);
-
- // Delete all old revisions.
- long refreshCount = getRefreshCount();
- for (Long revNum : m_revisions.keySet())
+ if (!revNum.equals(currentRevNum))
{
File revisionDir = new File(
m_archiveRootDir,
@@ -724,7 +722,13 @@
BundleCache.deleteDirectoryTree(revisionDir);
}
}
+ }
+ // If the revision has native libraries, then rename its directory
+ // to avoid the issue of being unable to load the same native library
+ // into two different class loaders.
+ if (hasNativeLibs)
+ {
// Increment the refresh count.
setRefreshCount(refreshCount + 1);
@@ -734,16 +738,16 @@
File revisionDir = new File(m_archiveRootDir,
REVISION_DIRECTORY + refreshCount + "." + currentRevNum.toString());
BundleCache.getSecureAction().renameFile(revisionDir, currentDir);
-
- // Clear the revision map since they are all invalid now.
- m_revisions.clear();
-
- // Recreate the revision for the current location.
- BundleRevision revision = createRevisionFromLocation(
- getRevisionLocation(currentRevNum), null, currentRevNum);
- // Add new revision to the revision map.
- m_revisions.put(currentRevNum, revision);
}
+
+ // Clear the revision map since they are all invalid now.
+ m_revisions.clear();
+
+ // Recreate the revision for the current location.
+ BundleRevision revision = createRevisionFromLocation(
+ getRevisionLocation(currentRevNum), null, currentRevNum);
+ // Add new revision to the revision map.
+ m_revisions.put(currentRevNum, revision);
}
/**
@@ -890,19 +894,19 @@
// Method from Harmony java.net.URIEncoderDecoder (luni subproject)
// used by URI to decode uri components.
- private static String decode(String s) throws UnsupportedEncodingException
+ private static String decode(String s) throws UnsupportedEncodingException
{
StringBuffer result = new StringBuffer();
ByteArrayOutputStream out = new ByteArrayOutputStream();
- for (int i = 0; i < s.length();)
+ for (int i = 0; i < s.length();)
{
char c = s.charAt(i);
- if (c == '%')
+ if (c == '%')
{
out.reset();
- do
+ do
{
- if ((i + 2) >= s.length())
+ if ((i + 2) >= s.length())
{
throw new IllegalArgumentException(
"Incomplete % sequence at: " + i);