You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cz...@apache.org on 2012/12/20 18:05:51 UTC
svn commit: r1424592 - in
/felix/sandbox/cziegeler/status-printer/src/main/java/org/apache/felix/status/impl/webconsole:
ResourceBundleManager.java WebConsoleAdapter.java
Author: cziegeler
Date: Thu Dec 20 17:05:51 2012
New Revision: 1424592
URL: http://svn.apache.org/viewvc?rev=1424592&view=rev
Log:
Add resource bundle handling for titles
Added:
felix/sandbox/cziegeler/status-printer/src/main/java/org/apache/felix/status/impl/webconsole/ResourceBundleManager.java (with props)
Modified:
felix/sandbox/cziegeler/status-printer/src/main/java/org/apache/felix/status/impl/webconsole/WebConsoleAdapter.java
Added: felix/sandbox/cziegeler/status-printer/src/main/java/org/apache/felix/status/impl/webconsole/ResourceBundleManager.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/status-printer/src/main/java/org/apache/felix/status/impl/webconsole/ResourceBundleManager.java?rev=1424592&view=auto
==============================================================================
--- felix/sandbox/cziegeler/status-printer/src/main/java/org/apache/felix/status/impl/webconsole/ResourceBundleManager.java (added)
+++ felix/sandbox/cziegeler/status-printer/src/main/java/org/apache/felix/status/impl/webconsole/ResourceBundleManager.java Thu Dec 20 17:05:51 2012
@@ -0,0 +1,179 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.status.impl.webconsole;
+
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.PropertyResourceBundle;
+import java.util.ResourceBundle;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleListener;
+import org.osgi.framework.Constants;
+
+
+/**
+ * The ResourceBundleManager manages resource bundle instance per OSGi Bundle.
+ * It contains a local cache, for bundles, but when a bundle is being unistalled,
+ * its resources stored in the cache are cleaned up.
+ */
+public class ResourceBundleManager implements BundleListener
+{
+
+ private final BundleContext bundleContext;
+
+ private final Map<Long, ResourceBundle> resourceBundleCaches;
+
+
+ /**
+ * Creates a new object and adds self as a bundle listener
+ *
+ * @param bundleContext the bundle context of the Web Console.
+ */
+ public ResourceBundleManager( final BundleContext bundleContext )
+ {
+ this.bundleContext = bundleContext;
+ this.resourceBundleCaches = new HashMap<Long, ResourceBundle>();
+
+ bundleContext.addBundleListener( this );
+ }
+
+
+ /**
+ * Removes the bundle lister.
+ */
+ public void dispose()
+ {
+ bundleContext.removeBundleListener( this );
+ }
+
+
+ /**
+ * This method is used to retrieve a /cached/ instance of the i18n resource associated
+ * with a given bundle.
+ *
+ * @param provider the bundle, provider of the resources
+ * @param locale the requested locale.
+ */
+ public ResourceBundle getResourceBundle( final Bundle provider ) {
+ ResourceBundle cache;
+ final Long key = new Long( provider.getBundleId() );
+ synchronized ( resourceBundleCaches ) {
+ cache = resourceBundleCaches.get( key );
+ if ( cache == null && !resourceBundleCaches.containsKey(key)) {
+ cache = this.loadResourceBundle(provider);
+ resourceBundleCaches.put( key, cache );
+ }
+ }
+
+ return cache;
+ }
+
+
+ // ---------- BundleListener
+
+ /**
+ * @see org.osgi.framework.BundleListener#bundleChanged(org.osgi.framework.BundleEvent)
+ */
+ public final void bundleChanged( BundleEvent event )
+ {
+ if ( event.getType() == BundleEvent.STOPPED )
+ {
+ final Long key = new Long( event.getBundle().getBundleId() );
+ synchronized ( resourceBundleCaches )
+ {
+ resourceBundleCaches.remove( key );
+ }
+ }
+ }
+
+ private static final Locale DEFAULT_LOCALE = Locale.ENGLISH;
+
+ private ResourceBundle loadResourceBundle(final Bundle bundle) {
+ final String path = "_" + DEFAULT_LOCALE.toString(); //$NON-NLS-1$
+ final URL source = ( URL ) getResourceBundleEntries(bundle).get( path );
+ if ( source != null ) {
+ try {
+ return new PropertyResourceBundle( source.openStream() );
+ } catch ( final IOException ignore ) {
+ // ignore
+ }
+ }
+ return null;
+ }
+
+
+ private synchronized Map getResourceBundleEntries(final Bundle bundle)
+ {
+ String file = ( String ) bundle.getHeaders().get( Constants.BUNDLE_LOCALIZATION );
+ if ( file == null )
+ {
+ file = Constants.BUNDLE_LOCALIZATION_DEFAULT_BASENAME;
+ }
+
+ // remove leading slash
+ if ( file.startsWith( "/" ) ) //$NON-NLS-1$
+ {
+ file = file.substring( 1 );
+ }
+
+ // split path and base name
+ int slash = file.lastIndexOf( '/' );
+ String fileName = file.substring( slash + 1 );
+ String path = ( slash <= 0 ) ? "/" : file.substring( 0, slash ); //$NON-NLS-1$
+
+ HashMap resourceBundleEntries = new HashMap();
+
+ Enumeration locales = bundle.findEntries( path, fileName + "*.properties", false ); //$NON-NLS-1$
+ if ( locales != null )
+ {
+ while ( locales.hasMoreElements() )
+ {
+ URL entry = ( URL ) locales.nextElement();
+
+ // calculate the key
+ String entryPath = entry.getPath();
+ final int start = entryPath.lastIndexOf( '/' ) + 1 + fileName.length(); // path, slash and base name
+ final int end = entryPath.length() - 11; // .properties suffix
+ entryPath = entryPath.substring( start, end );
+
+ // the default language is "name.properties" thus the entry
+ // path is empty and must default to "_"+DEFAULT_LOCALE
+ if (entryPath.length() == 0) {
+ entryPath = "_" + DEFAULT_LOCALE; //$NON-NLS-1$
+ }
+
+ // only add this entry, if the "language" is not provided
+ // by the main bundle or an earlier bound fragment
+ if (!resourceBundleEntries.containsKey( entryPath )) {
+ resourceBundleEntries.put( entryPath, entry );
+ }
+ }
+ }
+
+ return resourceBundleEntries;
+ }
+}
Propchange: felix/sandbox/cziegeler/status-printer/src/main/java/org/apache/felix/status/impl/webconsole/ResourceBundleManager.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/sandbox/cziegeler/status-printer/src/main/java/org/apache/felix/status/impl/webconsole/ResourceBundleManager.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Propchange: felix/sandbox/cziegeler/status-printer/src/main/java/org/apache/felix/status/impl/webconsole/ResourceBundleManager.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: felix/sandbox/cziegeler/status-printer/src/main/java/org/apache/felix/status/impl/webconsole/WebConsoleAdapter.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/status-printer/src/main/java/org/apache/felix/status/impl/webconsole/WebConsoleAdapter.java?rev=1424592&r1=1424591&r2=1424592&view=diff
==============================================================================
--- felix/sandbox/cziegeler/status-printer/src/main/java/org/apache/felix/status/impl/webconsole/WebConsoleAdapter.java (original)
+++ felix/sandbox/cziegeler/status-printer/src/main/java/org/apache/felix/status/impl/webconsole/WebConsoleAdapter.java Thu Dec 20 17:05:51 2012
@@ -23,6 +23,7 @@ import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
+import java.util.ResourceBundle;
import org.apache.felix.status.PrinterMode;
import org.apache.felix.status.StatusPrinter;
@@ -46,8 +47,11 @@ public class WebConsoleAdapter implement
private final Map<ServiceReference, ServiceRegistration> registrations = new HashMap<ServiceReference, ServiceRegistration>();
+ private final ResourceBundleManager rbManager;
+
public WebConsoleAdapter(final BundleContext btx) throws InvalidSyntaxException {
this.bundleContext = btx;
+ this.rbManager = new ResourceBundleManager(btx);
this.cfgPrinterTracker = new ServiceTracker( this.bundleContext,
this.bundleContext.createFilter("(|(" + Constants.OBJECTCLASS + "=" + ConsoleConstants.INTERFACE_CONFIGURATION_PRINTER + ")" +
"(&(" + ConsoleConstants.PLUGIN_LABEL + "=*)(&("
@@ -68,13 +72,20 @@ public class WebConsoleAdapter implement
}
this.registrations.clear();
}
+ this.rbManager.dispose();
}
public void add(final ServiceReference reference, final Object service) {
final ConfigurationPrinterAdapter cpa = ConfigurationPrinterAdapter.createAdapter(service, reference);
if ( cpa != null && cpa.title != null ) {
if ( cpa.title.startsWith("%") ) {
- cpa.title = cpa.title.substring(1);
+ final String key = cpa.title.substring(1);
+ final ResourceBundle rb = this.rbManager.getResourceBundle(reference.getBundle());
+ if ( rb == null || !rb.containsKey(key) ) {
+ cpa.title = key;
+ } else {
+ cpa.title = rb.getString(key);
+ }
}
if ( cpa.label == null ) {
cpa.label = cpa.title;