commit ec1120c240a552ec62ae7d298db58e7807522cc7 Author: ETj Date: Tue May 10 16:05:15 2011 +0200 Initial revision diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..79dd63f --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +## +## This file has been automatically generated with the command line: +## for pom in $(find -name "pom.xml") ; do path=${pom%*pom.xml} ; echo '#' $path ; echo ; echo ${path}target ; echo ; done > .gitignore +## +## - ETj + +nb*.xml +.classpath +.project +.settings +# ./ + +./target +target diff --git a/createGitIgnore b/createGitIgnore new file mode 100755 index 0000000..614a19d --- /dev/null +++ b/createGitIgnore @@ -0,0 +1,26 @@ +OUTFILE=gitignore + +cat >$OUTFILE < .gitignore +## +## - ETj + +nb*.xml +.classpath +.project +.settings +EOF + +for pom in $(find -name "pom.xml") +do + path=${pom%*pom.xml} + echo '#' $path >>$OUTFILE + echo >>$OUTFILE + echo ${path}target >>$OUTFILE + echo >>$OUTFILE +done + +echo New file gitignore has been created. You may now want to replace your original .gitignore file. +echo diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..c166bfb --- /dev/null +++ b/pom.xml @@ -0,0 +1,231 @@ + + + + 4.0.0 + + it.geosolutions + geoserver-manager + 1.1-SNAPSHOT + + jar + + GeoServer 2 Manager - REST based + + GeoServer Manager is a library to interact with GeoServer 2.x. + The scope of this library is to have a simple API, and use as few external + libs as possible. + + + 2007 + + + GeoSolutions + http://www.geosolutions.it + + + + + etj + Emanuele Tajariol + etj@geosolutions.it + GeoSolutions + http://www.geosolutions.it + + architect + developer + + +1 + + + + + + MIT License + http://opensource.org/licenses/mit-license.php + repo + + + + http://code.google.com/p/geoserver-manager/ + + + googlecode + http://code.google.com/p/geoserver-manager/issues/list + + + + + GeoServer Manager User List + geoserver-manager-users@googlegroups.com + http://groups.google.com/group/geoserver-manager-users/topics + + + + + scm:git:https://github.com/geosolutions-it/geoserver-manager.git + + master + https://github.com/geosolutions-it/geoserver-manager + + + + http://maven.geo-solutions.it + + false + geosolutions + ftp://maven.geo-solutions.it/ + + + demo.geosolutions + scp://demo.geosolutions.it/var/www/share/javadoc/gsman + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.0.2 + + 1.5 + 1.5 + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.7 + + + + + + + + + + + true + org.apache.maven.plugins + maven-source-plugin + + true + + + + attach-sources + + jar + + + + + + + + + + + + + + + + org.apache.maven.wagon + wagon-ftp + 1.0-beta-7 + + + + + + + + org.codehaus.mojo + cobertura-maven-plugin + + 2.2 + + + + + + + + commons-io + commons-io + 1.4 + + + + commons-httpclient + commons-httpclient + 3.1 + + + + org.jdom + jdom + 1.1 + + + + log4j + log4j + 1.2.16 + + + + + + + + junit + junit + 4.8.1 + test + + + + org.springframework + spring-core + 2.5.6.SEC02 + test + + + + + diff --git a/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTPublisher.java b/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTPublisher.java new file mode 100644 index 0000000..7367ef8 --- /dev/null +++ b/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTPublisher.java @@ -0,0 +1,704 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2007,2011 GeoSolutions S.A.S. + * http://www.geo-solutions.it + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package it.geosolutions.geoserver.rest; + +import it.geosolutions.geoserver.rest.decoder.RESTCoverageList; +import it.geosolutions.geoserver.rest.decoder.RESTCoverageStore; +import it.geosolutions.geoserver.rest.encoder.GSCoverageEncoder; +import it.geosolutions.geoserver.rest.encoder.GSFeatureTypeEncoder; +import it.geosolutions.geoserver.rest.encoder.GSLayerEncoder; +import it.geosolutions.geoserver.rest.encoder.GSWorkspaceEncoder; + +import java.io.File; +import java.io.FileNotFoundException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLEncoder; + +import org.apache.log4j.Logger; + +/** + * Connect to a GeoServer instance to publish or modify data. + *

