/* * 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.plugins.obr.internal; import java.io.IOException; import java.io.StringWriter; import javax.servlet.ServletException; import org.apache.felix.bundlerepository.Capability; import org.apache.felix.bundlerepository.Property; 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.utils.json.JSONWriter; import org.apache.felix.webconsole.AbstractWebConsolePlugin; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.Version; /** * This class provides a plugin for rendering the available OSGi Bundle Repositories * and the resources they provide. */ class FelixBundleRepositoryRenderHelper extends AbstractBundleRepositoryRenderHelper { FelixBundleRepositoryRenderHelper( AbstractWebConsolePlugin logger, BundleContext bundleContext ) { super( logger, bundleContext, RepositoryAdmin.class.getName() ); } @Override String getData( final String filter, final boolean details, Bundle[] bundles ) { RepositoryAdmin admin = ( RepositoryAdmin ) getRepositoryAdmin(); if ( admin != null ) { final StringWriter sw = new StringWriter(); JSONWriter json = new JSONWriter(sw); try { json.object(); json.key( "status" ); //$NON-NLS-1$ json.value(true); json.key( "details" ); //$NON-NLS-1$ json.value(details); final Repository repositories[] = admin.listRepositories(); if ( repositories != null ) { json.key("repositories");//$NON-NLS-1$ json.array(); for ( int i = 0; repositories != null && i < repositories.length; i++ ) { json.object(); json.key( "lastModified"); //$NON-NLS-1$ json.value( repositories[i].getLastModified()); json.key( "name"); //$NON-NLS-1$ json.value(repositories[i].getName() ); json.key( "url"); //$NON-NLS-1$ json.value( repositories[i].getURI() ); json.endObject(); } json.endArray(); } Resource[] resources = admin.discoverResources( filter ); if ( resources != null ) { json.key("resources");//$NON-NLS-1$ json.array(); for ( int i = 0; i < resources.length; i++ ) { toJSON( json, resources[i], bundles, details ); } json.endArray(); } json.endObject(); json.flush(); } catch ( IOException e ) { logger.log( "Failed to serialize repository to JSON object.", e ); } catch ( Exception e ) { logger.log( "Failed to parse filter '" + filter + "'", e ); try { String reason = "filter=" + filter; if ( e.getMessage() != null ) { reason = e.getMessage() + "(" + reason + ")"; } json.key("error"); //$NON-NLS-1$ json.value( reason ); json.endObject(); json.flush(); } catch ( IOException je ) { // ignore } } return sw.toString(); } // fall back to no data return "{}"; //$NON-NLS-1$ } @Override 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 ) ) //$NON-NLS-1$ { if ( !admin.removeRepository( uri ) ) { throw new ServletException( "Failed to remove repository with URL " + uri ); } } else if ( "add".equals( action ) || "refresh".equals( action ) ) //$NON-NLS-1$ //$NON-NLS-2$ { try { admin.addRepository( uri ); } catch ( IOException e ) { throw e; } catch ( Exception e ) { throw new ServletException( "Failed to " + action + " repository " + uri + ": " + e.toString() ); } } } @Override 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( "-" ) ) //$NON-NLS-1$ { 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 void toJSON( JSONWriter writer, Resource resource, Bundle[] bundles, boolean details ) throws IOException { final String symbolicName = resource.getSymbolicName(); final Version version = resource.getVersion(); String installed = ""; for ( int i = 0; symbolicName != null && installed.length() == 0 && bundles != null && i < bundles.length; i++ ) { final Version ver = bundles[i].getVersion(); if ( symbolicName.equals(bundles[i].getSymbolicName())) { installed = ver.toString(); } } writer.object(); writer.key( "id"); //$NON-NLS-1$ writer.value(resource.getId() ); writer.key( "presentationname" ); //$NON-NLS-1$ writer.value(resource.getPresentationName() ); writer.key( "symbolicname" ); //$NON-NLS-1$ writer.value( symbolicName ); writer.key( "url"); //$NON-NLS-1$ writer.value(resource.getURI() ); writer.key( "version" ); //$NON-NLS-1$ writer.value(version ); writer.key( "categories" ); //$NON-NLS-1$ writer.value(resource.getCategories() ); writer.key( "installed" ); //$NON-NLS-1$ writer.value(installed ); if ( details ) { Capability[] caps = resource.getCapabilities(); if ( caps != null ) { writer.key("capabilities"); //$NON-NLS-1$ writer.array(); for ( int i = 0; i < caps.length; i++ ) { writer.object(); writer.key( "name" ); //$NON-NLS-1$ writer.value(caps[i].getName() ); writer.key( "properties" ); //$NON-NLS-1$ toJSON( writer, caps[i].getProperties() ); writer.endObject(); } writer.endArray(); } Requirement[] reqs = resource.getRequirements(); if ( reqs != null ) { writer.key("requirements"); //$NON-NLS-1$ writer.array(); for ( int i = 0; i < reqs.length; i++ ) { writer.object(); writer.key( "name" ); //$NON-NLS-1$ writer.value(reqs[i].getName() ); writer.key( "filter" ); //$NON-NLS-1$ writer.value(reqs[i].getFilter() ); writer.key( "optional" ); //$NON-NLS-1$ writer.value(reqs[i].isOptional() ); writer.endObject(); } writer.endArray(); } final RepositoryAdmin admin = ( RepositoryAdmin ) getRepositoryAdmin(); Resolver resolver = admin.resolver(); resolver.add( resource ); resolver.resolve( Resolver.NO_OPTIONAL_RESOURCES ); Resource[] required = resolver.getRequiredResources(); if ( required != null ) { writer.key("required"); //$NON-NLS-1$ writer.array(); for ( int i = 0; required != null && i < required.length; i++ ) { toJSON( writer, required[i], bundles, false ); } writer.endArray(); } Resource[] optional = resolver.getOptionalResources(); if ( optional != null ) { writer.key("optional"); //$NON-NLS-1$ writer.array(); for ( int i = 0; optional != null && i < optional.length; i++ ) { toJSON( writer, optional[i], bundles, false ); } writer.endArray(); } Reason[] unsatisfied = resolver.getUnsatisfiedRequirements(); if ( unsatisfied != null) { writer.key("unsatisfied"); //$NON-NLS-1$ writer.array(); for ( int i = 0; unsatisfied != null && i < unsatisfied.length; i++ ) { writer.object(); writer.key( "name" ); //$NON-NLS-1$ writer.value(unsatisfied[i].getRequirement().getName() ); writer.key( "filter" ); //$NON-NLS-1$ writer.value(unsatisfied[i].getRequirement().getFilter() ); writer.key( "optional" ); //$NON-NLS-1$ writer.value(unsatisfied[i].getRequirement().isOptional() ); writer.endObject(); } writer.endArray(); } } writer.endObject(); } private void toJSON( final JSONWriter writer, final Property[] props ) throws IOException { writer.object(); for ( int i = 0; props != null && i < props.length; i++ ) { writer.key(props[i].getName()); writer.value(props[i].getValue()); } writer.endObject(); } }