/* (c) 2014 - 2016 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.config;
import org.apache.commons.io.FileUtils;
import org.geoserver.catalog.*;
import org.geoserver.platform.GeoServerExtensions;
import org.geoserver.platform.GeoServerResourceLoader;
import org.geoserver.platform.resource.Paths;
import org.geoserver.platform.resource.Resource;
import org.geoserver.platform.resource.Resource.Type;
import org.geoserver.util.EntityResolverProvider;
import org.geoserver.platform.resource.ResourceStore;
import org.geoserver.platform.resource.Resources;
import org.geotools.data.DataUtilities;
import org.geotools.styling.*;
import org.xml.sax.EntityResolver;
import javax.annotation.Nonnull;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
/**
* File or Resource access to GeoServer data directory. In addition to paths Catalog obhjects such as workspace or FeatureTypeInfo can be used to
* locate resources.
* <p>
* Example usage:
*
* <pre>
* <code>
* GeoServerDataDirectory dd = new GeoServerDataDirectory(resourceLoader);
*
* //find some data
* File shp = dd.findDataFile( "shapefiles/somedata.shp" );
*
* //create a directory for some data
* File shapefiles = dd.findOrCreateDataDirectory("shapefiles");
*
* //find a template file for a feature type
* FeatureTypeInfo ftinfo = ...;
* File template = dd.findSuppResourceFile(ftinfo,"title.ftl");
* </code>
* </pre>
*
* </p>
*
* @author Justin Deoliveira, OpenGeo
*/
@SuppressWarnings("unused")
public class GeoServerDataDirectory {
/**
* resource loader
*/
GeoServerResourceLoader resourceLoader;
EntityResolverProvider entityResolverProvider;
/**
* Creates the data directory specifying the resource loader.
*/
public GeoServerDataDirectory(GeoServerResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
/**
* Creates the data directory specifying the base directory.
*/
public GeoServerDataDirectory(File baseDirectory) {
this(new GeoServerResourceLoader(baseDirectory));
}
/**
* Returns the underlying resource loader.
*/
public GeoServerResourceLoader getResourceLoader() {
return resourceLoader;
}
public Resource get(String path) {
return resourceLoader.get(path);
}
/**
* The root of the data directory.
*/
public File root() {
return resourceLoader.getBaseDirectory();
}
/**
* Returns a directory under the {@link #root()} directory, if the directory does not exist it will be created.
*
* @return directory (created if needed)
*/
public File findOrCreateDir(String... location) throws IOException {
return get(Paths.path(location)).dir();
}
/**
* Returns a file under the {@link #root()} directory, if the file does not exist null is returned.
*/
public File findFile(String... location) throws IOException {
Resource resource = get(Paths.path(location));
return Resources.find(resource);
}
/**
* Returns the root of the directory which contains spatial data files, if the directory does exist, null is returned.
* <p>
* This directory is called 'data', and is located directly under {@link #root()}
* </p>
*/
public File findDataRoot() throws IOException {
Resource directory = get("data");
return Resources.directory(directory);
}
/**
* Returns the root of the directory which contains spatial data files, if the directory does not exist it will be created.
* <p>
* This directory is called 'data', and is located directly under {@link #root()}
* </p>
*/
public File findOrCreateDataRoot() throws IOException {
Resource directory = get("data");
return directory.dir(); // will create directory as needed
}
/**
* Returns a directory under the {@link #dataRoot()} directory, if the directory does not exist null will be returned.
*/
public File findDataDir(String... location) throws IOException {
Resource resource = get(Paths.path("data", Paths.path(location)));
return Resources.directory(resource);
}
/**
* Returns a directory under the {@link #dataRoot()} directory, if the directory does not exist it will be created.
*/
public File findOrCreateDataDir(String... location) throws IOException {
Resource resource = get(Paths.path("data", Paths.path(location)));
return resource.dir();
}
/**
* Returns a directory under the {@link #dataRoot()} directory.
*
* @param create Create directory if needed
* @param location directory location
* @return Directory (which may be newly created) or null if not found
* @deprecated Unused
*/
private File dataDir(boolean create, String... location) throws IOException {
Resource directory = get(Paths.path("data", Paths.path(location)));
if (create) {
return directory.dir();
} else {
return Resources.directory(directory);
}
}
/**
* Returns a file under the {@link #dataRoot()} directory, if the file does not exist null is returned.
*/
public File findDataFile(String... location) throws IOException {
Resource resource = get(Paths.path("data", Paths.path(location)));
return Resources.file(resource);
}
/**
* Returns a file under the {@link #dataRoot()} directory, if the file does not exist it a file object will still be returned.
*
* @deprecated Unused
*/
public File findOrResolveDataFile(String... location) throws IOException {
Resource resource = get(Paths.path("data", Paths.path(location)));
return resource.file();
}
/**
* Returns a file under the {@link #dataRoot()} directory.
*
* @param create Create file (if required)
* @param location file location
* @return File (created if needed) or null if not found
* @deprecated Unused
*/
private File dataFile(boolean create, String... location) throws IOException {
Resource resource = get(Paths.path("data", Paths.path(location)));
if (create) {
return resource.file();
} else {
return Resources.file(resource);
}
}
/**
* Returns the root of the directory which contains security configuration files, if the directory does exist, null is returned.
* <p>
* This directory is called 'security', and is located directly under {@link #root()}
* </p>
* @deprecated As of GeoServer 2.6, replaced by @link {@link #getSecurity()}
*/
@Deprecated
public File findSecurityRoot() throws IOException {
return Resources.directory(getSecurity());
}
/**
* Returns the root of the directory which contains security configuration files, if the directory does exist it is created.
* <p>
* This directory is called 'security', and is located directly under {@link #root()}
*
* @deprecated As of GeoServer 2.6, replaced by @link {@link #getSecurity()}
*/
@Deprecated
public File findOrCreateSecurityRoot() throws IOException {
return getSecurity().dir(); // will create directory as needed
}
/**
* Access to security directory.
*
* @deprecated As of GeoServer 2.6, replaced by @link {@link #getSecurity()}
*/
@Deprecated
private File securityRoot(boolean create) throws IOException {
final Resource directory = getSecurity();
final File f;
if (create) {
f = directory.dir();
} else {
f = Resources.directory(directory);
}
return f;
}
/**
* Returns a directory under the {@link #securityRoot()} directory, if the directory does not exist null will be returned.
*
* @deprecated As of GeoServer 2.6, replaced by @link {@link #getSecurity()}
*/
@Deprecated
public File findSecurityDir(String... location) throws IOException {
return Resources.directory(getSecurity(location));
}
/**
* Returns a directory under the {@link #securityRoot()} directory, if the directory does not exist it will be created.
*
* @deprecated As of GeoServer 2.6, replaced by @link {@link #getSecurity()}
*/
@Deprecated
public File findOrCreateSecurityDir(String... location) throws IOException {
return getSecurity(location).dir();
}
/**
* Copies a file into a security configuration directory.
* <p>
* If the security configuration directory does exist it will be created.
* </p>
* @deprecated As of GeoServer 2.6, replaced by @link {@link #getSecurity()}
*/
@Deprecated
public void copyToSecurityDir(File f) throws IOException {
Resource resource = getSecurity();
Resources.copy(f, resource);
}
/**
* Copies data into a security configuration directory.
* <p>
* If the security configuration directory does exist it will be created
* </p>
* @deprecated As of GeoServer 2.6, replaced by @link {@link #getSecurity()}
*/
@Deprecated
public void copyToSecurityDir(InputStream data, String filename) throws IOException {
Resource resource = getSecurity();
Resources.copy(data, resource, filename);
}
/**
* Returns the directory for the specified workspace, if the directory does not exist null is returned.
*
* @deprecated As of GeoServer 2.6, replaced by @link {@link #get(WorkspaceInfo)}
*/
@Deprecated
public File findWorkspaceDir(WorkspaceInfo ws) throws IOException {
Resource directory = get(ws);
return Resources.directory(directory);
}
/**
* Returns the directory for the specified workspace, if the directory does not exist it will be created.
*
* @param create If set to true the directory will be created when it does not exist.
*
* @deprecated As of GeoServer 2.6, replaced by {@link #get(WorkspaceInfo, String...)}
*/
@Deprecated
public File findOrCreateWorkspaceDir(WorkspaceInfo ws) throws IOException {
Resource directory = get(ws);
return directory.dir();
}
/**
* Returns the configuration file for the specified workspace, if the file does not exist null is returned.
*
* @deprecated As of GeoServer 2.6, replaced by {@link #config(WorkspaceInfo)}
*/
@Deprecated
public File findWorkspaceFile(WorkspaceInfo ws) throws IOException {
Resource workspaceFile = config(ws);
return Resources.file(workspaceFile);
}
/**
* Returns the configuration file for the specified workspace, if the file does not exist a file object will still be returned.
*
* @deprecated As of GeoServer 2.6, replaced by {@link #config(WorkspaceInfo)}
*/
@Deprecated
public File findOrResolveWorkspaceFile(WorkspaceInfo ws) throws IOException {
Resource workspaceFile = config(ws);
return workspaceFile.file();
}
/**
* Returns a supplementary configuration file for a workspace, if the file does not exist null is returned.
*
* @deprecated As of GeoServer 2.6, replaced by {@link #get(WorkspaceInfo, String...)}
*/
@Deprecated
public File findSuppWorkspaceFile(WorkspaceInfo ws, String filename) throws IOException {
Resource resource = get(ws, filename);
return Resources.file(resource);
}
/**
* Returns a supplementary configuration file in the workspaces directory, if the file does not exist null is returned.
*
* @deprecated As of GeoServer 2.6, replaced by {@link #getWorkspaces(String...)}
*/
@Deprecated
public File findSuppWorkspacesFile(WorkspaceInfo ws, String filename) throws IOException {
Resource resource = getWorkspaces(filename);
return Resources.file(resource);
}
/**
* Copies a file into a workspace configuration directory.
* <p>
* If the workspace configuration directory does exist it will be created.
* </p>
*
* @param ws Target workspace for copied file
* @param file File to copy
*
* @deprecated As of GeoServer 2.6, replaced by {@link #get(WorkspaceInfo, String...)}
*/
@Deprecated
public void copyToWorkspaceDir(WorkspaceInfo ws, File file) throws IOException {
Resource directory = get(ws);
Resources.copy(file, directory);
}
/**
* Copies data into a workspace configuration directory.
* <p>
* If the workspace configuration directory does exist it will be created
* </p>
* @deprecated As of GeoServer 2.6, replaced by {@link #get(WorkspaceInfo, String...)}
*/
@Deprecated
public void copyToWorkspaceDir(WorkspaceInfo ws, InputStream data, String filename)
throws IOException {
Resource directory = get(ws);
Resources.copy(data, directory, filename);
}
/**
* Copies data into the root workspaces configuration directory.
* <p>
* If the workspace configuration directory does exist it will be created
* </p>
* @deprecated As of GeoServer 2.6, replaced by {@link #get(WorkspaceInfo, String...)}
*/
@Deprecated
public void copyToWorkspacesDir(InputStream data, String filename) throws IOException {
Resources.copy(data, getWorkspaces(), filename);
}
/**
* Returns the directory in which a stores configuration is persisted, if the directory does not exists null is returned.
*
* @deprecated As of GeoServer 2.6, replaced by {@link #get(StoreInfo, String...)}
*/
@Deprecated
public File findStoreDir(StoreInfo store) throws IOException {
Resource directory = get(store);
return Resources.directory(directory);
}
@Deprecated
private String path(StoreInfo store) {
WorkspaceInfo workspace = store.getWorkspace();
return Paths.path("workspaces", workspace.getName(), store.getName());
}
/**
* Returns the directory in which a stores configuration is persisted, if the directory does not exist it is created.
*
* @deprecated As of GeoServer 2.6, replaced by {@link #get(StoreInfo, String...)}
*/
@Deprecated
public File findOrCreateStoreDir(StoreInfo store) throws IOException {
Resource resource = get(store);
return resource.dir();
}
/**
* Returns the configuration file for the specified store, if the file does not exist null is returned.
*
* @deprecated As of GeoServer 2.6, replaced by {@link #config(DataStoreInfo)}, {@link #config(CoverageStoreInfo)}, and {@link #config(WMSStoreInfo)}
*/
@Deprecated
public File findStoreFile(StoreInfo store) throws IOException {
Resource resource = config(store);
return Resources.file(resource);
}
/**
* Returns the configuration file for the specified store, if the file does not exist a file object is still returned.
*
* @deprecated As of GeoServer 2.6, replaced by {@link #get(StoreInfo, String...)}
*/
@Deprecated
public File findOrResolveStoreFile(StoreInfo store) throws IOException {
Resource resource = get(store);
return resource.file();
}
/**
* Returns a supplementary configuration file for a store, if the file does not exist null is returned.
*
* @deprecated As of GeoServer 2.6, replaced by {@link #get(StoreInfo, String...)}
*/
@Deprecated
public File findSuppStoreFile(StoreInfo store, String filename) throws IOException {
Resource resource = get(store, filename);
return Resources.file(resource);
}
/**
* Copies a file into a store configuration directory.
* <p>
* If the store configuration directory does exist it will be created
* </p>
* @deprecated As of GeoServer 2.6, replaced by {@link #get(StoreInfo, String...)}
*/
@Deprecated
public void copyToStoreDir(StoreInfo store, File file) throws IOException {
Resource directory = get(path(store));
Resources.copy(file, directory);
}
/**
* Copies data into a store configuration directory.
* <p>
* If the store configuration directory does exist it will be created
* </p>
* @deprecated As of GeoServer 2.6, replaced by {@link #get(StoreInfo, String...)}
*/
public void copyToStoreDir(StoreInfo store, InputStream data, String filename)
throws IOException {
Resource directory = get(store);
Resources.copy(data, directory, filename);
}
/**
* Returns the directory in which a resources configuration is persisted, if the directory does not exist null is returned.
*
* @deprecated As of GeoServer 2.6, replaced by {@link #get(ResourceInfo, String...)}
*/
@Deprecated
public File findResourceDir(ResourceInfo resource) throws IOException {
Resource directory = get(resource);
return Resources.directory(directory);
}
/**
* Finds the directory for the resource assuming a 1.x style data directory.
* <p>
* Something like:
*
* <pre>
* featureTypes/states_shapefile_states
* coverages/sfdem_dem
* </pre>
*
* </p>
*
* @param resource The resource.
*
* @return The directory for the resource, or null if it could not be found.
*/
public File findLegacyResourceDir(ResourceInfo resource) throws IOException {
StoreInfo store = resource.getStore();
String dirname = store.getName() + "_" + resource.getName();
File dir = null;
if (resource instanceof FeatureTypeInfo) {
dir = resourceLoader.find("featureTypes", dirname);
} else if (resource instanceof CoverageInfo) {
dir = resourceLoader.find("coverages", dirname);
}
return dir != null ? dir : null;
}
/**
* Returns the directory in which a resources configuration is persisted, if the directory does not exist it will be created.
*
* @deprecated As of GeoServer 2.6, replaced by {@link #get(ResourceInfo, String...)}
*/
public File findOrCreateResourceDir(ResourceInfo r) throws IOException {
Resource directory = get(r);
return directory.dir();
}
/**
* Returns the configuration file for the specified resource, if the file does not exist null is returned.
*
* @deprecated As of GeoServer 2.6, replaced by {@link #config(FeatureTypeInfo, String...)}, {@link #config(CoverageInfo, String...)}, {@link #config(WMSLayerInfo, String...)}
*/
@Deprecated
public File findResourceFile(ResourceInfo r) throws IOException {
Resource resource = config(r);
return Resources.file(resource);
}
/**
* Returns the configuration file for the specified resource, if the file does not exist a file object is still returned.
*
* @deprecated As of GeoServer 2.6, replaced by {@link #config(FeatureTypeInfo, String...)}, {@link #config(CoverageInfo, String...)}, {@link #config(WMSLayerInfo, String...)}
*/
@Deprecated
public File findOrResolveResourceFile(ResourceInfo r) throws IOException {
Resource resource = config(r);
return resource.file();
}
/**
* Returns a supplementary configuration file for a resource, if the file does not exist null is returned.
*
* @deprecated As of GeoServer 2.6, replaced by {@link #get(ResourceInfo, String...)}
*/
@Deprecated
public File findSuppResourceFile(ResourceInfo r, String filename) throws IOException {
Resource resource = get(r, filename);
return Resources.file(resource);
}
/**
* Returns a supplementary configuration file for a resource in a 1.x data directory format. If the file does not exist null is returned.
*
* @deprecated As of GeoServer 2.6, replaced by {@link #get(ResourceInfo, String...)}
*/
public File findSuppLegacyResourceFile(ResourceInfo r, String filename) throws IOException {
File rdir = findLegacyResourceDir(r);
if (rdir != null) {
File file = new File(rdir, filename);
return file.exists() ? file : null;
} else {
return null;
}
}
/**
* Copies a file into a feature type configuration directory.
* <p>
* If the resource directory does exist it will be created
* </p>
* @deprecated As of GeoServer 2.6, replaced by {@link #get(ResourceInfo, String...)}
*/
@Deprecated
public void copyToResourceDir(ResourceInfo resource, File file) throws IOException {
Resource directory = get(resource);
Resources.copy(file, directory);
}
/**
* Copies data into a feature type configuration directory.
* <p>
* If the resource directory does exist it will be created
* </p>
* @deprecated As of GeoServer 2.6, replaced by {@link #get(ResourceInfo, String...)}
*/
@Deprecated
public void copyToResourceDir(ResourceInfo resource, InputStream data, String filename)
throws IOException {
Resource directory = get(resource);
Resources.copy(data, directory, filename);
}
/**
* Returns the configuration file for the specified namespace, if the file does not exist null is returned.
* @deprecated As of GeoServer 2.6, replaced by {@link #get(WorkspaceInfo, String...)}
*/
@Deprecated
public File findNamespaceFile(WorkspaceInfo ws) throws IOException {
Resource directory = get(ws);
return Resources.directory(directory);
}
/**
* Returns the configuration file for the specified namespace, if the file does not exist a file object is still returned.
* @deprecated As of GeoServer 2.6, replaced by {@link #get(WorkspaceInfo, String...)}
*/
@Deprecated
public File findOrResolveNamespaceFile(WorkspaceInfo ws) throws IOException {
Resource directory = get(ws);
return directory.dir();
}
/**
* Returns the configuration file for the specified layer, if the file does not exist null is returned.
* @deprecated As of GeoServer 2.6, replaced by {@link #get(LayerInfo, String...)}
*/
@Deprecated
public File findLayerFile(LayerInfo layer) throws IOException {
Resource resource = get(layer);
return Resources.file(resource);
}
/**
* Returns the configuration file for the specified layer, if the file does not exist a file object is still returned.
*
* @deprecated As of GeoServer 2.6, replaced by {@link #get(LayerInfo, String...)}
*/
public File findOrResolveLayerFile(LayerInfo layer) throws IOException {
Resource resource = get(layer);
return resource.file();
}
/**
* Returns the directory in which global styles are persisted, if the directory does not exist null is returned.
*
* @deprecated As of GeoServer 2.6, replaced by {@link #get(StyleInfo, String...)}
*/
public File findStyleDir() throws IOException {
Resource styles = get(STYLE_DIR);
return Resources.directory(styles);
}
/**
* Returns the directory in which global styles are persisted, if the directory does not exist it will be created.
*
* @deprecated As of GeoServer 2.6, replaced by {@link #get(StyleInfo, String...)}
*/
public File findOrCreateStyleDir() throws IOException {
Resource styles = get(STYLE_DIR);
return styles.dir();
}
/**
* Styles directory (using StyleInfo).
*
* Package visibility {@link GeoServerPersister#dir(StyleInfo)}.
*
* @param create Create if needed
* @param styleInfo
*
* @throws IOException
*
* @deprecated As of GeoServer 2.6, replaced by {@link #get(StyleInfo, String...)}
*/
File styleDir(boolean create, StyleInfo styleInfo) throws IOException {
Resource styles = get(styleInfo);
return Resources.directory(styles, create);
}
/**
* Access to styles directory for provided workspace (or global styles directory if workspace not provided).
*
* Package visibility for {@link GeoServerPersister}.
*
* @param create Create directory if required
* @param workspaceInfo Workspace used to access styles directory
* @return styles directory
* @throws IOException
*
* @deprecated As of GeoServer 2.6, replaced by {@link #get(StyleInfo, String...)}
*/
File styleDir(boolean create, WorkspaceInfo workspaceInfo) throws IOException {
Resource styles = get(workspaceInfo, STYLE_DIR);
return Resources.directory(styles, create);
}
/**
* Returns the configuration file for the specified style, if the file does not exist null is returned.
*
* @deprecated As of GeoServer 2.6, replaced by {@link #config(StyleInfo, String...)}
*/
public File findStyleFile(StyleInfo s) throws IOException {
Resource resource = config(s);
return Resources.file(resource);
}
/**
* Returns the SLD file for the specified style, if the file does not exist null is returned.
*
* @deprecated As of GeoServer 2.6, replaced by {@link #style(StyleInfo, String...)}
*/
public File findStyleSldFile(StyleInfo s) throws IOException {
Resource resource = style(s);
return Resources.file(resource);
}
/**
* Returns the configuration file for the specified style, if the file does not exist a file object is still returned.
*
* @deprecated As of GeoServer 2.6, replaced by {@link #config(StyleInfo, String...)}
*/
public File findOrCreateStyleFile(StyleInfo s) throws IOException {
Resource resource = config(s);
return resource.file();
}
/**
* Returns the SLD file for the specified style, if the file does not exist a file object is still returned.
*
* @deprecated As of GeoServer 2.6, replaced by {@link #style(StyleInfo, String...)}
*/
public File findOrCreateStyleSldFile(StyleInfo s) throws IOException {
Resource resource = style(s);
return resource.file();
}
// Resource lookup methods
static final String WORKSPACE_XML = "workspace.xml";
static final String NAMESPACE_XML = "namespace.xml";
static final String DATASTORE_XML = "datastore.xml";
static final String COVERAGESTORE_XML = "coveragestore.xml";
static final String WMSSTORE_XML = "wmsstore.xml";
static final String FEATURETYPE_XML = "featuretype.xml";
static final String COVERAGE_XML = "coverage.xml";
static final String WMSLAYER_XML = "wmslayer.xml";
static final String LAYER_XML = "layer.xml";
static final String WORKSPACE_DIR = "workspaces";
static final String LAYERGROUP_DIR = "layergroups";
static final String STYLE_DIR = "styles";
static final String SECURITY_DIR = "security";
/**
* Retrieve a resource relative to the root of the data directory. An empty path will retrieve
* the directory itself.
* @return A {@link Resource}
*/
public @Nonnull Resource getRoot(String... path) {
Resource r = get(Paths.path(path));
assert r!=null;
return r;
}
/**
* Retrieve a resource in the the security directory. An empty path will retrieve
* the directory itself.
* @return A {@link Resource}
*/
public @Nonnull Resource getSecurity(String... path) {
Resource r = get( Paths.path( SECURITY_DIR, Paths.path(path)));
assert r!=null;
return r;
}
/**
* Retrieve a resource in the the workspaces directory. An empty path will retrieve
* the directory itself.
* @return A {@link Resource}
*/
public @Nonnull Resource getWorkspaces(String... path) {
Resource r = get( Paths.path( WORKSPACE_DIR, Paths.path(path)));
assert r!=null;
return r;
}
/**
* Retrieve the configuration xml for the default workspace.
* @return A {@link Resource}
*/
public @Nonnull Resource defaultWorkspaceConfig() {
Resource r = getRoot("default.xml");
assert r!=null;
return r;
}
/**
* Retrieve a resource in the the workspace configuration directory. An empty path will retrieve
* the directory itself.
* @param ws The workspace
* @return A {@link Resource}
*/
public @Nonnull Resource get(WorkspaceInfo ws, String... path) {
Resource r;
if(ws==null) {
return resourceLoader.get("");
} else {
r = getWorkspaces( ws.getName(), Paths.path(path));
}
assert r!=null;
return r;
}
/**
* Retrieve the workspace configuration XML as a Resource
* @param ws The workspace
* @return A {@link Resource}
*/
public @Nonnull Resource config(WorkspaceInfo ws) {
Resource r = get(ws, WORKSPACE_XML);
assert r!=null;
return r;
}
/**
* Retrieve a resource in the the configuration directory of the workspace associated with a
* namespace. An empty path will retrieve the directory itself.
* @param ws The namespace
* @return A {@link Resource}
*/
public @Nonnull Resource get(NamespaceInfo ns, String... path) {
Resource r = getWorkspaces(ns.getPrefix(), Paths.path(path));
assert r!=null;
return r;
}
/**
* Retrieve the namespace configuration XML as a Resource
* @param ns The namespace
* @return A {@link Resource}
*/
public @Nonnull Resource config(NamespaceInfo ns) {
Resource r = get(ns, NAMESPACE_XML);
assert r!=null;
return r;
}
/**
* Retrieve a resource in the the configuration directory of a Store. An empty path will
* retrieve the directory itself.
* @param store The store
* @return A {@link Resource}
*/
public @Nonnull Resource get(StoreInfo store, String... path) {
Resource r = get(store.getWorkspace(), store.getName(), Paths.path(path));
assert r!=null;
return r;
}
/**
* Retrieve the datastore configuration XML as a Resource
* @param ds The datastore
* @return A {@link Resource}
*/
public @Nonnull Resource config(DataStoreInfo ds) {
Resource r = get(ds, DATASTORE_XML);
assert r!=null;
return r;
}
/**
* Retrieve the coverage store configuration XML as a Resource
* @param cs The coverage store
* @return A {@link Resource}
*/
public @Nonnull Resource config(CoverageStoreInfo cs) {
Resource r = get(cs, COVERAGESTORE_XML);
assert r!=null;
return r;
}
/**
* Retrieve the WMS store configuration XML as a Resource
* @param wmss The coverage store
* @return A {@link Resource}
*/
public @Nonnull Resource config(WMSStoreInfo wmss) {
Resource r = get(wmss, WMSSTORE_XML);
assert r!=null;
return r;
}
/**
* Retrieve the WMS store configuration XML as a Resource
* @param wmss The coverage store
* @return A {@link Resource}
*/
private @Nonnull Resource config(StoreInfo si) {
final Resource r;
if(si instanceof DataStoreInfo) {
r=config((DataStoreInfo) si);
} else if(si instanceof CoverageStoreInfo) {
r=config((CoverageStoreInfo) si);
} else if(si instanceof WMSStoreInfo) {
r=config((WMSStoreInfo) si);
} else {
// It'd be nice if we could be generic and cover potential future StoreInfo types.
throw new IllegalArgumentException(
"Only DataStoreInfo, CoverageStoreInfo, and WMSStoreInfo are supported.");
}
assert r!=null;
return r;
}
/**
* Retrieve the resource configuration XML as a Resource
* @param wmss The resource
* @return A {@link Resource}
*/
private @Nonnull Resource config(ResourceInfo si) {
final Resource r;
if(si instanceof FeatureTypeInfo) {
r=config((FeatureTypeInfo) si);
} else if(si instanceof CoverageInfo) {
r=config((CoverageInfo) si);
} else if(si instanceof WMSLayerInfo) {
r=config((WMSLayerInfo) si);
} else {
// It'd be nice if we could be generic and cover potential future ResourceInfo types.
throw new IllegalArgumentException(
"Only FeatureTypeInfo, CoverageInfo, and WMSLayerInfo are supported.");
}
assert r!=null;
return r;
}
/**
* Retrieve a resource in the the configuration directory of a Resource. An empty path will
* retrieve the directory itself.
* @param ri The store
* @return A {@link Resource}
*/
public @Nonnull Resource get(ResourceInfo ri, String... path) {
Resource r = get(ri.getStore(), ri.getName(), Paths.path(path));
assert r!=null;
return r;
}
/**
* Retrieve the feature type configuration XML as a Resource
* @param fti The feature type
* @return A {@link Resource}
*/
public @Nonnull Resource config(FeatureTypeInfo fti) {
Resource r = get(fti, FEATURETYPE_XML);
assert r!=null;
return r;
}
/**
* Retrieve the coverage configuration XML as a Resource
* @param c The feature type
* @return A {@link Resource}
*/
public @Nonnull Resource config(CoverageInfo c) {
Resource r = get(c, COVERAGE_XML);
assert r!=null;
return r;
}
/**
* Retrieve the WMS layer configuration XML as a Resource
* @param wmsl The feature type
* @return A {@link Resource}
*/
public @Nonnull Resource config(WMSLayerInfo wmsl) {
Resource r = get(wmsl, WMSLAYER_XML);
assert r!=null;
return r;
}
/**
* Retrieve a resource in the the configuration directory of a Layer. An empty path will
* retrieve the directory itself.
* @param li The store
* @return A {@link Resource}
*/
public @Nonnull Resource get(LayerInfo l, String... path ) {
final Resource r;
if ( l.getResource() instanceof FeatureTypeInfo) {
r = get( l.getResource(), path );
}
else if ( l.getResource() instanceof CoverageInfo ) {
r = get( l.getResource(), path );
}
else if ( l.getResource() instanceof WMSLayerInfo ) {
r = get( l.getResource(), path );
}
else {
// It'd be nice if we could be generic and cover potential future ResourceInfo types.
throw new IllegalArgumentException(
"Only FeatureTypeInfo, CoverageInfo, and WMSLayerInfo are supported.");
}
assert r!=null;
return r;
}
/**
* Retrieve the layer configuration XML as a Resource
* @param li The feature type
* @return A {@link Resource}
*/
public @Nonnull Resource config(LayerInfo li) {
Resource r = get(li, LAYER_XML);
assert r!=null;
return r;
}
/**
* Retrieve a resource in the the layer groups directory. An empty path will retrieve
* the directory itself.
* @return A {@link Resource}
*/
public @Nonnull Resource getLayerGroups(String... path) {
Resource r = get( Paths.path( LAYERGROUP_DIR, Paths.path(path)));
assert r!=null;
return r;
}
/**
* Retrieve a resource in the the layer groups directory of a workspace. An empty path will retrieve
* the directory itself.
* @return A {@link Resource}
*/
public @Nonnull Resource getLayerGroups(WorkspaceInfo wsi, String... path) {
Resource r = get(wsi, Paths.path( LAYERGROUP_DIR, Paths.path(path)));
assert r!=null;
return r;
}
/**
* Retrieve a resource in the the configuration directory of a LayerGroup. An empty path will
* retrieve the directory itself. This directory is shared by all Layer Groups in a Workspace.
* @param lgi The store
* @return A {@link Resource}
*/
public @Nonnull Resource get(LayerGroupInfo lgi, String... path) {
WorkspaceInfo wsi = lgi.getWorkspace();
final Resource r;
if(wsi==null) {
r = getLayerGroups(path);
} else {
r = getLayerGroups(wsi, path);
}
assert r!=null;
return r;
}
/**
* Retrieve the layer group configuration XML as a Resource
* @param lgi The layer group
* @return A {@link Resource}
*/
public @Nonnull Resource config(LayerGroupInfo lgi) {
Resource r = get(lgi, String.format("%s.xml", lgi.getName()));
assert r!=null;
return r;
}
/**
* Retrieve a resource in the the styles directory. An empty path will retrieve
* the directory itself.
* @return A {@link Resource}
*/
public @Nonnull Resource getStyles(String... path) {
Resource r = get( Paths.path( STYLE_DIR, Paths.path(path)));
assert r!=null;
return r;
}
/**
* Retrieve a resource in the the styles directory of a workspace. An empty path will retrieve
* the directory itself.
* @return A {@link Resource}
*/
public @Nonnull Resource getStyles(WorkspaceInfo wsi, String... path) {
Resource r = get(wsi, Paths.path( STYLE_DIR, Paths.path(path)));
assert r!=null;
return r;
}
/**
* Retrieve a resource in the the configuration directory of a Resource. An empty path will
* retrieve the directory itself.
* @param si The store
* @return A {@link Resource}
*/
public @Nonnull Resource get(StyleInfo si, String... path) {
WorkspaceInfo workspace = si != null ? si.getWorkspace() : null;
final Resource r;
if (workspace == null) {
r = getStyles(path);
} else {
r = getStyles(workspace, path);
}
assert r!=null;
return r;
}
/**
* Retrieve the style configuration XML as a Resource
* @param c The style
* @return A {@link Resource}
*/
public @Nonnull Resource config(StyleInfo s) {
//special case for styles, if the file name (minus the suffix) matches the id of the style
// and the suffix is xml (rather than sld) we need to avoid overwritting the actual
// style file
final String filename;
if (s.getFilename() != null && s.getFilename().endsWith(".xml")
&& s.getFilename().startsWith(s.getName()+".")) {
//append a second .xml suffix
filename = s.getName() + ".xml.xml";
} else {
filename = s.getName() + ".xml";
}
Resource r = get(s, filename);
assert r!=null;
return r;
}
/**
* Retrieve the style definition (SLD) as a Resource
* @param c The style
* @return A {@link Resource}
*/
public @Nonnull Resource style(StyleInfo s) {
// Must be a simple filename
final String filename = s.getFilename();
Resource r = get(s, filename);
assert r!=null;
return r;
}
/**
* Retrieve the StyleInfo as a GeoTools Style object. Note this is just
* the data structure as written, the matching external graphics are unmodified
* and may not be (yet) available on the local system.
*
* @param s The style
* @return A {@link Resource}
*/
protected @Nonnull Style parsedStyleResources(StyleInfo s) throws IOException {
final Resource styleResource = style(s);
if ( styleResource.getType() == Type.UNDEFINED ){
throw new FileNotFoundException( "No such resource: " + s.getFilename());
}
final DefaultResourceLocator locator = new DefaultResourceLocator();
locator.setSourceUrl(Resources.toURL(styleResource));
StyledLayerDescriptor sld =
Styles.handler(s.getFormat()).parse(styleResource, s.getFormatVersion(), locator, null);
final Style style = Styles.style(sld);
assert style!=null;
return style;
}
/**
* Retrieve the style prepared for direct GeoTools use. All file references
* have been made absolute.
*
* @param s The style
* @return A {@link Resource}
*/
public @Nonnull Style parsedStyle(final StyleInfo s) throws IOException {
final Resource styleResource = style(s);
if ( styleResource.getType() == Type.UNDEFINED ){
throw new IOException( "No such resource: " + s.getFilename());
}
File input = styleResource.file();
DefaultResourceLocator locator = new DefaultResourceLocator() {
@Override
public URL locateResource(String uri) {
URL url = super.locateResource(uri);
if(url != null && url.getProtocol().equalsIgnoreCase("resource")) {
Resource resource = resourceLoader.fromURL(url);
File file;
if (Resources.exists(resource)) {
//GEOS-7741: cache resource as file, otherwise it can't be found
file = resource.file();
} else {
//GEOS-7025: Just get the path; don't try to create the file
file = Paths.toFile(root(), resource.path());
}
URL u = fileToUrlPreservingCqlTemplates(file);
if (url.getQuery() != null) {
try {
u = new URL(u.toString() + "?" + url.getQuery());
} catch (MalformedURLException ex) {
GeoServerPersister.LOGGER.log(Level.WARNING, "Error processing query string for resource with uri: " + uri, ex);
return null;
}
}
if (url.getRef() != null) {
try {
u = new URL(u.toString() + "#" + url.getRef());
} catch (MalformedURLException ex) {
GeoServerPersister.LOGGER.log(Level.WARNING, "Error processing # fragment for resource with uri: " + uri, ex);
return null;
}
}
return u;
} else {
return url;
}
}
@Override
protected URL validateRelativeURL(URL relativeUrl) {
// the resource:/ thing does not make for a valid url, so don't validate it
if (relativeUrl.getProtocol().equalsIgnoreCase("resource")) {
return relativeUrl;
} else {
return super.validateRelativeURL(relativeUrl);
}
}
};
locator.setSourceUrl(Resources.toURL(styleResource));
EntityResolver entityResolver = getEntityResolver();
final StyledLayerDescriptor sld =
Styles.handler(s.getFormat()).parse(input, s.getFormatVersion(), locator, getEntityResolver());
final Style style = Styles.style(sld);
assert style!=null;
return style;
}
private EntityResolver getEntityResolver() {
// would be best injected, but apparently most of the code is
// actually creating a GeoServerDataDirectory object programmatically and/or on the fly, so
// we have to resort to a dynamic spring context lookup instead
EntityResolver resolver = null;
EntityResolverProvider provider = GeoServerExtensions.bean(EntityResolverProvider.class);
if(provider != null) {
resolver = provider.getEntityResolver();
}
return resolver;
}
/**
* Retrieve the settings configuration XML as a Resource
* @param s The settings
* @return A {@link Resource}
*/
public @Nonnull Resource config(SettingsInfo s) {
Resource r = get(s.getWorkspace(), "settings.xml");
assert r!=null;
return r;
}
/**
* Retrieve the logging configuration XML as a Resource
* @param l The settings
* @return A {@link Resource}
*/
public @Nonnull Resource config(LoggingInfo l) {
Resource r = getRoot("logging.xml");
assert r!=null;
return r;
}
/**
* Retrieve the global configuration xml
* @param g The global info
* @return A {@link Resource}
*/
public @Nonnull Resource config(GeoServerInfo g) {
Resource r = getRoot("global.xml");
assert r!=null;
return r;
}
// SLD Manipulation
/**
* Copy file to styles directory (determined using {@link StyleInfo#getWorkspace()}).
*
* @param file
* @param style
* @throws IOException
*
* @deprecated As of GeoServer 2.6, replaced by {@link #get(StyleInfo, String...)}
*/
@Deprecated
public void copyToStyleDir(File file, StyleInfo style) throws IOException {
Resource styles = get(style);
FileUtils.copyFileToDirectory(file, styles.dir());
}
/**
* Returns the directory in which global layer groups are persisted, if the directory does not exist null is returned.
* @deprecated As of GeoServer 2.6, replaced by {@link #get(LayerGroupInfo, String...)}
*/
public File findLayerGroupDir() throws IOException {
Resource resource = getLayerGroups();
return Resources.directory(resource);
}
List<Resource> additionalStyleResources(StyleInfo s) throws IOException {
final List<Resource> resources = new ArrayList<Resource>();
final Resource baseDir = get(s);
try {
Style parsedStyle = parsedStyleResources(s);
parsedStyle.accept(new AbstractStyleVisitor() {
@Override
public void visit(ExternalGraphic exgr) {
if (exgr.getOnlineResource() == null) {
return;
}
try {
Resource r = resourceLoader.fromURL(exgr.getLocation());
if (r!=null && r.getType()!=Type.UNDEFINED){
resources.add(r);
}
} catch (IllegalArgumentException|MalformedURLException e) {
GeoServerPersister.LOGGER.log(Level.WARNING, "Error attemping to process SLD resource", e);
}
}
// TODO: Workaround for GEOT-4803, Remove when it is fixed, KS
@Override
public void visit(ChannelSelection cs) {
if (cs.getGrayChannel() != null) {
cs.getGrayChannel().accept(this);
}
final SelectedChannelType[] rgbChannels = cs.getRGBChannels();
for (SelectedChannelType ch : rgbChannels) {
if(ch!=null) ch.accept(this);
}
}
});
}
catch(FileNotFoundException e){
GeoServerPersister.LOGGER.log(Level.WARNING, "Error loading style:"+ e);
}
catch(IOException e) {
GeoServerPersister.LOGGER.log(Level.WARNING, "Error loading style", e);
}
return resources;
}
/**
* Wrapper for {@link DataUtilities#fileToURL} that unescapes braces used to delimit CQL templates.
*/
public static URL fileToUrlPreservingCqlTemplates(File file) {
URL url = DataUtilities.fileToURL(file);
if (!file.getPath().contains("${")) {
// guard against situations in which braces are used but not for CQL templates
return url;
} else {
try {
return new URL(url.toExternalForm().replace("%7B", "{").replace("%7D", "}"));
} catch (MalformedURLException e) {
return null;
}
}
}
public ResourceStore getResourceStore() {
return resourceLoader.getResourceStore();
}
}