/* (c) 2014 - 2017 Open Source Geospatial Foundation - all rights reserved
* (c) 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.kml;
import java.io.OutputStream;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.util.JAXBSource;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.geoserver.platform.ServiceException;
import de.micromata.opengis.kml.v_2_2_0.Kml;
/**
* Encodes a KML object onto an output stream
*
* @author Andrea Aime - GeoSolutions
*
*/
public class KMLEncoder {
private JAXBContext context;
private Templates templates;
public KMLEncoder() throws JAXBException, TransformerException {
// this creation is expensive, do it once and cache it
context = JAXBContext.newInstance((Kml.class));
String xslt = getClass().getResource("icon_style_patch.xsl").toString();
templates = TransformerFactory.newInstance().newTemplates(new StreamSource(xslt));
}
public void encode(Kml kml, OutputStream output, KmlEncodingContext context) {
try {
if ((context != null) && (context.getWms() == null)) {
// No need to transform WFS KML.
createMarshaller().marshal(kml, output);
} else {
Transformer transformer = templates.newTransformer();
JAXBSource source = new JAXBSource(createMarshaller(), kml);
transformer.transform(source, new StreamResult(output));
}
} catch (JAXBException | TransformerException e) {
throw new ServiceException(e);
} finally {
if(context != null) {
context.closeIterators();
}
}
}
private Marshaller createMarshaller() throws JAXBException {
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
// hmm... this one is nasty, without the reference implementation the prefixes
// are going to be a bit ugly. Not a big deal, to solve look at
// http://cglib.sourceforge.net/xref/samples/Beans.html
// try {
// Class.forName("com.sun.xml.internal.bind.marshaller.NamespacePrefixMapper");
// m.setProperty("com.sun.xml.bind.namespacePrefixMapper", new JKD6PrefixMapper());
// } catch(Exception e) {
//
// }
return m;
}
}