+ * There are no modifiable instance fields, so all the calls are thread-safe. + * + * @author ETj (etj at geo-solutions.it) + */ +public class GeoServerRESTPublisher { + + private static final Logger LOGGER = Logger.getLogger(GeoServerRESTPublisher.class); + private final String restURL; + private final String gsuser; + private final String gspass; + + /** + * Creates a GeoServerRESTPublisher for a given GeoServer instance + * with the given auth credentials. + * + * @param restURL the base GeoServer URL (e.g.: http://localhost:8080/geoserver) + * @param username username auth credential + * @param password password auth credential + */ + public GeoServerRESTPublisher(String restURL, String username, String password) { + this.restURL = restURL; + this.gsuser = username; + this.gspass = password; + } + + + //========================================================================== + //=== WORKSPACES + //========================================================================== + + /** + * Create a new Workspace + * + * @param workspace The name of the new workspace. + * + *

+ * This is the equivalent call with cUrl: + *

{@code curl -u admin:geoserver -XPOST \
+     *      -H 'Content-type: text/xml' \
+     *      -d "$WORKSPACE" \
+     *      http://$GSIP:$GSPORT/$SERVLET/rest/workspaces
+     * }
+ */ + public boolean createWorkspace(String workspace) { + String sUrl = restURL + "/rest/workspaces"; + GSWorkspaceEncoder wsenc = new GSWorkspaceEncoder(workspace); + String wsxml = wsenc.encodeXml(); + String result = HTTPUtils.postXml(sUrl, wsxml, gsuser, gspass); + return result != null; + } + + //========================================================================== + //=== STYLES + //========================================================================== + + /** + * Store and publish an SLD. + *

+ * This is the equivalent call with cUrl: + *

+     * {@code curl -u admin:geoserver -XPOST \
+     *      -H 'Content-type: application/vnd.ogc.sld+xml' \
+     *      -d @$FULLSLD \
+     *      http://$GSIP:$GSPORT/$SERVLET/rest/styles}
+ * + * @param sldBody the SLD document as an XML String. + * + * @return true if the operation completed successfully. + */ + public boolean publishStyle(String sldBody) { + String sUrl = restURL + "/rest/styles"; + String result = HTTPUtils.post(sUrl, sldBody, "application/vnd.ogc.sld+xml", gsuser, gspass); + return result != null; + } + + /** + * Store and publish an SLD. + * + * @param sldFile the File containing the SLD document. + * + * @return true if the operation completed successfully. + */ + public boolean publishStyle(File sldFile) { + return publishStyle(sldFile, null); + } + + /** + * Store and publish an SLD, assigning it a name. + * + * @param sldFile the File containing the SLD document. + * @param name the Style name. + * + * @return true if the operation completed successfully. + */ + public boolean publishStyle(File sldFile, String name) { + String sUrl = restURL + "/rest/styles"; + if(name != null) + sUrl += "?name=" + encode(name); + LOGGER.debug("POSTing new style " + name + " to " + sUrl); + String result = HTTPUtils.post(sUrl, sldFile, "application/vnd.ogc.sld+xml", gsuser, gspass); + return result != null; + } + + /** + * Remove a Style. + *

+ * The Style will be unpublished and the related SLD file will be removed. + * + * @param styleName the name of the Style to remove. + * + * @return true if the operation completed successfully. + */ + public boolean removeStyle(String styleName) { + styleName = styleName.replaceAll(":", "_"); // ??? + styleName = encode(styleName); // spaces may + String sUrl = restURL + "/rest/styles/" + styleName + "?purge=true"; + return HTTPUtils.delete(sUrl, gsuser, gspass); + } + + //========================================================================== + //=== SHAPEFILES + //========================================================================== + + /** + * Publish a zipped shapefile. + *
The CRS will be forced to EPSG:4326. + * + * @param workspace + * @param storename + * @param layername + * @param zipFile + * @return true if the operation completed successfully. + * @throws FileNotFoundException + */ + public boolean publishShp(String workspace, String storename, String layername, File zipFile) throws FileNotFoundException { + return publishShp(workspace, storename, layername, zipFile, "EPSG:4326"); + } + + /** + * Publish a zipped shapefile. + * + * @param workspace + * @param storename + * @param layerName + * @param nativeCrs + * @param defaultStyle may be null + * @return true if the operation completed successfully. + * @throws FileNotFoundException + */ + public boolean publishShp(String workspace, String storename, String layerName, File zipFile, String nativeCrs, String defaultStyle) throws FileNotFoundException { + boolean sent = publishShp(workspace, storename, layerName, zipFile, nativeCrs); + if (sent) { + + try { + GSLayerEncoder layerEncoder = new GSLayerEncoder(); + layerEncoder.setDefaultStyle(defaultStyle); + configureLayer(layerEncoder, layerName); + } catch (Exception e) { + sent = false; + } + } + + return sent; + } + + /** + * Publish a zipped shapefile. + * + *

These are the equivalent calls with cUrl: + *

{@code
+     *curl -u admin:geoserver -XPUT -H 'Content-type: application/zip' \
+     *      --data-binary @$ZIPFILE \
+     *      http://$GSIP:$GSPORT/$SERVLET/rest/workspaces/$WORKSPACE/datastores/$STORENAME/file.shp
+     *
+     *curl -u admin:geoserver -XPOST -H 'Content-type: text/xml'  \
+     *      -d "$BAREEPSG:4326true"  \
+     *      http://$GSIP:$GSPORT/$SERVLET/rest/workspaces/$WORKSPACE/datastores/$STORENAME/featuretypes/$LAYERNAME
+     * }
+ * + * @return true if the operation completed successfully. + */ + public boolean publishShp(String workspace, String storename, String layername, File zipFile, String srs) throws FileNotFoundException { + // build full URL + StringBuilder sbUrl = new StringBuilder(restURL).append("/rest/workspaces/").append(workspace).append("/datastores/").append(storename).append("/file.shp?"); +// if (workspace != null) { +// sbUrl.append("namespace=").append(workspace); +// } +// sbUrl.append("&SRS=4326&SRSHandling=Force"); // hack + + String sentResult = HTTPUtils.put(sbUrl.toString(), zipFile, "application/zip", gsuser, gspass); + boolean shpSent = sentResult != null; + + if (shpSent) { + LOGGER.info("Zipfile successfully uploaded (layer:" + layername + " zip:" + zipFile + ")"); + + StringBuilder postUrl = new StringBuilder(restURL) + .append("/rest/workspaces/").append(workspace) + .append("/datastores/").append(storename) + .append("/featuretypes/").append(layername); + + GSFeatureTypeEncoder fte = new GSFeatureTypeEncoder(); + fte.setName(layername); + fte.setSRS(srs); + + String configuredResult = HTTPUtils.putXml(postUrl.toString(), fte.encodeXml(), this.gsuser, this.gspass); + boolean shpConfigured = configuredResult != null; + + if (!shpConfigured) { + LOGGER.warn("Error in configuring " + workspace + ":" + storename + "/" + layername + " -- Zipfile was uploaded successfully: " + zipFile); + } else { + LOGGER.info("Shapefile successfully configured (layer:" + layername + ")"); + } + + return shpConfigured; + + } else { + LOGGER.warn("Error in sending zipfile " + workspace + ":" + storename + "/" + layername + " " + zipFile); + return false; + } + + } + + /** + * Publish a table in a PostGis store as a new layer. + * + *

This is the equivalent call with cUrl: + *

{@code curl -u admin:geoserver -XPOST -H 'Content-type: text/xml' \
+     *      -d "easia_gaul_1_aggrEPSG:4326true" \
+     *      http://localhost:8080/geoserver/rest/workspaces/it.geosolutions/datastores/pg_kids/featuretypes
+     * }
+ * + * and a PUT to + *
restURL + "/rest/layers/" + layerName + * + */ + public boolean publishDBLayer(String workspace, String storename, String layername, String srs, String defaultStyle) { + StringBuilder postUrl = new StringBuilder(restURL) + .append("/rest/workspaces/").append(workspace) + .append("/datastores/").append(storename) + .append("/featuretypes"); + + GSFeatureTypeEncoder fte = new GSFeatureTypeEncoder(); + fte.setName(layername); + fte.setSRS(srs); // srs=null?"EPSG:4326":srs); + String ftypeXml = fte.encodeXml(); + + String configuredResult = HTTPUtils.postXml(postUrl.toString(), ftypeXml, this.gsuser, this.gspass); + boolean published = configuredResult != null; + boolean configured = false; + + if (!published) { + LOGGER.warn("Error in publishing ("+configuredResult+") " + + workspace + ":" + storename + "/" + layername); + } else { + LOGGER.info("DB layer successfully added (layer:" + layername + ")"); + + GSLayerEncoder layerEncoder = new GSLayerEncoder(); + layerEncoder.setDefaultStyle(defaultStyle); + configured = configureLayer(layerEncoder, layername); + + if (!configured) { + LOGGER.warn("Error in configuring ("+configuredResult+") " + + workspace + ":" + storename + "/" + layername); + } else { + LOGGER.info("DB layer successfully configured (layer:" + layername + ")"); + } + } + + return published && configured; + } + + //========================================================================== + //=== GEOTIFF + //========================================================================== + + /** + * Publish a GeoTiff. + * + *

This is the equivalent call with cUrl: + *

{@code
+     *curl -u admin:geoserver -XPUT -H 'Content-type: text' -d "file:$FULLPATH" \
+     *      http://$GSIP:$GSPORT/$SERVLET/rest/workspaces/$WORKSPACE/coveragestores/$STORENAME/external.geotiff
+     * }
+ * + * @return true if the operation completed successfully. + * @deprecated UNTESTED + */ + public boolean publishGeoTIFF(String workspace, String storeName, File geotiff) throws FileNotFoundException { + String sUrl = restURL + "/rest/workspaces/" + workspace + "/coveragestores/" + storeName + "/geotiff"; + String sendResult = HTTPUtils.put(sUrl, geotiff, "text", gsuser, gspass); // CHECKME: text?!? + boolean sent = sendResult != null; + return sent; + } + + /** + * Publish a GeoTiff already in a filesystem readable by GeoServer. + * + * @param workspace an existing workspace + * @param storeName the coverageStore to be created + * @param geotiff the geoTiff to be published + * + * @return a PublishedCoverage, or null on errors + * @throws FileNotFoundException + */ + public RESTCoverageStore publishExternalGeoTIFF(String workspace, String storeName, File geotiff, String srs, String defaultStyle) throws FileNotFoundException { + // create store + String sUrl = restURL + "/rest/workspaces/" + workspace + "/coveragestores/" + storeName + "/external.geotiff"; + String sendResult = HTTPUtils.put(sUrl, geotiff.toURI().toString(), "text/plain", gsuser, gspass); + RESTCoverageStore store = RESTCoverageStore.build(sendResult); + + if (store!=null) { + try { +// // retrieve coverage name + GeoServerRESTReader reader = new GeoServerRESTReader(restURL, gsuser, gspass); + RESTCoverageList covList = reader.getCoverages(workspace, storeName); + if(covList.isEmpty()) { + LOGGER.error("No coverages found in new coveragestore " + storeName); + return null; + } + String coverageName = covList.get(0).getName(); + + // config coverage props (srs) + GSCoverageEncoder coverageEncoder = new GSCoverageEncoder(); + coverageEncoder.setSRS(srs); + configureCoverage(coverageEncoder, workspace, storeName, coverageName); + + // config layer props (style, ...) + GSLayerEncoder layerEncoder = new GSLayerEncoder(); + layerEncoder.setDefaultStyle(defaultStyle); + configureLayer(layerEncoder, coverageName); + + } catch (Exception e) { + LOGGER.warn("Could not configure external GEOTiff:" + storeName, e); + store = null; // TODO: should we remove the configured pc? + } + } + + return store; + } + + //========================================================================== + //=== MOSAIC + //========================================================================== + + /** + * Publish a Mosaic already in a filesystem readable by GeoServer. + * + *

Sample cUrl usage:
+ * <> + * curl -u admin:geoserver -XPUT -H 'Content-type: text' -d "file:$ABSPORTDIR" + * http://$GSIP:$GSPORT/$SERVLET/rest/workspaces/$WORKSPACE/coveragestores/$BAREDIR/external.imagemosaic + * + * @param workspace an existing workspace + * @param storeName the name of the coverageStore to be created + * @param mosaicDir the directory where the raster images are located + * @return true if the operation completed successfully. + * @throws FileNotFoundException + * + * @deprecated work in progress + */ + public RESTCoverageStore configureExternaMosaicDatastore(String workspace, String storeName, File mosaicDir) throws FileNotFoundException { + if (!mosaicDir.isDirectory()) { + throw new IllegalArgumentException("Not a directory '" + mosaicDir + "'"); + } + String sUrl = restURL + "/rest/workspaces/" + workspace + "/coveragestores/" + storeName + "/external.imagemosaic"; + String sendResult = HTTPUtils.put(sUrl, mosaicDir.toURI().toString(), "text/plain", gsuser, gspass); + return RESTCoverageStore.build(sendResult); + } + + /** + * Publish a Mosaic already in a filesystem readable by GeoServer. + * + *

Sample cUrl usage:
+ * curl -u admin:geoserver -XPUT -H 'Content-type: text' -d "file:$ABSPORTDIR" + * http://$GSIP:$GSPORT/$SERVLET/rest/workspaces/$WORKSPACE/coveragestores/$BAREDIR/external.imagemosaic + * + * @param workspace an existing workspace + * @param storeName the name of the coverageStore to be created + * @param mosaicDir the directory where the raster images are located + * @param defaultStyle may be null + * @return true if the operation completed successfully. + * @throws FileNotFoundException + * + * @deprecated work in progress + */ + public RESTCoverageStore publishExternalMosaic(String workspace, String storeName, File mosaicDir, String srs, String defaultStyle) throws FileNotFoundException { + RESTCoverageStore store = configureExternaMosaicDatastore(workspace, storeName, mosaicDir); + if (store != null ) { + try { +// // retrieve coverage name + GeoServerRESTReader reader = new GeoServerRESTReader(restURL, gsuser, gspass); + RESTCoverageList covList = reader.getCoverages(workspace, storeName); + if(covList.isEmpty()) { + LOGGER.error("No coverages found in new coveragestore " + storeName); + return null; + } + String coverageName = covList.get(0).getName(); + + + // config coverage props (srs) + GSCoverageEncoder coverageEncoder = new GSCoverageEncoder(); + coverageEncoder.setSRS(srs); + configureCoverage(coverageEncoder, workspace, storeName, coverageName); + + + // config layer props (style, ...) + GSLayerEncoder layerEncoder = new GSLayerEncoder(); + layerEncoder.setDefaultStyle(defaultStyle); + configureLayer(layerEncoder, storeName); + + } catch (Exception e) { + LOGGER.warn("Could not configure external mosaic:" + storeName, e); + store = null; // TODO: should we remove the configured store? + } + } + + return store; + } + + //========================================================================== + //=== COVERAGES + //========================================================================== + + /** + * Remove the Coverage configuration from GeoServer. + *
+ * First, the associated layer is removed, then the Coverage configuration itself. + *

+ * CHECKME Maybe the coveragestore has to be removed as well. + * + *

REST URL: + * http://localhost:8080/geoserver/rest/workspaces/it.geosolutions/coveragestores/gbRESTtestStore/coverages/resttestdem.xml + * + * @return true if the operation completed successfully. + */ + public boolean unpublishCoverage(String workspace, String storename, String layername) { + try { + // delete related layer + URL deleteLayerUrl = new URL(restURL + "/rest/layers/" + layername); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Going to delete " + "/rest/layers/" + layername); + } + boolean layerDeleted = HTTPUtils.delete(deleteLayerUrl.toExternalForm(), gsuser, gspass); + if (!layerDeleted) { + LOGGER.warn("Could not delete layer '" + layername + "'"); + return false; + } + // delete the coverage + URL deleteCovUrl = new URL(restURL + "/rest/workspaces/" + workspace + "/coveragestores/" + storename + "/coverages/" + layername); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Going to delete " + "/rest/workspaces/" + workspace + "/coveragestores/" + storename + "/coverages/" + layername); + } + boolean covDeleted = HTTPUtils.delete(deleteCovUrl.toExternalForm(), gsuser, gspass); + if (!covDeleted) { + LOGGER.warn("Could not delete coverage " + workspace + ":" + storename + "/" + layername + ", but layer was deleted."); + } else { + LOGGER.info("Coverage successfully deleted " + workspace + ":" + storename + "/" + layername); + } + return covDeleted; + + // the covstore is still there: should we delete it? + + } catch (MalformedURLException ex) { + LOGGER.error(ex); + return false; + } + } + + //========================================================================== + //=== FEATURETYPES + //========================================================================== + + /** + * Removes the featuretype and the associated layer. + *
You may also want to {@link #removeDatastore(String, String) remove the datastore}. + * + * @return true if the operation completed successfully. + */ + public boolean unpublishFeatureType(String workspace, String storename, String layername) { + try { + // delete related layer + URL deleteLayerUrl = new URL(restURL + "/rest/layers/" + layername); + boolean layerDeleted = HTTPUtils.delete(deleteLayerUrl.toExternalForm(), gsuser, gspass); + if (!layerDeleted) { + LOGGER.warn("Could not delete layer '" + layername + "'"); + return false; + } + // delete the coverage + URL deleteFtUrl = new URL(restURL + "/rest/workspaces/" + workspace + "/datastores/" + storename + "/featuretypes/" + layername); + boolean ftDeleted = HTTPUtils.delete(deleteFtUrl.toExternalForm(), gsuser, gspass); + if (!ftDeleted) { + LOGGER.warn("Could not delete featuretype " + workspace + ":" + storename + "/" + layername + ", but layer was deleted."); + } else { + LOGGER.info("FeatureType successfully deleted " + workspace + ":" + storename + "/" + layername); + } + + return ftDeleted; + + // the store is still there: should we delete it? + + } catch (MalformedURLException ex) { + LOGGER.error(ex); + return false; + } + } + + /** + * Remove a given Datastore in a given Workspace. + * + * @param workspace The name of the workspace + * @param storename The name of the Datastore to remove. + * @return true if the datastore was successfully removed. + */ + public boolean removeDatastore(String workspace, String storename) { + try { + URL deleteStore = new URL(restURL + "/rest/workspaces/" + workspace + "/datastores/" + storename); + boolean deleted = HTTPUtils.delete(deleteStore.toExternalForm(), gsuser, gspass); + if (!deleted) { + LOGGER.warn("Could not delete datastore " + workspace + ":" + storename); + } else { + LOGGER.info("Datastore successfully deleted " + workspace + ":" + storename); + } + + return deleted; + } catch (MalformedURLException ex) { + LOGGER.error(ex); + return false; + } + } + + /** + * Remove a given CoverageStore in a given Workspace. + * + * @param workspace The name of the workspace + * @param storename The name of the CoverageStore to remove. + * @return true if the CoverageStore was successfully removed. + */ + public boolean removeCoverageStore(String workspace, String storename) { + try { + URL deleteStore = new URL(restURL + "/rest/workspaces/" + workspace + "/coveragestores/" + storename); + boolean deleted = HTTPUtils.delete(deleteStore.toExternalForm(), gsuser, gspass); + if (!deleted) { + LOGGER.warn("Could not delete CoverageStore " + workspace + ":" + storename); + } else { + LOGGER.info("CoverageStore successfully deleted " + workspace + ":" + storename); + } + + return deleted; + } catch (MalformedURLException ex) { + LOGGER.error(ex); + return false; + } + } + + /** + * Remove a given Workspace. + * + * @param workspace The name of the workspace + * @return true if the WorkSpace was successfully removed. + */ + public boolean removeWorkspace(String workspace) { + workspace = sanitize(workspace); + try { + URL deleteUrl = new URL(restURL + "/rest/workspaces/" + workspace ); + boolean deleted = HTTPUtils.delete(deleteUrl.toExternalForm(), gsuser, gspass); + if (!deleted) { + LOGGER.warn("Could not delete Workspace " + workspace ); + } else { + LOGGER.info("Workspace successfully deleted " + workspace ); + } + + return deleted; + } catch (MalformedURLException ex) { + LOGGER.error(ex); + return false; + } + } + + public boolean removeLayerGroup(String name) { + try { + URL deleteUrl = new URL(restURL + "/rest/layergroups/" + name); + boolean deleted = HTTPUtils.delete(deleteUrl.toExternalForm(), gsuser, gspass); + if (!deleted) { + LOGGER.warn("Could not delete layergroup " + name); + } else { + LOGGER.info("Layergroup successfully deleted: " + name); + } + + return deleted; + } catch (MalformedURLException ex) { + LOGGER.error(ex); + return false; + } + } + + //========================================================================== + //=== + //========================================================================== + + /** + * Allows to configure some layer attributes such as WmsPath and DefaultStyle + * + */ + protected boolean configureLayer(final GSLayerEncoder layer, final String layerName) { + + if (layer.isEmpty()) { + return true; + } + + final String url = restURL + "/rest/layers/" + layerName; + + String layerXml = layer.encodeXml(); + String sendResult = HTTPUtils.putXml(url, layerXml, gsuser, gspass); + if (sendResult != null) { + if (LOGGER.isInfoEnabled()) { + LOGGER.info("Layer successfully configured: " + layerName); + } + } else { + LOGGER.warn("Error configuring layer " + layerName + " ("+sendResult+")"); + } + + return sendResult != null; + } + + /** + * Allows to configure some coverage's attributes + * + */ + protected boolean configureCoverage(final GSCoverageEncoder ce, String wsname, String csname, String cname) { + + final String url = restURL + "/rest/workspaces/"+wsname+"/coveragestores/"+csname+"/coverages/"+cname+".xml"; + + String xmlBody = ce.encodeXml(); + String sendResult = HTTPUtils.putXml(url, xmlBody, gsuser, gspass); + if (sendResult != null) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Coverage successfully configured "+wsname+":"+csname+":"+cname); + } + } else { + LOGGER.warn("Error configuring coverage " + wsname+":"+csname+":"+cname +" ("+sendResult+")"); + } + + return sendResult != null; + } + + /** + * + */ + protected String sanitize(String s) { + if(s.indexOf(".")!=-1) + return s+".DUMMY"; + return s; + } + + protected String encode(String s) { + return URLEncoder.encode(s); + } + +} diff --git a/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTReader.java b/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTReader.java new file mode 100644 index 0000000..bf83b7e --- /dev/null +++ b/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTReader.java @@ -0,0 +1,515 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2007,2011 GeoSolutions S.A.S. + * http://www.geo-solutions.it + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package it.geosolutions.geoserver.rest; + +import it.geosolutions.geoserver.rest.decoder.RESTCoverage; +import it.geosolutions.geoserver.rest.decoder.RESTCoverageList; +import it.geosolutions.geoserver.rest.decoder.RESTCoverageStore; +import it.geosolutions.geoserver.rest.decoder.RESTCoverageStoreList; +import it.geosolutions.geoserver.rest.decoder.RESTDataStoreList; +import it.geosolutions.geoserver.rest.decoder.RESTDataStore; +import it.geosolutions.geoserver.rest.decoder.RESTFeatureType; +import it.geosolutions.geoserver.rest.decoder.RESTLayer; +import it.geosolutions.geoserver.rest.decoder.RESTLayerGroup; +import it.geosolutions.geoserver.rest.decoder.RESTLayerGroupList; +import it.geosolutions.geoserver.rest.decoder.RESTLayerList; +import it.geosolutions.geoserver.rest.decoder.RESTNamespaceList; +import it.geosolutions.geoserver.rest.decoder.RESTResource; +import it.geosolutions.geoserver.rest.decoder.RESTStyleList; +import it.geosolutions.geoserver.rest.decoder.RESTWorkspaceList; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; + + +/** + * Connect to a GeoServer instance to read its data. + *
Info are returned as Strings or, for complex data, as XML elements + * wrapped in proper parsers (e.g.: {@link RESTLayer}, {@link RESTCoverageStore}, ...). + * + * @author ETj (etj at geo-solutions.it) + */ +public class GeoServerRESTReader { + + private final static Logger LOGGER = Logger.getLogger(GeoServerRESTReader.class); + private final String baseurl; + private String username; + private String password; + + /** + * Creates a GeoServerRESTReader for a given GeoServer instance and + * no auth credentials. + *

Note that GeoServer 2.0 REST interface requires username/password credentials by + * default, if not otherwise configured. . + * + * @param restUrl the base GeoServer URL(e.g.: http://localhost:8080/geoserver) + */ + public GeoServerRESTReader(URL restUrl) { + String extForm = restUrl.toExternalForm(); + this.baseurl = extForm.endsWith("/") ? + extForm.substring(0, extForm.length()-1) : + extForm; + } + + /** + * Creates a GeoServerRESTReader for a given GeoServer instance and + * no auth credentials. + *

Note that GeoServer 2.0 REST interface requires username/password credentials by + * default, if not otherwise configured. . + * + * @param restUrl the base GeoServer URL (e.g.: http://localhost:8080/geoserver) + */ + public GeoServerRESTReader(String restUrl) + throws MalformedURLException { + new URL(restUrl); // check URL correctness + this.baseurl = restUrl.endsWith("/") ? + restUrl.substring(0, restUrl.length()-1) : + restUrl; + } + + /** + * Creates a GeoServerRESTReader for a given GeoServer instance + * with the given auth credentials. + * + * @param restUrl the base GeoServer URL (e.g.: http://localhost:8080/geoserver) + * @param username username auth credential + * @param password password auth credential + */ + public GeoServerRESTReader(String restUrl, String username, String password) throws MalformedURLException { + this(restUrl); + this.username = username; + this.password = password; + } + + /** + * Creates a GeoServerRESTReader for a given GeoServer instance + * with the given auth credentials. + * + * @param restUrl the base GeoServer URL (e.g.: http://localhost:8080/geoserver) + * @param username username auth credential + * @param password password auth credential + */ + public GeoServerRESTReader(URL restUrl, String username, String password) { + this(restUrl); + this.username = username; + this.password = password; + } + + private String load(String url) { + LOGGER.info("Loading from REST path " + url); + try { + String response = HTTPUtils.get(baseurl + url, username, password); + return response; + } catch (MalformedURLException ex) { + LOGGER.warn("Bad URL", ex); + } + + return null; + } + + private String loadFullURL(String url) { + LOGGER.info("Loading from REST path " + url); + try { + String response = HTTPUtils.get(url, username, password); + return response; + } catch (MalformedURLException ex) { + LOGGER.warn("Bad URL", ex); + } + return null; + } + + /** + * Check if a GeoServer instance is running at the given URL. + *
+ * Return true if the configured GeoServer is up and replies to REST requests. + *
+ * Send a HTTP GET request to the configured URL.
+ * Return true if a HTTP 200 code (OK) is read from the HTTP response; + * any other response code, or connection error, will return a + * false boolean. + * + * @return true if a GeoServer instance was found at the configured URL. + */ + public boolean existGeoserver() { + return HTTPUtils.httpPing(baseurl + "/rest/", username, password); + } + + //========================================================================== + //=== STYLES + //========================================================================== + + /** + * Check if a Style exists in the configured GeoServer instance. + * @param styleName the name of the style to check for. + * @return true on HTTP 200, false on HTTP 404 + * @throws RuntimeException if any other HTTP code than 200 or 404 was retrieved. + */ + public boolean existsStyle(String styleName) throws RuntimeException { + String url = baseurl + "/rest/styles/" + styleName + ".xml"; + return HTTPUtils.exists(url, username, password); + } + + /** + * Get summary info about all Styles. + * + * @return summary info about Styles as a {@link RESTStyleList} + */ + public RESTStyleList getStyles() { + String url = "/rest/styles.xml"; + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("### Retrieving Styles list from " + url); + } + return RESTStyleList.build(load(url)); + } + + /** + * Get the SLD body of a Style. + */ + public String getSLD(String styleName) { + String url = "/rest/styles/"+styleName+".sld"; + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("### Retrieving SLD body from " + url); + } + return load(url); + } + + //========================================================================== + //=== DATASTORES + //========================================================================== + + /** + * Get summary info about all DataStores in a WorkSpace. + * + * @param workspace The name of the workspace + * + * @return summary info about Datastores as a {@link RESTDataStoreList} + */ + public RESTDataStoreList getDatastores(String workspace) { + String url = "/rest/workspaces/" + workspace + "/datastores.xml"; + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("### Retrieving DS list from " + url); + } + return RESTDataStoreList.build(load(url)); + } + + /** + * Get detailed info about a given Datastore in a given Workspace. + * + * @param workspace The name of the workspace + * @param dsName The name of the Datastore + * @return DataStore details as a {@link RESTDataStore} + */ + public RESTDataStore getDatastore(String workspace, String dsName) { + String url = "/rest/workspaces/" + workspace + "/datastores/" + dsName + ".xml"; + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("### Retrieving DS from " + url); + } + String response = load(url); +// System.out.println("DATASTORE " + workspace+":"+dsName+"\n"+response); + return RESTDataStore.build(response); + } + + /** + * Get detailed info about a FeatureType's Datastore. + * + * @param featureType the RESTFeatureType + * @return DataStore details as a {@link RESTDataStore} + */ + public RESTDataStore getDatastore(RESTFeatureType featureType) { + + String url = featureType.getStoreUrl(); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("### Retrieving DS from fullurl " + url); + } + String response = loadFullURL(url); + return RESTDataStore.build(response); + } + + //========================================================================== + //=== FEATURETYPES + //========================================================================== + + /** + * Get detailed info about a FeatureType given the Layer where it's published with. + * + * @param layer A layer publishing the FeatureType + * @return FeatureType details as a {@link RESTCoverage} + */ + + public RESTFeatureType getFeatureType(RESTLayer layer) { + if(layer.getType() != RESTLayer.TYPE.VECTOR) + throw new RuntimeException("Bad layer type for layer " + layer.getName()); + + String response = loadFullURL(layer.getResourceUrl()); + return RESTFeatureType.build(response); + } + + //========================================================================== + //=== COVERAGESTORES + //========================================================================== + + /** + * Get summary info about all CoverageStores in a WorkSpace. + * + * @param workspace The name of the workspace + * + * @return summary info about CoverageStores as a {@link RESTDataStoreList} + */ + public RESTCoverageStoreList getCoverageStores(String workspace) { + String url = "/rest/workspaces/" + workspace + "/coveragestores.xml"; + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("### Retrieving CS list from " + url); + } + return RESTCoverageStoreList.build(load(url)); + } + + /** + * Get detailed info about a given CoverageStore in a given Workspace. + * + * @param workspace The name of the workspace + * @param csName The name of the CoverageStore + * @return CoverageStore details as a {@link RESTCoverageStore} + */ + public RESTCoverageStore getCoverageStore(String workspace, String csName) { + String url = "/rest/workspaces/" + workspace + "/coveragestores/" + csName + ".xml"; + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("### Retrieving CS from " + url); + } + return RESTCoverageStore.build(load(url)); + } + + /** + * Get detailed info about a Coverage's Datastore. + * + * @param coverage the RESTFeatureType + * @return CoverageStore details as a {@link RESTCoverageStore} + */ + public RESTCoverageStore getCoverageStore(RESTCoverage coverage) { + + String url = coverage.getStoreUrl(); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("### Retrieving CS from fullurl " + url); + } + String response = loadFullURL(url); + return RESTCoverageStore.build(response); + } + + //========================================================================== + //=== COVERAGES + //========================================================================== + + /** + * Get list of coverages (usually only one). + * + * @param workspace The name of the workspace + * @param csName The name of the CoverageStore + * @return Coverages list as a {@link RESTCoverageList} + */ + public RESTCoverageList getCoverages(String workspace, String csName) { + // restURL + "/rest/workspaces/" + workspace + "/coveragestores/" + coverageStore + "/coverages.xml"; + String url = "/rest/workspaces/" + workspace + "/coveragestores/" + csName + "/coverages.xml"; + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("### Retrieving Covs from " + url); + } + return RESTCoverageList.build(load(url)); + } + + /** + * Get detailed info about a given Coverage. + * + * @param workspace The name of the workspace + * @param store The name of the CoverageStore + * @param name The name of the Coverage + * @return Coverage details as a {@link RESTCoverage} + */ + public RESTCoverage getCoverage(String workspace, String store, String name) { + String url = "/rest/workspaces/" + workspace + "/coveragestores/" + store + "/coverages/"+name+".xml"; + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("### Retrieving Coverage from " + url); + } + return RESTCoverage.build(load(url)); + } + + /** + * Get detailed info about a Coverage given the Layer where it's published with. + * + * @param layer A layer publishing the CoverageStore + * @return Coverage details as a {@link RESTCoverage} + */ + public RESTCoverage getCoverage(RESTLayer layer) { + if(layer.getType() != RESTLayer.TYPE.RASTER) + throw new RuntimeException("Bad layer type for layer " + layer.getName()); + + String response = loadFullURL(layer.getResourceUrl()); + return RESTCoverage.build(response); + } + + //========================================================================== + //========================================================================== + + /** + * Get detailed info about a Resource given the Layer where it's published with. + * The Resource can then be converted to RESTCoverage or RESTFeatureType + * + * @return Resource details as a {@link RESTResource} + */ + public RESTResource getResource(RESTLayer layer) { + String response = loadFullURL(layer.getResourceUrl()); + return RESTResource.build(response); + } + + //========================================================================== + //=== LAYERGROUPS + //========================================================================== + + /** + * Get summary info about all LayerGroups. + * + * @return summary info about LayerGroups as a {@link RESTLayerGroupList} + */ + public RESTLayerGroupList getLayerGroups() { + String url = "/rest/layergroups.xml"; + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("### Retrieving layergroups from " + url); + } + return RESTLayerGroupList.build(load(url)); + } + + /** + * Get detailed info about a given LayerGroup. + * + * @param name The name of the LayerGroup + * @return LayerGroup details as a {@link RESTLayerGroup} + */ + public RESTLayerGroup getLayerGroup(String name) { + String url = "/rest/layergroups/" + name + ".xml"; + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("### Retrieving layergroup from " + url); + } + return RESTLayerGroup.build(load(url)); + } + + //========================================================================== + //=== LAYERS + //========================================================================== + + /** + * Get summary info about all Layers. + * + * @return summary info about Layers as a {@link RESTLayerList} + */ + public RESTLayerList getLayers() { + String url = "/rest/layers.xml"; + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("### Retrieving layers from " + url); + } + return RESTLayerList.build(load(url)); + } + + /** + * Get detailed info about a given Layer. + * + * @param name The name of the Layer + * @return Layer details as a {@link RESTLayer} + */ + public RESTLayer getLayer(String name) { + String url = "/rest/layers/" + name + ".xml"; + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("### Retrieving layer from " + url); + } + return RESTLayer.build(load(url)); + } + + //========================================================================== + //=== NAMESPACES + //========================================================================== + + /** + * Get summary info about all Namespaces. + * + * @return summary info about Namespaces as a {@link RESTNamespaceList} + */ + public RESTNamespaceList getNamespaces() { + String url = "/rest/namespaces.xml"; + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("### Retrieving namespaces from " + url); + } + return RESTNamespaceList.build(load(url)); + } + + /** + * Get the names of all the Namespaces. + *
+ * This is a shortcut call: These info could be retrieved using {@link #getNamespaces getNamespaces} + * @return the list of the names of all Namespaces. + */ + public List getNamespaceNames() { + RESTNamespaceList list = getNamespaces(); + List names = new ArrayList(list.size()); + for (RESTNamespaceList.RESTShortNamespace item : list) { + names.add(item.getName()); + } + return names; + } + + //========================================================================== + //=== WORKSPACES + //========================================================================== + + /** + * Get summary info about all Workspaces. + * + * @return summary info about Workspaces as a {@link RESTWorkspaceList} + */ + public RESTWorkspaceList getWorkspaces() { + String url = "/rest/workspaces.xml"; + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("### Retrieving workspaces from " + url); + } + + return RESTWorkspaceList.build(load(url)); + } + + /** + * Get the names of all the Workspaces. + *
+ * This is a shortcut call: These info could be retrieved using {@link #getWorkspaces getWorkspaces} + * @return the list of the names of all Workspaces. + */ + public List getWorkspaceNames() { + RESTWorkspaceList list = getWorkspaces(); + List names = new ArrayList(list.size()); + for (RESTWorkspaceList.RESTShortWorkspace item : list) { + names.add(item.getName()); + } + return names; + } + +} diff --git a/src/main/java/it/geosolutions/geoserver/rest/HTTPUtils.java b/src/main/java/it/geosolutions/geoserver/rest/HTTPUtils.java new file mode 100644 index 0000000..8a612ac --- /dev/null +++ b/src/main/java/it/geosolutions/geoserver/rest/HTTPUtils.java @@ -0,0 +1,430 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2007,2011 GeoSolutions S.A.S. + * http://www.geo-solutions.it + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package it.geosolutions.geoserver.rest; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.ConnectException; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import org.apache.commons.httpclient.Credentials; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.UsernamePasswordCredentials; +import org.apache.commons.httpclient.auth.AuthScope; +import org.apache.commons.httpclient.methods.DeleteMethod; +import org.apache.commons.httpclient.methods.EntityEnclosingMethod; +import org.apache.commons.httpclient.methods.FileRequestEntity; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.commons.httpclient.methods.PutMethod; +import org.apache.commons.httpclient.methods.RequestEntity; +import org.apache.commons.httpclient.methods.StringRequestEntity; +import org.apache.commons.io.IOUtils; +import org.apache.log4j.Logger; + +/** + * Low level HTTP utilities. + */ +class HTTPUtils { + private static final Logger LOGGER = Logger.getLogger(HTTPUtils.class); + + /** + * Performs an HTTP GET on the given URL. + * + * @param url The URL where to connect to. + * @return The HTTP response as a String if the HTTP response code was 200 (OK). + * @throws MalformedURLException + */ + public static String get(String url) throws MalformedURLException { + return get(url, null, null); + } + + /** + * Performs an HTTP GET on the given URL. + *
Basic auth is used if both username and pw are not null. + * + * @param url The URL where to connect to. + * @param username Basic auth credential. No basic auth if null. + * @param pw Basic auth credential. No basic auth if null. + * @return The HTTP response as a String if the HTTP response code was 200 (OK). + * @throws MalformedURLException + */ + public static String get(String url, String username, String pw) throws MalformedURLException { + + GetMethod httpMethod = null; + try { + HttpClient client = new HttpClient(); + setAuth(client, url, username, pw); + httpMethod = new GetMethod(url); + client.getHttpConnectionManager().getParams().setConnectionTimeout(5000); + int status = client.executeMethod(httpMethod); + if(status == HttpStatus.SC_OK) { + InputStream is = httpMethod.getResponseBodyAsStream(); + String response = IOUtils.toString(is); + if(response.trim().length()==0) { // sometime gs rest fails + LOGGER.warn("ResponseBody is empty"); + return null; + } else { + return response; + } + } else { + LOGGER.info("("+status+") " + HttpStatus.getStatusText(status) + " -- " + url ); + } + } catch (ConnectException e) { + LOGGER.info("Couldn't connect to ["+url+"]"); + } catch (IOException e) { + LOGGER.info("Error talking to ["+url+"]", e); + } finally { + if(httpMethod != null) + httpMethod.releaseConnection(); + } + + return null; + } + + /** + * PUTs a File to the given URL. + *
Basic auth is used if both username and pw are not null. + * + * @param url The URL where to connect to. + * @param file The File to be sent. + * @param contentType The content-type to advert in the PUT. + * @param username Basic auth credential. No basic auth if null. + * @param pw Basic auth credential. No basic auth if null. + * @return The HTTP response as a String if the HTTP response code was 200 (OK). + * @throws MalformedURLException + * @return the HTTP response or null on errors. + */ + public static String put(String url, File file, String contentType, String username, String pw) { + return put(url, new FileRequestEntity(file, contentType), username, pw); + } + + /** + * PUTs a String to the given URL. + *
Basic auth is used if both username and pw are not null. + * + * @param url The URL where to connect to. + * @param content The content to be sent as a String. + * @param contentType The content-type to advert in the PUT. + * @param username Basic auth credential. No basic auth if null. + * @param pw Basic auth credential. No basic auth if null. + * @return The HTTP response as a String if the HTTP response code was 200 (OK). + * @throws MalformedURLException + * @return the HTTP response or null on errors. + */ + public static String put(String url, String content, String contentType, String username, String pw) { + try { + return put(url, new StringRequestEntity(content, contentType, null), username, pw); + } catch (UnsupportedEncodingException ex) { + LOGGER.error("Cannot PUT " + url, ex); + return null; + } + } + + /** + * PUTs a String representing an XML document to the given URL. + *
Basic auth is used if both username and pw are not null. + * + * @param url The URL where to connect to. + * @param content The XML content to be sent as a String. + * @param username Basic auth credential. No basic auth if null. + * @param pw Basic auth credential. No basic auth if null. + * @return The HTTP response as a String if the HTTP response code was 200 (OK). + * @throws MalformedURLException + * @return the HTTP response or null on errors. + */ + public static String putXml(String url, String content, String username, String pw) { + return put(url, content, "text/xml", username, pw); + } + + /** + * Performs a PUT to the given URL. + *
Basic auth is used if both username and pw are not null. + * + * @param url The URL where to connect to. + * @param requestEntity The request to be sent. + * @param username Basic auth credential. No basic auth if null. + * @param pw Basic auth credential. No basic auth if null. + * @return The HTTP response as a String if the HTTP response code was 200 (OK). + * @throws MalformedURLException + * @return the HTTP response or null on errors. + */ + public static String put(String url, RequestEntity requestEntity, String username, String pw) { + return send(new PutMethod(url), url, requestEntity, username, pw); + } + + /** + * POSTs a File to the given URL. + *
Basic auth is used if both username and pw are not null. + * + * @param url The URL where to connect to. + * @param file The File to be sent. + * @param contentType The content-type to advert in the POST. + * @param username Basic auth credential. No basic auth if null. + * @param pw Basic auth credential. No basic auth if null. + * @return The HTTP response as a String if the HTTP response code was 200 (OK). + * @throws MalformedURLException + * @return the HTTP response or null on errors. + */ + public static String post(String url, File file, String contentType, String username, String pw) { + return post(url, new FileRequestEntity(file, contentType), username, pw); + } + + /** + * POSTs a String to the given URL. + *
Basic auth is used if both username and pw are not null. + * + * @param url The URL where to connect to. + * @param content The content to be sent as a String. + * @param contentType The content-type to advert in the POST. + * @param username Basic auth credential. No basic auth if null. + * @param pw Basic auth credential. No basic auth if null. + * @return The HTTP response as a String if the HTTP response code was 200 (OK). + * @throws MalformedURLException + * @return the HTTP response or null on errors. + */ + public static String post(String url, String content, String contentType, String username, String pw) { + try { + return post(url, new StringRequestEntity(content, contentType, null), username, pw); + } catch (UnsupportedEncodingException ex) { + LOGGER.error("Cannot POST " + url, ex); + return null; + } + } + + /** + * POSTs a String representing an XML document to the given URL. + *
Basic auth is used if both username and pw are not null. + * + * @param url The URL where to connect to. + * @param content The XML content to be sent as a String. + * @param username Basic auth credential. No basic auth if null. + * @param pw Basic auth credential. No basic auth if null. + * @return The HTTP response as a String if the HTTP response code was 200 (OK). + * @throws MalformedURLException + * @return the HTTP response or null on errors. + */ + public static String postXml(String url, String content, String username, String pw) { + return post(url, content, "text/xml", username, pw); + } + + /** + * Performs a POST to the given URL. + *
Basic auth is used if both username and pw are not null. + * + * @param url The URL where to connect to. + * @param requestEntity The request to be sent. + * @param username Basic auth credential. No basic auth if null. + * @param pw Basic auth credential. No basic auth if null. + * @return The HTTP response as a String if the HTTP response code was 200 (OK). + * @throws MalformedURLException + * @return the HTTP response or null on errors. + */ + public static String post(String url, RequestEntity requestEntity, String username, String pw) { + return send(new PostMethod(url), url, requestEntity, username, pw); + } + + /** + * Send an HTTP request (PUT or POST) to a server. + *
Basic auth is used if both username and pw are not null. + *

+ * Only

are accepted as successful codes; in these cases the response string will be returned. + * + * @return the HTTP response or null on errors. + */ + private static String send(final EntityEnclosingMethod httpMethod, String url, RequestEntity requestEntity, String username, String pw) { + + try { + HttpClient client = new HttpClient(); + setAuth(client, url, username, pw); +// httpMethod = new PutMethod(url); + client.getHttpConnectionManager().getParams().setConnectionTimeout(5000); + if(requestEntity != null) + httpMethod.setRequestEntity(requestEntity); + int status = client.executeMethod(httpMethod); + + switch(status) { + case HttpURLConnection.HTTP_OK: + case HttpURLConnection.HTTP_CREATED: + case HttpURLConnection.HTTP_ACCEPTED: + String response = IOUtils.toString(httpMethod.getResponseBodyAsStream()); +// LOGGER.info("================= POST " + url); + LOGGER.info("HTTP "+ httpMethod.getStatusText()+": " + response); + return response; + default: + LOGGER.warn("Bad response: code["+status+"]" + + " msg["+httpMethod.getStatusText()+"]" + + " url["+url+"]" + + " method["+httpMethod.getClass().getSimpleName()+"]: " + + IOUtils.toString(httpMethod.getResponseBodyAsStream()) + ); + return null; + } + } catch (ConnectException e) { + LOGGER.info("Couldn't connect to ["+url+"]"); + return null; + } catch (IOException e) { + LOGGER.error("Error talking to " + url + " : " + e.getLocalizedMessage()); + return null; + } finally { + if(httpMethod != null) + httpMethod.releaseConnection(); + } + } + + public static boolean delete(String url, final String user, final String pw) { + + DeleteMethod httpMethod = null; + + try { + HttpClient client = new HttpClient(); + setAuth(client, url, user, pw); + httpMethod = new DeleteMethod(url); + client.getHttpConnectionManager().getParams().setConnectionTimeout(5000); + int status = client.executeMethod(httpMethod); + String response = ""; + if(status == HttpStatus.SC_OK) { + InputStream is = httpMethod.getResponseBodyAsStream(); + response = IOUtils.toString(is); + if(response.trim().equals("")) { // sometimes gs rest fails + if(LOGGER.isDebugEnabled()) + LOGGER.debug("ResponseBody is empty (this may be not an error since we just performed a DELETE call)"); + return true; + } + if(LOGGER.isDebugEnabled()) + LOGGER.debug("("+status+") " + httpMethod.getStatusText() + " -- " + url ); + return true; + } else { + LOGGER.info("("+status+") " + httpMethod.getStatusText() + " -- " + url ); + LOGGER.info("Response: '"+response+"'" ); + } + } catch (ConnectException e) { + LOGGER.info("Couldn't connect to ["+url+"]"); + } catch (IOException e) { + LOGGER.info("Error talking to ["+url+"]", e); + } finally { + if(httpMethod != null) + httpMethod.releaseConnection(); + } + + return false; + } + + /** + * @return true if the server response was an HTTP_OK + */ + public static boolean httpPing(String url) { + return httpPing(url, null, null); + } + + public static boolean httpPing(String url, String username, String pw) { + + GetMethod httpMethod = null; + + try { + HttpClient client = new HttpClient(); + setAuth(client, url, username, pw); + httpMethod = new GetMethod(url); + client.getHttpConnectionManager().getParams().setConnectionTimeout(2000); + int status = client.executeMethod(httpMethod); + if(status != HttpStatus.SC_OK) { + LOGGER.warn("PING failed at '"+url+"': ("+status+") " + httpMethod.getStatusText()); + return false; + } else { + return true; + } + + } catch (ConnectException e) { + return false; + } catch (IOException e) { + e.printStackTrace(); + return false; + } finally { + if(httpMethod != null) + httpMethod.releaseConnection(); + } + } + + /** + * Used to query for REST resources. + * + * @param url The URL of the REST resource to query about. + * @param username + * @param pw + * @return true on 200, false on 404. + * @throws RuntimeException on unhandled status or exceptions. + */ + public static boolean exists(String url, String username, String pw) { + + GetMethod httpMethod = null; + + try { + HttpClient client = new HttpClient(); + setAuth(client, url, username, pw); + httpMethod = new GetMethod(url); + client.getHttpConnectionManager().getParams().setConnectionTimeout(2000); + int status = client.executeMethod(httpMethod); + switch(status) { + case HttpStatus.SC_OK: + return true; + case HttpStatus.SC_NOT_FOUND: + return false; + default: + throw new RuntimeException("Unhandled response status at '"+url+"': ("+status+") " + httpMethod.getStatusText()); + } + } catch (ConnectException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + if(httpMethod != null) + httpMethod.releaseConnection(); + } + } + + + private static void setAuth(HttpClient client, String url, String username, String pw) throws MalformedURLException { + URL u = new URL(url); + if(username != null && pw != null) { + Credentials defaultcreds = new UsernamePasswordCredentials(username, pw); + client.getState().setCredentials(new AuthScope(u.getHost(), u.getPort()), defaultcreds); + client.getParams().setAuthenticationPreemptive(true); // GS2 by default always requires authentication + } else { + if(LOGGER.isDebugEnabled()) { + LOGGER.debug("Not setting credentials to access to " + url); + } + } + } + +} diff --git a/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTAbstractList.java b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTAbstractList.java new file mode 100644 index 0000000..3ea2069 --- /dev/null +++ b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTAbstractList.java @@ -0,0 +1,121 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2007,2011 GeoSolutions S.A.S. + * http://www.geo-solutions.it + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package it.geosolutions.geoserver.rest.decoder; + +import it.geosolutions.geoserver.rest.decoder.utils.JDOMListIterator; + +import it.geosolutions.geoserver.rest.decoder.utils.NameLinkElem; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.jdom.Element; + +/** + * Parses list of summary data. + * + *

This is the XML REST representation: + *

+  {@code
+
+      
+        elem1
+        
+      
+      
+        elem2
+        
+      
+
+}
+ * + * @author ETj (etj at geo-solutions.it) + */ +public class RESTAbstractList implements Iterable { + + protected final List elementList; + + protected RESTAbstractList(Element list) { + List tempList = new ArrayList(); + String baseName = null; + + for (Element listItem : (List) list.getChildren()) { + if(baseName == null) + baseName = listItem.getName(); + else + if(! baseName.equals(listItem.getName())) { + throw new RuntimeException("List elements mismatching (" + baseName+","+listItem.getName()+")"); + } + + tempList.add(listItem); + } + + elementList = Collections.unmodifiableList(tempList); + } + + public int size() { + return elementList.size(); + } + + public boolean isEmpty() { + return elementList.isEmpty(); + } + + public ELEM get(int index) { + return createElement(elementList.get(index)); + } + + public Iterator iterator() { + return new RESTAbstractListIterator(elementList); + } + + public List getNames() { + List names = new ArrayList(elementList.size()); + for (ELEM elem: this) { + names.add(elem.getName()); + } + return names; + } + + + private class RESTAbstractListIterator extends JDOMListIterator { + + public RESTAbstractListIterator(List orig) { + super(orig); + } + + @Override + public ELEM transform(Element listItem) { + return createElement(listItem); + } + } + + protected ELEM createElement(Element el) { + return (ELEM)new NameLinkElem(el); + } + +} diff --git a/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTCoverage.java b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTCoverage.java new file mode 100644 index 0000000..f5a343e --- /dev/null +++ b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTCoverage.java @@ -0,0 +1,240 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2007,2011 GeoSolutions S.A.S. + * http://www.geo-solutions.it + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package it.geosolutions.geoserver.rest.decoder; + +import it.geosolutions.geoserver.rest.decoder.utils.JDOMBuilder; +import org.jdom.Element; + +/** + * Parse Coverages returned as XML REST objects. + * + *

This is the XML REST representation: + *

+ *{@code
+
+  sfdem
+  sfdem
+  
+    sf
+    
+  
+  sfdem is a Tagged Image File Format with Geographic information
+  Generated from sfdem
+  
+    WCS
+    sfdem
+    sfdem
+  
+  PROJCS["NAD27 / UTM zone 13N",
+  GEOGCS["NAD27",
+    DATUM["North American Datum 1927",
+      SPHEROID["Clarke 1866", 6378206.4, 294.9786982138982, AUTHORITY["EPSG","7008"]],
+      TOWGS84[-4.2, 135.4, 181.9, 0.0, 0.0, 0.0, 0.0],
+      AUTHORITY["EPSG","6267"]],
+    PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]],
+    UNIT["degree", 0.017453292519943295],
+    AXIS["Geodetic longitude", EAST],
+    AXIS["Geodetic latitude", NORTH],
+    AUTHORITY["EPSG","4267"]],
+  PROJECTION["Transverse_Mercator"],
+  PARAMETER["central_meridian", -105.0],
+  PARAMETER["latitude_of_origin", 0.0],
+  PARAMETER["scale_factor", 0.9996],
+  PARAMETER["false_easting", 500000.0],
+  PARAMETER["false_northing", 0.0],
+  UNIT["m", 1.0],
+  AXIS["Easting", EAST],
+  AXIS["Northing", NORTH],
+  AUTHORITY["EPSG","26713"]]
+  EPSG:26713
+  
+    589980.0
+    609000.0
+    4913700.0
+    4928010.0
+    EPSG:26713
+  
+  
+    -103.87108701853181
+    -103.62940739432703
+    44.370187074132616
+    44.5016011535299
+    EPSG:4326
+  
+  true
+  
+    sfdem_sfdem
+  
+  
+    sfdem
+    
+  
+  GeoTIFF
+  
+    
+      0 0
+      634 477
+    
+    
+      30.0
+      -30.0
+      0.0
+      0.0
+      589995.0
+      4927995.0
+    
+    EPSG:26713
+  
+  
+    ARCGRID
+    IMAGEMOSAIC
+    GTOPO30
+    GEOTIFF
+    GIF
+    PNG
+    JPEG
+    TIFF
+  
+  
+    nearest neighbor
+    bilinear
+    bicubic
+  
+  nearest neighbor
+  
+    
+      GRAY_INDEX
+      GridSampleDimension[-9.999999933815813E36,-9.999999933815813E36]
+      
+        -9.999999933815813E36
+        -9.999999933815813E36
+      
+    
+  
+  
+    EPSG:26713
+  
+  
+    EPSG:26713
+  
+
+ * }
+ * + * @author etj + */ +public class RESTCoverage extends RESTResource { + + + public static RESTCoverage build(String response) { + Element elem = JDOMBuilder.buildElement(response); + return elem == null? null : new RESTCoverage(elem); + } + + public RESTCoverage(Element resource) { + super(resource); + } + + public RESTCoverage(RESTResource resource) { + super(resource.rootElem); + } + +// public String getName() { +// return rootElem.getChildText("name"); +// } + +// public String getNativeName() { +// return rootElem.getChildText("nativeName"); +// } + + public String getNativeFormat() { + return rootElem.getChildText("nativeFormat"); + } + +// public String getNameSpace() { +// return rootElem.getChild("namespace").getChildText("name"); +// } +// +// public String getTitle() { +// return rootElem.getChildText("title"); +// } + + public String getNativeCRS() { + return rootElem.getChildText("nativeCRS"); + } + + public String getSRS() { + return rootElem.getChildText("srs"); + } + + +// public String getStoreName() { +// return rootElem.getChild("store").getChildText("name"); +// } +// +// public String getStoreType() { +// return rootElem.getChild("store").getAttributeValue("class"); +// } + + /** + * Get the URL to retrieve the featuretype. + *
 {@code
+     * 
+     *      sfdem
+     *      
+     * 
+     * }
+     */
+//    public String getStoreUrl() {
+//		Element store = rootElem.getChild("store");
+//        Element atom = store.getChild("link", Namespace.getNamespace("atom", "http://www.w3.org/2005/Atom"));
+//        return atom.getAttributeValue("href");
+//    }
+
+//	public String getBBCRS() {
+//		Element elBBox = rootElem.getChild("latLonBoundingBox");
+//		return elBBox.getChildText("crs");
+//	}
+//
+//	protected double getLatLonEdge(String edge) {
+//		Element elBBox = rootElem.getChild("latLonBoundingBox");
+//		return Double.parseDouble(elBBox.getChildText(edge));
+//	}
+//
+//	public double getMinX() {
+//		return getLatLonEdge("minx");
+//	}
+//	public double getMaxX() {
+//		return getLatLonEdge("maxx");
+//	}
+//	public double getMinY() {
+//		return getLatLonEdge("miny");
+//	}
+//	public double getMaxY() {
+//		return getLatLonEdge("maxy");
+//	}
+}
diff --git a/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTCoverageList.java b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTCoverageList.java
new file mode 100644
index 0000000..9dcb575
--- /dev/null
+++ b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTCoverageList.java
@@ -0,0 +1,62 @@
+/*
+ *  GeoServer-Manager - Simple Manager Library for GeoServer
+ *  
+ *  Copyright (C) 2007,2011 GeoSolutions S.A.S.
+ *  http://www.geo-solutions.it
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package it.geosolutions.geoserver.rest.decoder;
+
+import it.geosolutions.geoserver.rest.decoder.utils.NameLinkElem;
+import it.geosolutions.geoserver.rest.decoder.utils.JDOMBuilder;
+import org.jdom.Element;
+
+/**
+ * Parses list of summary data about Coverages.
+ *
+ * 

This is the XML REST representation: + *

{@code 
+  
+    5-25-1-120-11-DOF
+    
+  
+
+ *
+}
+ * + * @author ETj (etj at geo-solutions.it) + */ +public class RESTCoverageList extends RESTAbstractList { + + public static RESTCoverageList build(String response) { + Element elem = JDOMBuilder.buildElement(response); + return elem == null? null : new RESTCoverageList(elem); + } + + protected RESTCoverageList(Element list) { + super(list); + } + +} diff --git a/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTCoverageStore.java b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTCoverageStore.java new file mode 100644 index 0000000..69b2863 --- /dev/null +++ b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTCoverageStore.java @@ -0,0 +1,98 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2007,2011 GeoSolutions S.A.S. + * http://www.geo-solutions.it + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package it.geosolutions.geoserver.rest.decoder; + +import it.geosolutions.geoserver.rest.decoder.utils.JDOMBuilder; +import org.jdom.Element; + +/** + * Parse CoverageStores returned as XML REST objects. + *

+ * This is the XML document returned by GeoServer when requesting a CoverageStore: + *

+ * {@code 
+ * 
+ *      testRESTStoreGeotiff
+ *      GeoTIFF
+ *      true
+ *      
+ *          it.geosolutions
+ *          http://localhost:8080/geoserver/rest/workspaces/it.geosolutions.xml
+ *      
+ *      file:/home/geosolutions/prj/git/gman/target/test-classes/testdata/resttestdem.tif
+ *      
+ *          
+ *      
+ * 
+ * }
+ * 
+ * + * Note: the whole XML fragment is stored in memory. At the moment, there are + * methods to retrieve only the more useful data. + * + * @author etj + */ +public class RESTCoverageStore { + private final Element cs; + + + public RESTCoverageStore(Element cs) { + this.cs = cs; + } + + public static RESTCoverageStore build(String response) { + if(response == null) + return null; + + Element pb = JDOMBuilder.buildElement(response); + if(pb != null) + return new RESTCoverageStore(pb); + else + return null; + } + + public String getName() { + return cs.getChildText("name"); + } + + public String getWorkspaceName() { + return cs.getChild("workspace").getChildText("name"); + } + + public String toString() { + StringBuilder sb = new StringBuilder(getClass().getSimpleName()) + .append('['); + if(cs == null) + sb.append("null"); + else + sb.append("name:").append(getName()) + .append(" wsname:").append(getWorkspaceName()); + + return sb.toString(); + } +} diff --git a/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTCoverageStoreList.java b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTCoverageStoreList.java new file mode 100644 index 0000000..84e4e18 --- /dev/null +++ b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTCoverageStoreList.java @@ -0,0 +1,61 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2007,2011 GeoSolutions S.A.S. + * http://www.geo-solutions.it + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package it.geosolutions.geoserver.rest.decoder; + +import it.geosolutions.geoserver.rest.decoder.utils.NameLinkElem; +import it.geosolutions.geoserver.rest.decoder.utils.JDOMBuilder; +import org.jdom.Element; + +/** + * Parses list of summary data about CoverageStores. + * + *

This is the XML REST representation: + *

{@code 
+  
+    sfdem
+    
+  
+
+ *
+}
+ * + * @author ETj (etj at geo-solutions.it) + */ +public class RESTCoverageStoreList extends RESTAbstractList { + + public static RESTCoverageStoreList build(String response) { + Element elem = JDOMBuilder.buildElement(response); + return elem == null? null : new RESTCoverageStoreList(elem); + } + + protected RESTCoverageStoreList(Element list) { + super(list); + } + +} diff --git a/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTDataStore.java b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTDataStore.java new file mode 100644 index 0000000..22c24f0 --- /dev/null +++ b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTDataStore.java @@ -0,0 +1,133 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2007,2011 GeoSolutions S.A.S. + * http://www.geo-solutions.it + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package it.geosolutions.geoserver.rest.decoder; + +import it.geosolutions.geoserver.rest.decoder.utils.JDOMBuilder; +import java.util.List; +import org.jdom.Element; + +/** + * Parse DataStores returned as XML REST objects. + *

+ * This is the XML document returned by GeoServer when requesting a DataStore: + *

+ * {@code
+
+    sf
+    true
+    
+        sf
+        
+    
+    
+        http://www.openplans.org/spearfish
+        file:data/sf
+    
+    
+        
+    
+
+ * }
+ * 
+ * Note: the whole XML fragment is stored in memory. At the moment, there are + * methods to retrieve only the more useful data. + * @author etj + */ +public class RESTDataStore { + + private final Element dsElem; + + public enum DBType { + + POSTGIS("postgis"), + SHP("shp"), + UNKNOWN(null); + private final String restName; + + private DBType(String restName) { + this.restName = restName; + } + + public static DBType get(String restName) { + for (DBType type : values()) { + if (type == UNKNOWN) { + continue; + } + if (type.restName.equals(restName)) { + return type; + } + } + return UNKNOWN; + } + }; + + public static RESTDataStore build(String xml) { + if (xml == null) { + return null; + } + + Element e = JDOMBuilder.buildElement(xml); + if (e != null) { + return new RESTDataStore(e); + } else { + return null; + } + } + + protected RESTDataStore(Element dsElem) { + this.dsElem = dsElem; + } + + public String getName() { + return dsElem.getChildText("name"); + } + + public String getWorkspaceName() { + return dsElem.getChild("workspace").getChildText("name"); + } + + protected String getConnectionParameter(String paramName) { + Element elConnparm = dsElem.getChild("connectionParameters"); + if (elConnparm != null) { + for (Element entry : (List) elConnparm.getChildren("entry")) { + String key = entry.getAttributeValue("key"); + if (paramName.equals(key)) { + return entry.getTextTrim(); + } + } + } + + return null; + } + + public DBType getType() { + return DBType.get(getConnectionParameter("dbtype")); + } +} diff --git a/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTDataStoreList.java b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTDataStoreList.java new file mode 100644 index 0000000..8ebef91 --- /dev/null +++ b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTDataStoreList.java @@ -0,0 +1,47 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2007,2011 GeoSolutions S.A.S. + * http://www.geo-solutions.it + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package it.geosolutions.geoserver.rest.decoder; + +import it.geosolutions.geoserver.rest.decoder.utils.NameLinkElem; +import it.geosolutions.geoserver.rest.decoder.utils.JDOMBuilder; +import org.jdom.Element; + +/** + * Parses list of summary data about Datastores. + * + * @author ETj (etj at geo-solutions.it) + */ +public class RESTDataStoreList extends RESTAbstractList { + + public static RESTDataStoreList build(String response) { + Element elem = JDOMBuilder.buildElement(response); + return elem == null? null : new RESTDataStoreList(elem); + } + + protected RESTDataStoreList(Element list) { + super(list); + } +} diff --git a/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTFeatureType.java b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTFeatureType.java new file mode 100644 index 0000000..38a8d6b --- /dev/null +++ b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTFeatureType.java @@ -0,0 +1,246 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2007,2011 GeoSolutions S.A.S. + * http://www.geo-solutions.it + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package it.geosolutions.geoserver.rest.decoder; + +import it.geosolutions.geoserver.rest.decoder.utils.JDOMBuilder; +import it.geosolutions.geoserver.rest.decoder.utils.JDOMListIterator; +import java.util.Iterator; +import org.jdom.Element; + +/** + * Parse FeatureTypes returned as XML REST objects. + * + *

This is the XML REST representation: + *

+ * {@code
+
+  tasmania_cities
+  tasmania_cities
+  
+    topp
+    
+  
+  Tasmania cities
+  Cities in Tasmania (actually, just the capital)
+  
+    cities
+    Tasmania
+  
+  GEOGCS["GCS_WGS_1984",
+  DATUM["WGS_1984",
+    SPHEROID["WGS_1984", 6378137.0, 298.257223563]],
+  PRIMEM["Greenwich", 0.0],
+  UNIT["degree", 0.017453292519943295],
+  AXIS["Longitude", EAST],
+  AXIS["Latitude", NORTH]]
+  EPSG:4326
+  
+    147.2910004483
+    147.2910004483
+    -42.851001816890005
+    -42.851001816890005
+    EPSG:4326
+  
+  
+    145.19754
+    148.27298000000002
+    -43.423512
+    -40.852802
+    EPSG:4326
+  
+  FORCE_DECLARED
+  true
+  
+    3600
+    false
+    10
+    true
+    tasmania_cities
+  
+  
+    taz_shapes
+    
+  
+  
+    
+      the_geom
+      0
+      1
+      false
+    
+    
+      CITY_NAME
+      0
+      1
+      false
+    
+    
+      ADMIN_NAME
+      0
+      1
+      false
+    
+    
+      CNTRY_NAME
+      0
+      1
+      false
+    
+    
+      STATUS
+      0
+      1
+      false
+    
+    
+      POP_CLASS
+      0
+      1
+      false
+    
+  
+  0
+  0
+
+ * }
+ * @author etj + */ +public class RESTFeatureType extends RESTResource { + + public static class Attribute { + private String name; + private String binding; + + public String getBinding() { + return binding; + } + + public void setBinding(String binding) { + this.binding = binding; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + public static RESTFeatureType build(String response) { + Element elem = JDOMBuilder.buildElement(response); + return elem == null? null : new RESTFeatureType(elem); + } + + public RESTFeatureType(Element resource) { + super(resource); + } + + public RESTFeatureType(RESTResource resource) { + super(resource.rootElem); + } + +// public String getName() { +// return rootElem.getChildText("name"); +// } + +// public String getNativeName() { +// return rootElem.getChildText("nativeName"); +// } + +// public String getNameSpace() { +// return rootElem.getChild("namespace").getChildText("name"); +// } + +// public String getStoreName() { +// return rootElem.getChild("store").getChildText("name"); +// } +// +// public String getStoreType() { +// return rootElem.getChild("store").getAttributeValue("class"); +// } + + /** + * Get the URL to retrieve the featuretype. + *
{@code
+        
+        tasmania_cities
+        
+    
+     * }
+     */
+//    public String getStoreUrl() {
+//		Element store = rootElem.getChild("store");
+//        Element atom = store.getChild("link", Namespace.getNamespace("atom", "http://www.w3.org/2005/Atom"));
+//        return atom.getAttributeValue("href");
+//    }
+
+//	public String getCRS() {
+//		Element elBBox = rootElem.getChild("latLonBoundingBox");
+//		return elBBox.getChildText("crs");
+//	}
+//
+//	protected double getLatLonEdge(String edge) {
+//		Element elBBox = rootElem.getChild("latLonBoundingBox");
+//		return Double.parseDouble(elBBox.getChildText(edge));
+//	}
+//
+//	public double getMinX() {
+//		return getLatLonEdge("minx");
+//	}
+//	public double getMaxX() {
+//		return getLatLonEdge("maxx");
+//	}
+//	public double getMinY() {
+//		return getLatLonEdge("miny");
+//	}
+//	public double getMaxY() {
+//		return getLatLonEdge("maxy");
+//	}
+
+    public Iterable getAttributes() {
+
+        return new Iterable() {
+            public Iterator iterator() {
+                return attributesIterator();
+            }
+        };
+    }
+
+    public Iterator attributesIterator() {
+        Element attrs = rootElem.getChild("attributes");
+        return new JDOMListIterator(attrs.getChildren()) {
+            @Override
+            public Attribute transform(Element listItem) {
+                Attribute ret = new Attribute();
+                ret.setName(listItem.getChildText("name"));
+                ret.setBinding(listItem.getChildText("binding"));
+                return ret;
+            }
+        };
+    }
+}
diff --git a/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTLayer.java b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTLayer.java
new file mode 100644
index 0000000..c194dbe
--- /dev/null
+++ b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTLayer.java
@@ -0,0 +1,180 @@
+/*
+ *  GeoServer-Manager - Simple Manager Library for GeoServer
+ *  
+ *  Copyright (C) 2007,2011 GeoSolutions S.A.S.
+ *  http://www.geo-solutions.it
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package it.geosolutions.geoserver.rest.decoder;
+
+import it.geosolutions.geoserver.rest.decoder.utils.JDOMBuilder;
+import org.jdom.Element;
+import org.jdom.Namespace;
+
+/**
+ * Parse Layers returned as XML REST objects.
+ *
+ * 

This is the XML REST representation: + *

+ * {@code
+
+    tasmania_cities
+    /
+    VECTOR
+    
+        capitals
+        
+    
+    
+        tasmania_cities
+        
+    
+    true
+    
+        0
+        0
+    
+
+ * }
+ * @author etj + */ +public class RESTLayer { + private final Element layerElem; + + public enum TYPE { + VECTOR("VECTOR"), + RASTER("RASTER"), + UNKNOWN(null); + + private final String restName; + + private TYPE(String restName) { + this.restName = restName; + } + + public static TYPE get(String restName) { + for (TYPE type : values()) { + if(type == UNKNOWN) + continue; + if(type.restName.equals(restName)) + return type; + } + return UNKNOWN; + } + }; + + public static RESTLayer build(String response) { + if(response == null) + return null; + + Element pb = JDOMBuilder.buildElement(response); + if(pb != null) + return new RESTLayer(pb); + else + return null; + } + + public RESTLayer(Element layerElem) { + this.layerElem = layerElem; + } + + public String getName() { + return layerElem.getChildText("name"); + } + + public String getTypeString() { + return layerElem.getChildText("type"); + } + + public TYPE getType() { + return TYPE.get(getTypeString()); + } + + public String getDefaultStyle() { + Element defaultStyle = layerElem.getChild("defaultStyle"); + return defaultStyle == null? null : defaultStyle.getChildText("name"); + } + + public String getTitle() { + Element resource = layerElem.getChild("resource"); + return resource.getChildText("title"); + } + + public String getAbstract() { + Element resource = layerElem.getChild("resource"); + return resource.getChildText("abstract"); + } + + public String getNameSpace() { + Element resource = layerElem.getChild("resource"); + return resource.getChild("namespace").getChildText("name"); + } + +// public String getStoreName() { +// Element resource = layerElem.getChild("resource"); +// return resource.getChild("store").getChildText("name"); +// } +// +// public String getStoreType() { +// Element resource = layerElem.getChild("resource"); +// return resource.getChild("store").getAttributeValue("class"); +// } + +// public String getCRS() { +// Element resource = layerElem.getChild("resource"); +// Element elBBox = resource.getChild("latLonBoundingBox"); +// return elBBox.getChildText("crs"); +// } + + /** + * Get the URL to retrieve the featuretype. + *
{@code
+        
+        tasmania_cities
+        
+    
+     * }
+     */
+    public String getResourceUrl() {
+		Element resource = layerElem.getChild("resource");
+        Element atom = resource.getChild("link", Namespace.getNamespace("atom", "http://www.w3.org/2005/Atom"));
+        return atom.getAttributeValue("href");
+    }
+
+//	protected double getLatLonEdge(String edge) {
+//		Element resource = layerElem.getChild("resource");
+//		Element elBBox = resource.getChild("latLonBoundingBox");
+//		return Double.parseDouble(elBBox.getChildText(edge));
+//	}
+//
+//	public double getMinX() {
+//		return getLatLonEdge("minx");
+//	}
+//	public double getMaxX() {
+//		return getLatLonEdge("maxx");
+//	}
+//	public double getMinY() {
+//		return getLatLonEdge("miny");
+//	}
+//	public double getMaxY() {
+//		return getLatLonEdge("maxy");
+//	}
+}
diff --git a/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTLayerGroup.java b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTLayerGroup.java
new file mode 100644
index 0000000..0587156
--- /dev/null
+++ b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTLayerGroup.java
@@ -0,0 +1,120 @@
+/*
+ *  GeoServer-Manager - Simple Manager Library for GeoServer
+ *  
+ *  Copyright (C) 2007,2011 GeoSolutions S.A.S.
+ *  http://www.geo-solutions.it
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package it.geosolutions.geoserver.rest.decoder;
+
+import it.geosolutions.geoserver.rest.decoder.utils.JDOMBuilder;
+import org.jdom.Element;
+
+/**
+ * Parse LayerGroups returned as XML REST objects.
+ *
+ * 

This is the XML REST representation: + *

+ * {@code
+
+  tasmania
+  
+    
+      tasmania_state_boundaries
+      
+    
+    
+      tasmania_water_bodies
+      
+    
+    
+      tasmania_roads
+      
+    
+    
+      tasmania_cities
+      
+    
+  
+  
+    
+      
+      
+}
+ * + * @author ETj (etj at geo-solutions.it) + */ +public class RESTStyleList extends RESTAbstractList { + + public static RESTStyleList build(String response) { + Element elem = JDOMBuilder.buildElement(response); + return elem == null? null : new RESTStyleList(elem); + } + + protected RESTStyleList(Element list) { + super(list); + } + +} diff --git a/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTWorkspaceList.java b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTWorkspaceList.java new file mode 100644 index 0000000..611f31d --- /dev/null +++ b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTWorkspaceList.java @@ -0,0 +1,128 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2007,2011 GeoSolutions S.A.S. + * http://www.geo-solutions.it + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package it.geosolutions.geoserver.rest.decoder; + +import it.geosolutions.geoserver.rest.decoder.utils.NameLinkElem; +import it.geosolutions.geoserver.rest.decoder.utils.JDOMBuilder; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.jdom.Element; + +/** + * Parses list of summary data about Workspaces. + *
Single items are handled by {@link RESTShortWorkspace}. + + * @author ETj (etj at geo-solutions.it) + */ +public class RESTWorkspaceList implements Iterable { + + private final List wsList; + + public static RESTWorkspaceList build(String response) { + if(response == null) + return null; + + Element elem = JDOMBuilder.buildElement(response); + if(elem != null) + return new RESTWorkspaceList(elem); + else + return null; + } + + protected RESTWorkspaceList(Element wslistroot) { + List tmpList = new ArrayList(); + for (Element wselem : (List) wslistroot.getChildren("workspace")) { + tmpList.add(wselem); + } + + wsList = Collections.unmodifiableList(tmpList); + } + + public int size() { + return wsList.size(); + } + + public boolean isEmpty() { + return wsList.isEmpty(); + } + + public RESTShortWorkspace get(int index) { + return new RESTShortWorkspace(wsList.get(index)); + } + + public Iterator iterator() { + return new RESTWSListIterator(wsList); + } + + + private static class RESTWSListIterator implements Iterator { + + private final Iterator iter; + + public RESTWSListIterator(List orig) { + iter = orig.iterator(); + } + + public boolean hasNext() { + return iter.hasNext(); + } + + public RESTShortWorkspace next() { + return new RESTShortWorkspace(iter.next()); + } + + public void remove() { + throw new UnsupportedOperationException("Not supported."); + } + } + + /** + * Workspace summary info. + *
This is an XML fragment: + *
+     * {@code
+     *   
+     *      it.geosolutions
+     *      
+     *  
+     * }
+     * 
+ */ + + public static class RESTShortWorkspace extends NameLinkElem { + + public RESTShortWorkspace(Element elem) { + super(elem); + } + } + +} diff --git a/src/main/java/it/geosolutions/geoserver/rest/decoder/package.html b/src/main/java/it/geosolutions/geoserver/rest/decoder/package.html new file mode 100644 index 0000000..869793b --- /dev/null +++ b/src/main/java/it/geosolutions/geoserver/rest/decoder/package.html @@ -0,0 +1,5 @@ + +Decoders for GeoServer's beans. +Only some getters are available; there were developed only the most used getters, +in order not to replicate the whole GeoServer beans hierarchy. + \ No newline at end of file diff --git a/src/main/java/it/geosolutions/geoserver/rest/decoder/utils/JDOMBuilder.java b/src/main/java/it/geosolutions/geoserver/rest/decoder/utils/JDOMBuilder.java new file mode 100644 index 0000000..e3efb62 --- /dev/null +++ b/src/main/java/it/geosolutions/geoserver/rest/decoder/utils/JDOMBuilder.java @@ -0,0 +1,61 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2007,2011 GeoSolutions S.A.S. + * http://www.geo-solutions.it + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package it.geosolutions.geoserver.rest.decoder.utils; + +import java.io.IOException; +import java.io.StringReader; +import org.apache.log4j.Logger; +import org.jdom.Document; +import org.jdom.Element; +import org.jdom.JDOMException; +import org.jdom.input.SAXBuilder; + +/** + * + * @author ETj (etj at geo-solutions.it) + */ +public class JDOMBuilder { + + private final static Logger LOGGER = Logger.getLogger(JDOMBuilder.class); + + public static Element buildElement(String response) { + if(response == null) + return null; + + try{ + SAXBuilder builder = new SAXBuilder(); + Document doc = builder.build(new StringReader(response)); + return doc.getRootElement(); + } catch (JDOMException ex) { + LOGGER.warn("Ex parsing response", ex); + } catch (IOException ex) { + LOGGER.warn("Ex loading response", ex); + } + + return null; + } + +} diff --git a/src/main/java/it/geosolutions/geoserver/rest/decoder/utils/JDOMListIterator.java b/src/main/java/it/geosolutions/geoserver/rest/decoder/utils/JDOMListIterator.java new file mode 100644 index 0000000..b36272c --- /dev/null +++ b/src/main/java/it/geosolutions/geoserver/rest/decoder/utils/JDOMListIterator.java @@ -0,0 +1,57 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2007,2011 GeoSolutions S.A.S. + * http://www.geo-solutions.it + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package it.geosolutions.geoserver.rest.decoder.utils; + +import java.util.Iterator; +import java.util.List; +import org.jdom.Element; + +/** + * + * @author ETj (etj at geo-solutions.it) + */ +public abstract class JDOMListIterator implements Iterator { + + private final Iterator iter; + + public JDOMListIterator(List orig) { + iter = orig.iterator(); + } + + public boolean hasNext() { + return iter.hasNext(); + } + + public ELEM next() { + return transform(iter.next()); + } + + public abstract ELEM transform(Element listItem); + + public void remove() { + throw new UnsupportedOperationException("Not supported."); + } +} diff --git a/src/main/java/it/geosolutions/geoserver/rest/decoder/utils/NameLinkElem.java b/src/main/java/it/geosolutions/geoserver/rest/decoder/utils/NameLinkElem.java new file mode 100644 index 0000000..0c77393 --- /dev/null +++ b/src/main/java/it/geosolutions/geoserver/rest/decoder/utils/NameLinkElem.java @@ -0,0 +1,45 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2007,2011 GeoSolutions S.A.S. + * http://www.geo-solutions.it + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package it.geosolutions.geoserver.rest.decoder.utils; + +import org.jdom.Element; + +/** + * + * @author ETj (etj at geo-solutions.it) + */ +public class NameLinkElem { + private final Element elem; + + public NameLinkElem(Element elem) { + this.elem = elem; + } + + public String getName() { + return elem.getChildText("name"); + } + +} diff --git a/src/main/java/it/geosolutions/geoserver/rest/decoder/utils/package.html b/src/main/java/it/geosolutions/geoserver/rest/decoder/utils/package.html new file mode 100644 index 0000000..ceb81b2 --- /dev/null +++ b/src/main/java/it/geosolutions/geoserver/rest/decoder/utils/package.html @@ -0,0 +1,3 @@ + +Some util classes. + \ No newline at end of file diff --git a/src/main/java/it/geosolutions/geoserver/rest/encoder/GSCoverageEncoder.java b/src/main/java/it/geosolutions/geoserver/rest/encoder/GSCoverageEncoder.java new file mode 100644 index 0000000..542c644 --- /dev/null +++ b/src/main/java/it/geosolutions/geoserver/rest/encoder/GSCoverageEncoder.java @@ -0,0 +1,42 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2007,2011 GeoSolutions S.A.S. + * http://www.geo-solutions.it + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package it.geosolutions.geoserver.rest.encoder; + +/** + * + * @author ETj (etj at geo-solutions.it) + */ +public class GSCoverageEncoder extends PropertyXMLEncoder { + + public GSCoverageEncoder() { + super("coverage"); + set("enabled", "true"); + } + + public void setSRS(String srs) { + setOrRemove("srs", srs); + } +} diff --git a/src/main/java/it/geosolutions/geoserver/rest/encoder/GSFeatureTypeEncoder.java b/src/main/java/it/geosolutions/geoserver/rest/encoder/GSFeatureTypeEncoder.java new file mode 100644 index 0000000..8e6ae0c --- /dev/null +++ b/src/main/java/it/geosolutions/geoserver/rest/encoder/GSFeatureTypeEncoder.java @@ -0,0 +1,51 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2007,2011 GeoSolutions S.A.S. + * http://www.geo-solutions.it + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package it.geosolutions.geoserver.rest.encoder; + +/** + * + * @author ETj (etj at geo-solutions.it) + */ +public class GSFeatureTypeEncoder extends PropertyXMLEncoder { + + public GSFeatureTypeEncoder() { + super("featureType"); + set("enabled", "true"); + } + + public void setName(String name) { + setOrRemove("name", name); + } + + public void setSRS(String srs) { + setOrRemove("srs", srs); + } + +// public void setNativeCRS(String crs) { +// setOrRemove("nativeCRS", crs); +// } + +} \ No newline at end of file diff --git a/src/main/java/it/geosolutions/geoserver/rest/encoder/GSLayerEncoder.java b/src/main/java/it/geosolutions/geoserver/rest/encoder/GSLayerEncoder.java new file mode 100644 index 0000000..0ae7c83 --- /dev/null +++ b/src/main/java/it/geosolutions/geoserver/rest/encoder/GSLayerEncoder.java @@ -0,0 +1,47 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2007,2011 GeoSolutions S.A.S. + * http://www.geo-solutions.it + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package it.geosolutions.geoserver.rest.encoder; + +/** + * + * @author ETj (etj at geo-solutions.it) + */ +public class GSLayerEncoder extends PropertyXMLEncoder { + + public GSLayerEncoder() { + super("layer"); + set("enabled", "true"); + } + + public void setWmsPath(String wmspath) { + setOrRemove("wmspath", wmspath); + } + + public void setDefaultStyle(String defaultStyle) { + setOrRemove("defaultStyle", defaultStyle); + } + +} diff --git a/src/main/java/it/geosolutions/geoserver/rest/encoder/GSWorkspaceEncoder.java b/src/main/java/it/geosolutions/geoserver/rest/encoder/GSWorkspaceEncoder.java new file mode 100644 index 0000000..350a9ce --- /dev/null +++ b/src/main/java/it/geosolutions/geoserver/rest/encoder/GSWorkspaceEncoder.java @@ -0,0 +1,47 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2007,2011 GeoSolutions S.A.S. + * http://www.geo-solutions.it + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package it.geosolutions.geoserver.rest.encoder; + +/** + * + * @author ETj (etj at geo-solutions.it) + */ +public class GSWorkspaceEncoder extends PropertyXMLEncoder { + + public GSWorkspaceEncoder() { + super("workspace"); + } + + public GSWorkspaceEncoder(String name) { + this(); + setName(name); + } + + public void setName(String name) { + setOrRemove("name", name); + } + +} \ No newline at end of file diff --git a/src/main/java/it/geosolutions/geoserver/rest/encoder/PropertyXMLEncoder.java b/src/main/java/it/geosolutions/geoserver/rest/encoder/PropertyXMLEncoder.java new file mode 100644 index 0000000..a17e655 --- /dev/null +++ b/src/main/java/it/geosolutions/geoserver/rest/encoder/PropertyXMLEncoder.java @@ -0,0 +1,101 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2007,2011 GeoSolutions S.A.S. + * http://www.geo-solutions.it + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package it.geosolutions.geoserver.rest.encoder; + +import java.util.HashMap; +import java.util.Map; +import org.jdom.Element; +import org.jdom.output.Format; +import org.jdom.output.XMLOutputter; + +/** + * Creates an XML document by mapping properties to XML nodes.
+ * You can set the root element in the constructor. + * Any key/value pair will be encoded as value node. + * Any key containing one or more slash ("/") will be encoded as nested nodes; + *

e.g.:

+ *
 {@code key = "k1/k2/k3", value = "value" }
+ * will be encoded as + *
 {@code value }
+ * + * @author ETj (etj at geo-solutions.it) + */ +public class PropertyXMLEncoder { + + private final static XMLOutputter OUTPUTTER = new XMLOutputter(Format.getCompactFormat()); + private final Map configElements = new HashMap(); + private final String rootName; + + public PropertyXMLEncoder(String rootName) { + this.rootName = rootName; + } + + protected void setOrRemove(String key, String value) { + if (value != null) { + configElements.put(key, value); + } else { + configElements.remove(key); + } + } + + protected void set(String key, String value) { + setOrRemove(key, value); + } + + public boolean isEmpty() { + return configElements.isEmpty(); + } + + public String encodeXml() { + + Element layer = new Element(rootName); + for (String key : configElements.keySet()) { + final String value = configElements.get(key); + add(layer, key, value); + } + + return OUTPUTTER.outputString(layer); + } + + private void add(Element e, String key, String value) { + if( ! key.contains("/") ) { + e.addContent(new Element(key).setText(value)); + } else { + int i = key.indexOf("/"); + String childName = key.substring(0,i); + String newkey = key.substring(i+1); + + Element child = e.getChild(childName); + if(child == null) { + child = new Element(childName); + e.addContent(child); + } + + add(child, newkey, value); + } + + } +} diff --git a/src/main/java/it/geosolutions/geoserver/rest/encoder/package.html b/src/main/java/it/geosolutions/geoserver/rest/encoder/package.html new file mode 100644 index 0000000..0ef2892 --- /dev/null +++ b/src/main/java/it/geosolutions/geoserver/rest/encoder/package.html @@ -0,0 +1,5 @@ + +Encoders for GeoServer's beans. +Only some setters are available; there were developed only the most used setters, +in order not to replicate the whole GeoServer beans hierarchy. + \ No newline at end of file diff --git a/src/main/java/it/geosolutions/geoserver/rest/package.html b/src/main/java/it/geosolutions/geoserver/rest/package.html new file mode 100644 index 0000000..e6cf841 --- /dev/null +++ b/src/main/java/it/geosolutions/geoserver/rest/package.html @@ -0,0 +1,3 @@ + +Main GSManager classes are here. + \ No newline at end of file diff --git a/src/test/java/it/geosolutions/geoserver/rest/ConfigTest.java b/src/test/java/it/geosolutions/geoserver/rest/ConfigTest.java new file mode 100644 index 0000000..73aa895 --- /dev/null +++ b/src/test/java/it/geosolutions/geoserver/rest/ConfigTest.java @@ -0,0 +1,114 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2007,2011 GeoSolutions S.A.S. + * http://www.geo-solutions.it + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package it.geosolutions.geoserver.rest; + + +import it.geosolutions.geoserver.rest.decoder.RESTCoverageStore; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FilenameFilter; +import java.io.IOException; + +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.io.filefilter.SuffixFileFilter; +import org.apache.log4j.Logger; +import org.springframework.core.io.ClassPathResource; + +/** + * Testcase for publishing layers on geoserver. + * We need a running GeoServer to properly run the tests. + * Login credentials are hardcoded at the moment (localhost:8080 admin/geoserver). + * If such geoserver instance cannot be contacted, tests will be skipped. + * + * + * @author etj + */ +public class ConfigTest extends GeoserverRESTTest { + private final static Logger LOGGER = Logger.getLogger(ConfigTest.class); + + private static final String DEFAULT_WS = "it.geosolutions"; + + + public ConfigTest(String testName) { + super(testName); + } + + public void testEtj() throws FileNotFoundException, IOException { + if (!enabled()) return; + deleteAll(); + + assertTrue(reader.getWorkspaces().isEmpty()); + assertTrue(publisher.createWorkspace(DEFAULT_WS)); + + insertStyles(); + insertExternalGeotiff(); + insertExternalShape(); + + boolean ok = publisher.publishDBLayer(DEFAULT_WS, "pg_kids", "easia_gaul_0_aggr", "EPSG:4326", "default_polygon"); +// assertTrue(ok); + } + + public void insertStyles() throws FileNotFoundException, IOException { + + File sldDir = new ClassPathResource("testdata").getFile(); + for(File sldFile : sldDir.listFiles((FilenameFilter)new SuffixFileFilter(".sld"))) { + LOGGER.info("Existing styles: " + reader.getStyles().getNames()); + String basename = FilenameUtils.getBaseName(sldFile.toString()); + LOGGER.info("Publishing style " + sldFile + " as " + basename); + assertTrue("Cound not publish " + sldFile, publisher.publishStyle(sldFile, basename)); + } + } + + + public void insertExternalGeotiff() throws FileNotFoundException, IOException { + + String storeName = "testRESTStoreGeotiff"; + String layerName = "resttestdem"; + + File geotiff = new ClassPathResource("testdata/resttestdem.tif").getFile(); + RESTCoverageStore pc = publisher.publishExternalGeoTIFF(DEFAULT_WS, storeName, geotiff, null, null); + + assertNotNull(pc); + } + + public void insertExternalShape() throws FileNotFoundException, IOException { + + File zipFile = new ClassPathResource("testdata/resttestshp.zip").getFile(); + + boolean published = publisher.publishShp(DEFAULT_WS, "anyname", "cities", zipFile, "EPSG:4326", "default_point"); + assertTrue("publish() failed", published); + + + //test delete + boolean ok = publisher.unpublishFeatureType(DEFAULT_WS, "anyname", "cities"); + assertTrue("Unpublish() failed", ok); + // remove also datastore + boolean dsRemoved = publisher.removeDatastore(DEFAULT_WS, "anyname"); + assertTrue("removeDatastore() failed", dsRemoved); + } + +} \ No newline at end of file diff --git a/src/test/java/it/geosolutions/geoserver/rest/GeoserverRESTPublisherTest.java b/src/test/java/it/geosolutions/geoserver/rest/GeoserverRESTPublisherTest.java new file mode 100644 index 0000000..e83d082 --- /dev/null +++ b/src/test/java/it/geosolutions/geoserver/rest/GeoserverRESTPublisherTest.java @@ -0,0 +1,334 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2007,2011 GeoSolutions S.A.S. + * http://www.geo-solutions.it + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package it.geosolutions.geoserver.rest; + +import it.geosolutions.geoserver.rest.decoder.RESTLayer; +import it.geosolutions.geoserver.rest.decoder.RESTCoverageStore; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; + +import org.apache.commons.io.IOUtils; +import org.apache.log4j.Logger; +import org.springframework.core.io.ClassPathResource; + +/** + * Testcase for publishing layers on geoserver. + * We need a running GeoServer to properly run the tests. + * If such geoserver instance cannot be contacted, tests will be skipped. + * + * @author etj + */ +public class GeoserverRESTPublisherTest extends GeoserverRESTTest { + + private final static Logger LOGGER = Logger.getLogger(GeoserverRESTPublisherTest.class); + private static final String DEFAULT_WS = "it.geosolutions"; + + public GeoserverRESTPublisherTest(String testName) { + super(testName); + } + + public void testWorkspaces() { + if (!enabled()) return; + deleteAll(); + + assertEquals(0, reader.getWorkspaces().size()); + + assertTrue(publisher.createWorkspace("WS1")); + assertTrue(publisher.createWorkspace("WS2")); + assertEquals(2, reader.getWorkspaces().size()); + + assertFalse(publisher.createWorkspace("WS2")); + assertEquals(2, reader.getWorkspaces().size()); + } + + public void testStyles() throws IOException { + if (!enabled()) return; + deleteAll(); + + assertEquals(0, reader.getStyles().size()); + + final String styleName = "restteststyle"; + File sldFile = new ClassPathResource("testdata/restteststyle.sld").getFile(); + + // insert style + assertTrue(publisher.publishStyle(sldFile)); + assertTrue(reader.existsStyle(styleName)); + + assertFalse(publisher.publishStyle(sldFile)); + assertTrue(reader.existsStyle(styleName)); + + String sld = reader.getSLD(styleName); + assertNotNull(sld); + assertEquals(1475, sld.length()); + + assertEquals(1, reader.getStyles().size()); + } + + public void testExternalGeotiff() throws FileNotFoundException, IOException { + if (!enabled()) return; + deleteAll(); + + String storeName = "testRESTStoreGeotiff"; + String layerName = "resttestdem"; + + assertTrue(reader.getWorkspaces().isEmpty()); + assertTrue(publisher.createWorkspace(DEFAULT_WS)); + + File geotiff = new ClassPathResource("testdata/resttestdem.tif").getFile(); + + // known state? + assertFalse("Cleanup failed", existsLayer(layerName)); + + // test insert + RESTCoverageStore pc = publisher.publishExternalGeoTIFF(DEFAULT_WS, storeName, geotiff, null, null); + assertNotNull("publish() failed", pc); + assertTrue(existsLayer(layerName)); + LOGGER.info(pc); + RESTCoverageStore reloadedCS = reader.getCoverageStore(DEFAULT_WS, storeName); + + assertEquals(pc.getName(), reloadedCS.getName()); + assertEquals(pc.getWorkspaceName(), reloadedCS.getWorkspaceName()); + + //test delete + assertTrue("Unpublish() failed", publisher.unpublishCoverage(DEFAULT_WS, storeName, layerName)); + assertTrue("Unpublish() failed", publisher.removeCoverageStore(DEFAULT_WS, storeName)); + assertFalse("Bad unpublish()", publisher.unpublishCoverage(DEFAULT_WS, storeName, layerName)); + assertFalse(existsLayer(layerName)); + } + + protected void cleanupTestFT(String layerName, String ns, String storeName) { + // dry run delete to work in a known state + RESTLayer testLayer = reader.getLayer(layerName); + if (testLayer != null) { + LOGGER.info("Clearing stale test layer " + layerName); + boolean ok = publisher.unpublishFeatureType(ns, storeName, layerName); + if (!ok) { + fail("Could not unpublish layer " + layerName); + } + } + if (publisher.removeDatastore(ns, storeName)) { + LOGGER.info("Cleared stale datastore " + storeName); + } + assertFalse("Cleanup failed", existsLayer(layerName)); + } + + protected void cleanupTestStyle(final String styleName) { + // dry run delete to work in a known state + if (reader.existsStyle(styleName)) { + LOGGER.info("Clearing stale test style " + styleName); + boolean ok = publisher.removeStyle(styleName); + if (!ok) { + fail("Could not unpublish style " + styleName); + } + } + assertFalse("Cleanup failed", reader.existsStyle(styleName)); + } + + public void testPublishDeleteShapeZip() throws FileNotFoundException, IOException { + if (!enabled()) { + return; + } +// Assume.assumeTrue(enabled); + + String ns = "it.geosolutions"; + String storeName = "resttestshp"; + String layerName = "cities"; + + File zipFile = new ClassPathResource("testdata/resttestshp.zip").getFile(); + + // known state? + cleanupTestFT(layerName, ns, storeName); + + // test insert + boolean published = publisher.publishShp(ns, storeName, layerName, zipFile); + assertTrue("publish() failed", published); + assertTrue(existsLayer(layerName)); + + RESTLayer layer = reader.getLayer(layerName); + + LOGGER.info("Layer style is " + layer.getDefaultStyle()); + + //test delete + boolean ok = publisher.unpublishFeatureType(ns, storeName, layerName); + assertTrue("Unpublish() failed", ok); + assertFalse(existsLayer(layerName)); + + // remove also datastore + boolean dsRemoved = publisher.removeDatastore(ns, storeName); + assertTrue("removeDatastore() failed", dsRemoved); + + } + + public void testPublishDeleteStyledShapeZip() throws FileNotFoundException, IOException { + if (!enabled()) { + return; + } +// Assume.assumeTrue(enabled); + + String ns = "it.geosolutions"; + String storeName = "resttestshp"; + String layerName = "cities"; + + File zipFile = new ClassPathResource("testdata/resttestshp.zip").getFile(); + cleanupTestFT(layerName, ns, storeName); + + final String styleName = "restteststyle"; + File sldFile = new ClassPathResource("testdata/restteststyle.sld").getFile(); + cleanupTestStyle(styleName); + + // insert style + boolean sldpublished = publisher.publishStyle(sldFile); // Will take the name from sld contents + assertTrue("style publish() failed", sldpublished); + assertTrue(reader.existsStyle(styleName)); + + // test insert + boolean published = publisher.publishShp(ns, storeName, layerName, zipFile, "EPSG:4326", styleName); + assertTrue("publish() failed", published); + assertTrue(existsLayer(layerName)); + + RESTLayer layer = reader.getLayer(layerName); +// RESTLayer layerDecoder = new RESTLayer(layer); + LOGGER.info("Layer style is " + layer.getDefaultStyle()); + assertEquals("Style not assigned properly", styleName, layer.getDefaultStyle()); + + //test delete + boolean ok = publisher.unpublishFeatureType(ns, storeName, layerName); + assertTrue("Unpublish() failed", ok); + assertFalse(existsLayer(layerName)); + + // remove also datastore + boolean dsRemoved = publisher.removeDatastore(ns, storeName); + assertTrue("removeDatastore() failed", dsRemoved); + + //test delete style + boolean oksld = publisher.removeStyle(styleName); + assertTrue("Unpublish() failed", oksld); + assertFalse(reader.existsStyle(styleName)); + } + + public void testPublishDeleteStyleFile() throws FileNotFoundException, IOException { + if (!enabled()) { + return; + } +// Assume.assumeTrue(enabled); + final String styleName = "restteststyle"; + + File sldFile = new ClassPathResource("testdata/restteststyle.sld").getFile(); + + // known state? + cleanupTestStyle(styleName); + + // test insert + boolean published = publisher.publishStyle(sldFile); // Will take the name from sld contents + assertTrue("publish() failed", published); + assertTrue(reader.existsStyle(styleName)); + + //test delete + boolean ok = publisher.removeStyle(styleName); + assertTrue("Unpublish() failed", ok); + assertFalse(reader.existsStyle(styleName)); + } + + public void testPublishDeleteStyleString() throws FileNotFoundException, IOException { + if (!enabled()) { + return; + } +// Assume.assumeTrue(enabled); + final String styleName = "restteststyle"; + + File sldFile = new ClassPathResource("testdata/restteststyle.sld").getFile(); + + // known state? + cleanupTestStyle(styleName); + + // test insert + String sldContent = IOUtils.toString(new FileInputStream(sldFile)); + + boolean published = publisher.publishStyle(sldContent); // Will take the name from sld contents + assertTrue("publish() failed", published); + assertTrue(reader.existsStyle(styleName)); + + //test delete + boolean ok = publisher.removeStyle(styleName); + assertTrue("Unpublish() failed", ok); + assertFalse(reader.existsStyle(styleName)); + } + + public void testDeleteUnexistingCoverage() throws FileNotFoundException, IOException { + if (!enabled()) { + return; + } +// Assume.assumeTrue(enabled); + + String wsName = "this_ws_does_not_exist"; + String storeName = "this_store_does_not_exist"; + String layerName = "this_layer_does_not_exist"; + + boolean ok = publisher.unpublishCoverage(wsName, storeName, layerName); + assertFalse("unpublished not existing layer", ok); + } + + public void testDeleteUnexistingFeatureType() throws FileNotFoundException, IOException { + if (!enabled()) { + return; + } +// Assume.assumeTrue(enabled); + + String wsName = "this_ws_does_not_exist"; + String storeName = "this_store_does_not_exist"; + String layerName = "this_layer_does_not_exist"; + + boolean ok = publisher.unpublishFeatureType(wsName, storeName, layerName); + assertFalse("unpublished not existing layer", ok); + } + + public void testDeleteUnexistingDatastore() throws FileNotFoundException, IOException { + if (!enabled()) { + return; + } +// Assume.assumeTrue(enabled); + + String wsName = "this_ws_does_not_exist"; + String storeName = "this_store_does_not_exist"; + + boolean ok = publisher.removeDatastore(wsName, storeName); + assertFalse("removed not existing datastore", ok); + } + +// public void testDeleteUnexistingFT() throws FileNotFoundException, IOException { +// String wsName = "this_ws_does_not_exist"; +// String storeName = "this_store_does_not_exist"; +// String layerName = "this_layer_does_not_exist"; +// +// boolean ok = publisher.unpublishFT(wsName, storeName, layerName); +// assertFalse("unpublished not existing layer", ok); +// } + private boolean existsLayer(String layername) { + return reader.getLayer(layername) != null; + } +} diff --git a/src/test/java/it/geosolutions/geoserver/rest/GeoserverRESTReaderTest.java b/src/test/java/it/geosolutions/geoserver/rest/GeoserverRESTReaderTest.java new file mode 100644 index 0000000..d92739c --- /dev/null +++ b/src/test/java/it/geosolutions/geoserver/rest/GeoserverRESTReaderTest.java @@ -0,0 +1,203 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2007,2011 GeoSolutions S.A.S. + * http://www.geo-solutions.it + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package it.geosolutions.geoserver.rest; + +import it.geosolutions.geoserver.rest.decoder.utils.NameLinkElem; +import it.geosolutions.geoserver.rest.decoder.RESTDataStoreList; +import it.geosolutions.geoserver.rest.decoder.RESTDataStore; +import it.geosolutions.geoserver.rest.decoder.RESTLayerList; +import it.geosolutions.geoserver.rest.decoder.RESTNamespaceList; +import it.geosolutions.geoserver.rest.decoder.RESTWorkspaceList; +import java.util.List; + + +/** + * + * @author etj + */ +public class GeoserverRESTReaderTest extends GeoserverRESTTest { + + public GeoserverRESTReaderTest(String testName) { + super(testName); + } + + /** + * Test of getLayers method, of class GeoServerRESTReader. + */ + public void testGetLayers() { + if(!enabled()) return; + + RESTLayerList result = reader.getLayers(); + assertNotNull(result); +// assertEquals(/*CHANGEME*/19, result.getChildren("layer").size()); // value in default gs installation + +// System.out.println("Layers:" + result.getChildren("layer").size()); + System.out.println("Layers:" + result.size()); + System.out.print("Layers:" ); + for (NameLinkElem shlayer : result) { + assertNotNull(shlayer.getName()); + System.out.print(shlayer.getName() + " "); + } +// for (Element layer : (List)result.getChildren("layer")) { +// System.out.print(layer.getChildText("name") + " "); +// } + System.out.println(); + } + + /** + * Test of getDatastores method, of class GeoServerRESTReader. + */ + public void testGetDatastores() { + if(!enabled()) return; + + RESTWorkspaceList wslist = reader.getWorkspaces(); + assertNotNull(wslist); +// assertEquals(7, wslist.size()); // value in default gs installation + + System.out.println("Workspaces: " + wslist.size()); + int dsnum = 0; + for (RESTWorkspaceList.RESTShortWorkspace ws : wslist) { + System.out.println("Getting DSlist for WS " + ws.getName() + "..." ); + RESTDataStoreList result = reader.getDatastores(ws.getName()); + assertNotNull(result); + dsnum += result.size(); + for (NameLinkElem ds : result) { + assertNotNull(ds.getName()); + System.out.print(ds.getName() + " " ); + RESTDataStore datastore = reader.getDatastore(ws.getName(), ds.getName()); + assertNotNull(datastore); + assertEquals(ds.getName(), datastore.getName()); + assertEquals(ws.getName(), datastore.getWorkspaceName()); + } + System.out.println(); + } + System.out.println(); + System.out.println("Datastores:" + dsnum); // value in default gs installation +// assertEquals(4, dsnum); // value in default gs installation + + } + + public void testGetWSDSNames() { + if(!enabled()) + return; + + RESTWorkspaceList wslist = reader.getWorkspaces(); + assertNotNull(wslist); +// assertEquals(7, wslist.size()); // value in default gs installation + + List wsnames = reader.getWorkspaceNames(); + assertNotNull(wsnames); +// assertEquals(7, wsnames.size()); // value in default gs installation + +// System.out.println("Workspaces: " + wslist.size()); + int dsnum = 0; + int wscnt = 0; + for (RESTWorkspaceList.RESTShortWorkspace ws : wslist) { + String wsname = wsnames.get(wscnt++); + + List dsnames = reader.getDatastores(wsname).getNames(); + RESTDataStoreList dslist = reader.getDatastores(ws.getName()); + assertNotNull(dsnames); + assertNotNull(dslist); + assertEquals(dsnames.size(), dslist.size()); + } + } + + /** + * Test of getDatastore method, of class GeoServerRESTReader. + */ + public void testGetDatastore() { + //tested in testGetDatastores() + } + + /** + * Test of getLayer method, of class GeoServerRESTReader. + */ + public void testGetLayer() { + } + + /** + * Test of getNamespaceNames method, of class GeoServerRESTReader. + */ + public void testGetNamespaces() { + if(!enabled()) return; + + RESTNamespaceList result = reader.getNamespaces(); + List names = reader.getNamespaceNames(); + assertNotNull(result); +// assertEquals(7, result.size()); // value in default gs installation + assertNotNull(names); + assertEquals(names.size(), result.size()); // value in default gs installation + + System.out.println("Namespaces:" + result.size()); + System.out.print("Namespaces:" ); + int namesIdx = 0; + for (RESTNamespaceList.RESTShortNamespace ns : result) { + assertEquals("namespace mismatch", names.get(namesIdx++), ns.getName()); + System.out.print(ns.getName() + " " ); + } + System.out.println(); + } + + + /** + * Test of getWorkspaceNames method, of class GeoServerRESTReader. + */ + public void testGetWorkspaces() { + if(!enabled()) return; + + RESTWorkspaceList wslist = reader.getWorkspaces(); + assertNotNull(wslist); +// assertEquals(7, wslist.size()); // value in default gs installation + + System.out.println("Workspaces:" + wslist.size()); + System.out.print("Workspaces:"); + for (RESTWorkspaceList.RESTShortWorkspace ws : wslist) { + System.out.print(ws.getName() + " "); + } + System.out.println(); + + assertEquals(wslist.size(), reader.getWorkspaceNames().size()); + } + /** + * Test of getWorkspaceNames method, of class GeoServerRESTReader. + */ + public void testGetWorkspaceNames() { + if(!enabled()) return; + + List names = reader.getWorkspaceNames(); + assertNotNull(names); +// assertEquals(7, names.size()); // value in default gs installation + + System.out.println("Workspaces:" + names.size()); + System.out.print("Workspaces:"); + for (String name : names) { + System.out.print(name + " "); + } + System.out.println(); + } + +} diff --git a/src/test/java/it/geosolutions/geoserver/rest/GeoserverRESTTest.java b/src/test/java/it/geosolutions/geoserver/rest/GeoserverRESTTest.java new file mode 100644 index 0000000..2d50bac --- /dev/null +++ b/src/test/java/it/geosolutions/geoserver/rest/GeoserverRESTTest.java @@ -0,0 +1,257 @@ +/* + * GeoServer-Manager - Simple Manager Library for GeoServer + * + * Copyright (C) 2007,2011 GeoSolutions S.A.S. + * http://www.geo-solutions.it + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package it.geosolutions.geoserver.rest; + +import it.geosolutions.geoserver.rest.decoder.utils.NameLinkElem; +import it.geosolutions.geoserver.rest.decoder.RESTCoverage; +import it.geosolutions.geoserver.rest.decoder.RESTCoverageStore; +import it.geosolutions.geoserver.rest.decoder.RESTDataStore; +import it.geosolutions.geoserver.rest.decoder.RESTFeatureType; +import it.geosolutions.geoserver.rest.decoder.RESTLayer; +import it.geosolutions.geoserver.rest.decoder.RESTLayerGroup; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.List; + +import junit.framework.TestCase; +import org.apache.log4j.Logger; + +/** + * Initializes REST params. + *

+ * Default target geoserver instance is at http://localhost:8080/geoserver. + *
Connection parameters can be customized by defining env vars + * resturl, restuser, restpw, + * + * @author etj + */ +public abstract class GeoserverRESTTest extends TestCase { + private final static Logger LOGGER = Logger.getLogger(GeoserverRESTTest.class); + + public static final String RESTURL; + public static final String RESTUSER; + public static final String RESTPW; + + public static final URL URL; + public static final GeoServerRESTReader reader; + public static final GeoServerRESTPublisher publisher; + + private static boolean enabled = false; + + static { + RESTURL = System.getProperty("resturl", "http://localhost:8080/geoserver"); + RESTUSER = System.getProperty("restuser", "admin"); + RESTPW = System.getProperty("restpw", "geoserver"); + + // These tests will destroy data, so let's make sure we do want to run them + enabled = System.getProperty("resttest", "false").equalsIgnoreCase("true"); + if( ! enabled ) + LOGGER.warn("Tests are disabled. Please read the documentation to enable them."); + + URL lurl = null; + try { + lurl = new URL(RESTURL); + } catch (MalformedURLException ex) { + } + + URL = lurl; + reader = new GeoServerRESTReader(lurl, RESTUSER, RESTPW); + publisher = new GeoServerRESTPublisher(RESTURL, RESTUSER, RESTPW); + } + + public GeoserverRESTTest(String testName) { + super(testName); + } + + + @Override + protected void setUp() throws Exception { + super.setUp(); + + if(enabled) { + if( ! reader.existGeoserver()) { + System.out.println(getClass().getSimpleName() + ": TESTS WILL BE SKIPPED SINCE NO GEOSERVER WAS FOUND AT " + RESTURL + " ("+ RESTUSER+":"+RESTPW+")"); + enabled = false; + } else { + System.out.println(getClass().getSimpleName() + ": using geoserver instance " + RESTUSER+":"+RESTPW+ " @ " + RESTURL); + } + } + + if(enabled) + System.out.println("\n-------------------> RUNNING TEST " + this.getName()); + else + System.out.println("Skipping test " + this.getClass().getSimpleName() + "::" + this.getName()); + } + + protected boolean enabled() { + return enabled; + } + + protected void deleteAll() { + LOGGER.info("Starting DELETEALL procedure"); + deleteAllLayerGroups(); + assertTrue("Some layergroups were not removed", reader.getLayerGroups().isEmpty()); + + deleteAllLayers(); + assertTrue("Some layers were not removed", reader.getLayers().isEmpty()); + + deleteAllCoverageStores(); + deleteAllDataStores(); + + deleteAllWorkspaces(); +// assertTrue("Some workspaces were not removed", reader.getWorkspaces().isEmpty()); + + deleteAllStyles(); + assertTrue("Some styles were not removed", reader.getStyles().isEmpty()); + + LOGGER.info("ENDING DELETEALL procedure"); + } + + private void deleteAllLayerGroups() { + List groups = reader.getLayerGroups().getNames(); + LOGGER.info("Found " + groups.size() + " layerGroups"); + for (String groupName : groups) { + RESTLayerGroup group = reader.getLayerGroup(groupName); + StringBuilder sb = new StringBuilder("Group: ").append(groupName).append(":"); + for (NameLinkElem layer : group.getLayerList()) { + sb.append(" ").append(layer); + } + + boolean removed = publisher.removeLayerGroup(groupName); + LOGGER.info(sb.toString()+ ": removed: " + removed); + assertTrue("LayerGroup not removed: " + groupName, removed); + } + + } + + private void deleteAllLayers() { + List layers = reader.getLayers().getNames(); + for (String layerName : layers) { + RESTLayer layer = reader.getLayer(layerName); + if(layer.getType() == RESTLayer.TYPE.VECTOR) + deleteFeatureType(layer); + else if(layer.getType() == RESTLayer.TYPE.RASTER) + deleteCoverage(layer); + else + LOGGER.error("Unknown layer type " + layer.getType()); + } + + } + + private void deleteAllCoverageStores() { + List workspaces = reader.getWorkspaceNames(); + for (String workspace : workspaces) { + List stores = reader.getCoverageStores(workspace).getNames(); + + for (String storename : stores) { +// RESTCoverageStore store = reader.getCoverageStore(workspace, storename); + + LOGGER.warn("Deleting CoverageStore " + workspace + " : " + storename); + boolean removed = publisher.removeCoverageStore(workspace, storename); + assertTrue("CoverageStore not removed " + workspace + " : " + storename, removed); + } + } + } + + private void deleteAllDataStores() { + List workspaces = reader.getWorkspaceNames(); + for (String workspace : workspaces) { + List stores = reader.getDatastores(workspace).getNames(); + + for (String storename : stores) { + RESTDataStore store = reader.getDatastore(workspace, storename); + +// if(store.getType() == RESTDataStore.DBType.POSTGIS) { +// LOGGER.info("Skipping PG datastore " + store.getWorkspaceName()+":"+store.getName()); +// continue; +// } + + LOGGER.warn("Deleting DataStore " + workspace + " : " + storename); + boolean removed = publisher.removeDatastore(workspace, storename); + assertTrue("DataStore not removed " + workspace + " : " + storename, removed); + } + } + } + + private void deleteAllWorkspaces() { + List workspaces = reader.getWorkspaceNames(); + for (String workspace : workspaces) { + LOGGER.warn("Deleting Workspace " + workspace ); + boolean removed = publisher.removeWorkspace(workspace); + assertTrue("Workspace not removed " + workspace, removed ); + + } + } + + private void deleteAllStyles() { + List styles = reader.getStyles().getNames(); + for (String style : styles) { + LOGGER.warn("Deleting Style " + style ); + boolean removed = publisher.removeStyle(style); + assertTrue("Style not removed " + style, removed ); + + } + } + + private void deleteFeatureType(RESTLayer layer) { + RESTFeatureType featureType = reader.getFeatureType(layer); + RESTDataStore datastore = reader.getDatastore(featureType); + + LOGGER.warn("Deleting FeatureType" + + datastore.getWorkspaceName() + " : " + + datastore.getName() + " / " + + featureType.getName() + ); + + boolean removed = publisher.unpublishFeatureType(datastore.getWorkspaceName(), datastore.getName(), layer.getName()); + assertTrue("FeatureType not removed:" + + datastore.getWorkspaceName() + " : " + + datastore.getName() + " / " + + featureType.getName(), + removed); + + } + + private void deleteCoverage(RESTLayer layer) { + RESTCoverage coverage = reader.getCoverage(layer); + RESTCoverageStore coverageStore = reader.getCoverageStore(coverage); + + LOGGER.warn("Deleting Coverage " + + coverageStore.getWorkspaceName() + " : " + + coverageStore.getName() + " / " + + coverage.getName()); + + boolean removed = publisher.unpublishCoverage(coverageStore.getWorkspaceName(), + coverageStore.getName(), + coverage.getName()); + assertTrue("Coverage not deleted " + + coverageStore.getWorkspaceName() + " : " + + coverageStore.getName() + " / " + + coverage.getName(), + removed); + } + +} \ No newline at end of file diff --git a/src/test/resources/log4j.properties b/src/test/resources/log4j.properties new file mode 100644 index 0000000..fd784be --- /dev/null +++ b/src/test/resources/log4j.properties @@ -0,0 +1,11 @@ + +log4j.rootLogger=DEBUG, A1 +log4j.appender.A1=org.apache.log4j.ConsoleAppender +log4j.appender.A1.layout=org.apache.log4j.PatternLayout + +# Print the date in ISO 8601 format +log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c @ %L - %m%n + +log4j.logger.it.geosolutions.geobatch.geoserver=DEBUG +log4j.logger.org.apache.commons.httpclient=INFO +log4j.logger.httpclient.wire=INFO diff --git a/src/test/resources/testdata/default_line.sld b/src/test/resources/testdata/default_line.sld new file mode 100644 index 0000000..86170d5 --- /dev/null +++ b/src/test/resources/testdata/default_line.sld @@ -0,0 +1,39 @@ + + + + + + Default Line + + + + A boring default style + A sample style that just prints out a green line + + + + + + + Rule 1 + Green Line + A green line with a 2 pixel width + + + + + #0000FF + + + + + + + + + diff --git a/src/test/resources/testdata/default_point.sld b/src/test/resources/testdata/default_point.sld new file mode 100644 index 0000000..e57a1e9 --- /dev/null +++ b/src/test/resources/testdata/default_point.sld @@ -0,0 +1,45 @@ + + + + + + Default Point + + + + A boring default style + A sample style that just prints out a purple square + + + + + + + Rule 1 + RedSquare + A red fill with an 11 pixel size + + + + + + square + + #FF0000 + + + 6 + + + + + + + + + diff --git a/src/test/resources/testdata/default_polygon.sld b/src/test/resources/testdata/default_polygon.sld new file mode 100644 index 0000000..f485002 --- /dev/null +++ b/src/test/resources/testdata/default_polygon.sld @@ -0,0 +1,43 @@ + + + + + + Default Polygon + + + + A boring default style + A sample style that just prints out a transparent red interior with a red outline + + + + + + + Rule 1 + RedFill RedOutline + 50% transparent red fill with a red outline 1 pixel in width + + + + + #AAAAAA + + + #000000 + 1 + + + + + + + + + diff --git a/src/test/resources/testdata/raster.sld b/src/test/resources/testdata/raster.sld new file mode 100644 index 0000000..77141c8 --- /dev/null +++ b/src/test/resources/testdata/raster.sld @@ -0,0 +1,20 @@ + + + + raster_layer + + raster + A boring default style + A sample style for rasters + + Feature + + + 1.0 + + + + + + \ No newline at end of file diff --git a/src/test/resources/testdata/resttestdem.tif b/src/test/resources/testdata/resttestdem.tif new file mode 100644 index 0000000..49fa615 Binary files /dev/null and b/src/test/resources/testdata/resttestdem.tif differ diff --git a/src/test/resources/testdata/resttestshp.zip b/src/test/resources/testdata/resttestshp.zip new file mode 100644 index 0000000..07ac13a Binary files /dev/null and b/src/test/resources/testdata/resttestshp.zip differ diff --git a/src/test/resources/testdata/restteststyle.sld b/src/test/resources/testdata/restteststyle.sld new file mode 100644 index 0000000..01f2928 --- /dev/null +++ b/src/test/resources/testdata/restteststyle.sld @@ -0,0 +1,84 @@ + + + + country + + restteststyle + STYLE FOR TESTING PURPOSES + A sample style that just draws out a solid gray interior with a black 1px outline + + name + Feature + SemanticType[ANY] + + Polygon + + + + #C8B679 + + + 1.0 + + + + + #000000 + + + butt + + + miter + + + 1 + + + 1 + + + 0 + + + + + + CNTRYNAME + + + + Times New Roman + + + 14 + + + Normal + + + 400 + + + + + + 10 + + + + + + #000000 + + + 1.0 + + + + + + + + +