/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.cocoon.sax.component;
import java.io.OutputStream;
import java.util.Map;
import java.util.Properties;
import java.util.Map.Entry;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import org.apache.cocoon.pipeline.SetupException;
import org.apache.cocoon.pipeline.caching.CacheKey;
import org.apache.cocoon.pipeline.caching.ParameterCacheKey;
import org.apache.cocoon.pipeline.component.CachingPipelineComponent;
import org.apache.cocoon.sax.AbstractSAXSerializer;
public class XMLSerializer extends AbstractSAXSerializer implements CachingPipelineComponent {
private static final SAXTransformerFactory SAX_TRANSFORMER_FACTORY = (SAXTransformerFactory) TransformerFactory
.newInstance();
private static final String EMPTY = "";
private static final String YES = "yes";
private static final String NO = "no";
private static final String METHOD = "method";
private static final String UTF_8 = "UTF-8";
private static final String XML = "xml";
private static final String HTML = "html";
private static final String TEXT_XML = "text/xml";
private static final String TEXT_HTML_UTF_8 = "text/html;charset=utf-8";
private static final String XHTML_STRICT_DOCTYPE_PUBLIC = "-//W3C//DTD XHTML 1.0 Strict//EN";
private static final String HTML_TRANSICTIONAL_DOCTYPE_PUBLIC = "-//W3C//DTD HTML 4.01 Transitional//EN";
private static final String XHTML_STRICT_DOCTYPE_SYSTEM = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd";
private Properties format;
private TransformerHandler transformerHandler;
public XMLSerializer() {
this(new Properties());
}
public XMLSerializer(Properties format) {
super();
if (format == null) {
throw new SetupException("No format properites passed as argument.");
}
this.format = format;
}
public CacheKey constructCacheKey() {
ParameterCacheKey parameterCacheKey = new ParameterCacheKey();
for (Entry<Object, Object> property : this.format.entrySet()) {
parameterCacheKey.addParameter(property.getKey().toString(), property.getValue().toString());
}
return parameterCacheKey;
}
public XMLSerializer setCDataSectionElements(String cdataSectionElements) {
if (cdataSectionElements == null || EMPTY.equals(cdataSectionElements)) {
throw new SetupException("A ... has to be passed as argument.");
}
this.format.put(OutputKeys.CDATA_SECTION_ELEMENTS, cdataSectionElements);
return this;
}
public XMLSerializer setDoctypePublic(String doctypePublic) {
if (doctypePublic == null || EMPTY.equals(doctypePublic)) {
throw new SetupException("A doctype-public has to be passed as argument.");
}
this.format.put(OutputKeys.DOCTYPE_PUBLIC, doctypePublic);
return this;
}
public XMLSerializer setDoctypeSystem(String doctypeSystem) {
if (doctypeSystem == null || EMPTY.equals(doctypeSystem)) {
throw new SetupException("A doctype-system has to be passed as argument.");
}
this.format.put(OutputKeys.DOCTYPE_SYSTEM, doctypeSystem);
return this;
}
public XMLSerializer setEncoding(String encoding) {
if (encoding == null || EMPTY.equals(encoding)) {
throw new SetupException("A encoding has to be passed as argument.");
}
this.format.put(OutputKeys.ENCODING, encoding);
return this;
}
public void setFormat(Properties format) {
this.format = format;
}
public XMLSerializer setIndent(boolean indent) {
this.format.put(OutputKeys.INDENT, indent ? YES : NO);
return this;
}
public XMLSerializer setMediaType(String mediaType) {
if (mediaType == null || EMPTY.equals(mediaType)) {
throw new SetupException("A media-type has to be passed as argument.");
}
this.format.put(OutputKeys.MEDIA_TYPE, mediaType);
return this;
}
public XMLSerializer setMethod(String method) {
if (method == null || EMPTY.equals(method)) {
throw new SetupException("A method has to be passed as argument.");
}
this.format.put(OutputKeys.METHOD, method);
return this;
}
public XMLSerializer setOmitXmlDeclaration(boolean omitXmlDeclration) {
this.format.put(OutputKeys.OMIT_XML_DECLARATION, omitXmlDeclration ? YES : NO);
return this;
}
@Override
public void setOutputStream(OutputStream outputStream) {
this.transformerHandler.setResult(new StreamResult(outputStream));
}
public XMLSerializer setStandAlone(boolean standalone) {
this.format.put(OutputKeys.STANDALONE, standalone ? YES : NO);
return this;
}
@Override
public void setup(Map<String, Object> inputParameters) {
try {
this.transformerHandler = SAX_TRANSFORMER_FACTORY.newTransformerHandler();
} catch (TransformerConfigurationException e) {
throw new SetupException("Can't setup transformer handler for the serializer.", e);
}
// set a default method because some transformer implementations run
// into NPEs if it is missing
if (!this.format.containsKey(METHOD)) {
this.format.put(METHOD, XML);
}
this.transformerHandler.getTransformer().setOutputProperties(this.format);
this.setContentHandler(this.transformerHandler);
}
public XMLSerializer setVersion(String version) {
if (version == null || EMPTY.equals(version)) {
throw new SetupException("A version has to be passed as argument.");
}
this.format.put(OutputKeys.VERSION, version);
return this;
}
protected Properties getFormat() {
return this.format;
}
public static XMLSerializer createXHTMLSerializer() {
XMLSerializer serializer = new XMLSerializer();
serializer.setContentType(TEXT_HTML_UTF_8);
serializer.setDoctypePublic(XHTML_STRICT_DOCTYPE_PUBLIC);
serializer.setDoctypeSystem(XHTML_STRICT_DOCTYPE_SYSTEM);
serializer.setEncoding(UTF_8);
serializer.setMethod(XML);
return serializer;
}
public static XMLSerializer createHTML4Serializer() {
XMLSerializer serializer = new XMLSerializer();
serializer.setContentType(TEXT_HTML_UTF_8);
serializer.setDoctypePublic(HTML_TRANSICTIONAL_DOCTYPE_PUBLIC);
serializer.setEncoding(UTF_8);
serializer.setMethod(HTML);
return serializer;
}
public static XMLSerializer createXMLSerializer() {
XMLSerializer serializer = new XMLSerializer();
serializer.setContentType(TEXT_XML);
serializer.setEncoding(UTF_8);
serializer.setMethod(XML);
return serializer;
}
}