/* (c) 2014 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.wfs.xml;
import java.io.Reader;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import javax.xml.namespace.QName;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.FeatureTypeInfo;
import org.geoserver.catalog.NamespaceInfo;
import org.geoserver.config.GeoServer;
import org.geoserver.ows.XmlRequestReader;
import org.geoserver.wfs.CatalogNamespaceSupport;
import org.geoserver.wfs.WFSException;
import org.geoserver.wfs.WFSInfo;
import org.geoserver.wfs.xml.gml3.AbstractGeometryTypeBinding;
import org.geoserver.wfs.xml.v1_0_0.WFSConfiguration;
import org.geotools.gml2.FeatureTypeCache;
import org.geotools.gml2.GML;
import org.geotools.gml2.SrsSyntax;
import org.geotools.gml3.GMLConfiguration;
import org.geotools.xml.Configuration;
import org.geotools.xml.OptionalComponentParameter;
import org.geotools.xml.Parser;
import org.opengis.feature.type.FeatureType;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.picocontainer.ComponentAdapter;
import org.picocontainer.MutablePicoContainer;
import org.picocontainer.Parameter;
import org.picocontainer.PicoContainer;
import org.picocontainer.defaults.BasicComponentParameter;
import org.picocontainer.defaults.SetterInjectionComponentAdapter;
import org.xml.sax.InputSource;
/**
* Some utilities shared among WFS xml readers/writers.
*
* @author Justin Deoliveira, OpenGeo
*
*/
public class WFSXmlUtils {
public static void initRequestParser(Parser parser, WFSInfo wfs, GeoServer geoServer, Map kvp) {
//check the strict flag to determine if we should validate or not
Boolean strict = (Boolean) kvp.get("strict");
if ( strict == null ) {
strict = Boolean.FALSE;
}
//check for cite compliance, we always validate for cite
if ( wfs.isCiteCompliant() ) {
strict = Boolean.TRUE;
}
parser.setValidating(strict.booleanValue());
WFSURIHandler.addToParser(geoServer, parser);
Catalog catalog = geoServer.getCatalog();
//"inject" namespace mappings
parser.getNamespaces().add(new CatalogNamespaceSupport(catalog));
}
public static Object parseRequest(Parser parser, Reader reader, WFSInfo wfs) throws Exception {
//set the input source with the correct encoding
InputSource source = new InputSource(reader);
source.setEncoding(wfs.getGeoServer().getSettings().getCharset());
return parser.parse(source);
}
public static void checkValidationErrors(Parser parser, XmlRequestReader requestReader) {
//TODO: HACK, disabling validation for transaction
if (!"Transaction".equalsIgnoreCase(requestReader.getElement().getLocalPart())) {
if (!parser.getValidationErrors().isEmpty()) {
WFSException exception = new WFSException("Invalid request", "InvalidParameterValue");
for (Iterator e = parser.getValidationErrors().iterator(); e.hasNext();) {
Exception error = (Exception) e.next();
exception.getExceptionText().add(error.getLocalizedMessage());
}
throw exception;
}
}
}
public static void initWfsConfiguration(
Configuration config, GeoServer gs, FeatureTypeSchemaBuilder schemaBuilder) {
MutablePicoContainer context = config.getContext();
//seed the cache with entries from the catalog
FeatureTypeCache featureTypeCache = new FeatureTypeCache();
Collection featureTypes = gs.getCatalog().getFeatureTypes();
for (Iterator f = featureTypes.iterator(); f.hasNext();) {
FeatureTypeInfo meta = (FeatureTypeInfo) f.next();
if ( !meta.enabled() ) {
continue;
}
FeatureType featureType = null;
try {
featureType = meta.getFeatureType();
}
catch(Exception e) {
throw new RuntimeException(e);
}
featureTypeCache.put(featureType);
}
//add the wfs handler factory to handle feature elements
context.registerComponentInstance(featureTypeCache);
context.registerComponentInstance(new WFSHandlerFactory(gs.getCatalog(), schemaBuilder));
}
public static void registerAbstractGeometryTypeBinding(final Configuration config, Map bindings,
QName qName) {
//use setter injection for AbstractGeometryType bindign to allow an
// optional crs to be set in teh binding context for parsing, this crs
// is set by the binding of a parent element.
// note: it is important that this component adapter is non-caching so
// that the setter property gets updated properly every time
bindings.put(
qName,
new SetterInjectionComponentAdapter(
qName, AbstractGeometryTypeBinding.class,
new Parameter[]{
new OptionalComponentParameter(CoordinateReferenceSystem.class),
new DirectObjectParameter(config, Configuration.class),
new DirectObjectParameter(getSrsSyntax(config), SrsSyntax.class)
}
)
);
}
public static SrsSyntax getSrsSyntax(Configuration obj) {
for (Configuration dep : ((List<Configuration>)obj.getDependencies())) {
if (dep instanceof org.geotools.gml2.GMLConfiguration) {
return ((org.geotools.gml2.GMLConfiguration) dep).getSrsSyntax();
}
if (dep instanceof org.geotools.gml3.GMLConfiguration) {
return ((org.geotools.gml3.GMLConfiguration) dep).getSrsSyntax();
}
}
return null;
}
public static void setSrsSyntax(Configuration obj, SrsSyntax srsSyntax) {
for (Configuration dep : ((List<Configuration>)obj.getDependencies())) {
if (dep instanceof org.geotools.gml2.GMLConfiguration) {
((org.geotools.gml2.GMLConfiguration) dep).setSrsSyntax(srsSyntax);
}
if (dep instanceof org.geotools.gml3.GMLConfiguration) {
((org.geotools.gml3.GMLConfiguration) dep).setSrsSyntax(srsSyntax);
}
}
}
static class DirectObjectParameter extends BasicComponentParameter {
Object obj;
Class clazz;
public DirectObjectParameter(Object obj, Class clazz) {
super(clazz);
this.obj = obj;
this.clazz = clazz;
}
public boolean isResolvable(PicoContainer container, ComponentAdapter adapter, Class expectedType) {
if (clazz.isAssignableFrom(expectedType)) {
return true;
}
return super.isResolvable(container, adapter, expectedType);
};
@Override
public Object resolveInstance(PicoContainer container, ComponentAdapter adapter, Class expectedType) {
if (clazz.isAssignableFrom(expectedType)) {
return obj;
}
return super.resolveInstance(container, adapter, expectedType);
}
}
}