/* Copyright (c) 2001 - 2009 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.catalog.rest; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.List; import org.geoserver.catalog.Catalog; import org.geoserver.catalog.CatalogBuilder; import org.geoserver.catalog.LayerInfo; import org.geoserver.catalog.StyleInfo; import org.geoserver.platform.GeoServerResourceLoader; import org.geoserver.rest.RestletException; import org.geoserver.rest.format.DataFormat; import org.geoserver.rest.format.MediaTypes; import org.geotools.styling.Style; import org.restlet.Context; import org.restlet.data.MediaType; import org.restlet.data.Request; import org.restlet.data.Response; import org.restlet.data.Status; public class StyleResource extends AbstractCatalogResource { /** * media type for SLD */ public static final MediaType MEDIATYPE_SLD = new MediaType( "application/vnd.ogc.sld+xml" ); static { MediaTypes.registerExtension( "sld", MEDIATYPE_SLD ); } public StyleResource(Context context, Request request, Response response, Catalog catalog) { super(context, request, response, StyleInfo.class, catalog); } @Override protected List<DataFormat> createSupportedFormats(Request request,Response response) { List<DataFormat> formats = super.createSupportedFormats(request,response); formats.add( new SLDFormat() ); return formats; } @Override protected Object handleObjectGet() { String style = getAttribute("style"); LOGGER.fine( "GET style " + style ); StyleInfo sinfo = catalog.getStyleByName( style ); //check the format, if specified as sld, return the sld itself DataFormat format = getFormatGet(); if ( format instanceof SLDFormat ) { try { return sinfo.getStyle(); } catch (IOException e) { throw new RestletException( "", Status.SERVER_ERROR_INTERNAL, e ); } } return sinfo; } @Override public boolean allowPost() { return getAttribute("style") == null; } @Override protected String handleObjectPost(Object object) throws Exception { String layer = getAttribute( "layer" ); if ( object instanceof StyleInfo ) { StyleInfo style = (StyleInfo) object; if ( layer != null ) { StyleInfo existing = catalog.getStyleByName( style.getName() ); if ( existing == null ) { //TODO: add a new style to catalog throw new RestletException( "No such style: " + style.getName(), Status.CLIENT_ERROR_NOT_FOUND ); } LayerInfo l = catalog.getLayerByName( layer ); l.getStyles().add( existing ); //check for default String def = getRequest().getResourceRef().getQueryAsForm().getFirstValue("default"); if ( "true".equals( def ) ) { l.setDefaultStyle( existing ); } catalog.save(l); LOGGER.info( "POST style " + style.getName() + " to layer " + layer); } else { catalog.add( style ); LOGGER.info( "POST style " + style.getName() ); } return style.getName(); } else if ( object instanceof Style ) { Style style = (Style) object; //figure out the name of the new style, first check if specified directly String name = getRequest().getResourceRef().getQueryAsForm().getFirstValue( "name"); if ( name == null ) { //infer name from sld name = style.getName(); } if ( name == null ) { throw new RestletException( "Style must have a name.", Status.CLIENT_ERROR_BAD_REQUEST ); } //ensure that the style does not already exist if ( catalog.getStyleByName( name ) != null ) { throw new RestletException( "Style " + name + " already exists.", Status.CLIENT_ERROR_FORBIDDEN ); } //serialize the style out into the data directory GeoServerResourceLoader loader = catalog.getResourceLoader(); File f; try { f = loader.find( "styles/" + name + ".sld" ); } catch (IOException e) { throw new RestletException( "Error looking up file", Status.SERVER_ERROR_INTERNAL, e ); } if ( f != null ) { String msg = "SLD file " + name + ".sld already exists."; throw new RestletException( msg, Status.CLIENT_ERROR_FORBIDDEN); } //TODO: have the writing out of the style delegate to ResourcePool.writeStyle() try { f = loader.createFile( "styles/" + name + ".sld") ; //serialize the file to the styles directory BufferedOutputStream out = new BufferedOutputStream( new FileOutputStream ( f ) ); SLDFormat format = new SLDFormat(true); format.toRepresentation(style).write(out); out.flush(); out.close(); } catch (IOException e) { throw new RestletException( "Error creating file", Status.SERVER_ERROR_INTERNAL, e ); } //create a style info object StyleInfo sinfo = catalog.getFactory().createStyle(); sinfo.setName( name ); sinfo.setFilename( f.getName() ); catalog.add( sinfo ); LOGGER.info( "POST SLD " + name); return name; } return null; } @Override public boolean allowPut() { return getAttribute("style") != null; } @Override protected void handleObjectPut(Object object) throws Exception { String style = getAttribute("style"); if ( object instanceof StyleInfo ) { StyleInfo s = (StyleInfo) object; StyleInfo original = catalog.getStyleByName( style ); new CatalogBuilder( catalog ).updateStyle( original, s ); catalog.save( original ); } else if ( object instanceof Style ) { /* * Force the .sld file to be overriden and it's Style object cleared from the * ResourcePool cache */ StyleInfo s = catalog.getStyleByName( style ); catalog.getResourcePool().writeStyle( s, (Style) object, true ); /* * make sure to save the StyleInfo so that the Catalog issues the notification events */ catalog.save(s); } LOGGER.info( "PUT style " + style); } @Override public boolean allowDelete() { return getAttribute( "style" ) != null; } @Override protected void handleObjectDelete() throws Exception { String style = getAttribute("style"); StyleInfo s = catalog.getStyleByName(style); //ensure that no layers reference the style List<LayerInfo> layers = catalog.getLayers(s); if ( !layers.isEmpty() ) { throw new RestletException( "Can't delete style referenced by existing layers.", Status.CLIENT_ERROR_FORBIDDEN ); } catalog.remove( s ); //check purge parameter to determine if the underlying file // should be deleted String p = getRequest().getResourceRef().getQueryAsForm().getFirstValue("purge"); boolean purge = (p != null) ? Boolean.parseBoolean(p) : false; catalog.getResourcePool().deleteStyle(s, purge); LOGGER.info( "DELETE style " + style); } }