Improve manifest localization by dealing with some special cases. (FELIX-1271)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@787775 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleImpl.java b/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
index b3e7cff..a1e0606 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
@@ -263,95 +263,134 @@
Map getCurrentLocalizedHeader(String locale)
{
- synchronized (m_cachedHeaders)
+ Map result = null;
+
+ // Spec says empty local returns raw headers.
+ if (locale.length() == 0)
{
- // If the bundle has been updated, clear the cached headers
- if (getLastModified() > m_cachedHeadersTimestamp)
+ result = new HashMap(getCurrentModule().getHeaders());
+ }
+
+ // If we have no result, try to get it from the cached headers.
+ if (result == null)
+ {
+ synchronized (m_cachedHeaders)
{
- m_cachedHeaders.clear();
+ // If the bundle is uninstalled, then the cached headers should
+ // only contain the localized headers for the default locale at
+ // the time of uninstall, so just return that.
+ if (getState() == Bundle.UNINSTALLED)
+ {
+ result = (Map) m_cachedHeaders.values().iterator().next();
+ }
+ // If the bundle has been updated, clear the cached headers.
+ else if (getLastModified() > m_cachedHeadersTimestamp)
+ {
+ m_cachedHeaders.clear();
+ }
+ // Otherwise, returned the cached headers if they exist.
+ else
+ {
+ // Check if headers for this locale have already been resolved
+ if (m_cachedHeaders.containsKey(locale))
+ {
+ result = (Map) m_cachedHeaders.get(locale);
+ }
+ }
+ }
+ }
+
+ // If the requested locale is not cached, then try to create it.
+ if (result == null)
+ {
+ // Get a modifiable copy of the raw headers.
+ Map headers = new HashMap(getCurrentModule().getHeaders());
+ // Assume for now that this will be the result.
+ result = headers;
+
+ // Check to see if we actually need to localize anything
+ boolean localize = false;
+ for (Iterator it = headers.values().iterator(); !localize && it.hasNext(); )
+ {
+ if (((String) it.next()).startsWith("%"))
+ {
+ localize = true;
+ }
+ }
+
+ if (!localize)
+ {
+ // If localization is not needed, just cache the headers and return them as-is
+ // Not sure if this is useful
+ updateHeaderCache(locale, headers);
}
else
{
- // Check if headers for this locale have already been resolved
- if (m_cachedHeaders.containsKey(locale))
+ // Do localization here and return the localized headers
+ String basename = (String) headers.get(Constants.BUNDLE_LOCALIZATION);
+ if (basename == null)
{
- return (Map) m_cachedHeaders.get(locale);
+ basename = Constants.BUNDLE_LOCALIZATION_DEFAULT_BASENAME;
+ }
+
+ // Create ordered list of files to load properties from
+ List resourceList = createResourceList(basename, locale);
+
+ // Create a merged props file with all available props for this locale
+ boolean found = false;
+ Properties mergedProperties = new Properties();
+ for (Iterator it = resourceList.iterator(); it.hasNext(); )
+ {
+ URL temp = getCurrentModule().getResourceByDelegation(
+ it.next() + ".properties");
+ if (temp != null)
+ {
+ found = true;
+ try
+ {
+ mergedProperties.load(temp.openConnection().getInputStream());
+ }
+ catch (IOException ex)
+ {
+ // File doesn't exist, just continue loop
+ }
+ }
+ }
+
+ // If the specified locale was not found, then the spec says we should
+ // return the default localization.
+ if (!found && !locale.equals(Locale.getDefault().toString()))
+ {
+ result = getCurrentLocalizedHeader(Locale.getDefault().toString());
+ }
+ // Otherwise, perform the localization based on the discovered
+ // properties and cache the result.
+ else
+ {
+ // Resolve all localized header entries
+ for (Iterator it = headers.entrySet().iterator(); it.hasNext(); )
+ {
+ Map.Entry entry = (Map.Entry) it.next();
+ String value = (String) entry.getValue();
+ if (value.startsWith("%"))
+ {
+ String newvalue;
+ String key = value.substring(value.indexOf("%") + 1);
+ newvalue = mergedProperties.getProperty(key);
+ if (newvalue==null)
+ {
+ newvalue = key;
+ }
+ entry.setValue(newvalue);
+ }
+ }
+
+ updateHeaderCache(locale, headers);
}
}
}
- Map rawHeaders = getCurrentModule().getHeaders();
- Map headers = new HashMap(rawHeaders.size());
- headers.putAll(rawHeaders);
-
- // Check to see if we actually need to localize anything
- boolean needsLocalization = false;
- for (Iterator it = headers.values().iterator(); it.hasNext(); )
- {
- if (((String) it.next()).startsWith("%"))
- {
- needsLocalization = true;
- break;
- }
- }
-
- if (!needsLocalization)
- {
- // If localization is not needed, just cache the headers and return them as-is
- // Not sure if this is useful
- updateHeaderCache(locale, headers);
- return headers;
- }
-
- // Do localization here and return the localized headers
- String basename = (String) headers.get(Constants.BUNDLE_LOCALIZATION);
- if (basename == null)
- {
- basename = Constants.BUNDLE_LOCALIZATION_DEFAULT_BASENAME;
- }
-
- // Create ordered list of files to load properties from
- List resourceList = createResourceList(basename, locale);
-
- // Create a merged props file with all available props for this locale
- Properties mergedProperties = new Properties();
- for (Iterator it = resourceList.iterator(); it.hasNext(); )
- {
- URL temp = this.getCurrentModule().getResourceByDelegation(it.next() + ".properties");
- if (temp == null)
- {
- continue;
- }
- try
- {
- mergedProperties.load(temp.openConnection().getInputStream());
- }
- catch (IOException ex)
- {
- // File doesn't exist, just continue loop
- }
- }
-
- // Resolve all localized header entries
- for (Iterator it = headers.entrySet().iterator(); it.hasNext(); )
- {
- Map.Entry entry = (Map.Entry) it.next();
- String value = (String) entry.getValue();
- if (value.startsWith("%"))
- {
- String newvalue;
- String key = value.substring(value.indexOf("%") + 1);
- newvalue = mergedProperties.getProperty(key);
- if (newvalue==null)
- {
- newvalue = key;
- }
- entry.setValue(newvalue);
- }
- }
-
- updateHeaderCache(locale, headers);
- return headers;
+ return result;
}
private void updateHeaderCache(String locale, Map localizedHeaders)
@@ -856,6 +895,17 @@
AdminPermission.LIFECYCLE));
}
+ // After a bundle is uninstalled, rhe spec says getHeaders() should
+ // return the localized headers for the default locale at the time of
+ // of uninstall. So, let's clear the existing header cache and populate
+ // it with the headers for the default locale.
+ synchronized (m_cachedHeaders)
+ {
+ m_cachedHeaders.clear();
+ Map map = getCurrentLocalizedHeader(Locale.getDefault().toString());
+ }
+
+ // Uninstall the bundle.
getFramework().uninstallBundle(this);
}