Return-Path: Delivered-To: apmail-felix-commits-archive@www.apache.org Received: (qmail 56193 invoked from network); 12 Mar 2010 12:15:43 -0000 Received: from unknown (HELO mail.apache.org) (140.211.11.3) by 140.211.11.9 with SMTP; 12 Mar 2010 12:15:43 -0000 Received: (qmail 64492 invoked by uid 500); 12 Mar 2010 12:15:07 -0000 Delivered-To: apmail-felix-commits-archive@felix.apache.org Received: (qmail 64470 invoked by uid 500); 12 Mar 2010 12:15:07 -0000 Mailing-List: contact commits-help@felix.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@felix.apache.org Delivered-To: mailing list commits@felix.apache.org Received: (qmail 64463 invoked by uid 99); 12 Mar 2010 12:15:07 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 12 Mar 2010 12:15:07 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 12 Mar 2010 12:15:05 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 0A03423888D1; Fri, 12 Mar 2010 12:14:45 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: svn commit: r922229 - in /felix/trunk/webconsole/src/main: java/org/apache/felix/webconsole/ java/org/apache/felix/webconsole/internal/core/ java/org/apache/felix/webconsole/internal/servlet/ resources/templates/ Date: Fri, 12 Mar 2010 12:14:44 -0000 To: commits@felix.apache.org From: fmeschbe@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20100312121445.0A03423888D1@eris.apache.org> 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 @@  -
+