Modified: felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/BundleRepositoryRender.java URL: http://svn.apache.org/viewvc/felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/BundleRepositoryRender.java?rev=662438&r1=662437&r2=662438&view=diff ============================================================================== --- felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/BundleRepositoryRender.java (original) +++ felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/BundleRepositoryRender.java Mon Jun 2 06:52:15 2008 @@ -17,12 +17,23 @@ package org.apache.felix.webconsole.internal.obr; +import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Comparator; +import java.util.Date; import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.SortedSet; import java.util.StringTokenizer; +import java.util.TreeSet; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import org.apache.felix.webconsole.Render; import org.apache.felix.webconsole.internal.Util; @@ -30,9 +41,12 @@ import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.Version; +import org.osgi.service.obr.Repository; +import org.osgi.service.obr.RepositoryAdmin; +import org.osgi.service.obr.Resource; -public abstract class BundleRepositoryRender extends AbstractObrPlugin implements Render +public class BundleRepositoryRender extends AbstractObrPlugin implements Render { public static final String NAME = "bundlerepo"; @@ -48,9 +62,9 @@ private String[] repoURLs; - public void setBundleContext( BundleContext bundleContext ) + public void activate( BundleContext bundleContext ) { - super.setBundleContext( bundleContext ); + super.activate( bundleContext ); String urlStr = bundleContext.getProperty( REPOSITORY_PROPERTY ); List urlList = new ArrayList(); @@ -80,77 +94,83 @@ } - /* - public void render(HttpServletRequest request, HttpServletResponse response) - throws IOException { - - PrintWriter pw = response.getWriter(); - this.header(pw); - - Iterator<?> repos; - BundleRepositoryAdmin repoAdmin = getBundleRepositoryAdmin(); - if (repoAdmin != null) { - repos = repoAdmin.getRepositories(); - } else { - repos = Collections.emptyList().iterator(); - } + public void render( HttpServletRequest request, HttpServletResponse response ) throws IOException + { - Set<String> activeURLs = new HashSet<String>(); - if (!repos.hasNext()) { - pw.println("<tr class='content'>"); - pw.println("<td class='content' colspan='4'>No Active Repositories</td>"); - pw.println("</tr>"); - } else { - while (repos.hasNext()) { - Repository repo = (Repository) repos.next(); - - activeURLs.add(repo.getURL().toString()); - - pw.println("<tr class='content'>"); - pw.println("<td class='content'>" + repo.getName() + "</td>"); - pw.println("<td class='content'>" + repo.getURL() + "</td>"); - pw.println("<td class='content'>" - + new Date(repo.getLastModified()) + "</td>"); - pw.println("<td class='content'>"); - pw.println("<form>"); - pw.println("<input type='hidden' name='" + Util.PARAM_ACTION - + "' value='" + RefreshRepoAction.NAME + "'>"); - pw.println("<input type='hidden' name='" - + RefreshRepoAction.PARAM_REPO + "' value='" - + repo.getURL() + "'>"); - pw.println("<input class='submit' type='submit' value='Refresh'>"); - pw.println("</form>"); - pw.println("</td>"); - pw.println("</tr>"); - } + PrintWriter pw = response.getWriter(); + this.header( pw ); + + RepositoryAdmin repoAdmin = getRepositoryAdmin(); + Repository[] repos; + if ( repoAdmin != null ) + { + repos = repoAdmin.listRepositories(); + } + else + { + repos = null; + } + + Set activeURLs = new HashSet(); + if ( repos == null || repos.length == 0 ) + { + pw.println( "<tr class='content'>" ); + pw.println( "<td class='content' colspan='4'>No Active Repositories</td>" ); + pw.println( "</tr>" ); + } + else + { + for ( int i = 0; i < repos.length; i++ ) + { + Repository repo = repos[i]; + + activeURLs.add( repo.getURL().toString() ); + + pw.println( "<tr class='content'>" ); + pw.println( "<td class='content'>" + repo.getName() + "</td>" ); + pw.println( "<td class='content'>" + repo.getURL() + "</td>" ); + pw.println( "<td class='content'>" + new Date( repo.getLastModified() ) + "</td>" ); + pw.println( "<td class='content'>" ); + pw.println( "<form>" ); + pw.println( "<input type='hidden' name='" + Util.PARAM_ACTION + "' value='" + RefreshRepoAction.NAME + + "'>" ); + pw.println( "<input type='hidden' name='" + RefreshRepoAction.PARAM_REPO + "' value='" + repo.getURL() + + "'>" ); + pw.println( "<input class='submit' type='submit' value='Refresh'>" ); + pw.println( "</form>" ); + pw.println( "</td>" ); + pw.println( "</tr>" ); } + } - // list any repositories configured but not active - for (int i = 0; i < this.repoURLs.length; i++) { - if (!activeURLs.contains(this.repoURLs[i])) { - pw.println("<tr class='content'>"); - pw.println("<td class='content'>-</td>"); - pw.println("<td class='content'>" + this.repoURLs[i] + "</td>"); - pw.println("<td class='content'>[inactive, click Refresh to activate]</td>"); - pw.println("<td class='content'>"); - pw.println("<form>"); - pw.println("<input type='hidden' name='" + Util.PARAM_ACTION - + "' value='" + RefreshRepoAction.NAME + "'>"); - pw.println("<input type='hidden' name='" - + RefreshRepoAction.PARAM_REPO + "' value='" - + this.repoURLs[i] + "'>"); - pw.println("<input class='submit' type='submit' value='Refresh'>"); - pw.println("</form>"); - pw.println("</td>"); - pw.println("</tr>"); - } + // list any repositories configured but not active + for ( int i = 0; i < this.repoURLs.length; i++ ) + { + if ( !activeURLs.contains( this.repoURLs[i] ) ) + { + pw.println( "<tr class='content'>" ); + pw.println( "<td class='content'>-</td>" ); + pw.println( "<td class='content'>" + this.repoURLs[i] + "</td>" ); + pw.println( "<td class='content'>[inactive, click Refresh to activate]</td>" ); + pw.println( "<td class='content'>" ); + pw.println( "<form>" ); + pw.println( "<input type='hidden' name='" + Util.PARAM_ACTION + "' value='" + RefreshRepoAction.NAME + + "'>" ); + pw.println( "<input type='hidden' name='" + RefreshRepoAction.PARAM_REPO + "' value='" + + this.repoURLs[i] + "'>" ); + pw.println( "<input class='submit' type='submit' value='Refresh'>" ); + pw.println( "</form>" ); + pw.println( "</td>" ); + pw.println( "</tr>" ); } + } + + this.footer( pw ); + + this.listResources( pw, repos ); + } - this.footer(pw); - this.listResources(pw); - } - */ private void header( PrintWriter pw ) { pw.println( "<table class='content' cellpadding='0' cellspacing='0' width='100%'>" ); @@ -194,72 +214,86 @@ } - /* - private void listResources(PrintWriter pw) { - InstallerService is = getInstallerService(); - if (is == null) { - return; + private void listResources( PrintWriter pw, Repository[] repos ) + { + + Map bundles = this.getBundles(); + + SortedSet resSet = new TreeSet( new Comparator() + { + public int compare( Object arg0, Object arg1 ) + { + return compare( ( Resource ) arg0, ( Resource ) arg1 ); } - Map<String, Version> bundles = this.getBundles(); - Iterator<?> resources = is.getBundleRepositoryAdmin().getResources(); - SortedSet<Resource> resSet = new TreeSet<Resource>( - new Comparator<Resource>() { - public int compare(Resource o1, Resource o2) { - if (o1 == o2 || o1.equals(o2)) { - return 0; - } - - if (o1.getPresentationName().equals( - o2.getPresentationName())) { - return o1.getVersion().compareTo(o2.getVersion()); - } - - return o1.getPresentationName().compareTo( - o2.getPresentationName()); - } - }); - - while (resources.hasNext()) { - Resource res = (Resource) resources.next(); - Version ver = bundles.get(res.getSymbolicName()); - if (ver == null || ver.compareTo(res.getVersion()) < 0) { - resSet.add(res); + public int compare( Resource o1, Resource o2 ) + { + if ( o1 == o2 || o1.equals( o2 ) ) + { + return 0; } - } - this.resourcesHeader(pw, !resSet.isEmpty()); + if ( o1.getPresentationName().equals( o2.getPresentationName() ) ) + { + return o1.getVersion().compareTo( o2.getVersion() ); + } - for (Resource resource : resSet) { - this.printResource(pw, resource); + return o1.getPresentationName().compareTo( o2.getPresentationName() ); } + } ); - this.resourcesFooter(pw, !resSet.isEmpty()); - } - - private void printResource(PrintWriter pw, Resource res) { - pw.println("<tr class='content'>"); - pw.println("<td class='content' valign='top' align='center'><input class='checkradio' type='checkbox' name='bundle' value='" - + res.getSymbolicName() + "," + res.getVersion() + "'></td>"); - - // check whether the resource is an assembly (category name) - String style = ""; - String[] cat = res.getCategories(); - for (int i = 0; cat != null && i < cat.length; i++) { - if ("assembly".equals(cat[i])) { - style = "style='font-weight:bold'"; + for ( int i = 0; i < repos.length; i++ ) + { + Resource[] resources = repos[i].getResources(); + for ( int j = 0; j < resources.length; j++ ) + { + Resource res = resources[j]; + Version ver = ( Version ) bundles.get( res.getSymbolicName() ); + if ( ver == null || ver.compareTo( res.getVersion() ) < 0 ) + { + resSet.add( res ); } } - pw.println("<td class='content' " + style + ">" - + res.getPresentationName() + " (" + res.getSymbolicName() - + ")</td>"); - pw.println("<td class='content' " + style + " valign='top'>" - + res.getVersion() + "</td>"); + } + + this.resourcesHeader( pw, !resSet.isEmpty() ); + + for ( Iterator ri = resSet.iterator(); ri.hasNext(); ) + { + Resource resource = ( Resource ) ri.next(); + this.printResource( pw, resource ); + } + + this.resourcesFooter( pw, !resSet.isEmpty() ); + } + - pw.println("</tr>"); + private void printResource( PrintWriter pw, Resource res ) + { + pw.println( "<tr class='content'>" ); + pw + .println( "<td class='content' valign='top' align='center'><input class='checkradio' type='checkbox' name='bundle' value='" + + res.getSymbolicName() + "," + res.getVersion() + "'></td>" ); + + // check whether the resource is an assembly (category name) + String style = ""; + String[] cat = res.getCategories(); + for ( int i = 0; cat != null && i < cat.length; i++ ) + { + if ( "assembly".equals( cat[i] ) ) + { + style = "style='font-weight:bold'"; + } } - */ + pw.println( "<td class='content' " + style + ">" + res.getPresentationName() + " (" + res.getSymbolicName() + + ")</td>" ); + pw.println( "<td class='content' " + style + " valign='top'>" + res.getVersion() + "</td>" ); + + pw.println( "</tr>" ); + } + + private void resourcesButtons( PrintWriter pw ) { pw.println( "<tr class='content'>" );
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=662438&r1=662437&r2=662438&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 Mon Jun 2 06:52:15 2008 @@ -18,47 +18,38 @@ import java.io.IOException; -import java.io.PrintWriter; import java.util.Dictionary; import java.util.Enumeration; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; -import java.util.List; import java.util.Map; -import java.util.SortedMap; -import java.util.TreeMap; import javax.servlet.GenericServlet; +import javax.servlet.Servlet; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.apache.commons.fileupload.FileItem; -import org.apache.commons.fileupload.FileUploadException; -import org.apache.commons.fileupload.disk.DiskFileItemFactory; -import org.apache.commons.fileupload.servlet.ServletFileUpload; -import org.apache.commons.fileupload.servlet.ServletRequestContext; +import org.apache.felix.webconsole.AbstractWebConsolePlugin; import org.apache.felix.webconsole.Action; import org.apache.felix.webconsole.Render; -import org.apache.felix.webconsole.internal.BaseManagementPlugin; +import org.apache.felix.webconsole.WebConsoleConstants; +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.compendium.AjaxConfigManagerAction; import org.apache.felix.webconsole.internal.compendium.ComponentConfigurationPrinter; import org.apache.felix.webconsole.internal.compendium.ComponentRenderAction; import org.apache.felix.webconsole.internal.compendium.ConfigManager; -import org.apache.felix.webconsole.internal.core.AjaxBundleDetailsAction; import org.apache.felix.webconsole.internal.core.BundleListRender; import org.apache.felix.webconsole.internal.core.InstallAction; import org.apache.felix.webconsole.internal.core.RefreshPackagesAction; import org.apache.felix.webconsole.internal.core.SetStartLevelAction; -import org.apache.felix.webconsole.internal.core.StartAction; -import org.apache.felix.webconsole.internal.core.StopAction; -import org.apache.felix.webconsole.internal.core.UninstallAction; -import org.apache.felix.webconsole.internal.core.UpdateAction; import org.apache.felix.webconsole.internal.misc.ConfigurationRender; +import org.apache.felix.webconsole.internal.obr.BundleRepositoryRender; import org.apache.felix.webconsole.internal.system.GCAction; import org.apache.felix.webconsole.internal.system.ShutdownAction; import org.apache.felix.webconsole.internal.system.ShutdownRender; @@ -84,6 +75,8 @@ /** Pseudo class version ID to keep the IDE quite. */ private static final long serialVersionUID = 1L; + public static final String ATTR_LABEL_MAP = OsgiManager.class.getName() + ".labelMap"; + /** * The name and value of a parameter which will prevent redirection to a * render after the action has been executed (value is "_noredir_"). This @@ -122,12 +115,17 @@ */ private static final String DEFAULT_MANAGER_ROOT = "/system/console"; + // private static final Class[] PLUGIN_CLASSES = + // { AjaxConfigManagerAction.class, ComponentConfigurationPrinter.class, ComponentRenderAction.class, + // ConfigManager.class, AjaxBundleDetailsAction.class, BundleListRender.class, InstallAction.class, + // RefreshPackagesAction.class, SetStartLevelAction.class, StartAction.class, StopAction.class, + // UninstallAction.class, UpdateAction.class, ConfigurationRender.class, GCAction.class, ShutdownAction.class, + // ShutdownRender.class, VMStatRender.class }; private static final Class[] PLUGIN_CLASSES = { AjaxConfigManagerAction.class, ComponentConfigurationPrinter.class, ComponentRenderAction.class, - ConfigManager.class, AjaxBundleDetailsAction.class, BundleListRender.class, InstallAction.class, - RefreshPackagesAction.class, SetStartLevelAction.class, StartAction.class, StopAction.class, - UninstallAction.class, UpdateAction.class, ConfigurationRender.class, GCAction.class, ShutdownAction.class, - ShutdownRender.class, VMStatRender.class }; + ConfigManager.class, BundleListRender.class, InstallAction.class, RefreshPackagesAction.class, + SetStartLevelAction.class, ConfigurationRender.class, GCAction.class, ShutdownAction.class, + ShutdownRender.class, VMStatRender.class, BundleRepositoryRender.class }; private BundleContext bundleContext; @@ -141,13 +139,17 @@ private ServiceTracker rendersTracker; + private ServiceTracker pluginsTracker; + private ServiceRegistration configurationListener; - private Map operations = new HashMap(); + private Map plugins = new HashMap(); - private SortedMap renders = new TreeMap(); + private Map labelMap = new HashMap(); + + private Map operations = new HashMap(); - private Render defaultRender; + private Servlet defaultRender; private String defaultRenderName; @@ -178,6 +180,8 @@ operationsTracker.open(); rendersTracker = new RenderServiceTracker( this ); rendersTracker.open(); + pluginsTracker = new PluginServiceTracker( this ); + pluginsTracker.open(); httpServiceTracker = new HttpServiceTracker( this ); httpServiceTracker.open(); @@ -187,18 +191,25 @@ try { Object plugin = pluginClass.newInstance(); - if ( plugin instanceof BaseManagementPlugin ) + if ( plugin instanceof OsgiManagerPlugin ) { - ( ( BaseManagementPlugin ) plugin ).setBundleContext( bundleContext ); - ( ( BaseManagementPlugin ) plugin ).setLogger( log ); + ( ( OsgiManagerPlugin ) plugin ).activate( bundleContext ); } - if ( plugin instanceof Action ) + if ( plugin instanceof AbstractWebConsolePlugin ) { - bindOperation( ( Action ) plugin ); + AbstractWebConsolePlugin amp = ( AbstractWebConsolePlugin ) plugin; + bindServlet( amp.getLabel(), amp ); } - if ( plugin instanceof Render ) + else { - bindRender( ( Render ) plugin ); + if ( plugin instanceof Action ) + { + bindOperation( ( Action ) plugin ); + } + if ( plugin instanceof Render ) + { + bindRender( ( Render ) plugin ); + } } } catch ( Throwable t ) @@ -230,16 +241,33 @@ rendersTracker = null; } + if ( pluginsTracker != null ) + { + pluginsTracker.close(); + pluginsTracker = null; + } + if ( httpServiceTracker != null ) { httpServiceTracker.close(); httpServiceTracker = null; } + // deactivate any remaining plugins + for ( Iterator pi = plugins.values().iterator(); pi.hasNext(); ) + { + Object plugin = pi.next(); + if ( plugin instanceof OsgiManagerPlugin ) + { + ( ( OsgiManagerPlugin ) plugin ).deactivate(); + } + } + // simply remove all operations, we should not be used anymore this.defaultRender = null; + this.plugins.clear(); + this.labelMap.clear(); this.operations.clear(); - this.renders.clear(); if ( log != null ) { @@ -263,38 +291,45 @@ } // check whether we are not at .../{webManagerRoot} - if ( request.getRequestURI().endsWith( this.webManagerRoot ) ) + if ( request.getPathInfo() == null ) { - response.sendRedirect( request.getRequestURI() + "/" + this.defaultRender.getName() ); + String path = request.getRequestURI(); + if ( !path.endsWith( "/" ) ) + { + path = path.concat( "/" ); + } + path = path.concat( defaultRenderName ); + response.sendRedirect( path ); return; } - // otherwise we render the response - Render render = this.getRender( request ); - if ( render == null ) + String label = request.getPathInfo(); + int slash = label.indexOf( "/", 1 ); + if ( slash < 2 ) + { + slash = label.length(); + } + + label = label.substring( 1, slash ); + Servlet plugin = ( Servlet ) plugins.get( label ); + if ( plugin != null ) + { + req.setAttribute( ATTR_LABEL_MAP, labelMap ); + plugin.service( req, res ); + } + else { response.sendError( HttpServletResponse.SC_NOT_FOUND ); return; } - String current = render.getName(); - boolean disabled = false; // should take action==shutdown into - // account: - // Boolean.valueOf(request.getParameter("disabled")).booleanValue(); - - PrintWriter pw = Util.startHtml( response, render.getLabel() ); - Util.navigation( pw, this.renders.values(), current, disabled ); - - render.render( request, response ); - - Util.endHhtml( pw ); } protected boolean handleAction( HttpServletRequest req, HttpServletResponse resp ) throws IOException { // check action - String actionName = this.getParameter( req, Util.PARAM_ACTION ); + String actionName = AbstractWebConsolePlugin.getParameter( req, Util.PARAM_ACTION ); if ( actionName != null ) { Action action = ( Action ) this.operations.get( actionName ); @@ -315,7 +350,8 @@ } // maybe overwrite redirect - if ( PARAM_NO_REDIRECT_AFTER_ACTION.equals( getParameter( req, PARAM_NO_REDIRECT_AFTER_ACTION ) ) ) + if ( PARAM_NO_REDIRECT_AFTER_ACTION.equals( AbstractWebConsolePlugin.getParameter( req, + PARAM_NO_REDIRECT_AFTER_ACTION ) ) ) { resp.setStatus( HttpServletResponse.SC_OK ); resp.setContentType( "text/html" ); @@ -341,98 +377,6 @@ } - protected Render getRender( HttpServletRequest request ) - { - - String page = request.getRequestURI(); - - // remove trailing slashes - while ( page.endsWith( "/" ) ) - { - page = page.substring( 0, page.length() - 1 ); - } - - // take last part of the name - int lastSlash = page.lastIndexOf( '/' ); - if ( lastSlash >= 0 ) - { - page = page.substring( lastSlash + 1 ); - } - - Render render = ( Render ) this.renders.get( page ); - return ( render == null ) ? this.defaultRender : render; - } - - - private String getParameter( HttpServletRequest request, String name ) - { - // just get the parameter if not a multipart/form-data POST - if ( !ServletFileUpload.isMultipartContent( new ServletRequestContext( request ) ) ) - { - return request.getParameter( name ); - } - - // check, whether we alread have the parameters - Map params = ( Map ) request.getAttribute( Util.ATTR_FILEUPLOAD ); - if ( params == null ) - { - // parameters not read yet, read now - // Create a factory for disk-based file items - DiskFileItemFactory factory = new DiskFileItemFactory(); - factory.setSizeThreshold( 256000 ); - - // Create a new file upload handler - ServletFileUpload upload = new ServletFileUpload( factory ); - upload.setSizeMax( -1 ); - - // Parse the request - params = new HashMap(); - try - { - List items = upload.parseRequest( request ); - for ( Iterator fiter = items.iterator(); fiter.hasNext(); ) - { - FileItem fi = ( FileItem ) fiter.next(); - FileItem[] current = ( FileItem[] ) params.get( fi.getFieldName() ); - if ( current == null ) - { - current = new FileItem[] - { fi }; - } - else - { - FileItem[] newCurrent = new FileItem[current.length + 1]; - System.arraycopy( current, 0, newCurrent, 0, current.length ); - newCurrent[current.length] = fi; - current = newCurrent; - } - params.put( fi.getFieldName(), current ); - } - } - catch ( FileUploadException fue ) - { - // TODO: log - } - request.setAttribute( Util.ATTR_FILEUPLOAD, params ); - } - - FileItem[] param = ( FileItem[] ) params.get( name ); - if ( param != null ) - { - for ( int i = 0; i < param.length; i++ ) - { - if ( param[i].isFormField() ) - { - return param[i].getString(); - } - } - } - - // no valid string parameter, fail - return null; - } - - BundleContext getBundleContext() { return bundleContext; @@ -543,6 +487,50 @@ } } + private static class PluginServiceTracker extends ServiceTracker + { + + private final OsgiManager osgiManager; + + + PluginServiceTracker( OsgiManager osgiManager ) + { + super( osgiManager.getBundleContext(), WebConsoleConstants.SERVICE_NAME, null ); + this.osgiManager = osgiManager; + } + + + public Object addingService( ServiceReference reference ) + { + Object label = reference.getProperty( WebConsoleConstants.PLUGIN_LABEL ); + if ( label instanceof String ) + { + Object operation = super.addingService( reference ); + if ( operation instanceof Servlet ) + { + // TODO: check reference properties !! + osgiManager.bindServlet( ( String ) label, ( Servlet ) operation ); + } + return operation; + } + + return null; + } + + + public void removedService( ServiceReference reference, Object service ) + { + Object label = reference.getProperty( WebConsoleConstants.PLUGIN_LABEL ); + if ( label instanceof String ) + { + // TODO: check reference properties !! + osgiManager.unbindServlet( ( String ) label ); + } + + super.removedService( reference, service ); + } + } + protected synchronized void bindHttpService( HttpService httpService ) { @@ -585,48 +573,85 @@ } + protected void bindServlet( String label, Servlet servlet ) + { + try + { + servlet.init( getServletConfig() ); + plugins.put( label, servlet ); + + if ( servlet instanceof GenericServlet ) + { + String title = ( ( GenericServlet ) servlet ).getServletName(); + if ( title != null ) + { + labelMap.put( label, title ); + } + } + + if ( this.defaultRender == null ) + { + this.defaultRender = servlet; + } + else if ( label.equals( this.defaultRenderName ) ) + { + this.defaultRender = servlet; + } + } + catch ( ServletException se ) + { + // TODO: log + } + } + + + protected void unbindServlet( String label ) + { + Servlet servlet = ( Servlet ) plugins.remove( label ); + if ( servlet != null ) + { + labelMap.remove( label ); + + if ( this.defaultRender == servlet ) + { + if ( this.plugins.isEmpty() ) + { + this.defaultRender = null; + } + else + { + this.defaultRender = ( Servlet ) plugins.values().iterator().next(); + } + } + + servlet.destroy(); + } + } + + protected void bindOperation( Action operation ) { - this.operations.put( operation.getName(), operation ); + operations.put( operation.getName(), operation ); } protected void unbindOperation( Action operation ) { - this.operations.remove( operation.getName() ); + operations.remove( operation.getName() ); } protected void bindRender( Render render ) { - this.renders.put( render.getName(), render ); - - if ( this.defaultRender == null ) - { - this.defaultRender = render; - } - else if ( render.getName().equals( this.defaultRenderName ) ) - { - this.defaultRender = render; - } + RenderBridge bridge = new RenderBridge( render ); + bridge.activate( getBundleContext() ); + bindServlet( render.getName(), bridge ); } protected void unbindRender( Render render ) { - this.renders.remove( render.getName() ); - - if ( this.defaultRender == render ) - { - if ( this.renders.isEmpty() ) - { - this.defaultRender = null; - } - else - { - this.defaultRender = ( Render ) renders.values().iterator().next(); - } - } + unbindServlet( render.getName() ); } @@ -646,9 +671,9 @@ configuration = config; defaultRenderName = ( String ) config.get( PROP_DEFAULT_RENDER ); - if ( defaultRenderName != null && renders.get( defaultRenderName ) != null ) + if ( defaultRenderName != null && plugins.get( defaultRenderName ) != null ) { - defaultRender = ( Render ) renders.get( defaultRenderName ); + defaultRender = ( Servlet ) plugins.get( defaultRenderName ); } // get the web manager root path Added: felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/RenderBridge.java URL: http://svn.apache.org/viewvc/felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/RenderBridge.java?rev=662438&view=auto ============================================================================== --- felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/RenderBridge.java (added) +++ felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/RenderBridge.java Mon Jun 2 06:52:15 2008 @@ -0,0 +1,71 @@ +/* + * 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.servlet; + + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.felix.webconsole.AbstractWebConsolePlugin; +import org.apache.felix.webconsole.Render; + + +public class RenderBridge extends AbstractWebConsolePlugin +{ + + /** Pseudo class version ID to keep the IDE quite. */ + private static final long serialVersionUID = 1L; + + private final Render render; + + + RenderBridge( Render render ) + { + this.render = render; + } + + + public Render getRender() + { + return render; + } + + + public String getTitle() + { + return render.getLabel(); + } + + + public String getLabel() + { + return render.getName(); + } + + + protected void renderContent( HttpServletRequest request, HttpServletResponse response ) throws ServletException, + IOException + { + render.render( request, response ); + } + +} Modified: felix/trunk/webconsole/src/main/resources/res/ui/admin.css URL: http://svn.apache.org/viewvc/felix/trunk/webconsole/src/main/resources/res/ui/admin.css?rev=662438&r1=662437&r2=662438&view=diff ============================================================================== --- felix/trunk/webconsole/src/main/resources/res/ui/admin.css (original) +++ felix/trunk/webconsole/src/main/resources/res/ui/admin.css Mon Jun 2 06:52:15 2008 @@ -43,7 +43,7 @@ */ margin: 0px; padding: 5px 0 0 8px; - font-size: 400%; + font-size: 300%; font-weight: bold; line-height: 120%; height: 95px; Added: felix/trunk/webconsole/src/main/resources/res/ui/bundles.js URL: http://svn.apache.org/viewvc/felix/trunk/webconsole/src/main/resources/res/ui/bundles.js?rev=662438&view=auto ============================================================================== --- felix/trunk/webconsole/src/main/resources/res/ui/bundles.js (added) +++ felix/trunk/webconsole/src/main/resources/res/ui/bundles.js Mon Jun 2 06:52:15 2008 @@ -0,0 +1,230 @@ +/* + * 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. + */ + +function render(/* int */ startlevel, /* Array of Bundle Object */ bundles) +{ + + header(); + + installForm( startlevel ); + + document.write( "<tr class='content'>" ); + document.write( "<td colspan='7' class='content'> </th>" ); + document.write( "</tr>" ); + + tableHeader(); + + if ( !bundles ) + { + document.write( "<tr class='content'>" ); + document.write( "<td class='content' colspan='6'>No Bundles installed currently</td>" ); + document.write( "</tr>" ); + } + else + { + for ( var i = 0; i < bundles.length; i++ ) + { + bundle( bundles[i] ); + } + } + + document.write( "<tr class='content'>" ); + document.write( "<td colspan='7' class='content'> </th>" ); + document.write( "</tr>" ); + + installForm( startlevel ); + + footer(); +} + + +function header() +{ + document.write( "<table class='content' cellpadding='0' cellspacing='0' width='100%'>" ); +} + + +function tableHeader() +{ + document.write( "<tr class='content'>" ); + document.write( "<th class='content'>ID</th>" ); + document.write( "<th class='content' width='100%'>Name</th>" ); + document.write( "<th class='content'>Status</th>" ); + document.write( "<th class='content' colspan='4'>Actions</th>" ); + document.write( "</tr>" ); +} + + +function footer() +{ + document.write( "</table>" ); +} + + +function bundle( /* Bundle */ bundle ) +{ + document.write( "<tr id='bundle" + bundle.bundleId + "'>" ); + document.write( bundleInternal( bundle ) ); + document.write( "</tr>" ); + document.write( "<tr id='bundle" + bundle.bundleId + "_details'>" ); + if (bundle.props) + { + document.write( bundleDetails( bundle.props ) ); + } + document.write( "</tr>" ); +} + + +/* String */ function bundleInternal( /* Bundle */ bundle ) +{ + var theBundle = "<td class='content right'>" + bundle.bundleId + "</td>"; + theBundle += "<td class='content'><a href='javascript:showDetails(" + bundle.bundleId + ")'>" + bundle.name + "</a></td>"; + theBundle += "<td class='content center'>" + bundle.state + "</td>"; + + // no buttons for system bundle + if ( bundle.bundleId == 0 ) + { + theBundle += "<td class='content' colspan='4'> </td>"; + } + else + { + theBundle += actionForm( bundle.hasStart, bundle.bundleId, "start", "Start" ); + theBundle += actionForm( bundle.hasStop, bundle.bundleId, "stop", "Stop" ); + theBundle += actionForm( bundle.hasUpdate, bundle.bundleId, "update", "Update" ); + theBundle += actionForm( bundle.hasUninstall, bundle.bundleId, "uninstall", "Uninstall" ); + } + + return theBundle; +} + + +/* String */ function actionForm( /* boolean */ enabled, /* long */ bundleId, /* String */ action, /* String */ actionLabel ) +{ + var theButton = "<td class='content' align='right'>"; + theButton += "<input class='submit' type='button' value='" + actionLabel + "'" + ( enabled ? "" : "disabled" ) + " onClick='changeBundle(" + bundleId + ", \"" + action + "\");' />"; + theButton += "</td>"; + return theButton; +} + + +function installForm( /* int */ startLevel ) +{ + document.write( "<form method='post' enctype='multipart/form-data'>" ); + document.write( "<tr class='content'>" ); + document.write( "<td class='content'> </td>" ); + document.write( "<td class='content'>" ); + document.write( "<input type='hidden' name='action' value='install' />" ); + document.write( "<input class='input' type='file' name='bundlefile'>" ); + document.write( " - Start <input class='checkradio' type='checkbox' name='bundlestart' value='start'>" ); + document.write( " - Start Level <input class='input' type='input' name='bundlestartelevel' value='" + startLevel + "' width='4'>" ); + document.write( "</td>" ); + document.write( "<td class='content' align='right' colspan='5' noWrap>" ); + document.write( "<input class='submit' style='width:auto' type='submit' value='Install or Update'>" ); + document.write( " " ); + document.write( "<input class='submit' style='width:auto' type='submit' value='Refresh Packages' onClick='this.form.action.value=\"refreshPackages\"; return true;'>" ); + document.write( "</td>" ); + document.write( "</tr>" ); + document.write( "</form>" ); +} + + +function changeBundle(/* long */ bundleId, /* String */ action) +{ + var parm = "bundles/" + bundleId + "?action=" + action; + sendRequest('POST', parm, bundleChanged); +} + + +function bundleChanged(obj) +{ + var bundleId = obj.bundleId; + if (obj.state) + { + // has status, so draw the line + var span = document.getElementById('bundle' + bundleId); + if (span) + { + span.innerHTML = bundleInternal( obj ); + } + + if (obj.props) + { + var span = document.getElementById('bundle' + bundleId + '_details'); + if (span && span.innerHTML) + { + span.innerHTML = bundleDetails( obj.props ); + } + } + + } + else + { + // no status, bundle has been uninstalled + var span = document.getElementById('bundle' + bundleId); + if (span) + { + span.parentNode.removeChild(span); + } + var span = document.getElementById('bundle' + bundleId + '_details'); + if (span) + { + span.parentNode.removeChild(span); + } + } + + // reload --- should do better and only update the bundle + // document.location = document.location; +} + + +function showDetails(bundleId) { + var span = document.getElementById('bundle' + bundleId + '_details'); + if (span) + { + if (span.innerHTML) + { + span.innerHTML = ''; + } + else + { + sendRequest('GET', "bundles/" + bundleId + ".json", displayBundleDetails); + } + } +} + + +function displayBundleDetails(obj) { + var span = document.getElementById('bundle' + obj.bundleId + '_details'); + if (span) + { + span.innerHTML = bundleDetails( obj.props ); + } +} + + +/* String */ function bundleDetails( props ) +{ + var innerHtml = '<td class=\"content\"> </td><td class=\"content\" colspan=\"6\"><table broder=\"0\">'; + for (var i=0; i < props.length; i++) + { + innerHtml += '<tr><td valign=\"top\" noWrap>' + props[i].key + '</td><td valign=\"top\">' + props[i].value + '</td></tr>'; + } + innerHtml += '</table></td>'; + + return innerHtml; +} +
