Author: fmeschbe
Date: Fri Mar 12 12:14:44 2010
New Revision: 922229
URL: http://svn.apache.org/viewvc?rev=922229&view=rev
Log:
FELIX-2165 remove Action interface, merge InstallAction into BundlesServlet and
add workaround code to support Maven Sling Plugins use of the .../install URL.
Removed:
felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/Action.java
felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/InstallAction.java
Modified:
felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/BundlesServlet.java
felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java
felix/trunk/webconsole/src/main/resources/templates/bundles_upload.html
Modified:
felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/BundlesServlet.java
URL:
http://svn.apache.org/viewvc/felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/BundlesServlet.java?rev=922229&r1=922228&r2=922229&view=diff
==============================================================================
---
felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/BundlesServlet.java
(original)
+++
felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/BundlesServlet.java
Fri Mar 12 12:14:44 2010
@@ -17,6 +17,7 @@
package org.apache.felix.webconsole.internal.core;
+import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -35,15 +36,19 @@ import java.util.Locale;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.TreeMap;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.fileupload.FileItem;
import org.apache.felix.bundlerepository.impl.R4Attribute;
import org.apache.felix.bundlerepository.impl.R4Export;
import org.apache.felix.bundlerepository.impl.R4Import;
import org.apache.felix.bundlerepository.impl.R4Package;
+import org.apache.felix.webconsole.AbstractWebConsolePlugin;
import org.apache.felix.webconsole.ConfigurationPrinter;
import org.apache.felix.webconsole.DefaultVariableResolver;
import org.apache.felix.webconsole.SimpleWebConsolePlugin;
@@ -65,6 +70,7 @@ import org.osgi.framework.ServiceRegistr
import org.osgi.framework.Version;
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;
@@ -83,6 +89,15 @@ public class BundlesServlet extends Simp
private static final String TITLE = "Bundles";
private static final String CSS[] = { "/res/ui/bundles.css" };
+ private static final String FIELD_STARTLEVEL = "bundlestartlevel";
+
+ private static final String FIELD_START = "bundlestart";
+
+ private static final String FIELD_BUNDLEFILE = "bundlefile";
+
+ // set to ask for PackageAdmin.refreshPackages() after install/update
+ private static final String FIELD_REFRESH_PACKAGES = "refreshPackages";
+
// 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.
@@ -257,84 +272,97 @@ public class BundlesServlet extends Simp
*/
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 = WebConsoleUtil.getParameter( req, "action" );
+ if ( "refreshPackages".equals( action ) )
+ {
+ getPackageAdmin().refreshPackages( null );
+ success = true;
+ }
+ else if ( "install".equals( action ) )
+ {
+ installBundles( req );
- final String action = req.getParameter( "action" );
-
- Bundle bundle = getBundle( req.getPathInfo() );
+ if (req.getRequestURI().endsWith( "/install" )) {
+ // just send 200/OK, no content
+ resp.setContentLength( 0 );
+ } else {
+ // redirect to URL
+ resp.sendRedirect( req.getRequestURI() );
+ }
- if ( bundle != null )
+ return;
+ }
+ else
{
- if ( action == null )
+ final RequestInfo reqInfo = new RequestInfo( req );
+ if ( reqInfo.bundle == null && reqInfo.bundleRequested )
{
- success = true;
+ resp.sendError( 404 );
+ return;
}
- else if ( "start".equals( action ) )
+
+ final Bundle bundle = reqInfo.bundle;
+ if ( bundle != null )
{
- // start bundle
- success = true;
- try
+ if ( action == null )
{
- bundle.start();
+ success = true;
}
- catch ( BundleException be )
+ else if ( "start".equals( action ) )
{
- log( "Cannot start", be );
+ // start bundle
+ success = true;
+ try
+ {
+ bundle.start();
+ }
+ catch ( BundleException be )
+ {
+ log( "Cannot start", be );
+ }
}
- }
- else if ( "stop".equals( action ) )
- {
- // stop bundle
- success = true;
- try
+ else if ( "stop".equals( action ) )
{
- bundle.stop();
+ // stop bundle
+ success = true;
+ try
+ {
+ bundle.stop();
+ }
+ catch ( BundleException be )
+ {
+ log( "Cannot stop", be );
+ }
}
- catch ( BundleException be )
+ else if ( "refresh".equals( action ) )
{
- log( "Cannot stop", be );
+ // refresh bundle wiring
+ refresh( bundle );
+ success = true;
}
- }
- else if ( "refresh".equals( action ) )
- {
- // refresh bundle wiring
- refresh( bundle );
- success = true;
- }
- else if ( "update".equals( action ) )
- {
- // update the bundle
- update( bundle );
- success = true;
- }
- else if ( "uninstall".equals( action ) )
- {
- // uninstall bundle
- success = true;
- try
+ else if ( "update".equals( action ) )
{
- bundle.uninstall();
- bundle = null; // bundle has gone !
+ // update the bundle
+ update( bundle );
+ success = true;
}
- catch ( BundleException be )
+ else if ( "uninstall".equals( action ) )
{
- log( "Cannot uninstall", be );
+ // uninstall bundle
+ success = true;
+ try
+ {
+ bundle.uninstall();
+ }
+ catch ( BundleException be )
+ {
+ log( "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
@@ -346,7 +374,7 @@ public class BundlesServlet extends Simp
}
final String pluginRoot = ( String ) req.getAttribute(
WebConsoleConstants.ATTR_PLUGIN_ROOT );
final String servicesRoot = getServicesRoot( req );
- this.renderJSON(resp, null, pluginRoot, servicesRoot,
req.getLocale() );
+ this.renderJSON( resp, null, pluginRoot, servicesRoot,
req.getLocale() );
}
else
{
@@ -1369,4 +1397,265 @@ public class BundlesServlet extends Simp
return log;
}
+
+
+ //---------- Bundle Installation handler (former InstallAction)
+
+ private void installBundles( HttpServletRequest request ) throws
IOException
+ {
+
+ // get the uploaded data
+ final Map params = ( Map ) request.getAttribute(
AbstractWebConsolePlugin.ATTR_FILEUPLOAD );
+ if ( params == null )
+ {
+ return;
+ }
+
+ final FileItem startItem = getParameter( params, FIELD_START );
+ final FileItem startLevelItem = getParameter( params, FIELD_STARTLEVEL
);
+ final FileItem[] bundleItems = getFileItems( params, FIELD_BUNDLEFILE
);
+ final FileItem refreshPackagesItem = getParameter( params,
FIELD_REFRESH_PACKAGES );
+
+ // don't care any more if no bundle item
+ if ( bundleItems.length == 0 )
+ {
+ return;
+ }
+
+ // default values
+ // it exists
+ int startLevel = -1;
+ String bundleLocation = "inputstream:";
+
+ // convert the start level value
+ if ( startLevelItem != null )
+ {
+ try
+ {
+ startLevel = Integer.parseInt( startLevelItem.getString() );
+ }
+ catch ( NumberFormatException nfe )
+ {
+ getLog().log( LogService.LOG_INFO,
+ "Cannot parse start level parameter " + startLevelItem + "
to a number, not setting start level" );
+ }
+ }
+
+ for ( int i = 0; i < bundleItems.length; i++ )
+ {
+ final FileItem bundleItem = bundleItems[i];
+ // write the bundle data to a temporary file to ease processing
+ File tmpFile = null;
+ try
+ {
+ // copy the data to a file for better processing
+ tmpFile = File.createTempFile( "install", ".tmp" );
+ bundleItem.write( tmpFile );
+ }
+ catch ( Exception e )
+ {
+ getLog().log( LogService.LOG_ERROR, "Problem accessing
uploaded bundle file: " + bundleItem.getName(),
+ e );
+
+ // remove the tmporary file
+ if ( tmpFile != null )
+ {
+ tmpFile.delete();
+ tmpFile = null;
+ }
+ }
+
+ // install or update the bundle now
+ if ( tmpFile != null )
+ {
+ // start, refreshPackages just needs to exist, don't care for
value
+ boolean start = startItem != null;
+ boolean refreshPackages = refreshPackagesItem != null;
+
+ bundleLocation = "inputstream:" + bundleItem.getName();
+ installBundle( bundleLocation, tmpFile, startLevel, start,
refreshPackages );
+ }
+ }
+ }
+
+
+ private FileItem getParameter( Map params, String name )
+ {
+ FileItem[] items = ( FileItem[] ) params.get( name );
+ if ( items != null )
+ {
+ for ( int i = 0; i < items.length; i++ )
+ {
+ if ( items[i].isFormField() )
+ {
+ return items[i];
+ }
+ }
+ }
+
+ // nothing found, fail
+ return null;
+ }
+
+
+ private FileItem[] getFileItems( Map params, String name )
+ {
+ final List files = new ArrayList();
+ FileItem[] items = ( FileItem[] ) params.get( name );
+ if ( items != null )
+ {
+ for ( int i = 0; i < items.length; i++ )
+ {
+ if ( !items[i].isFormField() && items[i].getSize() > 0 )
+ {
+ files.add( items[i] );
+ }
+ }
+ }
+
+ return ( FileItem[] ) files.toArray( new FileItem[files.size()] );
+ }
+
+
+ private void installBundle( String location, File bundleFile, int
startLevel, boolean start, boolean refreshPackages )
+ throws IOException
+ {
+ if ( bundleFile != null )
+ {
+
+ // try to get the bundle name, fail if none
+ String symbolicName = getSymbolicName( bundleFile );
+ if ( symbolicName == null )
+ {
+ bundleFile.delete();
+ throw new IOException( Constants.BUNDLE_SYMBOLICNAME + "
header missing, cannot install bundle" );
+ }
+
+ // check for existing bundle first
+ Bundle updateBundle = null;
+ if ( Constants.SYSTEM_BUNDLE_SYMBOLICNAME.equals( symbolicName ) )
+ {
+ updateBundle = getBundleContext().getBundle( 0 );
+ }
+ else
+ {
+ Bundle[] bundles = getBundleContext().getBundles();
+ for ( int i = 0; i < bundles.length; i++ )
+ {
+ if ( ( bundles[i].getLocation() != null &&
bundles[i].getLocation().equals( location ) )
+ || ( bundles[i].getSymbolicName() != null &&
bundles[i].getSymbolicName().equals( symbolicName ) ) )
+ {
+ updateBundle = bundles[i];
+ break;
+ }
+ }
+ }
+
+ if ( updateBundle != null )
+ {
+
+ updateBackground( updateBundle, bundleFile, refreshPackages );
+
+ }
+ else
+ {
+
+ installBackground( bundleFile, location, startLevel, start,
refreshPackages );
+
+ }
+ }
+ }
+
+
+ private String getSymbolicName( File bundleFile )
+ {
+ JarFile jar = null;
+ try
+ {
+ jar = new JarFile( bundleFile );
+ Manifest m = jar.getManifest();
+ if ( m != null )
+ {
+ return m.getMainAttributes().getValue(
Constants.BUNDLE_SYMBOLICNAME );
+ }
+ }
+ catch ( IOException ioe )
+ {
+ getLog().log( LogService.LOG_WARNING, "Cannot extract symbolic
name of bundle file " + bundleFile, ioe );
+ }
+ finally
+ {
+ if ( jar != null )
+ {
+ try
+ {
+ jar.close();
+ }
+ catch ( IOException ioe )
+ {
+ // ignore
+ }
+ }
+ }
+
+ // fall back to "not found"
+ return null;
+ }
+
+
+ private void installBackground( final File bundleFile, final String
location, final int startlevel,
+ final boolean doStart, final boolean refreshPackages )
+ {
+
+ InstallHelper t = new InstallHelper( getBundleContext(), bundleFile,
location, startlevel, doStart,
+ refreshPackages )
+ {
+ protected Logger getLog()
+ {
+ return BundlesServlet.this.getLog();
+ }
+
+
+ protected Object getService( String serviceName )
+ {
+ if ( serviceName.equals( PackageAdmin.class.getName() ) )
+ {
+ return BundlesServlet.this.getPackageAdmin();
+ }
+ else if ( serviceName.equals( StartLevel.class.getName() ) )
+ {
+ return BundlesServlet.this.getStartLevel();
+ }
+
+ return null;
+ }
+ };
+
+ t.start();
+ }
+
+
+ private void updateBackground( final Bundle bundle, final File bundleFile,
final boolean refreshPackages )
+ {
+ UpdateHelper t = new UpdateHelper( bundle, bundleFile, refreshPackages
)
+ {
+ protected Logger getLog()
+ {
+ return BundlesServlet.this.getLog();
+ }
+
+
+ protected Object getService( String serviceName )
+ {
+ if ( serviceName.equals( PackageAdmin.class.getName() ) )
+ {
+ return BundlesServlet.this.getPackageAdmin();
+ }
+
+ return null;
+ }
+ };
+
+ t.start();
+ }
}
Modified:
felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java
URL:
http://svn.apache.org/viewvc/felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java?rev=922229&r1=922228&r2=922229&view=diff
==============================================================================
---
felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java
(original)
+++
felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java
Fri Mar 12 12:14:44 2010
@@ -29,7 +29,6 @@ import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
-
import javax.servlet.GenericServlet;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
@@ -39,13 +38,10 @@ import javax.servlet.http.HttpServletReq
import javax.servlet.http.HttpServletResponse;
import org.apache.felix.webconsole.AbstractWebConsolePlugin;
-import org.apache.felix.webconsole.Action;
import org.apache.felix.webconsole.BrandingPlugin;
import org.apache.felix.webconsole.WebConsoleConstants;
-import org.apache.felix.webconsole.WebConsoleUtil;
import org.apache.felix.webconsole.internal.Logger;
import org.apache.felix.webconsole.internal.OsgiManagerPlugin;
-import org.apache.felix.webconsole.internal.Util;
import org.apache.felix.webconsole.internal.WebConsolePluginAdapter;
import org.apache.felix.webconsole.internal.core.BundlesServlet;
import org.apache.felix.webconsole.internal.filter.FilteringResponseWrapper;
@@ -132,7 +128,6 @@ public class OsgiManager extends Generic
"org.apache.felix.webconsole.internal.compendium.PreferencesConfigurationPrinter",
"org.apache.felix.webconsole.internal.core.BundlesServlet",
"org.apache.felix.webconsole.internal.core.ServicesServlet",
- "org.apache.felix.webconsole.internal.core.InstallAction",
"org.apache.felix.webconsole.internal.deppack.DepPackServlet",
"org.apache.felix.webconsole.internal.misc.LicenseServlet",
"org.apache.felix.webconsole.internal.misc.ConfigurationRender",
@@ -149,8 +144,6 @@ public class OsgiManager extends Generic
private HttpService httpService;
- private ServiceTracker operationsTracker;
-
private ServiceTracker pluginsTracker;
private ServiceTracker brandingTracker;
@@ -165,8 +158,6 @@ public class OsgiManager extends Generic
// are plugin titles
private Map labelMap = new HashMap();
- private Map operations = new HashMap();
-
private AbstractWebConsolePlugin defaultPlugin;
private String defaultRenderName;
@@ -277,16 +268,9 @@ public class OsgiManager extends Generic
{
bindServlet( ( AbstractWebConsolePlugin ) plugin );
}
- else
+ else if ( plugin instanceof BrandingPlugin )
{
- if ( plugin instanceof Action )
- {
- bindOperation( ( Action ) plugin );
- }
- if ( plugin instanceof BrandingPlugin )
- {
-
AbstractWebConsolePlugin.setBrandingPlugin((BrandingPlugin) plugin);
- }
+ AbstractWebConsolePlugin.setBrandingPlugin( (
BrandingPlugin ) plugin );
}
}
catch ( NoClassDefFoundError ncdfe )
@@ -311,8 +295,6 @@ public class OsgiManager extends Generic
}
// start tracking external plugins after setting up our own plugins
- operationsTracker = new OperationServiceTracker( this );
- operationsTracker.open();
pluginsTracker = new PluginServiceTracker( this );
pluginsTracker.open();
brandingTracker = new BrandingServiceTracker(this);
@@ -328,14 +310,9 @@ public class OsgiManager extends Generic
HttpServletRequest request = ( HttpServletRequest ) req;
HttpServletResponse response = ( HttpServletResponse ) res;
- // handle the request action, terminate if done
- if ( this.handleAction( request, response ) )
- {
- return;
- }
-
// check whether we are not at .../{webManagerRoot}
- if ( request.getPathInfo() == null || request.getPathInfo().equals(
"/" ) )
+ final String pathInfo = request.getPathInfo();
+ if ( pathInfo == null || pathInfo.equals( "/" ) )
{
String path = request.getRequestURI();
if ( !path.endsWith( "/" ) )
@@ -347,15 +324,23 @@ public class OsgiManager extends Generic
return;
}
- String label = request.getPathInfo();
- int slash = label.indexOf( "/", 1 );
+ int slash = pathInfo.indexOf( "/", 1 );
if ( slash < 2 )
{
- slash = label.length();
+ slash = pathInfo.length();
}
- label = label.substring( 1, slash );
+ final String label = pathInfo.substring( 1, slash );
AbstractWebConsolePlugin plugin = ( AbstractWebConsolePlugin )
plugins.get( label );
+
+ if ( plugin == null )
+ {
+ if ( "install".equals( label ) )
+ {
+ plugin = ( AbstractWebConsolePlugin ) plugins.get(
BundlesServlet.NAME );
+ }
+ }
+
if ( plugin != null )
{
// the official request attributes
@@ -393,11 +378,6 @@ public class OsgiManager extends Generic
}
// stop listening for plugins
- if ( operationsTracker != null )
- {
- operationsTracker.close();
- operationsTracker = null;
- }
if ( pluginsTracker != null )
{
pluginsTracker.close();
@@ -422,62 +402,10 @@ public class OsgiManager extends Generic
// simply remove all operations, we should not be used anymore
this.plugins.clear();
this.labelMap.clear();
- this.operations.clear();
}
//---------- internal
- protected boolean handleAction( HttpServletRequest req,
HttpServletResponse resp ) throws IOException, ServletException
- {
- // check action
- String actionName = WebConsoleUtil.getParameter( req,
Util.PARAM_ACTION );
- if ( actionName != null )
- {
- Action action = ( Action ) this.operations.get( actionName );
- if ( action != null )
- {
- boolean redirect = true;
- try
- {
- redirect = action.performAction( req, resp );
- }
- catch ( IOException ioe )
- {
- log.log( LogService.LOG_WARNING, ioe.getMessage(), ioe );
- }
- catch ( ServletException se )
- {
- log.log( LogService.LOG_WARNING, se.getMessage(),
se.getRootCause() );
- }
-
- // maybe overwrite redirect
- if ( PARAM_NO_REDIRECT_AFTER_ACTION.equals(
WebConsoleUtil.getParameter( req,
- PARAM_NO_REDIRECT_AFTER_ACTION ) ) )
- {
- resp.setStatus( HttpServletResponse.SC_OK );
- resp.setContentType( "text/html" );
- resp.getWriter().println( "Ok" );
- return true;
- }
-
- if ( redirect )
- {
- String uri = req.getRequestURI();
- // Object pars =
- // req.getAttribute(Action.ATTR_REDIRECT_PARAMETERS);
- // if (pars instanceof String) {
- // uri += "?" + pars;
- // }
- resp.sendRedirect( uri );
- }
- return true;
- }
- }
-
- return false;
- }
-
-
BundleContext getBundleContext()
{
return bundleContext;
@@ -537,41 +465,6 @@ public class OsgiManager extends Generic
}
}
- private static class OperationServiceTracker extends ServiceTracker
- {
-
- private final OsgiManager osgiManager;
-
-
- OperationServiceTracker( OsgiManager osgiManager )
- {
- super( osgiManager.getBundleContext(), Action.SERVICE, null );
- this.osgiManager = osgiManager;
- }
-
-
- public Object addingService( ServiceReference reference )
- {
- Object operation = super.addingService( reference );
- if ( operation instanceof Action )
- {
- osgiManager.bindOperation( ( Action ) operation );
- }
- return operation;
- }
-
-
- public void removedService( ServiceReference reference, Object service
)
- {
- if ( service instanceof Action )
- {
- osgiManager.bindOperation( ( Action ) service );
- }
-
- super.removedService( reference, service );
- }
- }
-
private static class PluginServiceTracker extends ServiceTracker
{
@@ -819,18 +712,6 @@ public class OsgiManager extends Generic
}
- protected void bindOperation( Action operation )
- {
- operations.put( operation.getName(), operation );
- }
-
-
- protected void unbindOperation( Action operation )
- {
- operations.remove( operation.getName() );
- }
-
-
private Dictionary getConfiguration()
{
return configuration;
Modified:
felix/trunk/webconsole/src/main/resources/templates/bundles_upload.html
URL:
http://svn.apache.org/viewvc/felix/trunk/webconsole/src/main/resources/templates/bundles_upload.html?rev=922229&r1=922228&r2=922229&view=diff
==============================================================================
--- felix/trunk/webconsole/src/main/resources/templates/bundles_upload.html
[UTF-8] (original)
+++ felix/trunk/webconsole/src/main/resources/templates/bundles_upload.html
[UTF-8] Fri Mar 12 12:14:44 2010
@@ -1,6 +1,6 @@
<script type="text/javascript"
src="${appRoot}/res/lib/jquery.multifile-1.4.6.js"></script>
-<form method="post" enctype="multipart/form-data" action="../"
style="width:50%">
+<form method="post" enctype="multipart/form-data" action="${pluginRoot}"
style="width:50%">
<!-- top heading -->
<div class="ui-widget-header ui-corner-top buttonGroup">