package org.geoserver.geosearch;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.NoSuchElementException;
import java.util.logging.Logger;
import java.util.logging.Level;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.FeatureTypeInfo;
import org.geoserver.catalog.NamespaceInfo;
import org.geoserver.config.GeoServer;
import org.geoserver.ows.util.KvpMap;
import org.geoserver.ows.util.KvpUtils;
import org.geoserver.rest.util.RESTUtils;
import org.geoserver.rest.RestletException;
import org.geoserver.wms.WMS;
import org.geoserver.wms.WMSInfo;
import org.geoserver.wms.WebMapService;
import org.geoserver.wms.kvp.GetMapKvpRequestReader;
import org.geotools.util.logging.Logging;
import org.restlet.Restlet;
import org.restlet.data.ClientInfo;
import org.restlet.data.MediaType;
import org.restlet.data.Method;
import org.restlet.data.Form;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.data.Status;
import org.restlet.resource.OutputRepresentation;
import org.restlet.resource.StringRepresentation;
import org.vfny.geoserver.wms.requests.GetMapRequest;
import org.vfny.geoserver.wms.responses.GetMapResponse;
public class FeatureRestlet extends Restlet {
private static Logger LOGGER = Logging.getLogger("org.geoserver.geosearch");
private WMSInfo myWMSInfo;
private Catalog catalog;
private GeoServer geoserver;
private WMS wms;
private WebMapService webMapService;
public void setWmsInfo(WMSInfo wms){
myWMSInfo = wms;
}
public WMSInfo getWmsInfo(){
return myWMSInfo;
}
public GeoServer getGeoServer() {
return geoserver;
}
public WMS getWMS() {
return wms;
}
public void setWMS(WMS wms) {
this.wms = wms;
}
public void setGeoServer(GeoServer geoserver) {
this.geoserver = geoserver;
}
public void setCatalog(Catalog catalog) {
this.catalog = catalog;
}
public void setWebMapService(WebMapService webMapService) {
this.webMapService = webMapService;
}
public FeatureRestlet() {
}
public void handle(Request request, Response response){
if (request.getMethod().equals(Method.GET)){
try {
doGet(request, response);
}
catch (Exception e) {
throw new RuntimeException( e );
}
} else {
response.setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
}
}
public void doGet(Request request, Response response) throws Exception{
String layer = (String) request.getAttributes().get("layer");
String namespace = (String) request.getAttributes().get("namespace");
String feature = (String) request.getAttributes().get("feature");
Form form = request.getResourceRef().getQueryAsForm();
String reqRaw = form.getFirstValue("raw");
ClientInfo cliInfo = request.getClientInfo();
String agent = null;
if(cliInfo != null) {
agent = cliInfo.getAgent();
}
boolean wantsRaw = (
agent == null
|| cliInfo.getAgent().contains("Googlebot")
|| (reqRaw != null && Boolean.parseBoolean(reqRaw)) );
// We only show the actual KML placemark to googlebot or users who append ?raw=true
if ( ! wantsRaw ) {
response.redirectSeeOther(feature+".html");
} else {
int startIndex = 0;
int maxFeatures = 100;
String regionateBy = null;
String regionateAttr = null;
try {
startIndex = Integer.valueOf(form.getFirstValue("startindex",
true));
} catch (Exception e) {
}
try {
maxFeatures = Integer.valueOf(form.getFirstValue("maxfeatures",
true));
} catch (Exception e) {
}
regionateBy = form.getFirstValue("regionateBy", true);
// if (regionateBy == null) regionateBy = "sld";
regionateBy = "random";
regionateAttr = form.getFirstValue("regionateAttr", true);
NamespaceInfo ns = catalog.getNamespaceByPrefix(namespace);
if (ns == null) {
throw new RestletException("No such namespace:" + namespace,
Status.CLIENT_ERROR_NOT_FOUND);
}
FeatureTypeInfo featureType = null;
try {
featureType = catalog.getFeatureTypeByName(ns, layer);
} catch (NoSuchElementException e) {
// ignore, handled later
}
if (featureType == null) {
throw new RestletException("No such layer:" + layer,
Status.CLIENT_ERROR_NOT_FOUND);
}
if (!(Boolean)featureType.getMetadata().get("indexingEnabled")) {
throw new RestletException("Layer not indexable: " + layer,
Status.CLIENT_ERROR_FORBIDDEN);
}
// create some kvp and pass through to GetMapKvpreader
KvpMap raw = new KvpMap();
raw.put("layers", namespace + ":" + layer);
raw.put("format", "kml");
raw.put("format_options", "selfLinks:true;relLinks:true;");
// regionateby:" + regionateBy + (regionateAttr != null ? ";regionateAttr:" + regionateAttr : ""));
if (feature != null) {
raw.put("featureid", feature);
} else {
raw.put("startIndex", Integer.toString(startIndex));
raw.put("maxfeatures", Integer.toString(maxFeatures));
}
GetMapKvpRequestReader reader = new GetMapKvpRequestReader(getWMS());
reader.setHttpRequest(RESTUtils.getServletRequest(request));
// parse into request object
raw = KvpUtils.normalize(raw);
KvpMap kvp = new KvpMap(raw);
KvpUtils.parse(kvp);
final GetMapRequest getMapRequest = (GetMapRequest) reader.read(
(GetMapRequest) reader.createRequest(), kvp, raw);
getMapRequest.setBaseUrl(RESTUtils.getBaseURL(request));
// delegate to wms reflector
final GetMapResponse getMapResponse = webMapService
.reflect(getMapRequest);
// wrap response in a reslet output rep
OutputRepresentation output = new OutputRepresentation(
new MediaType("application/vnd.google-earth.kml+xml")) {
public void write(OutputStream outputStream) throws IOException {
try {
getMapResponse.execute(getMapRequest);
getMapResponse.writeTo(outputStream);
} catch (IOException ioe) {
throw ioe;
} catch (Exception e) {
PrintStream printStream = new PrintStream(outputStream);
printStream.println("Unable to index feature due to: "
+ e.getMessage());
LOGGER.log(Level.WARNING, "Failure to index features.",
e);
}
}
};
response.setEntity(output);
}
}
}