/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved. * This code is licensed under the GPL 2.0 license, availible at the root * application directory. */ package org.geoserver.rest; import java.util.HashMap; import java.util.Map; import java.util.logging.Logger; import org.geoserver.ows.util.RequestUtils; import org.geoserver.platform.GeoServerExtensions; import org.restlet.Context; import org.restlet.data.MediaType; import org.restlet.data.Request; import org.restlet.data.Response; import org.restlet.data.Status; import org.restlet.resource.Resource; import org.restlet.resource.StringRepresentation; import org.vfny.geoserver.global.GeoServer; /** * Base class that converts back and forth between varied data formats and a Java Map to * simplify the implementation of a RESTful web API. * * @author David Winslow <dwinslow@openplans.org> */ public abstract class MapResource extends Resource { private Map myFormatMap; private DataFormat myRequestFormat; private GeoServer myGeoserver; protected static Logger LOG = org.geotools.util.logging.Logging.getLogger("org.geoserver.community"); public MapResource() { super(); myFormatMap = getSupportedFormats(); myGeoserver = (GeoServer)GeoServerExtensions.bean("geoServer"); } public MapResource(Context context, Request request, Response response) { super(context, request, response); myFormatMap = getSupportedFormats(); myRequestFormat = (DataFormat) myFormatMap.get(request.getAttributes().get("type")); } /** * This method should return a map of format name == DataFormat for the MapResource to use * in translating to and from different output Formats */ public abstract Map getSupportedFormats(); public void handleGet() { try { Object details = getMap(); if (details instanceof Map){ ((Map)details).put("page", getPageDetails()); } String formatName = (String)getRequest().getAttributes().get("type"); myRequestFormat = (DataFormat) myFormatMap.get(formatName); getResponse().setEntity(myRequestFormat.makeRepresentation(details)); if ((myRequestFormat == null) | (details == null)) { LOG.info("Failed MapResource request; format: " + myRequestFormat + "; details: " + details); throw new RestletException(new StringRepresentation( "Could not find requested resource; format=" + formatName + "; resource type is: " + MediaType.TEXT_PLAIN ), Status.CLIENT_ERROR_NOT_FOUND ); } } catch (RestletException re) { getResponse().setEntity(re.getRepresentation()); getResponse().setStatus(re.getStatus()); } } /** * This method must be overridden by subclasses; it will be called to handle the HTTP GET method. * @param details the Map equivalent of the uploaded Representation */ public abstract Object getMap() throws RestletException; /** * Put some metadata about the HTTP location of the resource into a * map so that it can be made available to the DataFormat. * * @return a Map containing page metadata */ public Map getPageDetails() { Map map = new HashMap(); String currentURL = getRequest().getResourceRef().getBaseRef().toString(); currentURL = RequestUtils.proxifiedBaseURL(currentURL, myGeoserver.getProxyBaseUrl()); // LOG.info("Proxy Base URL: " + myGeoserver.getProxyBaseUrl()); String formatName = (String) getRequest().getAttributes().get("type"); if (formatName != null) { currentURL = currentURL.substring(0, currentURL.length() - (formatName.length() + 2)); } if (currentURL.endsWith("/")){ currentURL = currentURL.substring(0, currentURL.length() - 1); } map.put("currentURL", currentURL); return map; } public void handlePut() { try { myRequestFormat = (DataFormat)myFormatMap.get(getRequest().getAttributes().get("type")); Object details = myRequestFormat.readRepresentation(getRequest().getEntity()); if ((myRequestFormat == null) || (details == null)) { throw new RestletException(new StringRepresentation("Could not find requested resource", MediaType.TEXT_PLAIN), Status.CLIENT_ERROR_NOT_FOUND ); } putMap(details); } catch (RestletException re) { getResponse().setEntity(re.getRepresentation()); getResponse().setStatus(re.getStatus()); } } /** * This method should be overridden by subclasses that wish to implement the HTTP PUT method. * @param details the Map equivalent of the uploaded Representation * @throws RestletException if anything goes wrong. The Status and Representation in the RestletException will be sent to the client. */ protected void putMap(Object details) throws RestletException { throw new RestletException("PUT not supported for this resource", Status.CLIENT_ERROR_METHOD_NOT_ALLOWED); } }