| /* |
| * 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.webconsole.internal; |
| |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Comparator; |
| import java.util.Enumeration; |
| import java.util.Locale; |
| |
| import org.osgi.framework.Bundle; |
| import org.osgi.framework.Constants; |
| import org.osgi.framework.Version; |
| |
| |
| /** |
| * The <code>Util</code> class contains various utility methods used internally |
| * by the web console implementation and the build-in plugins. |
| */ |
| public class Util |
| { |
| |
| // FIXME: from the constants below only PARAM_ACTION is used, consider removal of others? |
| |
| /** web apps subpage */ |
| public static final String PAGE_WEBAPPS = "/webapps"; |
| |
| /** vm statistics subpage */ |
| public static final String PAGE_VM_STAT = "/vmstat"; |
| |
| /** Logs subpage */ |
| public static final String PAGE_LOGS = "/logs"; |
| |
| /** Parameter name */ |
| public static final String PARAM_ACTION = "action"; |
| |
| /** Parameter name */ |
| public static final String PARAM_CONTENT = "content"; |
| |
| /** Parameter name */ |
| public static final String PARAM_SHUTDOWN = "shutdown"; |
| |
| /** Parameter value */ |
| public static final String VALUE_SHUTDOWN = "shutdown"; |
| |
| /** |
| * Return a display name for the given <code>bundle</code>: |
| * <ol> |
| * <li>If the bundle has a non-empty <code>Bundle-Name</code> manifest |
| * header that value is returned.</li> |
| * <li>Otherwise the symbolic name is returned if set</li> |
| * <li>Otherwise the bundle's location is returned if defined</li> |
| * <li>Finally, as a last resort, the bundles id is returned</li> |
| * </ol> |
| * |
| * @param bundle the bundle which name to retrieve |
| * @param locale the locale, in which the bundle name is requested |
| * @return the bundle name - see the description of the method for more details. |
| */ |
| public static String getName( Bundle bundle, Locale locale ) |
| { |
| final String loc = locale == null ? null : locale.toString(); |
| String name = ( String ) bundle.getHeaders( loc ).get( Constants.BUNDLE_NAME ); |
| if ( name == null || name.length() == 0 ) |
| { |
| name = bundle.getSymbolicName(); |
| if ( name == null ) |
| { |
| name = bundle.getLocation(); |
| if ( name == null ) |
| { |
| name = String.valueOf( bundle.getBundleId() ); |
| } |
| } |
| } |
| return name; |
| } |
| |
| /** |
| * Returns the value of the header or the empty string if the header |
| * is not available. |
| * |
| * @param bundle the bundle which header to retrieve |
| * @param headerName the name of the header to retrieve |
| * @return the header or empty string if it is not set |
| */ |
| public static String getHeaderValue( Bundle bundle, String headerName ) |
| { |
| Object value = bundle.getHeaders().get(headerName); |
| if ( value != null ) |
| { |
| return value.toString(); |
| } |
| return ""; |
| } |
| |
| /** |
| * Orders the bundles according to their name as returned by |
| * {@link #getName(Bundle, Locale)}, with the exception that the system bundle is |
| * always place as the first entry. If two bundles have the same name, they |
| * are ordered according to their version. If they have the same version, |
| * the bundle with the lower bundle id comes before the other. |
| * |
| * @param bundles the bundles to sort |
| * @param locale the locale, used to obtain the localized bundle name |
| */ |
| public static void sort( Bundle[] bundles, Locale locale ) |
| { |
| Arrays.sort( bundles, new BundleNameComparator( locale ) ); |
| } |
| |
| |
| /** |
| * This method is the same as Collections#list(Enumeration). The reason to |
| * duplicate it here, is that it is missing in OSGi/Minimum execution |
| * environment. |
| * |
| * @param e the enumeration which to convert |
| * @return the list containing all enumeration entries. |
| */ |
| public static final ArrayList list( Enumeration e ) |
| { |
| ArrayList l = new ArrayList(); |
| while ( e.hasMoreElements() ) |
| { |
| l.add( e.nextElement() ); |
| } |
| return l; |
| } |
| |
| /** |
| * This method expects a locale string in format language_COUNTRY, or |
| * language. The method will determine which is the correct form of locale |
| * string and construct a <code>Locale</code> object. |
| * |
| * @param locale the locale string, if <code>null</code> - default locale is |
| * returned |
| * @return a locale object |
| * @see Locale |
| */ |
| public static final Locale parseLocaleString(String locale) |
| { |
| if (locale == null) |
| { |
| return Locale.getDefault(); |
| } |
| int idx = locale.indexOf('_'); |
| String language; |
| String country = ""; |
| if (idx < 0) |
| { // "en" |
| language = locale; |
| } |
| else |
| { // "en_US" |
| language = locale.substring(0, idx); // "en" |
| idx++; // "_" |
| int last = locale.indexOf('_', idx); // "US" |
| if (last < 0) |
| { |
| last = locale.length(); |
| } |
| country = locale.substring(idx, last); |
| } |
| return new Locale(language, country); |
| } |
| |
| private static final class BundleNameComparator implements Comparator |
| { |
| private final Locale locale; |
| |
| |
| BundleNameComparator( final Locale locale ) |
| { |
| this.locale = locale; |
| } |
| |
| |
| public int compare( Object o1, Object o2 ) |
| { |
| return compare( ( Bundle ) o1, ( Bundle ) o2 ); |
| } |
| |
| |
| public int compare( Bundle b1, Bundle b2 ) |
| { |
| |
| // the same bundles |
| if ( b1 == b2 || b1.getBundleId() == b2.getBundleId() ) |
| { |
| return 0; |
| } |
| |
| // special case for system bundle, which always is first |
| if ( b1.getBundleId() == 0 ) |
| { |
| return -1; |
| } |
| else if ( b2.getBundleId() == 0 ) |
| { |
| return 1; |
| } |
| |
| // compare the symbolic names |
| int snComp = Util.getName( b1, locale ).compareToIgnoreCase( Util.getName( b2, locale ) ); |
| if ( snComp != 0 ) |
| { |
| return snComp; |
| } |
| |
| // same names, compare versions |
| Version v1 = Version.parseVersion( ( String ) b1.getHeaders().get( Constants.BUNDLE_VERSION ) ); |
| Version v2 = Version.parseVersion( ( String ) b2.getHeaders().get( Constants.BUNDLE_VERSION ) ); |
| int vComp = v1.compareTo( v2 ); |
| if ( vComp != 0 ) |
| { |
| return vComp; |
| } |
| |
| // same version ? Not really, but then, we compare by bundle id |
| if ( b1.getBundleId() < b2.getBundleId() ) |
| { |
| return -1; |
| } |
| |
| // b1 id must be > b2 id because equality is already checked |
| return 1; |
| } |
| } |
| } |