/*
* #%L
* server
* %%
* Copyright (C) 2012 - 2015 valdasraps
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/lgpl-3.0.html>.
* #L%
*/
package lt.emasina.resthub.server.app;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URL;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import lt.emasina.resthub.server.exception.ClientErrorException;
import lt.emasina.resthub.util.ResourceInjector;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.restlet.Message;
import org.restlet.Request;
import org.restlet.data.Parameter;
import org.restlet.data.Status;
import org.restlet.resource.ResourceException;
import org.restlet.resource.ServerResource;
import org.restlet.util.Series;
import com.google.inject.Inject;
import lt.emasina.resthub.server.ServerAppConfig;
import org.restlet.data.Header;
/**
* BaseResource class
*
* @author valdo
*/
public abstract class BaseResource extends ServerResource {
@Inject
private static volatile ResourceInjector memberInjector;
@Inject
protected ServerAppConfig cfg;
private final AtomicBoolean injected = new AtomicBoolean(false);
@Override
protected void doInit() throws ResourceException {
if (injected.compareAndSet(false, true)) {
memberInjector.injectMembers(this);
}
}
protected boolean isAttr(String name) {
return getRequest().getAttributes().containsKey(name);
}
protected String getAttr(String name) throws ResourceException {
return getAttr(String.class, name);
}
protected <T> T getAttr(Class<T> clazz, String name) throws ResourceException {
String str = (String) getRequest().getAttributes().get(name);
return convertValue(clazz, str);
}
protected boolean isParam(String name) throws ResourceException {
return getQuery().getNames().contains(name);
}
protected <T> T getParam(Class<T> clazz, String name, T defaultValue) throws ResourceException {
T v = getParam(clazz, name);
return v == null ? defaultValue : v;
}
protected <T> T getParam(Class<T> clazz, String name) throws ResourceException {
String str = (String) getQuery().getFirstValue(name);
return convertValue(clazz, str);
}
protected <T> T getHeaderValue(Class<T> clazz, String name) throws ResourceException {
return getHeaderValue(getRequest(), clazz, name);
}
protected void injectResourceData(Object o) {
memberInjector.injectMembers(o);
}
public URL getReference(Object... pathElement) {
return cfg.getReference(getHostRef(), null, pathElement);
}
public void addHeader(String name, String value) {
BaseResource.addHeader(getResponse(), name, value);
}
/**
* Static fields and methods
*/
private static final String UTF8 = "UTF-8";
private static final SimpleDateFormat[] DATE_FORMATS = {
new SimpleDateFormat("EEE,dd MMM yyyy HH:mm:ss zzz"),
new SimpleDateFormat("EEEEEE,dd-MMM-yy HH:mm:ss zzz"),
new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy"),
new SimpleDateFormat("y-M-d"),
new SimpleDateFormat("y-M-d H:m:s")
};
@SuppressWarnings("unchecked")
public static <T> T getHeaderValue(Request request, Class<T> clazz, String name) throws ResourceException {
Series<Parameter> headers = (Series<Parameter>) request.getAttributes().get("org.restlet.http.headers");
return convertValue(clazz, headers.getValues(name));
}
@SuppressWarnings("unchecked")
public static <T> T convertValue(Class<T> clazz, String str) throws ResourceException {
if (str != null) {
/*
try {
str = URLDecoder.decode(str, UTF8);
} catch (UnsupportedEncodingException ex) {
throw new ClientErrorException(Status.CLIENT_ERROR_BAD_REQUEST, ex);
}
*/
if (clazz.isEnum()) {
Integer i = convertValue(Integer.class, str);
if (i != null) {
T[] values = clazz.getEnumConstants();
if (i >= 0 && i < values.length) {
return values[i];
}
}
} else {
if (clazz.equals(String.class)) {
return (T) str;
}
if (!str.isEmpty()) {
if (Number.class.isAssignableFrom(clazz)) {
str = str.replace(",", "");
}
if (clazz.equals(Integer.class)) {
return (T) Integer.valueOf(str);
}
if (clazz.equals(Long.class)) {
return (T) Long.valueOf(str.replace(",", ""));
}
if (clazz.equals(Float.class)) {
return (T) Float.valueOf(str);
}
if (clazz.equals(Double.class)) {
return (T) Double.valueOf(str);
}
if (clazz.equals(BigDecimal.class)) {
return (T) new BigDecimal(str);
}
if (clazz.equals(BigInteger.class)) {
return (T) new BigInteger(str);
}
if (clazz.equals(Boolean.class)) {
return (T) Boolean.valueOf(str);
}
try {
if (clazz.equals(JSONObject.class)) {
return (T) new JSONObject(str);
}
if (clazz.equals(JSONArray.class)) {
return (T) new JSONArray(str);
}
} catch (JSONException ex) {
throw new ClientErrorException(Status.CLIENT_ERROR_BAD_REQUEST, ex);
}
if (clazz.equals(Date.class) || clazz.equals(Timestamp.class)) {
Date d = null;
ParseException parseEx = null;
for (SimpleDateFormat formatString : DATE_FORMATS) {
try {
d = formatString.parse(str);
} catch (ParseException ex) {
parseEx = ex;
}
}
if (d == null) {
throw new ClientErrorException(Status.CLIENT_ERROR_BAD_REQUEST, parseEx);
}
if (clazz.equals(Timestamp.class)) {
return (T) new Timestamp(d.getTime());
} else {
return (T) d;
}
}
}
}
}
return (T) null;
}
@SuppressWarnings("unchecked")
public static void addHeader(Message message, String name, String value) {
message.getHeaders().add(new Header(name, value));
}
@SuppressWarnings("unchecked")
public static void removeHeader(Message message, String name, String value) {
Set<Header> headersToRemove = new HashSet<>();
for(Header header: message.getHeaders()) {
if (header.getName().equals(name) && header.getValue().equals(value)){
headersToRemove.add(header);
}
}
message.getHeaders().removeAll(headersToRemove);
}
}