package org.geowebcache.diskquota.rest;
import java.io.IOException;
import java.io.StringReader;
import org.geowebcache.diskquota.ConfigLoader;
import org.geowebcache.diskquota.DiskQuotaConfig;
import org.geowebcache.diskquota.DiskQuotaMonitor;
import org.geowebcache.io.GeoWebCacheXStream;
import org.json.JSONException;
import org.json.JSONObject;
import org.restlet.data.MediaType;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.data.Status;
import org.restlet.ext.json.JsonRepresentation;
import org.restlet.resource.Representation;
import org.restlet.resource.Resource;
import org.restlet.resource.StringRepresentation;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.HierarchicalStreamDriver;
import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver;
import com.thoughtworks.xstream.io.json.JsonHierarchicalStreamDriver;
/**
* REST resource mapping the DiskQuota {@link DiskQuotaConfig configuration}.
* <p>
* Allows GET and PUT methods for JSON and XML formats.
* <p>
*
* @author groldan
*
*/
public class DiskQuotaConfigurationResource extends Resource {
private DiskQuotaMonitor monitor;
/**
* Set by {@link DiskQuotaFinder}
*/
public void setMonitor(DiskQuotaMonitor monitor) {
this.monitor = monitor;
}
@Override
public boolean allowGet() {
return true;
}
@Override
public boolean allowPut() {
return true;
}
@Override
public void handleGet() {
final Request request = getRequest();
final Response response = getResponse();
final String formatExtension = (String) request.getAttributes().get("extension");
final DiskQuotaConfig config = monitor.getConfig();
Representation representation;
if ("json".equals(formatExtension)) {
try {
representation = getJsonRepresentation(config);
} catch (JSONException e) {
throw new RuntimeException(e);
}
} else if ("xml".equals(formatExtension)) {
representation = getXmlRepresentation(config);
} else {
response.setStatus(Status.CLIENT_ERROR_BAD_REQUEST,
"Unknown or missing format extension : " + formatExtension);
return;
}
response.setEntity(representation);
response.setStatus(Status.SUCCESS_OK);
}
@Override
public void put(final Representation entity) {
final Request request = getRequest();
final Response response = getResponse();
final String formatExtension = (String) request.getAttributes().get("extension");
DiskQuotaConfig config = monitor.getConfig();
DiskQuotaConfig newConfig = null;
try {
if ("json".equals(formatExtension)) {
newConfig = fromJSON(entity);
applyDiff(config, newConfig);
response.setEntity(getJsonRepresentation(config));
} else if ("xml".equals(formatExtension)) {
newConfig = fromXML(entity);
applyDiff(config, newConfig);
response.setEntity(getXmlRepresentation(config));
} else {
response.setStatus(Status.CLIENT_ERROR_UNSUPPORTED_MEDIA_TYPE);
return;
}
} catch (Exception e) {
response.setStatus(Status.CLIENT_ERROR_BAD_REQUEST, e.getMessage());
response.setEntity(e.getMessage(), MediaType.TEXT_PLAIN);
return;
}
monitor.saveConfig();
response.setStatus(Status.SUCCESS_OK);
}
/**
* Applies the set values in {@code newConfig} (the non null ones) to {@code config}
*
* @param config
* @param newConfig
* @throws IllegalArgumentException
* as per {@link DiskQuotaConfig#setCacheCleanUpFrequency},
* {@link DiskQuotaConfig#setDiskBlockSize},
* {@link DiskQuotaConfig#setMaxConcurrentCleanUps} ,
* {@link DiskQuotaConfig#setCacheCleanUpUnits}
*/
private void applyDiff(DiskQuotaConfig config, DiskQuotaConfig newConfig)
throws IllegalArgumentException {
// apply diff
if (newConfig != null) {
if (null != newConfig.isEnabled()) {
config.setEnabled(newConfig.isEnabled());
}
if (null != newConfig.getCacheCleanUpFrequency()) {
config.setCacheCleanUpFrequency(newConfig.getCacheCleanUpFrequency());
}
if (null != newConfig.getDiskBlockSize()) {
config.setDiskBlockSize(newConfig.getDiskBlockSize());
}
if (null != newConfig.getMaxConcurrentCleanUps()) {
config.setMaxConcurrentCleanUps(newConfig.getMaxConcurrentCleanUps());
}
if (null != newConfig.getCacheCleanUpUnits()) {
config.setCacheCleanUpUnits(newConfig.getCacheCleanUpUnits());
}
if (null != newConfig.getGlobalExpirationPolicyName()) {
config.setGlobalExpirationPolicyName(newConfig.getGlobalExpirationPolicyName());
}
if (null != newConfig.getGlobalQuota()) {
config.setGlobalQuota(newConfig.getGlobalQuota());
}
if (null != newConfig.getLayerQuotas()) {
config.setLayerQuotas(newConfig.getLayerQuotas());
}
}
}
@Override
public Representation getPreferredRepresentation() {
DiskQuotaConfig config = monitor.getConfig();
JsonRepresentation jsonRepresentation;
try {
jsonRepresentation = getJsonRepresentation(config);
} catch (JSONException e) {
throw new RuntimeException(e);
}
return jsonRepresentation;
}
private JsonRepresentation getJsonRepresentation(DiskQuotaConfig config) throws JSONException {
JsonRepresentation rep = null;
XStream xs = ConfigLoader.getConfiguredXStream(new GeoWebCacheXStream(
new JsonHierarchicalStreamDriver()));
JSONObject obj = new JSONObject(xs.toXML(config));
rep = new JsonRepresentation(obj);
return rep;
}
private Representation getXmlRepresentation(DiskQuotaConfig config) {
XStream xStream = ConfigLoader.getConfiguredXStream(new GeoWebCacheXStream());
String xml = xStream.toXML(config);
return new StringRepresentation(xml, MediaType.TEXT_XML);
}
private DiskQuotaConfig fromXML(Representation entity) throws IOException {
final String text = entity.getText();
StringReader reader = new StringReader(text);
XStream xstream = ConfigLoader.getConfiguredXStream(new GeoWebCacheXStream());
DiskQuotaConfig diskQuotaConfig = ConfigLoader.loadConfiguration(reader, xstream);
return diskQuotaConfig;
}
private DiskQuotaConfig fromJSON(Representation entity) throws IOException {
final String text = entity.getText();
HierarchicalStreamDriver driver = new JettisonMappedXmlDriver();
XStream xStream = new GeoWebCacheXStream(driver);
xStream = ConfigLoader.getConfiguredXStream(xStream);
DiskQuotaConfig configuration;
StringReader reader = new StringReader(text);
configuration = ConfigLoader.loadConfiguration(reader, xStream);
return configuration;
}
}