Skip to content

Commit

Permalink
Move SLD package extension in StyleResource. Added docs, unit tests a…
Browse files Browse the repository at this point in the history
…nd code refactor
  • Loading branch information
josegar74 committed Jan 19, 2015
1 parent c3dd923 commit 4af2491
Show file tree
Hide file tree
Showing 7 changed files with 254 additions and 88 deletions.
11 changes: 6 additions & 5 deletions doc/en/user/source/rest/api/styles.rst
Expand Up @@ -28,7 +28,7 @@ Controls all styles.
* - POST * - POST
- Create a new style - Create a new style
- 201 with ``Location`` header - 201 with ``Location`` header
- SLD, XML, JSON - SLD, XML, JSON, ZIP
:ref:`See note below <rest_api_styles_post_put>` :ref:`See note below <rest_api_styles_post_put>`
- -
- :ref:`name <rest_api_styles_name>` :ref:`raw <rest_api_styles_raw>` - :ref:`name <rest_api_styles_name>` :ref:`raw <rest_api_styles_raw>`
Expand All @@ -52,6 +52,7 @@ supported out of the box include:


* SLD 1.0 with a mime type of ``application/vnd.ogc.sld+xml`` * SLD 1.0 with a mime type of ``application/vnd.ogc.sld+xml``
* SLD 1.1 / SE 1.1 with a mime type of ``application/vnd.ogc.se+xml`` * SLD 1.1 / SE 1.1 with a mime type of ``application/vnd.ogc.se+xml``
* SLD package (zip file containing sld and image files used in the style) with a mime type of application/zip


Other extensions (such as :ref:`css <extensions_css>`) add support for Other extensions (such as :ref:`css <extensions_css>`) add support for
additional formats. additional formats.
Expand Down Expand Up @@ -94,7 +95,7 @@ Controls a given style.
* - GET * - GET
- Return style ``s`` - Return style ``s``
- 200 - 200
- SLD, HTML, XML, JSON - SLD, HTML, XML, JSON, ZIP
- HTML - HTML
- :ref:`quietOnNotFound <rest_api_styles_quietOnNotFound>` - :ref:`quietOnNotFound <rest_api_styles_quietOnNotFound>`
* - POST * - POST
Expand All @@ -106,7 +107,7 @@ Controls a given style.
* - PUT * - PUT
- Modify style ``s`` - Modify style ``s``
- 200 - 200
- SLD, XML, JSON, :ref:`See note above <rest_api_styles_post_put>` - SLD, XML, JSON, ZIP :ref:`See note above <rest_api_styles_post_put>`
- -
- :ref:`raw <rest_api_styles_raw>` - :ref:`raw <rest_api_styles_raw>`
* - DELETE * - DELETE
Expand Down Expand Up @@ -171,7 +172,7 @@ Controls all styles in a given workspace.
* - POST * - POST
- Create a new style within workspace ``ws`` - Create a new style within workspace ``ws``
- 201 with ``Location`` header - 201 with ``Location`` header
- SLD, XML, JSON, :ref:`See note above <rest_api_styles_post_put>` - SLD, XML, JSON, ZIP :ref:`See note above <rest_api_styles_post_put>`
- -
- :ref:`name <rest_api_styles_name>` :ref:`raw <rest_api_styles_raw>` - :ref:`name <rest_api_styles_name>` :ref:`raw <rest_api_styles_raw>`
* - PUT * - PUT
Expand Down Expand Up @@ -217,7 +218,7 @@ Controls a particular style in a given workspace.
* - PUT * - PUT
- Modify style ``s`` within workspace ``ws`` - Modify style ``s`` within workspace ``ws``
- 200 - 200
- SLD, XML, JSON - SLD, XML, JSON, ZIP
:ref:`See note above <rest_api_styles_post_put>` :ref:`See note above <rest_api_styles_post_put>`
- -
- :ref:`raw <rest_api_styles_raw>` - :ref:`raw <rest_api_styles_raw>`
Expand Down
55 changes: 55 additions & 0 deletions doc/en/user/source/rest/examples/curl.rst
Expand Up @@ -332,6 +332,61 @@ And finally apply that style to the layer. Note the use of the ``<workspace>`` t
.. todo:: The WMS request above results in an "Internal error featureType: acme:roads does not have a properly configured datastore" Tested on 2.2.2. .. todo:: The WMS request above results in an "Internal error featureType: acme:roads does not have a properly configured datastore" Tested on 2.2.2.




Creating a layer style (SLD package)
------------------------------------

This example will create a new style on the server and populate it the contents of a local SLD file and related images provided in a SLD package. A SLD package is a zip file containing the SLD style and related image files used in the SLD.

The following creates a new style named ``roads_style``.

.. note:: Each code block below contains a single command that may be extended over multiple lines.

