/*******************************************************************************
* 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.client;
import java.io.InputStream;
import java.net.URI;
import java.util.Collection;
import java.util.Map;
import org.json.JSONObject;
import org.osgi.framework.dto.BundleDTO;
import org.osgi.framework.dto.ServiceReferenceDTO;
import org.osgi.framework.startlevel.dto.BundleStartLevelDTO;
import org.osgi.framework.startlevel.dto.FrameworkStartLevelDTO;
import org.osgi.service.rest.client.RestClient;
import org.restlet.data.MediaType;
import org.restlet.data.Method;
import org.restlet.data.Status;
import org.restlet.engine.header.Header;
import org.restlet.ext.json.JsonRepresentation;
import org.restlet.representation.Representation;
import org.restlet.resource.ClientResource;
import org.restlet.resource.ResourceException;
import org.restlet.util.Series;
/**
* Implementation of the (Java) REST client
*
* @author Jan S. Rellermeyer, IBM Research
*/
public class RestClientImpl implements RestClient {
private static final String MT_FRAMEWORK_STARTLEVEL = "application/org.osgi.framework.startlevel";
private static final String MT_BUNDLE = "application/org.osgi.bundle";
private static final String MT_BUNDLES = "application/org.osgi.bundles";
private static final String MT_BUNDLES_REPRESENTATIONS = "application/org.osgi.bundles.representations";
private static final String MT_BUNDLE_STATE = "application/org.osgi.bundle.state";
private static final String MT_BUNDLE_HEADER = "application/org.osgi.bundle.header";
private static final String MT_BUNDLE_STARTLEVEL = "application/org.osgi.bundle.startlevel";
private static final String MT_SERVICE = "application/org.osgi.service";
private static final String MT_SERVICES = "application/org.osgi.services";
private static final String MT_SERVICES_REPRESENTATIONS = "application/org.osgi.services.representations";
private static final String MT_JSON_EXT = "+json";
private static final String MT_XML_EXT = "+xml";
private final MediaType FRAMEWORK_STARTLEVEL;
private final MediaType BUNDLE;
private final MediaType BUNDLES;
private final MediaType BUNDLES_REPRESENTATIONS;
private final MediaType BUNDLE_STATE;
private final MediaType BUNDLE_HEADER;
private final MediaType BUNDLE_STARTLEVEL;
private final MediaType SERVICE;
private final MediaType SERVICES;
private final MediaType SERVICES_REPRESENTATIONS;
private final URI baseUri;
protected RestClientImpl(final URI uri, final boolean useXml) {
this.baseUri = uri.normalize().resolve("/");
final String ext = useXml ? MT_XML_EXT : MT_JSON_EXT;
FRAMEWORK_STARTLEVEL = new MediaType(MT_FRAMEWORK_STARTLEVEL + ext);
BUNDLE = new MediaType(MT_BUNDLE + ext);
BUNDLES = new MediaType(MT_BUNDLES + ext);
BUNDLES_REPRESENTATIONS = new MediaType(MT_BUNDLES_REPRESENTATIONS + ext);
BUNDLE_STATE = new MediaType(MT_BUNDLE_STATE + ext);
BUNDLE_HEADER = new MediaType(MT_BUNDLE_HEADER + ext);
BUNDLE_STARTLEVEL = new MediaType(MT_BUNDLE_STARTLEVEL + ext);
SERVICE = new MediaType(MT_SERVICE + ext);
SERVICES = new MediaType(MT_SERVICES + ext);
SERVICES_REPRESENTATIONS = new MediaType(MT_SERVICES_REPRESENTATIONS + ext);
}
/**
* @see org.osgi.rest.client.RestClient#getFrameworkStartLevel()
*/
public FrameworkStartLevelDTO getFrameworkStartLevel() throws Exception {
final Representation repr = new ClientResource(Method.GET,
baseUri.resolve("framework/startlevel"))
.get(FRAMEWORK_STARTLEVEL);
return DTOReflector.getDTO(FrameworkStartLevelDTO.class, repr);
}
/**
* @see org.osgi.rest.client.RestClient#setFrameworkStartLevel(org.osgi.dto.framework
* .startlevel.FrameworkStartLevelDTO)
*/
public void setFrameworkStartLevel(final FrameworkStartLevelDTO startLevel)
throws Exception {
new ClientResource(Method.PUT, baseUri.resolve("framework/startlevel")).put(
DTOReflector.getJson(FrameworkStartLevelDTO.class, startLevel),
FRAMEWORK_STARTLEVEL);
}
/**
* @see org.osgi.rest.client.RestClient#getBundles()
*/
public Collection<String> getBundlePaths() throws Exception {
final ClientResource res = new ClientResource(Method.GET,
baseUri.resolve("framework/bundles"));
final Representation repr = res.get(BUNDLES);
System.err.println("HAVING MEDIA TYPE " + repr.getMediaType());
return DTOReflector.getStrings(repr);
}
/**
* @see org.osgi.rest.client.RestClient#getBundleRepresentations()
*/
public Collection<BundleDTO> getBundles() throws Exception {
try {
final Representation repr = new ClientResource(Method.GET,
baseUri.resolve("framework/bundles/representations"))
.get(BUNDLES_REPRESENTATIONS);
return DTOReflector.getDTOs(BundleDTO.class, repr);
} catch (final ResourceException e) {
if (Status.CLIENT_ERROR_NOT_FOUND.equals(e.getStatus())) {
return null;
}
throw e;
}
}
/**
* @see org.osgi.rest.client.RestClient#getBundle(long)
*/
public BundleDTO getBundle(final long id) throws Exception {
return getBundle("framework/bundle/" + id);
}
/**
* @see org.osgi.rest.client.RestClient#getBundle(java.lang.String)
*/
public BundleDTO getBundle(final String bundlePath) throws Exception {
try {
final Representation repr = new ClientResource(Method.GET,
baseUri.resolve(bundlePath)).get(BUNDLE);
return DTOReflector.getDTO(BundleDTO.class, repr);
} catch (final ResourceException e) {
if (Status.CLIENT_ERROR_NOT_FOUND.equals(e.getStatus())) {
return null;
}
throw e;
}
}
/**
* @see org.osgi.rest.client.RestClient#getBundleState(long)
*/
public int getBundleState(final long id) throws Exception {
return getBundleState("framework/bundle/" + id);
}
/**
* @see org.osgi.rest.client.RestClient#getBundleState(java.lang.String)
*/
public int getBundleState(final String bundlePath) throws Exception {
final Representation repr = new ClientResource(Method.GET,
baseUri.resolve(bundlePath + "/state")).get(BUNDLE_STATE);
// FIXME: hardcoded to JSON
final JSONObject obj = new JsonRepresentation(repr).getJsonObject();
return obj.getInt("state");
}
/**
* @see org.osgi.rest.client.RestClient#startBundle(long)
*/
public void startBundle(final long id) throws Exception {
startBundle("framework/bundle/" + id, 0);
}
/**
* @see org.osgi.rest.client.RestClient#startBundle(long)
*/
public void startBundle(final long id, final int options) throws Exception {
startBundle("framework/bundle/" + id, options);
}
/**
* @see org.osgi.rest.client.RestClient#startBundle(java.lang.String)
*/
public void startBundle(final String bundlePath) throws Exception {
startBundle(bundlePath, 0);
}
/**
* @see org.osgi.rest.client.RestClient#startBundle(java.lang.String)
*/
public void startBundle(final String bundlePath, final int options)
throws Exception {
// FIXME: hardcoded to JSON
final JSONObject state = new JSONObject();
state.put("state", 32);
state.put("options", options);
new ClientResource(Method.PUT, baseUri.resolve(bundlePath + "/state"))
.put(state, BUNDLE_STATE);
}
/**
* @see org.osgi.rest.client.RestClient#stopBundle(long)
*/
public void stopBundle(final long id) throws Exception {
stopBundle("framework/bundle/" + id, 0);
}
/**
* @see org.osgi.rest.client.RestClient#stopBundle(long)
*/
public void stopBundle(final long id, final int options) throws Exception {
stopBundle("framework/bundle/" + id, options);
}
/**
* @see org.osgi.rest.client.RestClient#stopBundle(java.lang.String)
*/
public void stopBundle(final String bundlePath) throws Exception {
stopBundle(bundlePath, 0);
}
/**
* @see org.osgi.rest.client.RestClient#stopBundle(java.lang.String)
*/
public void stopBundle(final String bundlePath, final int options)
throws Exception {
final JSONObject state = new JSONObject();
state.put("state", 4);
state.put("options", options);
new ClientResource(Method.PUT, baseUri.resolve(bundlePath + "/state"))
.put(state, BUNDLE_STATE);
}
/**
* @see org.osgi.rest.client.RestClient#getBundleHeaders(long)
*/
public Map<String, String> getBundleHeaders(final long id) throws Exception {
return getBundleHeaders("framework/bundle/" + id);
}
/**
* @see org.osgi.rest.client.RestClient#getBundleHeaders(java.lang.String)
*/
public Map<String, String> getBundleHeaders(final String bundlePath)
throws Exception {
final Representation repr = new ClientResource(Method.GET,
baseUri.resolve(bundlePath + "/header"))
.get(BUNDLE_HEADER);
return DTOReflector.getMap(repr);
}
/**
* @see org.osgi.rest.client.RestClient#getBundleStartLevel(long)
*/
public BundleStartLevelDTO getBundleStartLevel(final long id)
throws Exception {
return getBundleStartLevel("framework/bundle/" + id);
}
/**
* @see org.osgi.rest.client.RestClient#getBundleStartLevel(java.lang.String)
*/
public BundleStartLevelDTO getBundleStartLevel(final String bundlePath)
throws Exception {
final Representation repr = new ClientResource(Method.GET,
baseUri.resolve(bundlePath + "/startlevel"))
.get(BUNDLE_STARTLEVEL);
return DTOReflector.getDTO(BundleStartLevelDTO.class, repr);
}
/**
* @see org.osgi.rest.client.RestClient#setBundleStartLevel(long,
* org.osgi.dto.framework.startlevel.BundleStartLevelDTO)
*/
public void setBundleStartLevel(final long id,
final int startLevel) throws Exception {
setBundleStartLevel("framework/bundle/" + id, startLevel);
}
/**
* @see org.osgi.rest.client.RestClient#setBundleStartLevel(java.lang.String,
* org.osgi.dto.framework.startlevel.BundleStartLevelDTO)
*/
public void setBundleStartLevel(final String bundlePath,
final int startLevel) throws Exception {
BundleStartLevelDTO bsl = new BundleStartLevelDTO();
bsl.startLevel = startLevel;
new ClientResource(Method.PUT, baseUri.resolve(bundlePath
+ "/startlevel")).put(
DTOReflector.getJson(BundleStartLevelDTO.class, bsl),
BUNDLE_STARTLEVEL);
}
/**
* @see org.osgi.rest.client.RestClient#installBundle(java.net.URL)
*/
public BundleDTO installBundle(final String url) throws Exception {
final ClientResource res = new ClientResource(Method.POST,
baseUri.resolve("framework/bundles"));
final Representation repr = res.post(url, MediaType.TEXT_PLAIN);
return getBundle(repr.getText());
}
/**
* @see org.osgi.rest.client.RestClient#installBundle(java.io.InputStream)
*/
public BundleDTO installBundle(final String location, final InputStream in)
throws Exception {
final ClientResource res = new ClientResource(Method.POST,
baseUri.resolve("framework/bundles"));
@SuppressWarnings("unchecked")
Series<Header> headers = (Series<Header>) res.getRequestAttributes().get("org.restlet.http.headers");
if (headers == null) {
headers = new Series<Header>(Header.class);
res.getRequestAttributes().put("org.restlet.http.headers", headers);
}
headers.add("Content-Location", location);
/*
* does not work in the current RESTLET version:
* res.getRequest().getAttributes() .put("message.entity.locationRef",
* new Reference(location));
*/
final Representation repr = res.post(in);
return getBundle(repr.getText());
}
/**
* @see org.osgi.rest.client.RestClient#updateBundle(long)
*/
public BundleDTO updateBundle(final long id) throws Exception {
new ClientResource(Method.PUT, baseUri.resolve("framework/bundle/"
+ id)).put("", MediaType.TEXT_PLAIN);
return null; // TODO return a BundleDTO
}
/**
* @see org.osgi.rest.client.RestClient#updateBundle(long, java.net.URL)
*/
public BundleDTO updateBundle(final long id, final String url) throws Exception {
new ClientResource(Method.PUT, baseUri.resolve("framework/bundle/"
+ id)).put(url, MediaType.TEXT_PLAIN);
return null; // TODO return a BundleDTO
}
/**
* @see org.osgi.rest.client.RestClient#updateBundle(long,
* java.io.InputStream)
*/
public BundleDTO updateBundle(final long id, final InputStream in)
throws Exception {
new ClientResource(Method.PUT, baseUri.resolve("framework/bundle/"
+ id)).put(in);
return null; // TODO return a BundleDTO
}
/**
* @see org.osgi.rest.client.RestClient#uninstallBundle(long)
*/
public BundleDTO uninstallBundle(final long id) throws Exception {
return uninstallBundle("framework/bundle/" + id);
}
/**
* @see org.osgi.rest.client.RestClient#uninstallBundle(java.lang.String)
*/
public BundleDTO uninstallBundle(final String bundlePath) throws Exception {
final ClientResource res = new ClientResource(Method.DELETE,
baseUri.resolve(bundlePath));
res.delete();
return null; // TODO return a BundleDTO
}
/**
* @see org.osgi.rest.client.RestClient#getServices()
*/
public Collection<String> getServicePaths() throws Exception {
return getServicePaths(null);
}
/**
* @see org.osgi.rest.client.RestClient#getServices(java.lang.String)
*/
public Collection<String> getServicePaths(final String filter) throws Exception {
final ClientResource res = new ClientResource(Method.GET,
baseUri.resolve("framework/services"));
if (filter != null) {
res.addQueryParameter("filter", filter);
}
final Representation repr = res.get(SERVICES);
return DTOReflector.getStrings(repr);
}
/**
* @see org.osgi.rest.client.RestClient#getServiceRepresentations()
*/
public Collection<ServiceReferenceDTO> getServiceReferences()
throws Exception {
return getServiceReferences(null);
}
/**
* @see org.osgi.rest.client.RestClient#getServiceRepresentations(java.lang.String
* )
*/
public Collection<ServiceReferenceDTO> getServiceReferences(
final String filter) throws Exception {
final ClientResource res = new ClientResource(Method.GET,
baseUri.resolve("framework/services/representations"));
if (filter != null) {
res.addQueryParameter("filter", filter);
}
final Representation repr = res.get(SERVICES_REPRESENTATIONS);
return DTOReflector.getDTOs(ServiceReferenceDTO.class, repr);
}
/**
* @see org.osgi.rest.client.RestClient#getServiceReference(long)
*/
public ServiceReferenceDTO getServiceReference(final long id)
throws Exception {
return getServiceReference("framework/service/" + id);
}
/**
* @see org.osgi.rest.client.RestClient#getServiceReference(java.lang.String)
*/
public ServiceReferenceDTO getServiceReference(final String servicePath)
throws Exception {
final Representation repr = new ClientResource(Method.GET,
baseUri.resolve(servicePath)).get(SERVICE);
return DTOReflector.getDTO(ServiceReferenceDTO.class,
repr);
}
}