blob: dd4f58ec3a0552b00b2b3f58af09cfa02a972659 [file] [log] [blame]
/*
* 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.axiom.om;
import java.util.HashMap;
import java.util.Map;
import org.apache.axiom.om.format.xop.ContentTransferEncodingPolicy;
import org.apache.axiom.om.format.xop.ContentTypeProvider;
import org.apache.axiom.om.impl.MTOMConstants;
import org.apache.axiom.om.util.StAXWriterConfiguration;
import org.apache.axiom.soap.SOAPVersion;
import org.apache.axiom.util.UIDGenerator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Formats options for OM Output.
* <p>
* Setting of all the properties in a OMOutputFormat should be done before calling the
* getContentType() method. It is advised to set all the properties at the creation time of the
* OMOutputFormat and not to change them later.
*/
public class OMOutputFormat {
private static final Log log = LogFactory.getLog(OMOutputFormat.class);
private String mimeBoundary;
private String rootContentId;
private int nextid;
private boolean doOptimize;
private boolean doingSWA;
private boolean isSoap11;
private int optimizedThreshold;
/** Field DEFAULT_CHAR_SET_ENCODING. Specifies the default character encoding scheme to be used. */
public static final String DEFAULT_CHAR_SET_ENCODING = "utf-8";
private String charSetEncoding;
private String xmlVersion;
private String contentType;
/**
* Flag set if {@link #contentType} has been set explicitly through
* {@link #setContentType(String)}. If this attribute is <code>false</code> and
* {@link #contentType} is non null, then it was calculated by {@link #getContentType()}.
*/
private boolean contentTypeSet;
private boolean ignoreXMLDeclaration;
private boolean autoCloseWriter;
public static final String ACTION_PROPERTY = "action";
@SuppressWarnings("deprecation")
private StAXWriterConfiguration writerConfiguration;
private ContentTypeProvider contentTypeProvider;
private ContentTransferEncodingPolicy contentTransferEncodingPolicy;
/**
* @deprecated Use {@link ContentTransferEncodingPolicy#USE_BASE64_FOR_NON_TEXTUAL_PARTS} instead.
*/
public static final String USE_CTE_BASE64_FOR_NON_TEXTUAL_ATTACHMENTS =
"org.apache.axiom.om.OMFormat.use.cteBase64.forNonTextualAttachments";
/**
* @deprecated As of version 1.2.13, Axiom always respects the order of attachments.
*/
public static final String RESPECT_SWA_ATTACHMENT_ORDER =
"org.apache.axiom.om.OMFormat.respectSWAAttachmentOrder";
/**
* @deprecated As of version 1.2.13, Axiom always respects the order of attachments.
*/
public static final Boolean RESPECT_SWA_ATTACHMENT_ORDER_DEFAULT =
Boolean.TRUE;
private Map<String,Object> map; // Map of generic properties
public OMOutputFormat() {
isSoap11 = true;
}
/**
* Constructs a new instance by copying the configuration from an existing instance. Note that
* this will only copy configuration data, but not information that is subject to
* auto-generation, such as the root content ID or the MIME boundary.
*
* @param format
* the existing instance
*/
public OMOutputFormat(OMOutputFormat format) {
doOptimize = format.doOptimize;
doingSWA = format.doingSWA;
isSoap11 = format.isSoap11;
optimizedThreshold = format.optimizedThreshold;
charSetEncoding = format.charSetEncoding;
xmlVersion = format.xmlVersion;
if (format.contentTypeSet) {
contentTypeSet = true;
contentType = format.contentType;
}
ignoreXMLDeclaration = format.ignoreXMLDeclaration;
autoCloseWriter = format.autoCloseWriter;
writerConfiguration = format.writerConfiguration;
contentTypeProvider = format.contentTypeProvider;
contentTransferEncodingPolicy = format.contentTransferEncodingPolicy;
if (format.map != null) {
map = new HashMap<String,Object>(format.map);
}
}
/**
* @param key String
* @return property or null
*/
public Object getProperty(String key) {
if (map == null) {
return null;
}
return map.get(key);
}
/**
* @param key String
* @param value Object
* @return old value or null
*/
public Object setProperty(String key, Object value) {
if (map == null) {
map = new HashMap<String,Object>();
}
return map.put(key, value);
}
/**
* @param key
* @return true if known key
*/
public boolean containsKey(String key) {
if (map == null) {
return false;
}
return map.containsKey(key);
}
/**
* Indicates whether the document should be serialized using MTOM.
*
* @return <code>true</code> if the document should be serialized using MTOM; <code>false</code>
* otherwise; the return value is always <code>false</code> if {@link #isDoingSWA()}
* returns <code>true</code>
*/
public boolean isOptimized() {
return doOptimize && !doingSWA; // optimize is disabled if SWA
}
/**
* Return the content-type value that should be written with the message.
* (i.e. if optimized, then a multipart/related content-type is returned).
* @return content-type value
*/
public String getContentType() {
String ct = null;
if (log.isDebugEnabled()) {
log.debug("Start getContentType: " + toString());
}
if (contentType == null) {
if (isSoap11) {
contentType = SOAPVersion.SOAP11.getMediaType().toString();
} else {
contentType = SOAPVersion.SOAP12.getMediaType().toString();
}
}
// If MTOM or SWA, the returned content-type is an
// appropriate multipart/related content type.
if (isOptimized()) {
ct = this.getContentTypeForMTOM(contentType);
} else if (isDoingSWA()) {
ct = this.getContentTypeForSwA(contentType);
} else {
ct = contentType;
}
if (log.isDebugEnabled()) {
log.debug("getContentType= {" + ct + "} " + toString());
}
return ct;
}
/**
* Set a raw content-type
* (i.e. "text/xml" (SOAP 1.1) or "application/xml" (REST))
* If this method is not invoked, OMOutputFormat will choose
* a content-type value consistent with the soap version.
* @param c
*/
public void setContentType(String c) {
contentTypeSet = true;
contentType = c;
}
public String getMimeBoundary() {
if (mimeBoundary == null) {
mimeBoundary = UIDGenerator.generateMimeBoundary();
}
return mimeBoundary;
}
public String getRootContentId() {
if (rootContentId == null) {
rootContentId = "0." + UIDGenerator.generateContentId();
}
return rootContentId;
}
public String getNextContentId() {
nextid++;
return nextid + "." + UIDGenerator.generateContentId();
}
/**
* Returns the character set encoding scheme.
*
* @return Returns encoding string or null if it has not been set.
*/
public String getCharSetEncoding() {
return this.charSetEncoding;
}
public void setCharSetEncoding(String charSetEncoding) {
this.charSetEncoding = charSetEncoding;
}
public String getXmlVersion() {
return xmlVersion;
}
public void setXmlVersion(String xmlVersion) {
this.xmlVersion = xmlVersion;
}
public void setSOAP11(boolean b) {
isSoap11 = b;
}
public boolean isSOAP11() {
return isSoap11;
}
public boolean isIgnoreXMLDeclaration() {
return ignoreXMLDeclaration;
}
public void setIgnoreXMLDeclaration(boolean ignoreXMLDeclaration) {
this.ignoreXMLDeclaration = ignoreXMLDeclaration;
}
/**
* Specifies that the document should be serialized using MTOM. Note that this setting is
* ignored if SwA is enabled using {@link #setDoingSWA(boolean)}.
*
* @param optimize
* <code>true</code> if the document should be serialized using MTOM;
* <code>false</code> otherwise
*/
public void setDoOptimize(boolean optimize) {
doOptimize = optimize;
}
/**
* Indicates whether the document should be serialized using SwA.
*
* @return <code>true</code> if the document should be serialized using SwA; <code>false</code>
* otherwise
*/
public boolean isDoingSWA() {
return doingSWA;
}
/**
* Specifies that the document should be serialized using SwA (SOAP with Attachments). When SwA
* is enabled, then any configuration done using {@link #setDoOptimize(boolean)} is ignored.
*
* @param doingSWA
* <code>true</code> if the document should be serialized using SwA;
* <code>false</code> otherwise
*/
public void setDoingSWA(boolean doingSWA) {
this.doingSWA = doingSWA;
}
/**
* Generates a Content-Type value for MTOM messages. This is a MIME Multipart/Related
* Content-Type value as defined by RFC 2387 and the XOP specification. The generated
* header will look like the following:
*
* Content-Type: multipart/related; boundary="[MIME BOUNDARY VALUE]";
* type="application/xop+xml";
* start="[MESSAGE CONTENT ID]";
* start-info="[MESSAGE CONTENT TYPE]";
*
* @param SOAPContentType
* @return TODO
*/
public String getContentTypeForMTOM(String SOAPContentType) {
// If an action was set, we need to include it within the value
// for the start-info attribute.
if (containsKey(ACTION_PROPERTY)) {
String action = (String) getProperty(ACTION_PROPERTY);
if (action != null && action.length() > 0) {
SOAPContentType = SOAPContentType + "; action=\\\"" + action + "\\\"";
}
}
StringBuffer sb = new StringBuffer();
sb.append("multipart/related");
sb.append("; ");
sb.append("boundary=");
// The value of the boundary parameter must be enclosed in double quotation
// marks, according to the Basic Profile 2.0 Specification, Rule R1109:
// "Parameters on the Content-Type MIME header field-value in a request
// MESSAGE MUST be a quoted string."
sb.append("\"");
sb.append(getMimeBoundary());
sb.append("\"");
sb.append("; ");
sb.append("type=\"" + MTOMConstants.MTOM_TYPE + "\"");
sb.append("; ");
sb.append("start=\"<").append(getRootContentId()).append(">\"");
sb.append("; ");
sb.append("start-info=\"").append(SOAPContentType).append("\"");
return sb.toString();
}
public String getContentTypeForSwA(String SOAPContentType) {
StringBuffer sb = new StringBuffer();
sb.append("multipart/related");
sb.append("; ");
sb.append("boundary=");
// The value of the boundary parameter must be enclosed in double quotation
// marks, according to the Basic Profile 2.0 Specification, Rule R1109:
// "Parameters on the Content-Type MIME header field-value in a request
// MESSAGE MUST be a quoted string."
sb.append("\"");
sb.append(getMimeBoundary());
sb.append("\"");
sb.append("; ");
sb.append("type=\"").append(SOAPContentType).append("\"");
sb.append("; ");
sb.append("start=\"<").append(getRootContentId()).append(">\"");
return sb.toString();
}
/**
* @deprecated
*/
public boolean isAutoCloseWriter() {
return autoCloseWriter;
}
/**
* @deprecated
*/
public void setAutoCloseWriter(boolean autoCloseWriter) {
this.autoCloseWriter = autoCloseWriter;
}
public void setMimeBoundary(String mimeBoundary) {
this.mimeBoundary = mimeBoundary;
}
public void setRootContentId(String rootContentId) {
this.rootContentId = rootContentId;
}
/**
* Use toString for logging state of the OMOutputFormat
*/
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("OMOutputFormat [");
sb.append(" mimeBoundary =");
sb.append(mimeBoundary);
sb.append(" rootContentId=");
sb.append(rootContentId);
sb.append(" doOptimize=");
sb.append(doOptimize);
sb.append(" doingSWA=");
sb.append(doingSWA);
sb.append(" isSOAP11=");
sb.append(isSoap11);
sb.append(" charSetEncoding=");
sb.append(charSetEncoding);
sb.append(" xmlVersion=");
sb.append(xmlVersion);
sb.append(" contentType=");
sb.append(contentType);
sb.append(" ignoreXmlDeclaration=");
sb.append(ignoreXMLDeclaration);
sb.append(" autoCloseWriter=");
sb.append(autoCloseWriter);
// TODO Print all properties
sb.append(" actionProperty=");
sb.append(getProperty(ACTION_PROPERTY));
sb.append(" optimizedThreshold=");
sb.append(optimizedThreshold);
sb.append("]");
return sb.toString();
}
public void setOptimizedThreshold(int optimizedThreshold) {
this.optimizedThreshold = optimizedThreshold;
}
public int getOptimizedThreshold() {
return optimizedThreshold;
}
/**
* Get the currently configured StAX writer configuration.
*
* @return the current configuration; {@link StAXWriterConfiguration#DEFAULT} if none has been
* set explicitly
* @deprecated
*/
public StAXWriterConfiguration getStAXWriterConfiguration() {
return writerConfiguration == null ? StAXWriterConfiguration.DEFAULT : writerConfiguration;
}
/**
* Set the StAX writer configuration that will be used when requesting an
* {@link javax.xml.stream.XMLStreamWriter} from {@link org.apache.axiom.om.util.StAXUtils}.
*
* @param writerConfiguration
* the configuration
* @deprecated
*/
public void setStAXWriterConfiguration(StAXWriterConfiguration writerConfiguration) {
this.writerConfiguration = writerConfiguration;
}
public ContentTypeProvider getContentTypeProvider() {
return contentTypeProvider;
}
public void setContentTypeProvider(ContentTypeProvider contentTypeProvider) {
this.contentTypeProvider = contentTypeProvider;
}
public ContentTransferEncodingPolicy getContentTransferEncodingPolicy() {
return contentTransferEncodingPolicy;
}
public void setContentTransferEncodingPolicy(
ContentTransferEncodingPolicy contentTransferEncodingPolicy) {
this.contentTransferEncodingPolicy = contentTransferEncodingPolicy;
}
}