.. code-block:: console
curl -u admin:geoserver -XPOST -H "Content-type: application/zip"
--data-binary @roads_style.zip
http://localhost:8080/geoserver/rest/styles
If executed correctly, the response should contain the following::

< HTTP/1.1 201 Created

The SLD itself can be downloaded through a a GET request:

.. code-block:: console
curl -v -u admin:geoserver -XGET
http://localhost:8080/geoserver/rest/styles/roads_style.sld
Changing a layer style (SLD package)
------------------------------------

This example will alter a layer style using a SLD package. A SLD package is a zip file containing the SLD style and related image files used in the SLD.

In the previous example, we created a new style ``roads_style``, we can update the SLD package styling and apply the new changes to the style.

.. note:: Each code block below contains a single command that may be extended over multiple lines.

.. code-block:: console
curl -u admin:geoserver -XPUT -H "Content-type: application/zip"
--data-binary @roads_style.zip
http://localhost:8080/geoserver/rest/workspaces/w1/styles/roads_style.zip
If executed correctly, the response should contain the following::

< HTTP/1.1 200 OK


The SLD itself can be downloaded through a a GET request:

.. code-block:: console
curl -v -u admin:geoserver -XGET
http://localhost:8080/geoserver/rest/styles/roads_style.sld
Adding a PostGIS database Adding a PostGIS database
------------------------- -------------------------


Expand Down
3 changes: 3 additions & 0 deletions src/main/src/main/java/applicationContext.xml
Expand Up @@ -236,6 +236,9 @@


<!-- default style handlers --> <!-- default style handlers -->
<bean id="sldHandler" class="org.geoserver.catalog.SLDHandler"/> <bean id="sldHandler" class="org.geoserver.catalog.SLDHandler"/>
<bean id="sldPackageHandler" class="org.geoserver.catalog.SLDPackageHandler">
<constructor-arg ref="sldHandler"/>
</bean>


<!-- JDBC VirtualTable callback --> <!-- JDBC VirtualTable callback -->
<bean id="virtualTableCallback" class="org.geoserver.catalog.VirtualTableCallback"/> <bean id="virtualTableCallback" class="org.geoserver.catalog.VirtualTableCallback"/>
Expand Down
122 changes: 122 additions & 0 deletions src/main/src/main/java/org/geoserver/catalog/SLDPackageHandler.java
@@ -0,0 +1,122 @@
/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2014 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.catalog;

import com.google.common.io.Files;
import org.apache.commons.io.FileUtils;
import org.geotools.map.StyleLayer;
import org.geotools.styling.*;
import org.geotools.util.Version;
import org.geotools.util.logging.Logging;
import org.xml.sax.EntityResolver;

import java.io.*;
import java.util.List;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
* SLD package style handler.
*
* @author Jose García
*
*/
public class SLDPackageHandler extends StyleHandler {

static Logger LOGGER = Logging.getLogger(SLDPackageHandler.class);

public static final String FORMAT = "zip";
public static final String MIMETYPE = "application/zip";

private SLDHandler sldHandler;

protected SLDPackageHandler(SLDHandler sldHandler) {
super("ZIP", FORMAT);
this.sldHandler = sldHandler;
}

@Override
public String mimeType(Version version) {
return MIMETYPE;
}


@Override
public StyledLayerDescriptor parse(Object input, Version version, ResourceLocator resourceLocator, EntityResolver entityResolver) throws IOException {
File sldFile = null;
try
{
sldFile = unzipSldPackage(input);
return sldHandler.parse(sldFile, version, resourceLocator, entityResolver);
}
finally
{
if (sldFile != null) FileUtils.deleteQuietly(sldFile.getParentFile());
}
}


@Override
public void encode(StyledLayerDescriptor sld, Version version, boolean pretty, OutputStream output) throws IOException {
ZipOutputStream zos = new ZipOutputStream(output);

try {
String sldName = (sld.getName() != null)?sld.getName():"style";
zos.putNextEntry(new ZipEntry(sldName + ".sld"));

OutputStream sldOutputStream = new ByteArrayOutputStream();
sldHandler.encode(sld, version, pretty, sldOutputStream);

zos.write(((ByteArrayOutputStream) sldOutputStream).toByteArray());
zos.closeEntry();
}
finally {
zos.close();
}

}

@Override
public List<Exception> validate(Object input, Version version, EntityResolver entityResolver) throws IOException {
File sldFile = null;
try
{
sldFile = unzipSldPackage(input);
return sldHandler.validate(input, version, entityResolver);
}
finally
{
if (sldFile != null) FileUtils.deleteQuietly(sldFile.getParentFile());
}
}

/**
* Unzips a SLD package to a temporal folder, returning the SLD file path.
*
* @param input
* @return
* @throws IOException
*/
private File unzipSldPackage(Object input) throws IOException {
File myTempDir = Files.createTempDir();

org.geoserver.data.util.IOUtils.decompress((InputStream) input, myTempDir);

File[] files = myTempDir.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.toLowerCase().endsWith(".sld");
}
});

