package com.sixsq.slipstream.util;
/*
* +=================================================================+
* SlipStream Server (WAR)
* =====
* Copyright (C) 2013 SixSq Sarl (sixsq.com)
* =====
* Licensed 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.
* -=================================================================-
*/
import com.google.gson.*;
import org.restlet.Context;
import org.restlet.Response;
import org.restlet.data.Form;
import org.restlet.data.MediaType;
import org.restlet.data.Parameter;
import org.restlet.engine.header.Header;
import org.restlet.engine.header.HeaderConstants;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.resource.ClientResource;
import org.restlet.resource.ResourceException;
import org.restlet.resource.Resource;
import org.restlet.util.Series;
import java.io.IOException;
import java.lang.reflect.Type;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import java.util.logging.Logger;
public class SscljProxy {
public enum Method {
GET,
PUT,
POST;
}
private static final String SSCLJ_SERVER = "http://localhost:8201";
private static final String ISO_8601_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
private static final Logger logger = Logger.getLogger(SscljProxy.class.getName());
public static Response get(String resource, String username) {
return request(Method.GET, resource, null, username, null, null, null);
}
public static Response get(String resource, String username, Boolean throwException) {
return request(Method.GET, resource, null, username, null, null, throwException);
}
public static Response put(String resource, String username, Object obj) {
return request(Method.PUT, resource, obj, username, null, null, null);
}
public static Response post(String resource, Object obj) {
return request(Method.POST, resource, obj, null, null, null, null);
}
public static Response post(String resource, String username, Object obj) {
return request(Method.POST, resource, obj, username, null, null, null);
}
public static Response post(String resource, MediaType mediaType, Boolean throwException) {
return request(Method.POST, resource, null, null, null, mediaType, throwException);
}
public static Response post(String resource, Form queryParameters, MediaType mediaType, Boolean throwException) {
return request(Method.POST, resource, null, null, queryParameters, mediaType, throwException);
}
private static Response request(Method method, String resource, Object obj, String username,
Iterable<Parameter> queryParameters, MediaType mediaType,
Boolean throwExceptions) {
ClientResource client = null;
Response response = null;
Representation responseEntity = null;
StringRepresentation content = new StringRepresentation("");
logger.fine("Calling SSCLJ via HTTP with: "
+ "method=" + String.valueOf(method)
+ ", resource=" + resource
+ ", object=" + String.valueOf(obj)
+ ", username=" + username
+ ", mediaType=" + String.valueOf(mediaType));
try {
if (mediaType == null) {
mediaType = MediaType.APPLICATION_JSON;
}
if (obj != null) {
content = new StringRepresentation(toJson(obj));
content.setMediaType(mediaType);
}
client = new ClientResource(createContext(), SSCLJ_SERVER + "/" + resource);
client.setRetryOnError(false);
client.setEntityBuffering(true);
if (queryParameters != null) {
client.addQueryParameters(queryParameters);
}
if (username != null) {
Series<Header> headers = getHeaders(client);
headers.add("slipstream-authn-info", username);
}
switch (method) {
case GET:
responseEntity = client.get(mediaType);
break;
case PUT:
responseEntity = client.put(content, mediaType);
break;
case POST:
responseEntity = client.post(content, mediaType);
break;
default:
throw new UnsupportedOperationException("Method " + method.toString() + "not supported");
}
// Hack: to load the response content from the buffer before releasing it.
// Without this hack it will not be available once this function returns.
try {
responseEntity.getText();
} catch (IOException ignored) {}
} catch (ResourceException re) {
String message = "ResourceException: " + re.getMessage();
try {
Response resp = client.getResponse();
message += "\n\twith status: " + resp.getStatus().toString();
message += "\n\twith content: " + resp.getEntityAsText();
} catch (Exception ignored) {}
logger.warning(message);
if (shouldThrow(throwExceptions)) {
throw re;
}
} catch (Exception e) {
logger.warning(e.getMessage());
if (shouldThrow(throwExceptions)) {
throw e;
}
} finally {
releaseResources(client, responseEntity);
logger.fine("SSCLJ HTTP call: resources released");
}
if (client != null) {
response = client.getResponse();
}
return response;
}
private static boolean shouldThrow(Boolean throwExceptions) {
return throwExceptions != null && throwExceptions;
}
private static Context createContext() {
Context context = new Context();
Series<Parameter> parameters = context.getParameters();
parameters.add("socketTimeout", "1000");
parameters.add("idleTimeout", "1000");
parameters.add("idleCheckInterval", "1000");
parameters.add("socketConnectTimeoutMs", "1000");
return context;
}
private static void releaseResources(ClientResource resource, Representation response) {
if (response != null) {
try {
response.exhaust();
} catch (IOException e) {
logger.warning(e.getMessage());
}
response.release();
}
if (resource != null) {
resource.release();
}
}
public static String toJson(Object obj) {
Gson gson = new GsonBuilder()
.registerTypeAdapter(Date.class, new DateTypeAdapter())
.setPrettyPrinting()
.create();
return gson.toJson(obj);
}
@SuppressWarnings("unchecked")
public static Series<Header> getHeaders(Resource resource) {
Series<Header> headers = (Series<Header>)resource.getRequestAttributes().get(HeaderConstants.ATTRIBUTE_HEADERS);
if (headers == null) {
headers = new Series<Header>(Header.class);
resource.getRequestAttributes().put(HeaderConstants.ATTRIBUTE_HEADERS, headers);
}
return headers;
}
// See https://code.google.com/p/google-gson/issues/detail?id=281
public static class DateTypeAdapter implements JsonSerializer<Date>, JsonDeserializer<Date> {
private final DateFormat dateFormat;
private DateTypeAdapter() {
dateFormat = new SimpleDateFormat(ISO_8601_PATTERN, Locale.US);
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
}
public synchronized JsonElement serialize(Date date, Type type,
JsonSerializationContext jsonSerializationContext) {
return new JsonPrimitive(dateFormat.format(date));
}
public synchronized Date deserialize(JsonElement jsonElement, Type type,
JsonDeserializationContext jsonDeserializationContext) {
try {
return dateFormat.parse(jsonElement.getAsString());
} catch (ParseException e) {
throw new JsonParseException(e);
}
}
}
}