/******************************************************************************* * Copyright (c) 2015 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Eclipse Distribution License v1.0 which accompany this distribution. * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * Jan S. Rellermeyer, IBM Research - initial API and implementation *******************************************************************************/ package org.osgi.impl.service.rest; import java.net.URI; import java.net.URISyntaxException; import java.util.HashMap; import java.util.Map; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.osgi.impl.service.rest.resources.BundleHeaderResource; import org.osgi.impl.service.rest.resources.BundleRepresentationsResource; import org.osgi.impl.service.rest.resources.BundleResource; import org.osgi.impl.service.rest.resources.BundleStartLevelResource; import org.osgi.impl.service.rest.resources.BundleStateResource; import org.osgi.impl.service.rest.resources.BundlesResource; import org.osgi.impl.service.rest.resources.ExtensionsResource; import org.osgi.impl.service.rest.resources.FrameworkStartLevelResource; import org.osgi.impl.service.rest.resources.ServiceListResource; import org.osgi.impl.service.rest.resources.ServiceRepresentationsResource; import org.osgi.impl.service.rest.resources.ServiceResource; import org.osgi.service.rest.RestApiExtension; import org.osgi.util.tracker.ServiceTracker; import org.osgi.util.tracker.ServiceTrackerCustomizer; import org.restlet.Application; import org.restlet.Restlet; import org.restlet.resource.ServerResource; import org.restlet.routing.Router; /** * Rest service implementation. Manages the routing of paths to resources, etc. * * @author Jan S. Rellermeyer, IBM Research */ public class RestService extends Application { public static final String BUNDLE_CONTEXT_ATTR = "context"; public static final String TRACKER_ATTR = "tracker"; public static final String SERVICE_ID_KEY = "serviceId"; public static final String FILTER_ID_KEY = "filter"; public static final String BUNDLE_ID_KEY = "bundleId"; private final BundleContext context; private ServiceTracker<RestApiExtension, Class<? extends ServerResource>> tracker; RestService(final BundleContext context) { this.context = context; } @Override public synchronized Restlet createInboundRoot() { final Map<String, Object> attributes = new HashMap<String, Object>(); attributes.put(BUNDLE_CONTEXT_ATTR, context); final Router root = new Router(getContext()); // framework final Router framework = new Router(getContext()); root.attach("/framework", framework); framework.attach("/startlevel", FrameworkStartLevelResource.class); // the registered bundles framework.attach("/bundles", BundlesResource.class); framework.attach("/bundles/representations", BundleRepresentationsResource.class); // a specific bundle framework.attach("/bundle/{" + BUNDLE_ID_KEY + "}", BundleResource.class); framework.attach("/bundle/{" + BUNDLE_ID_KEY + "}/state", BundleStateResource.class); framework.attach("/bundle/{" + BUNDLE_ID_KEY + "}/startlevel", BundleStartLevelResource.class); framework.attach("/bundle/{" + BUNDLE_ID_KEY + "}/header", BundleHeaderResource.class); // available services framework.attach("/services", ServiceListResource.class); framework.attach("/services/representations", ServiceRepresentationsResource.class); // a specific service framework.attach("/service/{" + SERVICE_ID_KEY + "}", ServiceResource.class); // enable the extension mechanism final Router extensions = new Router(getContext()); root.attach("/extensions", extensions); getTunnelService().setExtensionsTunnel(true); tracker = new ServiceTracker<RestApiExtension, Class<? extends ServerResource>>( context, RestApiExtension.class, new ExtensionsTrackerCustomizer(extensions)); tracker.open(); attributes.put(TRACKER_ATTR, tracker); getContext().setAttributes(attributes); extensions.attach("", ExtensionsResource.class); return root; } protected static class ExtensionsTrackerCustomizer implements ServiceTrackerCustomizer<RestApiExtension, Class<? extends ServerResource>> { private final Router router; public ExtensionsTrackerCustomizer(final Router router) { this.router = router; } public Class<? extends ServerResource> addingService( final ServiceReference<RestApiExtension> reference) { final String uri_path = (String) reference .getProperty(RestApiExtension.URI_PATH); @SuppressWarnings("unchecked") final Class<? extends ServerResource> proprietary_extension_unit = (Class<? extends ServerResource>) reference .getProperty("restlet"); // check if the uri is valid. try { final URI uri = new URI("/" + uri_path); router.attach(uri.toString(), proprietary_extension_unit); return proprietary_extension_unit; } catch (URISyntaxException e) { e.printStackTrace(); } return null; } public void modifiedService( final ServiceReference<RestApiExtension> reference, final Class<? extends ServerResource> service) { removedService(reference, service); addingService(reference); } public void removedService( final ServiceReference<RestApiExtension> reference, final Class<? extends ServerResource> service) { router.detach(service); } } }