if (files.length != 1) {
throw new IOException("No SLD file");
}

return files[0];
}

}
7 changes: 5 additions & 2 deletions src/rest/src/main/java/org/geoserver/rest/util/RESTUtils.java
Expand Up @@ -583,14 +583,17 @@ public static void remapping(String workspace, String store, StringBuilder itemP




/** /**
* Unzips a ZipInputStream to a directory * Unzips a InputStream to a directory
* *
* @param in * @param in
* @param outputDirectory * @param outputDirectory
* @throws IOException * @throws IOException
*/ */
public static void unzipInputStream(ZipInputStream zin, File outputDirectory) throws IOException { public static void unzipInputStream(InputStream in, File outputDirectory) throws IOException {
ZipInputStream zin = null;

try { try {
zin = new ZipInputStream(in);


ZipEntry entry; ZipEntry entry;
byte[] buffer = new byte[2048]; byte[] buffer = new byte[2048];
Expand Down
Expand Up @@ -10,7 +10,6 @@
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.zip.ZipInputStream;


import com.google.common.io.Files; import com.google.common.io.Files;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
Expand All @@ -27,7 +26,6 @@
import org.geoserver.platform.resource.Resource; import org.geoserver.platform.resource.Resource;
import org.geoserver.rest.RestletException; import org.geoserver.rest.RestletException;
import org.geoserver.rest.format.DataFormat; import org.geoserver.rest.format.DataFormat;
import org.geoserver.rest.util.RESTUtils;
import org.geotools.factory.CommonFactoryFinder; import org.geotools.factory.CommonFactoryFinder;
import org.geotools.styling.SLDParser; import org.geotools.styling.SLDParser;
import org.geotools.styling.Style; import org.geotools.styling.Style;
Expand Down Expand Up @@ -159,43 +157,6 @@ else if (getRequest().getEntity().getMediaType().equals(MediaType.APPLICATION_ZI


serializeSldFileInCatalog(new File(getStylePath(styleInfo)), uploadedFile); serializeSldFileInCatalog(new File(getStylePath(styleInfo)), uploadedFile);


/**
* Following code causes this (replaced by serializeSldFileInCatalog, just streams the file to the proper folder):
*
* java.lang.Error: Failed to encode the xlink location
* at org.geotools.styling.SLDTransformer$SLDTranslator.visit(SLDTransformer.java:658)
* at org.geotools.styling.ExternalGraphicImpl.accept(ExternalGraphicImpl.java:138)
* at org.geotools.styling.SLDTransformer$SLDTranslator.visit(SLDTransformer.java:808)
* at org.geotools.styling.GraphicImpl.accept(GraphicImpl.java:349)
* at org.geotools.styling.SLDTransformer$SLDTranslator.visit(SLDTransformer.java:781)
* at org.geotools.styling.PointSymbolizerImpl.accept(PointSymbolizerImpl.java:93)
* at org.geotools.styling.SLDTransformer$SLDTranslator.visit(SLDTransformer.java:746)
* at org.geotools.styling.RuleImpl.accept(RuleImpl.java:312)
* at org.geotools.styling.SLDTransformer$SLDTranslator.visit(SLDTransformer.java:1085)
* at org.geotools.styling.SLDTransformer$SLDTranslator.visit(SLDTransformer.java:1042)
* at org.geotools.styling.SLDTransformer$SLDTranslator.visit(SLDTransformer.java:866)
* at org.geotools.styling.SLDTransformer$SLDTranslator.visit(SLDTransformer.java:838)
* at org.geotools.styling.StyledLayerDescriptorImpl.accept(StyledLayerDescriptorImpl.java:196)
* at org.geotools.styling.SLDTransformer$SLDTranslator.encode(SLDTransformer.java:1220)
* at org.geotools.styling.SLDTransformer$SLDTranslator.encode(SLDTransformer.java:1229)
* at org.geotools.xml.transform.TransformerBase$XMLReaderSupport.parse(TransformerBase.java:1026)
* at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:677)
* at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:746)
* at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:359)
* at org.geotools.xml.transform.TransformerBase$Task.run(TransformerBase.java:300)
* at org.geotools.xml.transform.TransformerBase.transform(TransformerBase.java:133)
* at org.geotools.xml.transform.TransformerBase.transform(TransformerBase.java:112)
* at org.geoserver.catalog.SLDHandler.encode10(SLDHandler.java:193)
* at org.geoserver.catalog.SLDHandler.encode(SLDHandler.java:182)
* at org.geoserver.catalog.ResourcePool.writeStyle(ResourcePool.java:1799)
*/
/*ResourcePool resourcePool = catalog.getResourcePool();
try {
resourcePool.writeStyle(styleInfo, styleSld);
} catch (IOException e) {
throw new RestletException("Error writing style", Status.SERVER_ERROR_INTERNAL, e);
}*/

catalog.add(styleInfo); catalog.add(styleInfo);


LOGGER.info("POST Style Package: " + name + ", workspace: " + workspace); LOGGER.info("POST Style Package: " + name + ", workspace: " + workspace);
Expand Down Expand Up @@ -351,46 +312,6 @@ else if (getRequest().getEntity().getMediaType().equals(MediaType.APPLICATION_ZI
StyleInfo styleInfo = catalog.getStyleByName( workspace, style ); StyleInfo styleInfo = catalog.getStyleByName( workspace, style );
serializeSldFileInCatalog(new File(getStylePath(styleInfo)), uploadedFile); serializeSldFileInCatalog(new File(getStylePath(styleInfo)), uploadedFile);


/**
* Following code causes this (replaced by serializeSldFileInCatalog, just streams the file to the proper folder):
*
* java.lang.Error: Failed to encode the xlink location
* at org.geotools.styling.SLDTransformer$SLDTranslator.visit(SLDTransformer.java:658)
* at org.geotools.styling.ExternalGraphicImpl.accept(ExternalGraphicImpl.java:138)
* at org.geotools.styling.SLDTransformer$SLDTranslator.visit(SLDTransformer.java:808)
* at org.geotools.styling.GraphicImpl.accept(GraphicImpl.java:349)
* at org.geotools.styling.SLDTransformer$SLDTranslator.visit(SLDTransformer.java:781)
* at org.geotools.styling.PointSymbolizerImpl.accept(PointSymbolizerImpl.java:93)
* at org.geotools.styling.SLDTransformer$SLDTranslator.visit(SLDTransformer.java:746)
* at org.geotools.styling.RuleImpl.accept(RuleImpl.java:312)
* at org.geotools.styling.SLDTransformer$SLDTranslator.visit(SLDTransformer.java:1085)
* at org.geotools.styling.SLDTransformer$SLDTranslator.visit(SLDTransformer.java:1042)
* at org.geotools.styling.SLDTransformer$SLDTranslator.visit(SLDTransformer.java:866)
* at org.geotools.styling.SLDTransformer$SLDTranslator.visit(SLDTransformer.java:838)
* at org.geotools.styling.StyledLayerDescriptorImpl.accept(StyledLayerDescriptorImpl.java:196)
* at org.geotools.styling.SLDTransformer$SLDTranslator.encode(SLDTransformer.java:1220)
* at org.geotools.styling.SLDTransformer$SLDTranslator.encode(SLDTransformer.java:1229)
* at org.geotools.xml.transform.TransformerBase$XMLReaderSupport.parse(TransformerBase.java:1026)
* at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:677)
* at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:746)
* at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:359)
* at org.geotools.xml.transform.TransformerBase$Task.run(TransformerBase.java:300)
* at org.geotools.xml.transform.TransformerBase.transform(TransformerBase.java:133)
* at org.geotools.xml.transform.TransformerBase.transform(TransformerBase.java:112)
* at org.geoserver.catalog.SLDHandler.encode10(SLDHandler.java:193)
* at org.geoserver.catalog.SLDHandler.encode(SLDHandler.java:182)
* at org.geoserver.catalog.ResourcePool.writeStyle(ResourcePool.java:1799)
*/
/* ResourcePool resourcePool = catalog.getResourcePool();
try {
resourcePool.writeStyle(styleInfo, styleSld);
} catch (IOException e) {
throw new RestletException("Error writing style", Status.SERVER_ERROR_INTERNAL, e);
}*/

// With serializeSldFileInCatalog is not required
//catalog.save( styleInfo );

LOGGER.info("PUT Style Package: " + name + ", workspace: " + workspace); LOGGER.info("PUT Style Package: " + name + ", workspace: " + workspace);


} catch (RestletException e) { } catch (RestletException e) {
Expand Down Expand Up @@ -469,7 +390,8 @@ protected void handleObjectDelete() throws Exception {
*/ */
private File unzipSldPackage(InputStream object) throws IOException { private File unzipSldPackage(InputStream object) throws IOException {
File tempDir = Files.createTempDir(); File tempDir = Files.createTempDir();
RESTUtils.unzipInputStream(new ZipInputStream((InputStream) object), tempDir);
org.geoserver.data.util.IOUtils.decompress(object, tempDir);


return tempDir; return tempDir;
} }
Expand Down

0 comments on commit 4af2491

Please sign in to comment.