/* (c) 2014 - 2015 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.wps.ppio; import java.io.OutputStream; import javax.xml.namespace.QName; import javax.xml.transform.sax.SAXTransformerFactory; import javax.xml.transform.sax.TransformerHandler; import javax.xml.transform.stream.StreamResult; import org.geoserver.platform.GeoServerExtensions; import org.geoserver.util.EntityResolverProvider; import org.geotools.xml.Configuration; import org.geotools.xml.Parser; import org.xml.sax.ContentHandler; /** * Process parameter input / output for objects which are XML based. * * @author Justin Deoliveira, OpenGEO */ public abstract class XMLPPIO extends ComplexPPIO { /** */ protected QName element; protected volatile EntityResolverProvider resolverProvider; /** * Constructor specifying 'text/xml' as mime type. */ protected XMLPPIO(Class externalType, Class internalType, QName element) { this( externalType, internalType, "text/xml", element ); } /** * Constructor explicitly specifying mime type. */ protected XMLPPIO(Class externalType, Class internalType, String mimeType, QName element) { super( externalType, internalType, mimeType); if (element == null) { throw new NullPointerException("element must not be null"); } this.element = element; } /** * The qualified name of the XML element in the XML representation of the object. */ public QName getElement() { return element; } /** * Encodes the internal representation of the object to an XML stream. * * @param object An object of type {@link #getType()}. * @param handler An XML content handler. */ public abstract void encode( Object object, ContentHandler handler ) throws Exception; /** * Encodes the internal object representation of a parameter as a string. */ public void encode( Object value, OutputStream os) throws Exception { // create the document serializer TransformerHandler serializer = ((SAXTransformerFactory)SAXTransformerFactory.newInstance()).newTransformerHandler(); serializer.setResult(new StreamResult(os)); // cascade on the other encode method encode(value, serializer); } @Override public String getFileExtension() { return "xml"; } /** * Returns a parser using the given configuration * * @param configuration * */ protected Parser getParser(Configuration configuration) { Parser parser = new Parser(configuration); // spring injection would have been preferred, but it changes the order in which PPIO // are listed, which in turn chances the behavior of WPS (e.g., default mimeType) parser.setEntityResolver(getResolveProvider().getEntityResolver()); return parser; } private EntityResolverProvider getResolveProvider() { // double checked locking with volatile, works fine since Java 5.0 // (http://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java, scroll down towards the end) if (resolverProvider == null) { synchronized (this) { if (resolverProvider == null) { resolverProvider = GeoServerExtensions.bean(EntityResolverProvider.class); } } } return resolverProvider; } }