/* 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.util.List; import java.util.Map; import org.geoserver.catalog.CascadeDeleteVisitor; import org.geoserver.catalog.Catalog; import org.geoserver.catalog.CatalogBuilder; import org.geoserver.catalog.CoverageStoreInfo; import org.geoserver.catalog.DataStoreInfo; import org.geoserver.catalog.NamespaceInfo; import org.geoserver.catalog.StoreInfo; import org.geoserver.catalog.WMSStoreInfo; import org.geoserver.catalog.WorkspaceInfo; import org.geoserver.config.util.XStreamPersister; import org.geoserver.rest.PageInfo; import org.geoserver.rest.RestletException; import org.geoserver.rest.format.DataFormat; import org.restlet.Context; import org.restlet.data.Request; import org.restlet.data.Response; import org.restlet.data.Status; import org.restlet.resource.Resource; import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; import freemarker.ext.beans.CollectionModel; import freemarker.template.Configuration; import freemarker.template.SimpleHash; public class WorkspaceResource extends AbstractCatalogResource { public WorkspaceResource(Context context, Request request, Response response, Catalog catalog) { super(context, request, response, WorkspaceInfo.class, catalog); } @Override protected DataFormat createHTMLFormat(Request request, Response response) { return new WorkspaceHTMLFormat(request,response,this,catalog); } @Override protected void configurePersister(XStreamPersister persister, DataFormat format) { persister.setCallback( new XStreamPersister.Callback() { @Override protected void postEncodeWorkspace(WorkspaceInfo ws, HierarchicalStreamWriter writer, MarshallingContext context) { PageInfo pg = getPageInfo(); //add a link to the stores writer.startNode( "dataStores"); encodeCollectionLink("datastores", writer); writer.endNode(); writer.startNode( "coverageStores"); encodeCollectionLink("coveragestores", writer); writer.endNode(); writer.startNode( "wmsStores"); encodeCollectionLink("wmsstores", writer); writer.endNode(); } }); } @Override public boolean allowGet() { return getAttribute( "workspace" ) != null; } @Override protected Object handleObjectGet() { String ws = getAttribute( "workspace" ); LOGGER.fine( "GET workspace " + ws); return catalog.getWorkspaceByName( ws ); } @Override public boolean allowPost() { return getAttribute( "workspace") == null; } @Override protected String handleObjectPost(Object object) throws Exception { WorkspaceInfo workspace = (WorkspaceInfo) object; catalog.add( workspace ); //create a namespace corresponding to the workspace if one does not // already exist NamespaceInfo namespace = catalog.getNamespaceByPrefix( workspace.getName() ); if ( namespace == null ) { LOGGER.fine( "Automatically creating namespace for workspace " + workspace.getName() ); namespace = catalog.getFactory().createNamespace(); namespace.setPrefix( workspace.getName() ); namespace.setURI( "http://" + workspace.getName() ); catalog.add( namespace ); } LOGGER.info( "POST workspace " + workspace.getName() ); return workspace.getName(); } @Override public boolean allowPut() { return getAttribute( "workspace") != null; } @Override protected void handleObjectPut(Object object) throws Exception { WorkspaceInfo workspace = (WorkspaceInfo) object; String ws = getAttribute("workspace"); if ( "default".equals( ws ) ) { catalog.setDefaultWorkspace( workspace ); } else { WorkspaceInfo original = catalog.getWorkspaceByName( ws ); //ensure this is not a name change if ( workspace.getName() != null && !workspace.getName().equals( original.getName() ) ) { throw new RestletException( "Can't change the name of a workspace.", Status.CLIENT_ERROR_FORBIDDEN ); } new CatalogBuilder(catalog).updateWorkspace( original, workspace ); catalog.save( original ); } LOGGER.info( "PUT workspace " + ws ); } @Override public boolean allowDelete() { return getAttribute( "workspace" ) != null && !"default".equals( getAttribute("workspace")); } @Override protected void handleObjectDelete() throws Exception { String workspace = getAttribute("workspace"); boolean recurse = getQueryStringValue("recurse", Boolean.class, false); WorkspaceInfo ws = catalog.getWorkspaceByName( workspace ); if (!recurse) { if ( !catalog.getStoresByWorkspace(ws, StoreInfo.class).isEmpty() ) { throw new RestletException( "Workspace not empty", Status.CLIENT_ERROR_FORBIDDEN ); } //check for "linked" workspace NamespaceInfo ns = catalog.getNamespaceByPrefix( ws.getName() ); if ( ns != null ) { if ( !catalog.getFeatureTypesByNamespace( ns ).isEmpty() ) { throw new RestletException( "Namespace for workspace not empty.", Status.CLIENT_ERROR_FORBIDDEN ); } catalog.remove( ns ); } catalog.remove( ws ); } else { //recursive delete new CascadeDeleteVisitor(catalog).visit(ws); } LOGGER.info( "DELETE workspace " + ws ); } static class WorkspaceHTMLFormat extends CatalogFreemarkerHTMLFormat { Catalog catalog; public WorkspaceHTMLFormat(Request request, Response response, Resource resource, Catalog catalog ) { super(WorkspaceInfo.class, request, response, resource); this.catalog = catalog; } @Override protected Configuration createConfiguration(Object data, Class clazz) { Configuration cfg = super.createConfiguration(data, clazz); cfg.setObjectWrapper(new ObjectToMapWrapper<WorkspaceInfo>(WorkspaceInfo.class) { @Override protected void wrapInternal(Map properties, SimpleHash model, WorkspaceInfo object) { List<DataStoreInfo> dataStores = catalog.getStoresByWorkspace(object, DataStoreInfo.class); properties.put( "dataStores", new CollectionModel( dataStores, new ObjectToMapWrapper(DataStoreInfo.class) ) ); List<CoverageStoreInfo> coverageStores = catalog.getStoresByWorkspace(object, CoverageStoreInfo.class); properties.put( "coverageStores", new CollectionModel( coverageStores, new ObjectToMapWrapper(CoverageStoreInfo.class) ) ); List<WMSStoreInfo> wmsStores = catalog.getStoresByWorkspace(object, WMSStoreInfo.class); properties.put( "wmsStores", new CollectionModel( wmsStores, new ObjectToMapWrapper(WMSStoreInfo.class) ) ); properties.put( "isDefault", object.equals( catalog.getDefaultWorkspace() ) ); } }); return cfg; } }; }