blob: 7f8a0275968cf02fcd4642989ffdaa3e3d999ee7 [file] [log] [blame]
/*
* 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.core;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.felix.bundlerepository.*;
import org.apache.felix.webconsole.internal.BaseWebConsolePlugin;
import org.apache.felix.webconsole.internal.Util;
import org.apache.felix.webconsole.internal.servlet.OsgiManager;
import org.json.*;
import org.osgi.framework.*;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.component.ComponentConstants;
import org.osgi.service.log.LogService;
import org.osgi.service.packageadmin.ExportedPackage;
import org.osgi.service.packageadmin.PackageAdmin;
import org.osgi.service.startlevel.StartLevel;
/**
* The <code>BundlesServlet</code> TODO
*/
public class BundlesServlet extends BaseWebConsolePlugin
{
public static final String NAME = "bundles";
public static final String LABEL = "Bundles";
public static final String BUNDLE_ID = "bundleId";
// bootdelegation property entries. wildcards are converted to package
// name prefixes. whether an entry is a wildcard or not is set as a flag
// in the bootPkgWildcards array.
// see #activate and #isBootDelegated
private String[] bootPkgs;
// a flag for each entry in bootPkgs indicating whether the respective
// entry was declared as a wildcard or not
// see #activate and #isBootDelegated
private boolean[] bootPkgWildcards;
public void activate( BundleContext bundleContext )
{
super.activate( bundleContext );
// bootdelegation property parsing from Apache Felix R4SearchPolicyCore
String bootDelegation = bundleContext.getProperty( Constants.FRAMEWORK_BOOTDELEGATION );
bootDelegation = ( bootDelegation == null ) ? "java.*" : bootDelegation + ",java.*";
StringTokenizer st = new StringTokenizer( bootDelegation, " ," );
bootPkgs = new String[st.countTokens()];
bootPkgWildcards = new boolean[bootPkgs.length];
for ( int i = 0; i < bootPkgs.length; i++ )
{
bootDelegation = st.nextToken();
if ( bootDelegation.endsWith( "*" ) )
{
bootPkgWildcards[i] = true;
bootDelegation = bootDelegation.substring( 0, bootDelegation.length() - 1 );
}
bootPkgs[i] = bootDelegation;
}
}
public String getLabel()
{
return NAME;
}
public String getTitle()
{
return LABEL;
}
protected void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException,
IOException
{
final RequestInfo reqInfo = new RequestInfo(request);
if ( reqInfo.bundle == null && reqInfo.bundleRequested ) {
response.sendError(404);
return;
}
if ( reqInfo.extension.equals("json") )
{
this.renderJSON(response, reqInfo.bundle);
// nothing more to do
return;
}
super.doGet( request, response );
}
protected void doPost( HttpServletRequest req, HttpServletResponse resp ) throws ServletException, IOException
{
final RequestInfo reqInfo = new RequestInfo(req);
if ( reqInfo.bundle == null && reqInfo.bundleRequested ) {
resp.sendError(404);
return;
}
boolean success = false;
final String action = req.getParameter( "action" );
Bundle bundle = getBundle( req.getPathInfo() );
if ( bundle != null )
{
if ( action == null )
{
success = true;
}
else if ( "start".equals( action ) )
{
// start bundle
success = true;
try
{
bundle.start();
}
catch ( BundleException be )
{
getLog().log( LogService.LOG_ERROR, "Cannot start", be );
}
}
else if ( "stop".equals( action ) )
{
// stop bundle
success = true;
try
{
bundle.stop();
}
catch ( BundleException be )
{
getLog().log( LogService.LOG_ERROR, "Cannot stop", be );
}
}
else if ( "refresh".equals( action ) )
{
// refresh bundle wiring
refresh( bundle );
success = true;
}
else if ( "uninstall".equals( action ) )
{
// uninstall bundle
success = true;
try
{
bundle.uninstall();
bundle = null; // bundle has gone !
}
catch ( BundleException be )
{
getLog().log( LogService.LOG_ERROR, "Cannot uninstall", be );
}
}
}
if ( "refreshPackages".equals( action ) )
{
getPackageAdmin().refreshPackages( null );
success = true;
}
if ( success )
{
// let's wait a little bit to give the framework time
// to process our request
try {
Thread.sleep(800);
} catch (InterruptedException e) {
// we ignore this
}
this.renderJSON(resp, null);
}
else
{
super.doPost( req, resp );
}
}
private Bundle getBundle( String pathInfo )
{
// only use last part of the pathInfo
pathInfo = pathInfo.substring( pathInfo.lastIndexOf( '/' ) + 1 );
// assume bundle Id
try
{
final long bundleId = Long.parseLong( pathInfo );
if ( bundleId >= 0 )
{
return getBundleContext().getBundle( bundleId );
}
}
catch ( NumberFormatException nfe )
{
// check if this follows the pattern {symbolic-name}[:{version}]
final int pos = pathInfo.indexOf(':');
final String symbolicName;
final String version;
if ( pos == -1 ) {
symbolicName = pathInfo;
version = null;
} else {
symbolicName = pathInfo.substring(0, pos);
version = pathInfo.substring(pos+1);
}
// search
final Bundle[] bundles = getBundleContext().getBundles();
for(int i=0; i<bundles.length; i++)
{
final Bundle bundle = bundles[i];
// check symbolic name first
if ( symbolicName.equals(bundle.getSymbolicName()) )
{
if ( version == null || version.equals(bundle.getHeaders().get(Constants.BUNDLE_VERSION)) )
{
return bundle;
}
}
}
}
return null;
}
private void appendBundleInfoCount( final StringBuffer buf, String msg, int count )
{
buf.append(count);
buf.append(" bundle");
if ( count != 1 )
buf.append( 's' );
buf.append(' ');
buf.append(msg);
}
protected void renderContent( HttpServletRequest request, HttpServletResponse response ) throws IOException
{
// get request info from request attribute
final RequestInfo reqInfo = getRequestInfo(request);
final PrintWriter pw = response.getWriter();
final String appRoot = ( String ) request.getAttribute( OsgiManager.ATTR_APP_ROOT );
Util.script(pw, appRoot, "bundles.js");
Util.startScript( pw );
pw.println( "var imgRoot = '" + appRoot + "/res/imgs';");
pw.println( "var startLevel = " + getStartLevel().getInitialBundleStartLevel() + ";");
pw.println( "var drawDetails = " + reqInfo.bundleRequested + ";");
Util.endScript( pw );
Util.script(pw, appRoot, "bundles.js");
pw.println( "<div id='plugin_content'/>");
Util.startScript( pw );
pw.print( "renderBundles(");
writeJSON(pw, reqInfo.bundle);
pw.println(");" );
Util.endScript( pw );
}
private void renderJSON( final HttpServletResponse response, final Bundle bundle ) throws IOException
{
response.setContentType( "application/json" );
response.setCharacterEncoding( "UTF-8" );
final PrintWriter pw = response.getWriter();
writeJSON(pw, bundle);
}
private void writeJSON( final PrintWriter pw, final Bundle bundle) throws IOException
{
final Bundle[] allBundles = this.getBundles();
final String statusLine = this.getStatusLine(allBundles);
final Bundle[] bundles = ( bundle != null ) ? new Bundle[]
{ bundle } : allBundles;
Util.sort( bundles );
final JSONWriter jw = new JSONWriter( pw );
try
{
jw.object();
jw.key( "status" );
jw.value( statusLine );
jw.key( "data" );
jw.array();
for ( int i = 0; i < bundles.length; i++ )
{
bundleInfo( jw, bundles[i], bundle != null );
}
jw.endArray();
jw.endObject();
}
catch ( JSONException je )
{
throw new IOException( je.toString() );
}
}
private String getStatusLine(final Bundle[] bundles)
{
int active = 0, installed = 0, resolved = 0, fragments = 0;
for ( int i = 0; i < bundles.length; i++ )
{
switch ( bundles[i].getState() )
{
case Bundle.ACTIVE:
active++;
break;
case Bundle.INSTALLED:
installed++;
break;
case Bundle.RESOLVED:
if ( bundles[i].getHeaders().get(Constants.FRAGMENT_HOST) != null )
{
fragments++;
}
else
{
resolved++;
}
break;
}
}
final StringBuffer buffer = new StringBuffer();
buffer.append("Bundle information: ");
appendBundleInfoCount(buffer, "in total", bundles.length);
if ( active == bundles.length || active + fragments == bundles.length )
{
buffer.append(" - all ");
appendBundleInfoCount(buffer, "active.", bundles.length);
}
else
{
if ( active != 0 )
{
buffer.append(", ");
appendBundleInfoCount(buffer, "active", active);
}
if ( fragments != 0 )
{
buffer.append(", ");
appendBundleInfoCount(buffer, "active fragments", fragments);
}
if ( resolved != 0 )
{
buffer.append(", ");
appendBundleInfoCount(buffer, "resolved", resolved);
}
if ( installed != 0 )
{
buffer.append(", ");
appendBundleInfoCount(buffer, "installed", installed);
}
buffer.append('.');
}
return buffer.toString();
}
private void bundleInfo( JSONWriter jw, Bundle bundle, boolean details ) throws JSONException
{
jw.object();
jw.key( "id" );
jw.value( bundle.getBundleId() );
jw.key( "name" );
jw.value( Util.getName( bundle ) );
jw.key( "state" );
jw.value( toStateString( bundle ) );
jw.key( "version" );
jw.value( Util.getHeaderValue(bundle, Constants.BUNDLE_VERSION) );
jw.key( "symbolicName" );
jw.value( Util.getHeaderValue(bundle, Constants.BUNDLE_SYMBOLICNAME) );
jw.key( "actions" );
jw.array();
if ( bundle.getBundleId() != 0 )
{
if ( hasStart(bundle) )
{
action( jw, hasStart( bundle ), "start", "Start", "start" );
}
else
{
action( jw, hasStop( bundle ), "stop", "Stop", "stop" );
}
action( jw, true, "refresh", "Refresh Package Imports", "refresh" );
action( jw, hasUninstall( bundle ), "uninstall", "Uninstall", "delete" );
}
jw.endArray();
if ( details )
{
bundleDetails( jw, bundle );
}
jw.endObject();
}
protected Bundle[] getBundles()
{
return getBundleContext().getBundles();
}
private String toStateString( final Bundle bundle )
{
switch ( bundle.getState() )
{
case Bundle.INSTALLED:
return "Installed";
case Bundle.RESOLVED:
if ( isFragmentBundle(bundle) )
{
return "Fragment";
}
return "Resolved";
case Bundle.STARTING:
return "Starting";
case Bundle.ACTIVE:
return "Active";
case Bundle.STOPPING:
return "Stopping";
case Bundle.UNINSTALLED:
return "Uninstalled";
default:
return "Unknown: " + bundle.getState();
}
}
private void action( JSONWriter jw, boolean enabled, String op, String opLabel, String image ) throws JSONException
{
jw.object();
jw.key( "enabled" ).value( enabled );
jw.key( "name" ).value( opLabel );
jw.key( "link" ).value( op );
jw.key( "image" ).value( image );
jw.endObject();
}
private boolean isFragmentBundle( Bundle bundle)
{
return bundle.getHeaders().get(Constants.FRAGMENT_HOST) != null;
}
private boolean hasStart( Bundle bundle )
{
if ( isFragmentBundle(bundle) )
{
return false;
}
return bundle.getState() == Bundle.INSTALLED || bundle.getState() == Bundle.RESOLVED;
}
private boolean hasStop( Bundle bundle )
{
if ( isFragmentBundle(bundle) )
{
return false;
}
return bundle.getState() == Bundle.ACTIVE;
}
private boolean hasUninstall( Bundle bundle )
{
return bundle.getState() == Bundle.INSTALLED || bundle.getState() == Bundle.RESOLVED
|| bundle.getState() == Bundle.ACTIVE;
}
private void bundleDetails( JSONWriter jw, Bundle bundle ) throws JSONException
{
Dictionary headers = bundle.getHeaders();
jw.key( "props" );
jw.array();
keyVal( jw, "Symbolic Name", bundle.getSymbolicName() );
keyVal( jw, "Version", headers.get( Constants.BUNDLE_VERSION ) );
keyVal( jw, "Location", bundle.getLocation() );
keyVal( jw, "Last Modification", new Date( bundle.getLastModified() ) );
String docUrl = ( String ) headers.get( Constants.BUNDLE_DOCURL );
if ( docUrl != null )
{
keyVal( jw, "Bundle Documentation", docUrl );
}
keyVal( jw, "Vendor", headers.get( Constants.BUNDLE_VENDOR ) );
keyVal( jw, "Copyright", headers.get( Constants.BUNDLE_COPYRIGHT ) );
keyVal( jw, "Description", headers.get( Constants.BUNDLE_DESCRIPTION ) );
keyVal( jw, "Start Level", getStartLevel( bundle ) );
keyVal( jw, "Bundle Classpath", headers.get( Constants.BUNDLE_CLASSPATH ) );
if ( bundle.getState() == Bundle.INSTALLED )
{
listImportExportsUnresolved( jw, bundle );
}
else
{
listImportExport( jw, bundle );
}
listServices( jw, bundle );
listHeaders( jw, bundle );
jw.endArray();
}
private Integer getStartLevel( Bundle bundle )
{
StartLevel sl = getStartLevel();
return ( sl != null ) ? new Integer( sl.getBundleStartLevel( bundle ) ) : null;
}
private void listImportExport( JSONWriter jw, Bundle bundle ) throws JSONException
{
PackageAdmin packageAdmin = getPackageAdmin();
if ( packageAdmin == null )
{
return;
}
Map usingBundles = new TreeMap();
ExportedPackage[] exports = packageAdmin.getExportedPackages( bundle );
if ( exports != null && exports.length > 0 )
{
// do alphabetical sort
Arrays.sort( exports, new Comparator()
{
public int compare( ExportedPackage p1, ExportedPackage p2 )
{
return p1.getName().compareTo( p2.getName() );
}
public int compare( Object o1, Object o2 )
{
return compare( ( ExportedPackage ) o1, ( ExportedPackage ) o2 );
}
} );
JSONArray val = new JSONArray();
for ( int j = 0; j < exports.length; j++ )
{
ExportedPackage export = exports[j];
collectExport( val, export.getName(), export.getVersion() );
Bundle[] ubList = export.getImportingBundles();
if ( ubList != null )
{
for ( int i = 0; i < ubList.length; i++ )
{
Bundle ub = ubList[i];
usingBundles.put( ub.getSymbolicName(), ub );
}
}
}
keyVal( jw, "Exported Packages", val );
}
else
{
keyVal( jw, "Exported Packages", "None" );
}
exports = packageAdmin.getExportedPackages( ( Bundle ) null );
if ( exports != null && exports.length > 0 )
{
// collect import packages first
final List imports = new ArrayList();
for ( int i = 0; i < exports.length; i++ )
{
final ExportedPackage ep = exports[i];
final Bundle[] importers = ep.getImportingBundles();
for ( int j = 0; importers != null && j < importers.length; j++ )
{
if ( importers[j].getBundleId() == bundle.getBundleId() )
{
imports.add( ep );
break;
}
}
}
// now sort
JSONArray val = new JSONArray();
if ( imports.size() > 0 )
{
final ExportedPackage[] packages = ( ExportedPackage[] ) imports.toArray( new ExportedPackage[imports
.size()] );
Arrays.sort( packages, new Comparator()
{
public int compare( ExportedPackage p1, ExportedPackage p2 )
{
return p1.getName().compareTo( p2.getName() );
}
public int compare( Object o1, Object o2 )
{
return compare( ( ExportedPackage ) o1, ( ExportedPackage ) o2 );
}
} );
// and finally print out
for ( int i = 0; i < packages.length; i++ )
{
ExportedPackage ep = packages[i];
collectImport( val, ep.getName(), ep.getVersion(), false, ep );
}
}
else
{
// add description if there are no imports
val.put( "None" );
}
keyVal( jw, "Imported Packages", val );
}
if ( !usingBundles.isEmpty() )
{
JSONArray val = new JSONArray();
for ( Iterator ui = usingBundles.values().iterator(); ui.hasNext(); )
{
Bundle usingBundle = ( Bundle ) ui.next();
val.put( getBundleDescriptor( usingBundle ) );
}
keyVal( jw, "Importing Bundles", val );
}
}
private void listImportExportsUnresolved( JSONWriter jw, Bundle bundle ) throws JSONException
{
Dictionary dict = bundle.getHeaders();
String target = ( String ) dict.get( Constants.EXPORT_PACKAGE );
if ( target != null )
{
R4Package[] pkgs = R4Package.parseImportOrExportHeader( target );
if ( pkgs != null && pkgs.length > 0 )
{
// do alphabetical sort
Arrays.sort( pkgs, new Comparator()
{
public int compare( R4Package p1, R4Package p2 )
{
return p1.getName().compareTo( p2.getName() );
}
public int compare( Object o1, Object o2 )
{
return compare( ( R4Package ) o1, ( R4Package ) o2 );
}
} );
JSONArray val = new JSONArray();
for ( int i = 0; i < pkgs.length; i++ )
{
R4Export export = new R4Export( pkgs[i] );
collectExport( val, export.getName(), export.getVersion() );
}
keyVal( jw, "Exported Packages", val );
}
else
{
keyVal( jw, "Exported Packages", "None" );
}
}
target = ( String ) dict.get( Constants.IMPORT_PACKAGE );
if ( target != null )
{
R4Package[] pkgs = R4Package.parseImportOrExportHeader( target );
if ( pkgs != null && pkgs.length > 0 )
{
Map imports = new TreeMap();
for ( int i = 0; i < pkgs.length; i++ )
{
R4Package pkg = pkgs[i];
imports.put( pkg.getName(), new R4Import( pkg ) );
}
// collect import packages first
final Map candidates = new HashMap();
PackageAdmin packageAdmin = getPackageAdmin();
if ( packageAdmin != null )
{
ExportedPackage[] exports = packageAdmin.getExportedPackages( ( Bundle ) null );
if ( exports != null && exports.length > 0 )
{
for ( int i = 0; i < exports.length; i++ )
{
final ExportedPackage ep = exports[i];
R4Import imp = ( R4Import ) imports.get( ep.getName() );
if ( imp != null && imp.isSatisfied( toR4Export( ep ) ) )
{
candidates.put( ep.getName(), ep );
}
}
}
}
// now sort
JSONArray val = new JSONArray();
if ( imports.size() > 0 )
{
for ( Iterator ii = imports.values().iterator(); ii.hasNext(); )
{
R4Import r4Import = ( R4Import ) ii.next();
ExportedPackage ep = ( ExportedPackage ) candidates.get( r4Import.getName() );
// if there is no matching export, check whether this
// bundle has the package, ignore the entry in this case
if ( ep == null )
{
String path = r4Import.getName().replace( '.', '/' );
if ( bundle.getResource( path ) != null )
{
continue;
}
}
collectImport( val, r4Import.getName(), r4Import.getVersion(), r4Import.isOptional(), ep );
}
}
else
{
// add description if there are no imports
val.put( "None" );
}
keyVal( jw, "Imported Packages", val );
}
}
}
private void listServices( JSONWriter jw, Bundle bundle ) throws JSONException
{
ServiceReference[] refs = bundle.getRegisteredServices();
if ( refs == null || refs.length == 0 )
{
return;
}
for ( int i = 0; i < refs.length; i++ )
{
String key = "Service ID " + refs[i].getProperty( Constants.SERVICE_ID );
JSONArray val = new JSONArray();
appendProperty( val, refs[i], Constants.OBJECTCLASS, "Types" );
appendProperty( val, refs[i], Constants.SERVICE_PID, "PID" );
appendProperty( val, refs[i], ConfigurationAdmin.SERVICE_FACTORYPID, "Factory PID" );
appendProperty( val, refs[i], ComponentConstants.COMPONENT_NAME, "Component Name" );
appendProperty( val, refs[i], ComponentConstants.COMPONENT_ID, "Component ID" );
appendProperty( val, refs[i], ComponentConstants.COMPONENT_FACTORY, "Component Factory" );
appendProperty( val, refs[i], Constants.SERVICE_DESCRIPTION, "Description" );
appendProperty( val, refs[i], Constants.SERVICE_VENDOR, "Vendor" );
keyVal( jw, key, val);
}
}
private void listHeaders( JSONWriter jw, Bundle bundle ) throws JSONException
{
JSONArray val = new JSONArray();
Dictionary headers = bundle.getHeaders();
Enumeration he = headers.keys();
while ( he.hasMoreElements() )
{
Object header = he.nextElement();
String value = String.valueOf(headers.get( header ));
// Package headers may be long, support line breaking by
// ensuring blanks after comma and semicolon.
value = value.replaceAll( "([;,])", "$1 " );
val.put( header + ": " + value );
}
keyVal( jw, "Manifest Headers", val );
}
private void appendProperty( JSONArray array, ServiceReference ref, String name, String label )
{
StringBuffer dest = new StringBuffer();
Object value = ref.getProperty( name );
if ( value instanceof Object[] )
{
Object[] values = ( Object[] ) value;
dest.append( label ).append( ": " );
for ( int j = 0; j < values.length; j++ )
{
if ( j > 0 )
dest.append( ", " );
dest.append( values[j] );
}
array.put(dest.toString());
}
else if ( value != null )
{
dest.append( label ).append( ": " ).append( value );
array.put(dest.toString());
}
}
private void keyVal( JSONWriter jw, String key, Object value ) throws JSONException
{
if ( key != null && value != null )
{
jw.object();
jw.key( "key" );
jw.value( key );
jw.key( "value" );
jw.value( value );
jw.endObject();
}
}
private void collectExport( JSONArray array, String name, Version version )
{
StringBuffer val = new StringBuffer();
boolean bootDel = isBootDelegated( name );
if ( bootDel )
{
val.append( "!! " );
}
val.append( name );
val.append( ",version=" );
val.append( version );
if ( bootDel )
{
val.append( " -- Overwritten by Boot Delegation" );
}
array.put(val.toString());
}
private void collectImport( JSONArray array, String name, Version version, boolean optional, ExportedPackage export )
{
StringBuffer val = new StringBuffer();
boolean bootDel = isBootDelegated( name );
String marker = null;
val.append( name );
val.append( ",version=" ).append( version );
val.append( " from " );
if ( export != null )
{
val.append( getBundleDescriptor( export.getExportingBundle() ) );
if ( bootDel )
{
val.append( " -- Overwritten by Boot Delegation" );
marker = "INFO";
}
}
else
{
val.append( " -- Cannot be resolved" );
marker = "ERROR";
if ( optional )
{
val.append( " but is not required" );
}
if ( bootDel )
{
val.append( " and overwritten by Boot Delegation" );
}
}
if ( marker != null ) {
val.insert(0, ": ");
val.insert(0, marker);
}
array.put(val);
}
// returns true if the package is listed in the bootdelegation property
private boolean isBootDelegated( String pkgName )
{
// bootdelegation analysis from Apache Felix R4SearchPolicyCore
// Only consider delegation if we have a package name, since
// we don't want to promote the default package. The spec does
// not take a stand on this issue.
if ( pkgName.length() > 0 )
{
// Delegate any packages listed in the boot delegation
// property to the parent class loader.
for ( int i = 0; i < bootPkgs.length; i++ )
{
// A wildcarded boot delegation package will be in the form of
// "foo.", so if the package is wildcarded do a startsWith() or
// a regionMatches() to ignore the trailing "." to determine if
// the request should be delegated to the parent class loader.
// If the package is not wildcarded, then simply do an equals()
// test to see if the request should be delegated to the parent
// class loader.
if ( ( bootPkgWildcards[i] && ( pkgName.startsWith( bootPkgs[i] ) || bootPkgs[i].regionMatches( 0,
pkgName, 0, pkgName.length() ) ) )
|| ( !bootPkgWildcards[i] && bootPkgs[i].equals( pkgName ) ) )
{
return true;
}
}
}
return false;
}
private R4Export toR4Export( ExportedPackage export )
{
R4Attribute version = new R4Attribute( Constants.VERSION_ATTRIBUTE, export.getVersion().toString(), false );
return new R4Export( export.getName(), null, new R4Attribute[]
{ version } );
}
private String getBundleDescriptor( Bundle bundle )
{
StringBuffer val = new StringBuffer();
if ( bundle.getSymbolicName() != null )
{
// list the bundle name if not null
val.append( bundle.getSymbolicName() );
val.append( " (" ).append( bundle.getBundleId() );
val.append( ")" );
}
else if ( bundle.getLocation() != null )
{
// otherwise try the location
val.append( bundle.getLocation() );
val.append( " (" ).append( bundle.getBundleId() );
val.append( ")" );
}
else
{
// fallback to just the bundle id
// only append the bundle
val.append( bundle.getBundleId() );
}
return val.toString();
}
private void refresh( final Bundle bundle )
{
getPackageAdmin().refreshPackages( new Bundle[]
{ bundle } );
}
private final class RequestInfo
{
public final String extension;
public final Bundle bundle;
public final boolean bundleRequested;
protected RequestInfo( final HttpServletRequest request )
{
String info = request.getPathInfo();
// remove label and starting slash
info = info.substring(getLabel().length() + 1);
// get extension
if ( info.endsWith(".json") )
{
extension = "json";
info = info.substring(0, info.length() - 5);
}
else
{
extension = "html";
}
// we only accept direct requests to a bundle if they have a slash after the label
String bundleInfo = null;
if (info.startsWith("/") )
{
bundleInfo = info.substring(1);
}
if ( bundleInfo == null )
{
bundle = null;
bundleRequested = false;
}
else
{
bundle = getBundle(bundleInfo);
bundleRequested = true;
}
request.setAttribute(BundlesServlet.class.getName(), this);
}
}
public static RequestInfo getRequestInfo(final HttpServletRequest request)
{
return (RequestInfo)request.getAttribute(BundlesServlet.class.getName());
}
}