FELIX-2217 Enhance OBR support to accomodate both the "old" OSGi OBR API and the "new" Apache Felix OBR API
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@926131 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/webconsole/pom.xml b/webconsole/pom.xml
index 64c97d3..d1886d9 100644
--- a/webconsole/pom.xml
+++ b/webconsole/pom.xml
@@ -92,18 +92,18 @@
org.osgi.service.http,
org.apache.felix.scr;
org.apache.felix.shell;
- org.apache.felix.bundlerepository;
org.osgi.service.*;resolution:=optional,
javax.portlet;resolution:=optional,
javax.servlet.*;version=2.4,
*
</Import-Package>
+ <DynamicImport-Package>
+ org.apache.felix.bundlerepository,
+ org.osgi.service.obr
+ </DynamicImport-Package>
<Embed-Dependency>
<!-- Import/Export-Package parsing -->
- org.apache.felix.bundlerepository;
- inline=org/apache/felix/bundlerepository/impl/R4*.class|
- org/apache/felix/bundlerepository/impl/Util.class|
- org/apache/felix/bundlerepository/impl/VersionRange.class,
+ org.apache.felix.utils;inline=org/apache/felix/utils/manifest/**,
<!-- ServiceTracker -->
org.osgi.compendium;
@@ -166,10 +166,7 @@
<_donotcopy>LICENSE.json</_donotcopy>
<!-- <_donotcopy>(LICENSE.json|NOTICE.bare)</_donotcopy> -->
<Embed-Dependency>
- org.apache.felix.bundlerepository;
- inline=org/apache/felix/bundlerepository/impl/R4*.class|
- org/apache/felix/bundlerepository/impl/Util.class|
- org/apache/felix/bundlerepository/impl/VersionRange.class
+ org.apache.felix.utils;inline=org/apache/felix/utils/manifest/**
</Embed-Dependency>
</instructions>
</configuration>
@@ -236,11 +233,26 @@
<!-- Parsing Import/Export-Package headers -->
<dependency>
<groupId>org.apache.felix</groupId>
- <artifactId>org.apache.felix.bundlerepository</artifactId>
- <version>1.5.0-SNAPSHOT</version>
- <scope>compile</scope>
+ <artifactId>org.apache.felix.utils</artifactId>
+ <version>0.1.0-SNAPSHOT</version>
+ <scope>provided</scope>
<optional>true</optional>
</dependency>
-
+
+ <!-- OSGi and Apache Felix OBR API -->
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.osgi.service.obr</artifactId>
+ <version>1.0.2</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.bundlerepository</artifactId>
+ <version>1.5.0-SNAPSHOT</version>
+ <scope>provided</scope>
+ <optional>true</optional>
+ </dependency>
+
</dependencies>
</project>
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/UpdateHelper.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/UpdateHelper.java
index 1b47bd7..bba71e0 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/UpdateHelper.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/UpdateHelper.java
@@ -22,16 +22,16 @@
import java.io.File;
import java.io.InputStream;
-import org.apache.felix.bundlerepository.RepositoryAdmin;
-import org.apache.felix.bundlerepository.Resolver;
-import org.apache.felix.bundlerepository.Resource;
+import org.apache.felix.bundlerepository.Reason;
import org.apache.felix.webconsole.SimpleWebConsolePlugin;
-import org.apache.felix.webconsole.internal.obr.DeployerThread;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
-import org.osgi.framework.InvalidSyntaxException;
import org.osgi.service.log.LogService;
+import org.osgi.service.obr.RepositoryAdmin;
+import org.osgi.service.obr.Requirement;
+import org.osgi.service.obr.Resolver;
+import org.osgi.service.obr.Resource;
class UpdateHelper extends BaseUpdateInstallHelper
@@ -82,8 +82,14 @@
throw new BundleException( "Cannot update bundle: Symbolic Name is required for OBR update" );
}
- // try updating from OBR
- if ( updateFromOBR() )
+ // try updating from Apache Felix OBR
+ if ( updateFromFelixOBR() )
+ {
+ return bundle;
+ }
+
+ // try updating from OSGi OBR
+ if ( updateFromOsgiOBR() )
{
return bundle;
}
@@ -114,12 +120,71 @@
}
- private boolean updateFromOBR() throws InvalidSyntaxException
+ private boolean updateFromFelixOBR()
{
- RepositoryAdmin ra = ( RepositoryAdmin ) getService( RepositoryAdmin.class.getName() );
+ org.apache.felix.bundlerepository.RepositoryAdmin ra = ( org.apache.felix.bundlerepository.RepositoryAdmin ) getService( "org.apache.felix.bundlerepository.RepositoryAdmin" );
if ( ra != null )
{
- getLog().log( LogService.LOG_DEBUG, "Trying to update from OSGi Bundle Repository" );
+ getLog().log( LogService.LOG_DEBUG, "Trying to update from OSGi Bundle Repository (Apache Felix API)" );
+
+ final org.apache.felix.bundlerepository.Resolver resolver = ra.resolver();
+
+ String version = ( String ) bundle.getHeaders().get( Constants.BUNDLE_VERSION );
+ if ( version == null )
+ {
+ version = "0.0.0";
+ }
+ final String filter = "(&(symbolicname=" + bundle.getSymbolicName() + ")(!(version=" + version
+ + "))(version>=" + version + "))";
+ final org.apache.felix.bundlerepository.Requirement req = ra.getHelper().requirement(
+ bundle.getSymbolicName(), filter );
+ final org.apache.felix.bundlerepository.Resource[] resources = ra
+ .discoverResources( new org.apache.felix.bundlerepository.Requirement[]
+ { req } );
+ final org.apache.felix.bundlerepository.Resource resource = selectHighestVersion( resources );
+ if ( resource != null )
+ {
+ resolver.add( resource );
+
+ if ( !resolver.resolve() )
+ {
+ logRequirements( "Cannot updated bundle from OBR due to unsatisfied requirements", resolver
+ .getUnsatisfiedRequirements() );
+ }
+ else
+ {
+ logResource( "Installing Requested Resources", resolver.getAddedResources() );
+ logResource( "Installing Required Resources", resolver.getRequiredResources() );
+ logResource( "Installing Optional Resources", resolver.getOptionalResources() );
+
+ // deploy the resolved bundles and ensure they are started
+ resolver.deploy( org.apache.felix.bundlerepository.Resolver.START );
+ getLog().log( LogService.LOG_INFO, "Bundle updated from OSGi Bundle Repository" );
+
+ return true;
+ }
+ }
+ else
+ {
+ getLog().log( LogService.LOG_INFO,
+ "Nothing to update, OSGi Bundle Repository does not provide more recent version" );
+ }
+ }
+ else
+ {
+ getLog().log( LogService.LOG_DEBUG, "Cannot updated from OSGi Bundle Repository: Service not available" );
+ }
+
+ // fallback to false, nothing done
+ return false;
+ }
+
+ private boolean updateFromOsgiOBR()
+ {
+ RepositoryAdmin ra = ( RepositoryAdmin ) getService( "org.osgi.service.obr.RepositoryAdmin" );
+ if ( ra != null )
+ {
+ getLog().log( LogService.LOG_DEBUG, "Trying to update from OSGi Bundle Repository (OSGi API)" );
final Resolver resolver = ra.resolver();
@@ -139,21 +204,17 @@
if ( !resolver.resolve() )
{
- DeployerThread.logRequirements( getLog(),
- "Cannot updated bundle from OBR due to unsatisfied requirements", resolver
- .getUnsatisfiedRequirements() );
+ logRequirements( "Cannot updated bundle from OBR due to unsatisfied requirements", resolver
+ .getUnsatisfiedRequirements() );
}
else
{
- DeployerThread.logResource( getLog(), "Installing Requested Resources", resolver
- .getAddedResources() );
- DeployerThread.logResource( getLog(), "Installing Required Resources", resolver
- .getRequiredResources() );
- DeployerThread.logResource( getLog(), "Installing Optional Resources", resolver
- .getOptionalResources() );
+ logResource( "Installing Requested Resources", resolver.getAddedResources() );
+ logResource( "Installing Required Resources", resolver.getRequiredResources() );
+ logResource( "Installing Optional Resources", resolver.getOptionalResources() );
// deploy the resolved bundles and ensure they are started
- resolver.deploy( Resolver.START );
+ resolver.deploy( true );
getLog().log( LogService.LOG_INFO, "Bundle updated from OSGi Bundle Repository" );
return true;
@@ -175,6 +236,67 @@
}
+ //---------- Apache Felix OBR API helper
+
+ private org.apache.felix.bundlerepository.Resource selectHighestVersion(
+ final org.apache.felix.bundlerepository.Resource[] candidates )
+ {
+ if ( candidates == null || candidates.length == 0 )
+ {
+ // nothing to do if there are none
+ return null;
+ }
+ else if ( candidates.length == 1 )
+ {
+ // simple choice if there is a single one
+ return candidates[0];
+ }
+
+ // now go on looking for the highest version
+ org.apache.felix.bundlerepository.Resource best = candidates[0];
+ for ( int i = 1; i < candidates.length; i++ )
+ {
+ if ( best.getVersion().compareTo( candidates[i].getVersion() ) < 0 )
+ {
+ best = candidates[i];
+ }
+ }
+ return best;
+ }
+
+
+ private void logResource( String message, org.apache.felix.bundlerepository.Resource[] res )
+ {
+ if ( res != null && res.length > 0 )
+ {
+ getLog().log( LogService.LOG_INFO, message );
+ for ( int i = 0; i < res.length; i++ )
+ {
+ getLog().log( LogService.LOG_INFO,
+ " " + i + ": " + res[i].getSymbolicName() + ", " + res[i].getVersion() );
+ }
+ }
+ }
+
+
+ private void logRequirements( String message, Reason[] reasons )
+ {
+ getLog().log( LogService.LOG_ERROR, message );
+ for ( int i = 0; reasons != null && i < reasons.length; i++ )
+ {
+ String moreInfo = reasons[i].getRequirement().getComment();
+ if ( moreInfo == null )
+ {
+ moreInfo = reasons[i].getRequirement().getFilter().toString();
+ }
+ getLog().log( LogService.LOG_ERROR,
+ " " + i + ": " + reasons[i].getRequirement().getName() + " (" + moreInfo + ")" );
+ }
+ }
+
+
+ //---------- OSGi OBR API helper
+
private Resource selectHighestVersion( final Resource[] candidates )
{
if ( candidates == null || candidates.length == 0 )
@@ -199,4 +321,33 @@
}
return best;
}
+
+
+ private void logResource( String message, Resource[] res )
+ {
+ if ( res != null && res.length > 0 )
+ {
+ getLog().log( LogService.LOG_INFO, message );
+ for ( int i = 0; i < res.length; i++ )
+ {
+ getLog().log( LogService.LOG_INFO,
+ " " + i + ": " + res[i].getSymbolicName() + ", " + res[i].getVersion() );
+ }
+ }
+ }
+
+
+ private void logRequirements( String message, Requirement[] reasons )
+ {
+ getLog().log( LogService.LOG_ERROR, message );
+ for ( int i = 0; reasons != null && i < reasons.length; i++ )
+ {
+ String moreInfo = reasons[i].getComment();
+ if ( moreInfo == null )
+ {
+ moreInfo = reasons[i].getFilter().toString();
+ }
+ getLog().log( LogService.LOG_ERROR, " " + i + ": " + reasons[i].getName() + " (" + moreInfo + ")" );
+ }
+ }
}
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/AbstractBundleRepositoryRenderHelper.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/AbstractBundleRepositoryRenderHelper.java
new file mode 100644
index 0000000..af686cd
--- /dev/null
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/AbstractBundleRepositoryRenderHelper.java
@@ -0,0 +1,74 @@
+/*
+ * 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.obr;
+
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import org.apache.felix.webconsole.AbstractWebConsolePlugin;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.util.tracker.ServiceTracker;
+
+
+abstract class AbstractBundleRepositoryRenderHelper
+{
+
+ protected final AbstractWebConsolePlugin logger;
+
+ private final ServiceTracker repositoryAdmin;
+
+
+ protected AbstractBundleRepositoryRenderHelper( final AbstractWebConsolePlugin logger,
+ final BundleContext bundleContext, final String serviceName )
+ {
+ this.logger = logger;
+ this.repositoryAdmin = new ServiceTracker( bundleContext, serviceName, null );
+ this.repositoryAdmin.open();
+ }
+
+
+ void dispose()
+ {
+ repositoryAdmin.close();
+ }
+
+
+ boolean hasRepositoryAdmin()
+ {
+ return getRepositoryAdmin() != null;
+ }
+
+
+ protected final Object getRepositoryAdmin()
+ {
+ return repositoryAdmin.getService();
+ }
+
+
+ abstract void doDeploy( String[] bundles, boolean start, boolean optional );
+
+
+ abstract void doAction( String action, String urlParam ) throws IOException, ServletException;
+
+
+ abstract String getData( final String filter, final boolean details, final Bundle[] bundles );
+
+}
\ No newline at end of file
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/BundleRepositoryRender.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/BundleRepositoryRender.java
index 324c90b..4206b6d 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/BundleRepositoryRender.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/BundleRepositoryRender.java
@@ -18,28 +18,19 @@
*/
package org.apache.felix.webconsole.internal.obr;
+
import java.io.IOException;
import java.util.Enumeration;
+
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.apache.felix.bundlerepository.Capability;
-import org.apache.felix.bundlerepository.Reason;
-import org.apache.felix.bundlerepository.Requirement;
import org.apache.felix.webconsole.DefaultVariableResolver;
import org.apache.felix.webconsole.SimpleWebConsolePlugin;
import org.apache.felix.webconsole.WebConsoleUtil;
import org.apache.felix.webconsole.internal.OsgiManagerPlugin;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.Constants;
-import org.apache.felix.bundlerepository.Repository;
-import org.apache.felix.bundlerepository.RepositoryAdmin;
-import org.apache.felix.bundlerepository.Resolver;
-import org.apache.felix.bundlerepository.Resource;
-import org.osgi.framework.InvalidSyntaxException;
+
/**
* This class provides a plugin for rendering the available OSGi Bundle Repositories
@@ -49,368 +40,212 @@
{
private static final String LABEL = "obr";
private static final String TITLE = "OSGi Repository";
- private static final String[] CSS = { "/res/ui/obr.css" };
-
- // Define a constant of that name to prevent NoClassDefFoundError in
- // updateFromOBR trying to load the class with RepositoryAdmin.class
- private static final String REPOSITORY_ADMIN_NAME = RepositoryAdmin.class.getName();
+ private static final String[] CSS =
+ { "/res/ui/obr.css" };
// templates
private final String TEMPLATE;
+ private AbstractBundleRepositoryRenderHelper helper;
+
+
/**
*
*/
public BundleRepositoryRender()
{
- super(LABEL, TITLE, CSS);
+ super( LABEL, TITLE, CSS );
// load templates
- TEMPLATE = readTemplateFile("/templates/obr.html");
+ TEMPLATE = readTemplateFile( "/templates/obr.html" );
}
+
+ public void deactivate()
+ {
+ if ( helper != null )
+ {
+ helper.dispose();
+ helper = null;
+ }
+
+ super.deactivate();
+ }
+
+
/**
* @see org.apache.felix.webconsole.AbstractWebConsolePlugin#renderContent(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
protected void renderContent( HttpServletRequest request, HttpServletResponse response ) throws IOException
{
String query = request.getQueryString();
- if (query == null || query.length() == 0)
+ if ( query == null || query.length() == 0 )
{
- response.sendRedirect(LABEL + "?list=a");
+ response.sendRedirect( LABEL + "?list=a" );
return;
}
// prepare variables
- DefaultVariableResolver vars = ((DefaultVariableResolver) WebConsoleUtil.getVariableResolver(request));
- vars.put("__data__", getData(request));
+ DefaultVariableResolver vars = ( ( DefaultVariableResolver ) WebConsoleUtil.getVariableResolver( request ) );
+ vars.put( "__data__", getData( request ) );
- response.getWriter().print(TEMPLATE);
+ response.getWriter().print( TEMPLATE );
}
+
/**
* @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
- protected void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException
+ protected void doPost( HttpServletRequest request, HttpServletResponse response ) throws ServletException,
+ IOException
{
- final RepositoryAdmin admin = getRepositoryAdmin();
-
- if (admin == null)
+ if ( !hasRepositoryAdmin() )
{
- response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
- "RepositoryAdmin service is missing");
+ response.sendError( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "RepositoryAdmin service is missing" );
return;
}
- final String action = request.getParameter("action");
- final String deploy = request.getParameter("deploy");
- final String deploystart = request.getParameter("deploystart");
- final String optional = request.getParameter("optional");
+ final String action = request.getParameter( "action" );
+ final String deploy = request.getParameter( "deploy" );
+ final String deploystart = request.getParameter( "deploystart" );
+ final String optional = request.getParameter( "optional" );
- if (action != null)
+ if ( action != null )
{
- doAction(action, request.getParameter("url"), admin);
- response.getWriter().print(getData(request));
+ doAction( action, request.getParameter( "url" ) );
+ response.getWriter().print( getData( request ) );
return;
}
- if (deploy != null || deploystart != null)
+ if ( deploy != null || deploystart != null )
{
- doDeploy(request.getParameterValues("bundle"), deploystart != null, optional != null, admin);
- doGet(request, response);
+ doDeploy( request.getParameterValues( "bundle" ), deploystart != null, optional != null );
+ doGet( request, response );
return;
}
- super.doPost(request, response);
+ super.doPost( request, response );
}
- private final RepositoryAdmin getRepositoryAdmin()
+
+ AbstractBundleRepositoryRenderHelper getHelper()
{
- try
- {
- return ( RepositoryAdmin ) super.getService( REPOSITORY_ADMIN_NAME );
- }
- catch (Throwable t)
- {
- log("Cannot create RepositoryAdmin service tracker", t);
- return null;
- }
- }
-
- private final String getData(HttpServletRequest request)
- {
- final Bundle[] bundles = getBundleContext().getBundles();
- try
- {
- RepositoryAdmin admin = getRepositoryAdmin();
- Resource[] resources = null;
- boolean details = request.getParameter("details") != null;
- if (admin != null)
- {
- String list = request.getParameter("list");
- String query = request.getParameter("query");
- if (list != null)
- {
- String filter;
- if ("-".equals(list))
- {
- StringBuffer sb = new StringBuffer("(!(|");
- for (int c = 0; c < 26; c++)
- {
- sb.append("(presentationname=").append((char) ('a' + c))
- .append("*)(presentationname=")
- .append((char)('A' + c)).append("*)");
- }
- sb.append("))");
- filter = sb.toString();
- }
- else
- {
- filter = "(|(presentationname=" + list.toLowerCase() + "*)(presentationname=" + list.toUpperCase() + "*))";
- }
- resources = admin.discoverResources(filter);
- }
- else if (query != null)
- {
- if (query.indexOf('=') > 0)
- {
- resources = admin.discoverResources(new Requirement[] { parseRequirement(admin, query) });
- }
- else
- {
- resources = admin.discoverResources("(|(presentationame=*" + query + "*)(symbolicname=*" + query + "*))");
- }
- }
- else
- {
- StringBuffer sb = new StringBuffer("(&");
- for (Enumeration e = request.getParameterNames(); e.hasMoreElements();)
- {
- String k = (String) e.nextElement();
- String v = request.getParameter(k);
- if (v != null && v.length() > 0
- && !"details".equals(k) && !"deploy".equals(k)
- && !"deploystart".equals(k) && !"bundle".equals(k)
- && !"optional".equals(k))
- {
- sb.append("(").append(k).append("=").append(v).append(")");
- }
- }
- sb.append(")");
- resources = admin.discoverResources(sb.toString());
-
- }
- }
- JSONObject json = new JSONObject();
- json.put("status", admin != null);
- if (admin != null)
- {
- final Repository repositories[] = admin.listRepositories();
- for (int i = 0; repositories != null && i < repositories.length; i++)
- {
- json.append("repositories", new JSONObject()
- .put("lastModified", repositories[i].getLastModified())
- .put("name", repositories[i].getName())
- .put("url", repositories[i].getURI()));
- }
- }
- for (int i = 0; resources != null && i < resources.length; i++)
- {
- json.append("resources", toJSON(resources[i], bundles, details));
- }
- return json.toString();
- }
- catch (InvalidSyntaxException e)
- {
- log("Failed to parse filter.", e);
- return "";
- }
- catch (JSONException e)
- {
- log("Failed to serialize repository to JSON object.", e);
- return "";
- }
- }
-
- private Requirement parseRequirement(RepositoryAdmin admin, String req) throws InvalidSyntaxException {
- int p = req.indexOf(':');
- String name;
- String filter;
- if (p > 0) {
- name = req.substring(0, p);
- filter = req.substring(p + 1);
- } else {
- if (req.contains("package")) {
- name = "package";
- } else if (req.contains("service")) {
- name = "service";
- } else {
- name = "bundle";
- }
- filter = req;
- }
- if (!filter.startsWith("(")) {
- filter = "(" + filter + ")";
- }
- return admin.requirement(name, filter);
- }
-
- private final void doAction(String action, String urlParam, RepositoryAdmin admin)
- throws IOException, ServletException
- {
- Repository[] repos = admin.listRepositories();
- Repository repo = getRepository(repos, urlParam);
-
- String uri = repo != null ? repo.getURI() : urlParam;
-
- if ("delete".equals(action))
- {
- if (!admin.removeRepository(uri))
- {
- throw new ServletException("Failed to remove repository with URL " + uri);
- }
- }
- else if ("add".equals(action) || "refresh".equals(action))
+ if ( helper == null )
{
try
{
- admin.addRepository(uri);
+ helper = new FelixBundleRepositoryRenderHelper( this, getBundleContext() );
}
- catch (IOException e)
+ catch ( Throwable felixt )
{
- throw e;
- }
- catch (Exception e)
- {
- throw new ServletException("Failed to " + action + " repository " + uri
- + ": " + e.toString());
- }
+ // ClassNotFoundException, ClassDefNotFoundError
- }
- }
-
- private final void doDeploy(String[] bundles, boolean start, boolean optional, RepositoryAdmin repoAdmin)
- {
- try
- {
- // check whether we have to do something
- if (bundles == null || bundles.length == 0)
- {
- log("No resources to deploy");
- return;
- }
-
- Resolver resolver = repoAdmin.resolver();
-
- // prepare the deployment
- for (int i = 0; i < bundles.length; i++)
- {
- String bundle = bundles[i];
- if (bundle == null || bundle.equals("-"))
+ try
{
- continue;
+ helper = new OsgiBundleRepositoryRenderHelper( this, getBundleContext() );
}
-
- String filter = "(id=" + bundle + ")";
- Resource[] resources = repoAdmin.discoverResources(filter);
- if (resources != null && resources.length > 0)
+ catch ( Throwable osgit )
{
- resolver.add(resources[0]);
+ // ClassNotFoundException, ClassDefNotFoundError
}
}
-
- DeployerThread dt = new DeployerThread( resolver, this, start, optional );
- dt.start();
}
- catch (InvalidSyntaxException e)
+
+ return helper;
+ }
+
+
+ private boolean hasRepositoryAdmin()
+ {
+ AbstractBundleRepositoryRenderHelper helper = getHelper();
+ return helper != null && helper.hasRepositoryAdmin();
+ }
+
+
+ private String getData( final HttpServletRequest request )
+ {
+ AbstractBundleRepositoryRenderHelper helper = getHelper();
+ if ( helper == null || !helper.hasRepositoryAdmin() )
{
- throw new IllegalStateException(e);
+ return "";
+ }
+
+ boolean details = request.getParameter( "details" ) != null;
+
+ final String filter;
+ String list = WebConsoleUtil.urlDecode( request.getParameter( "list" ) );
+ String query = WebConsoleUtil.urlDecode( request.getParameter( "query" ) );
+ if ( list != null )
+ {
+ if ( "-".equals( list ) )
+ {
+ StringBuffer sb = new StringBuffer( "(!(|" );
+ for ( int c = 0; c < 26; c++ )
+ {
+ sb.append( "(presentationname=" ).append( ( char ) ( 'a' + c ) ).append( "*)(presentationname=" )
+ .append( ( char ) ( 'A' + c ) ).append( "*)" );
+ }
+ sb.append( "))" );
+ filter = sb.toString();
+ }
+ else
+ {
+ filter = "(|(presentationname=" + list.toLowerCase() + "*)(presentationname=" + list.toUpperCase()
+ + "*))";
+ }
+ }
+ else if ( query != null )
+ {
+ if ( query.indexOf( '=' ) > 0 )
+ {
+ if (query.startsWith( "(" )) {
+ filter = query;
+ } else {
+ filter = "(" + query + ")";
+ }
+ }
+ else
+ {
+ filter = "(|(presentationame=*" + query + "*)(symbolicname=*" + query + "*))";
+ }
+ }
+ else
+ {
+ StringBuffer sb = new StringBuffer( "(&" );
+ for ( Enumeration e = request.getParameterNames(); e.hasMoreElements(); )
+ {
+ String k = ( String ) e.nextElement();
+ String v = request.getParameter( k );
+ if ( v != null && v.length() > 0 && !"details".equals( k ) && !"deploy".equals( k )
+ && !"deploystart".equals( k ) && !"bundle".equals( k ) && !"optional".equals( k ) )
+ {
+ sb.append( "(" ).append( k ).append( "=" ).append( v ).append( ")" );
+ }
+ }
+ sb.append( ")" );
+ filter = sb.toString();
+ }
+
+ return helper.getData( filter, details, getBundleContext().getBundles() );
+ }
+
+
+ private void doAction( String action, String urlParam ) throws IOException, ServletException
+ {
+ AbstractBundleRepositoryRenderHelper helper = getHelper();
+ if ( helper != null )
+ {
+ helper.doAction( action, urlParam );
}
}
- private final Repository getRepository(Repository[] repos, String repositoryUrl)
+
+ private void doDeploy( String[] bundles, boolean start, boolean optional )
{
- if (repositoryUrl == null || repositoryUrl.length() == 0)
+ AbstractBundleRepositoryRenderHelper helper = getHelper();
+ if ( helper != null )
{
- return null;
+ helper.doDeploy( bundles, start, optional );
}
-
- for (int i = 0; i < repos.length; i++)
- {
- if (repositoryUrl.equals(repos[i].getURI()))
- {
- return repos[i];
- }
- }
-
- return null;
- }
-
- private final JSONObject toJSON(Resource resource, Bundle[] bundles, boolean details)
- throws JSONException
- {
- final String symbolicName = resource.getSymbolicName();
- final String version = resource.getVersion().toString();
- boolean installed = false;
- for (int i = 0; symbolicName != null && !installed && bundles != null
- && i < bundles.length; i++)
- {
- final String ver = (String) bundles[i].getHeaders("").get(
- Constants.BUNDLE_VERSION);
- installed = symbolicName.equals(bundles[i].getSymbolicName())
- && version.equals(ver);
- }
- JSONObject json = new JSONObject(resource.getProperties()) //
- .put("id", resource.getId()) //
- .put("presentationname", resource.getPresentationName()) //
- .put("symbolicname", symbolicName) //
- .put("url", resource.getURI()) //
- .put("version", version) //
- .put("categories", resource.getCategories()) //
- .put("installed", installed);
-
- if (details)
- {
- Capability[] caps = resource.getCapabilities();
- for (int i = 0; caps != null && i < caps.length; i++)
- {
- json.append("capabilities", new JSONObject().
- put("name", caps[i].getName()).
- put("properties", new JSONObject(caps[i].getProperties())));
- }
- Requirement[] reqs = resource.getRequirements();
- for (int i = 0; reqs != null && i < reqs.length; i++)
- {
- json.append("requirements", new JSONObject().
- put("name", reqs[i].getName()).
- put("filter", reqs[i].getFilter()).
- put("optional", reqs[i].isOptional()));
- }
-
- final RepositoryAdmin admin = getRepositoryAdmin();
- Resolver resolver = admin.resolver();
- resolver.add(resource);
- resolver.resolve(Resolver.NO_OPTIONAL_RESOURCES);
- Resource[] required = resolver.getRequiredResources();
- for (int i = 0; required != null && i < required.length; i++)
- {
- json.append("required", toJSON(required[i], bundles, false));
- }
- Resource[] optional = resolver.getOptionalResources();
- for (int i = 0; optional != null && i < optional.length; i++)
- {
- json.append("optional", toJSON(optional[i], bundles, false));
- }
- Reason[] unsatisfied = resolver.getUnsatisfiedRequirements();
- for (int i = 0; unsatisfied != null && i < unsatisfied.length; i++)
- {
- json.append("unsatisfied", new JSONObject().
- put("name", unsatisfied[i].getRequirement().getName()).
- put("filter", unsatisfied[i].getRequirement().getFilter()).
- put("optional", unsatisfied[i].getRequirement().isOptional()));
- }
- }
- return json;
}
}
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/FelixBundleRepositoryRenderHelper.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/FelixBundleRepositoryRenderHelper.java
new file mode 100644
index 0000000..0ba2eeb
--- /dev/null
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/FelixBundleRepositoryRenderHelper.java
@@ -0,0 +1,247 @@
+/*
+ * 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.obr;
+
+
+import java.io.IOException;
+import javax.servlet.ServletException;
+import org.apache.felix.bundlerepository.Capability;
+import org.apache.felix.bundlerepository.Reason;
+import org.apache.felix.bundlerepository.Repository;
+import org.apache.felix.bundlerepository.RepositoryAdmin;
+import org.apache.felix.bundlerepository.Requirement;
+import org.apache.felix.bundlerepository.Resolver;
+import org.apache.felix.bundlerepository.Resource;
+import org.apache.felix.webconsole.AbstractWebConsolePlugin;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+
+
+/**
+ * This class provides a plugin for rendering the available OSGi Bundle Repositories
+ * and the resources they provide.
+ */
+public class FelixBundleRepositoryRenderHelper extends AbstractBundleRepositoryRenderHelper
+{
+
+ public FelixBundleRepositoryRenderHelper( AbstractWebConsolePlugin logger, BundleContext bundleContext )
+ {
+ super( logger, bundleContext, RepositoryAdmin.class.getName() );
+ }
+
+
+ String getData( final String filter, final boolean details, Bundle[] bundles )
+ {
+ RepositoryAdmin admin = ( RepositoryAdmin ) getRepositoryAdmin();
+ if ( admin != null )
+ {
+ try
+ {
+ JSONObject json = new JSONObject();
+ json.put( "status", admin != null );
+ if ( admin != null )
+ {
+ final Repository repositories[] = admin.listRepositories();
+ for ( int i = 0; repositories != null && i < repositories.length; i++ )
+ {
+ json.append( "repositories", new JSONObject().put( "lastModified",
+ repositories[i].getLastModified() ).put( "name", repositories[i].getName() ).put( "url",
+ repositories[i].getURI() ) );
+ }
+ }
+
+ Resource[] resources = admin.discoverResources( filter );
+ for ( int i = 0; resources != null && i < resources.length; i++ )
+ {
+ json.append( "resources", toJSON( resources[i], bundles, details ) );
+ }
+
+ return json.toString();
+ }
+ catch ( InvalidSyntaxException e )
+ {
+ logger.log( "Failed to parse filter.", e );
+ }
+ catch ( JSONException e )
+ {
+ logger.log( "Failed to serialize repository to JSON object.", e );
+ }
+ }
+
+ // fall back to no data
+ return "";
+ }
+
+
+ final void doAction( String action, String urlParam ) throws IOException, ServletException
+ {
+ RepositoryAdmin admin = ( RepositoryAdmin ) getRepositoryAdmin();
+ Repository[] repos = admin.listRepositories();
+ Repository repo = getRepository( repos, urlParam );
+
+ String uri = repo != null ? repo.getURI() : urlParam;
+
+ if ( "delete".equals( action ) )
+ {
+ if ( !admin.removeRepository( uri ) )
+ {
+ throw new ServletException( "Failed to remove repository with URL " + uri );
+ }
+ }
+ else if ( "add".equals( action ) || "refresh".equals( action ) )
+ {
+ try
+ {
+ admin.addRepository( uri );
+ }
+ catch ( IOException e )
+ {
+ throw e;
+ }
+ catch ( Exception e )
+ {
+ throw new ServletException( "Failed to " + action + " repository " + uri + ": " + e.toString() );
+ }
+
+ }
+ }
+
+
+ final void doDeploy( String[] bundles, boolean start, boolean optional )
+ {
+ try
+ {
+ // check whether we have to do something
+ if ( bundles == null || bundles.length == 0 )
+ {
+ logger.log( "No resources to deploy" );
+ return;
+ }
+
+ RepositoryAdmin repoAdmin = ( RepositoryAdmin ) getRepositoryAdmin();
+ Resolver resolver = repoAdmin.resolver();
+
+ // prepare the deployment
+ for ( int i = 0; i < bundles.length; i++ )
+ {
+ String bundle = bundles[i];
+ if ( bundle == null || bundle.equals( "-" ) )
+ {
+ continue;
+ }
+
+ String filter = "(id=" + bundle + ")";
+ Resource[] resources = repoAdmin.discoverResources( filter );
+ if ( resources != null && resources.length > 0 )
+ {
+ resolver.add( resources[0] );
+ }
+ }
+
+ FelixDeployer.deploy( resolver, logger, start, optional );
+ }
+ catch ( InvalidSyntaxException e )
+ {
+ throw new IllegalStateException( e );
+ }
+ }
+
+
+ private final Repository getRepository( Repository[] repos, String repositoryUrl )
+ {
+ if ( repositoryUrl == null || repositoryUrl.length() == 0 )
+ {
+ return null;
+ }
+
+ for ( int i = 0; i < repos.length; i++ )
+ {
+ if ( repositoryUrl.equals( repos[i].getURI() ) )
+ {
+ return repos[i];
+ }
+ }
+
+ return null;
+ }
+
+
+ private final JSONObject toJSON( Resource resource, Bundle[] bundles, boolean details ) throws JSONException
+ {
+ final String symbolicName = resource.getSymbolicName();
+ final String version = resource.getVersion().toString();
+ boolean installed = false;
+ for ( int i = 0; symbolicName != null && !installed && bundles != null && i < bundles.length; i++ )
+ {
+ final String ver = ( String ) bundles[i].getHeaders( "" ).get( Constants.BUNDLE_VERSION );
+ installed = symbolicName.equals( bundles[i].getSymbolicName() ) && version.equals( ver );
+ }
+ JSONObject json = new JSONObject( resource.getProperties() ) //
+ .put( "id", resource.getId() ) //
+ .put( "presentationname", resource.getPresentationName() ) //
+ .put( "symbolicname", symbolicName ) //
+ .put( "url", resource.getURI() ) //
+ .put( "version", version ) //
+ .put( "categories", resource.getCategories() ) //
+ .put( "installed", installed );
+
+ if ( details )
+ {
+ Capability[] caps = resource.getCapabilities();
+ for ( int i = 0; caps != null && i < caps.length; i++ )
+ {
+ json.append( "capabilities", new JSONObject().put( "name", caps[i].getName() ).put( "properties",
+ new JSONObject( caps[i].getProperties() ) ) );
+ }
+ Requirement[] reqs = resource.getRequirements();
+ for ( int i = 0; reqs != null && i < reqs.length; i++ )
+ {
+ json.append( "requirements", new JSONObject().put( "name", reqs[i].getName() ).put( "filter",
+ reqs[i].getFilter() ).put( "optional", reqs[i].isOptional() ) );
+ }
+
+ final RepositoryAdmin admin = ( RepositoryAdmin ) getRepositoryAdmin();
+ Resolver resolver = admin.resolver();
+ resolver.add( resource );
+ resolver.resolve( Resolver.NO_OPTIONAL_RESOURCES );
+ Resource[] required = resolver.getRequiredResources();
+ for ( int i = 0; required != null && i < required.length; i++ )
+ {
+ json.append( "required", toJSON( required[i], bundles, false ) );
+ }
+ Resource[] optional = resolver.getOptionalResources();
+ for ( int i = 0; optional != null && i < optional.length; i++ )
+ {
+ json.append( "optional", toJSON( optional[i], bundles, false ) );
+ }
+ Reason[] unsatisfied = resolver.getUnsatisfiedRequirements();
+ for ( int i = 0; unsatisfied != null && i < unsatisfied.length; i++ )
+ {
+ json.append( "unsatisfied", new JSONObject().put( "name", unsatisfied[i].getRequirement().getName() )
+ .put( "filter", unsatisfied[i].getRequirement().getFilter() ).put( "optional",
+ unsatisfied[i].getRequirement().isOptional() ) );
+ }
+ }
+ return json;
+ }
+}
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/DeployerThread.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/FelixDeployer.java
similarity index 72%
rename from webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/DeployerThread.java
rename to webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/FelixDeployer.java
index d814bb8..b7c7329 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/DeployerThread.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/FelixDeployer.java
@@ -26,7 +26,7 @@
import org.osgi.service.log.LogService;
-public class DeployerThread extends Thread
+class FelixDeployer implements Runnable
{
private final Resolver obrResolver;
@@ -37,25 +37,23 @@
private final boolean optionalDependencies;
-
- public DeployerThread( Resolver obrResolver, AbstractWebConsolePlugin logger, boolean startBundles,
- boolean optionalDependencies )
+ static void deploy(Resolver obrResolver, AbstractWebConsolePlugin logger, boolean startBundles,
+ boolean optionalDependencies)
{
- this( obrResolver, logger, startBundles, optionalDependencies, "OBR Bundle Deployer" );
+ final FelixDeployer d = new FelixDeployer(obrResolver, logger, startBundles, optionalDependencies);
+ final Thread t = new Thread(d, "OBR Bundle Deployer (Apache Felix API)");
+ t.start();
}
-
- public DeployerThread( Resolver obrResolver, AbstractWebConsolePlugin logger, boolean startBundles,
- boolean optionalDependencies, String name )
+ private FelixDeployer(Resolver obrResolver, AbstractWebConsolePlugin logger, boolean startBundles,
+ boolean optionalDependencies)
{
- super( name );
this.obrResolver = obrResolver;
this.logger = logger;
this.startBundles = startBundles;
this.optionalDependencies = optionalDependencies;
}
-
public void run()
{
int flags = 0;
@@ -66,15 +64,15 @@
if ( obrResolver.resolve( flags ) )
{
- logResource( logger, "Installing Requested Resources", obrResolver.getAddedResources() );
- logResource( logger, "Installing Required Resources", obrResolver.getRequiredResources() );
- logResource( logger, "Installing Optional Resources", obrResolver.getOptionalResources() );
+ logResource( "Installing Requested Resources", obrResolver.getAddedResources() );
+ logResource( "Installing Required Resources", obrResolver.getRequiredResources() );
+ logResource( "Installing Optional Resources", obrResolver.getOptionalResources() );
obrResolver.deploy( flags );
}
else
{
- logRequirements( logger, "Cannot Install requested bundles due to unsatisfied requirements",
+ logRequirements( "Cannot Install requested bundles due to unsatisfied requirements",
obrResolver.getUnsatisfiedRequirements() );
}
}
@@ -85,7 +83,7 @@
}
- public static void logResource( AbstractWebConsolePlugin logger, String message, Resource[] res )
+ private void logResource( String message, Resource[] res )
{
if ( res != null && res.length > 0 )
{
@@ -99,7 +97,7 @@
}
- public static void logRequirements( AbstractWebConsolePlugin logger, String message, Reason[] reasons )
+ private void logRequirements( String message, Reason[] reasons )
{
logger.log( LogService.LOG_ERROR, message );
for ( int i = 0; reasons != null && i < reasons.length; i++ )
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/OsgiBundleRepositoryRenderHelper.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/OsgiBundleRepositoryRenderHelper.java
new file mode 100644
index 0000000..6dbe992
--- /dev/null
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/OsgiBundleRepositoryRenderHelper.java
@@ -0,0 +1,254 @@
+/*
+ * 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.obr;
+
+
+import java.io.IOException;
+import java.net.URL;
+import javax.servlet.ServletException;
+import org.apache.felix.webconsole.AbstractWebConsolePlugin;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.service.obr.Capability;
+import org.osgi.service.obr.Repository;
+import org.osgi.service.obr.RepositoryAdmin;
+import org.osgi.service.obr.Requirement;
+import org.osgi.service.obr.Resolver;
+import org.osgi.service.obr.Resource;
+
+
+/**
+ * This class provides a plugin for rendering the available OSGi Bundle Repositories
+ * and the resources they provide.
+ */
+public class OsgiBundleRepositoryRenderHelper extends AbstractBundleRepositoryRenderHelper
+{
+ public OsgiBundleRepositoryRenderHelper( final AbstractWebConsolePlugin logger, final BundleContext bundleContext )
+ {
+ super( logger, bundleContext, RepositoryAdmin.class.getName() );
+ }
+
+
+ String getData( final String filter, final boolean details, Bundle[] bundles )
+ {
+ try
+ {
+ RepositoryAdmin admin = ( RepositoryAdmin ) getRepositoryAdmin();
+ if ( admin == null )
+ {
+ return "";
+ }
+
+ JSONObject json = new JSONObject();
+ json.put( "status", admin != null );
+ if ( admin != null )
+ {
+ final Repository repositories[] = admin.listRepositories();
+ for ( int i = 0; repositories != null && i < repositories.length; i++ )
+ {
+ json.append( "repositories", new JSONObject().put( "lastModified",
+ repositories[i].getLastModified() ).put( "name", repositories[i].getName() ).put( "url",
+ repositories[i].getURL() ) );
+ }
+ }
+
+ Resource[] resources = admin.discoverResources( filter );
+ for ( int i = 0; resources != null && i < resources.length; i++ )
+ {
+ json.append( "resources", toJSON( resources[i], bundles, details ) );
+ }
+
+ return json.toString();
+ }
+ catch ( JSONException e )
+ {
+ logger.log( "Failed to serialize repository to JSON object.", e );
+ return "";
+ }
+ }
+
+
+ private String parseRequirement( String req )
+ {
+ int p = req.indexOf( ':' );
+ String filter;
+ if ( p > 0 )
+ {
+ filter = req.substring( p + 1 );
+ }
+ else
+ {
+ filter = req;
+ }
+ if ( !filter.startsWith( "(" ) )
+ {
+ filter = "(" + filter + ")";
+ }
+ return filter;
+ }
+
+
+ void doAction( String action, String urlParam ) throws IOException, ServletException
+ {
+ RepositoryAdmin admin = ( RepositoryAdmin ) getRepositoryAdmin();
+ Repository[] repos = admin.listRepositories();
+ Repository repo = getRepository( repos, urlParam );
+
+ URL uri = repo != null ? repo.getURL() : new URL( urlParam );
+
+ if ( "delete".equals( action ) )
+ {
+ if ( !admin.removeRepository( uri ) )
+ {
+ throw new ServletException( "Failed to remove repository with URL " + uri );
+ }
+ }
+ else if ( "add".equals( action ) || "refresh".equals( action ) )
+ {
+ try
+ {
+ admin.addRepository( uri );
+ }
+ catch ( IOException e )
+ {
+ throw e;
+ }
+ catch ( Exception e )
+ {
+ throw new ServletException( "Failed to " + action + " repository " + uri + ": " + e.toString() );
+ }
+
+ }
+ }
+
+
+ final void doDeploy( String[] bundles, boolean start, boolean optional )
+ {
+ // check whether we have to do something
+ if ( bundles == null || bundles.length == 0 )
+ {
+ logger.log( "No resources to deploy" );
+ return;
+ }
+
+ RepositoryAdmin repoAdmin = ( RepositoryAdmin ) getRepositoryAdmin();
+ Resolver resolver = repoAdmin.resolver();
+
+ // prepare the deployment
+ for ( int i = 0; i < bundles.length; i++ )
+ {
+ String bundle = bundles[i];
+ if ( bundle == null || bundle.equals( "-" ) )
+ {
+ continue;
+ }
+
+ String filter = "(id=" + bundle + ")";
+ Resource[] resources = repoAdmin.discoverResources( filter );
+ if ( resources != null && resources.length > 0 )
+ {
+ resolver.add( resources[0] );
+ }
+ }
+
+ OsgiDeployer.deploy( resolver, logger, start );
+ }
+
+
+ private final Repository getRepository( Repository[] repos, String repositoryUrl )
+ {
+ if ( repositoryUrl == null || repositoryUrl.length() == 0 )
+ {
+ return null;
+ }
+
+ for ( int i = 0; i < repos.length; i++ )
+ {
+ if ( repositoryUrl.equals( repos[i].getURL().toString() ) )
+ {
+ return repos[i];
+ }
+ }
+
+ return null;
+ }
+
+
+ private final JSONObject toJSON( Resource resource, Bundle[] bundles, boolean details ) throws JSONException
+ {
+ final String symbolicName = resource.getSymbolicName();
+ final String version = resource.getVersion().toString();
+ boolean installed = false;
+ for ( int i = 0; symbolicName != null && !installed && bundles != null && i < bundles.length; i++ )
+ {
+ final String ver = ( String ) bundles[i].getHeaders( "" ).get( Constants.BUNDLE_VERSION );
+ installed = symbolicName.equals( bundles[i].getSymbolicName() ) && version.equals( ver );
+ }
+ JSONObject json = new JSONObject( resource.getProperties() ) //
+ .put( "id", resource.getId() ) //
+ .put( "presentationname", resource.getPresentationName() ) //
+ .put( "symbolicname", symbolicName ) //
+ .put( "url", resource.getURL() ) //
+ .put( "version", version ) //
+ .put( "categories", resource.getCategories() ) //
+ .put( "installed", installed );
+
+ if ( details )
+ {
+ Capability[] caps = resource.getCapabilities();
+ for ( int i = 0; caps != null && i < caps.length; i++ )
+ {
+ json.append( "capabilities", new JSONObject().put( "name", caps[i].getName() ).put( "properties",
+ new JSONObject( caps[i].getProperties() ) ) );
+ }
+ Requirement[] reqs = resource.getRequirements();
+ for ( int i = 0; reqs != null && i < reqs.length; i++ )
+ {
+ json.append( "requirements", new JSONObject().put( "name", reqs[i].getName() ).put( "filter",
+ reqs[i].getFilter() ).put( "optional", reqs[i].isOptional() ) );
+ }
+
+ final RepositoryAdmin admin = ( RepositoryAdmin ) getRepositoryAdmin();
+ Resolver resolver = admin.resolver();
+ resolver.add( resource );
+ resolver.resolve(); // (Resolver.NO_OPTIONAL_RESOURCES);
+ Resource[] required = resolver.getRequiredResources();
+ for ( int i = 0; required != null && i < required.length; i++ )
+ {
+ json.append( "required", toJSON( required[i], bundles, false ) );
+ }
+ Resource[] optional = resolver.getOptionalResources();
+ for ( int i = 0; optional != null && i < optional.length; i++ )
+ {
+ json.append( "optional", toJSON( optional[i], bundles, false ) );
+ }
+ Requirement/*Reason*/[] unsatisfied = resolver.getUnsatisfiedRequirements();
+ for ( int i = 0; unsatisfied != null && i < unsatisfied.length; i++ )
+ {
+ json.append( "unsatisfied", new JSONObject().put( "name", unsatisfied[i].getName() ).put( "filter",
+ unsatisfied[i].getFilter() ).put( "optional", unsatisfied[i].isOptional() ) );
+ }
+ }
+ return json;
+ }
+
+}
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/DeployerThread.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/OsgiDeployer.java
similarity index 69%
copy from webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/DeployerThread.java
copy to webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/OsgiDeployer.java
index d814bb8..5533d30 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/DeployerThread.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/obr/OsgiDeployer.java
@@ -19,14 +19,14 @@
package org.apache.felix.webconsole.internal.obr;
-import org.apache.felix.bundlerepository.Reason;
-import org.apache.felix.bundlerepository.Resolver;
-import org.apache.felix.bundlerepository.Resource;
import org.apache.felix.webconsole.AbstractWebConsolePlugin;
import org.osgi.service.log.LogService;
+import org.osgi.service.obr.Requirement;
+import org.osgi.service.obr.Resolver;
+import org.osgi.service.obr.Resource;
-public class DeployerThread extends Thread
+public class OsgiDeployer implements Runnable
{
private final Resolver obrResolver;
@@ -35,42 +35,35 @@
private final boolean startBundles;
- private final boolean optionalDependencies;
-
- public DeployerThread( Resolver obrResolver, AbstractWebConsolePlugin logger, boolean startBundles,
- boolean optionalDependencies )
+ static void deploy( Resolver obrResolver, AbstractWebConsolePlugin logger, boolean startBundles )
{
- this( obrResolver, logger, startBundles, optionalDependencies, "OBR Bundle Deployer" );
+ final OsgiDeployer d = new OsgiDeployer( obrResolver, logger, startBundles );
+ final Thread t = new Thread( d, "OBR Bundle Deployer (OSGi API)" );
+ t.start();
}
- public DeployerThread( Resolver obrResolver, AbstractWebConsolePlugin logger, boolean startBundles,
- boolean optionalDependencies, String name )
+ public OsgiDeployer( Resolver obrResolver, AbstractWebConsolePlugin logger, boolean startBundles )
{
- super( name );
this.obrResolver = obrResolver;
this.logger = logger;
this.startBundles = startBundles;
- this.optionalDependencies = optionalDependencies;
}
public void run()
{
- int flags = 0;
- flags += (startBundles ? Resolver.START : 0);
- flags += (optionalDependencies ? 0 : Resolver.NO_OPTIONAL_RESOURCES);
try
{
- if ( obrResolver.resolve( flags ) )
+ if ( obrResolver.resolve() )
{
logResource( logger, "Installing Requested Resources", obrResolver.getAddedResources() );
logResource( logger, "Installing Required Resources", obrResolver.getRequiredResources() );
logResource( logger, "Installing Optional Resources", obrResolver.getOptionalResources() );
- obrResolver.deploy( flags );
+ obrResolver.deploy( startBundles );
}
else
{
@@ -99,17 +92,17 @@
}
- public static void logRequirements( AbstractWebConsolePlugin logger, String message, Reason[] reasons )
+ public static void logRequirements( AbstractWebConsolePlugin logger, String message, Requirement[] reasons )
{
logger.log( LogService.LOG_ERROR, message );
for ( int i = 0; reasons != null && i < reasons.length; i++ )
{
- String moreInfo = reasons[i].getRequirement().getComment();
+ String moreInfo = reasons[i].getComment();
if ( moreInfo == null )
{
- moreInfo = reasons[i].getRequirement().getFilter().toString();
+ moreInfo = reasons[i].getFilter().toString();
}
- logger.log( LogService.LOG_ERROR, " " + i + ": " + reasons[i].getRequirement().getName() + " (" + moreInfo + ")" );
+ logger.log( LogService.LOG_ERROR, " " + i + ": " + reasons[i].getName() + " (" + moreInfo + ")" );
}
}