Author: bimargulies
Date: Fri Jan 18 16:37:33 2008
New Revision: 613330
URL: http://svn.apache.org/viewvc?rev=613330&view=rev
Log:
More MTOM Aegis. Now we add in the xmime schema to legitimize the use
of xmime:contentType, and we use it.
Added:
incubator/cxf/trunk/common/schemas/src/main/resources/schemas/wsdl/xmime.xsd
(with props)
Modified:
incubator/cxf/trunk/common/common/src/main/java/org/apache/cxf/common/util/PackageUtils.java
incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/Context.java
incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/databinding/AegisDatabinding.java
incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/Type.java
incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/basic/Base64Type.java
incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/mtom/AbstractXOPType.java
incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/mtom/DataHandlerType.java
incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/aegis/mtom/MtomTest.java
Modified:
incubator/cxf/trunk/common/common/src/main/java/org/apache/cxf/common/util/PackageUtils.java
URL:
http://svn.apache.org/viewvc/incubator/cxf/trunk/common/common/src/main/java/org/apache/cxf/common/util/PackageUtils.java?rev=613330&r1=613329&r2=613330&view=diff
==============================================================================
---
incubator/cxf/trunk/common/common/src/main/java/org/apache/cxf/common/util/PackageUtils.java
(original)
+++
incubator/cxf/trunk/common/common/src/main/java/org/apache/cxf/common/util/PackageUtils.java
Fri Jan 18 16:37:33 2008
@@ -117,7 +117,7 @@
token = removeIllegalIdentifierChars(token);
// this will check for reserved keywords
- if (contiansReservedKeywords(token)) {
+ if (containsReservedKeywords(token)) {
token = '_' + token;
}
@@ -177,7 +177,7 @@
return buf.toString();
}
- private static boolean contiansReservedKeywords(String token) {
+ private static boolean containsReservedKeywords(String token) {
return KEYWORDS.contains(token);
}
Added:
incubator/cxf/trunk/common/schemas/src/main/resources/schemas/wsdl/xmime.xsd
URL:
http://svn.apache.org/viewvc/incubator/cxf/trunk/common/schemas/src/main/resources/schemas/wsdl/xmime.xsd?rev=613330&view=auto
==============================================================================
---
incubator/cxf/trunk/common/schemas/src/main/resources/schemas/wsdl/xmime.xsd
(added)
+++
incubator/cxf/trunk/common/schemas/src/main/resources/schemas/wsdl/xmime.xsd
Fri Jan 18 16:37:33 2008
@@ -0,0 +1,32 @@
+<?xml version="1.0" ?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:xmime="http://www.w3.org/2005/05/xmlmime"
+ targetNamespace="http://www.w3.org/2005/05/xmlmime" >
+
+ <xs:attribute name="contentType">
+ <xs:simpleType>
+ <xs:restriction base="xs:string" >
+ <xs:minLength value="3" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+
+ <xs:attribute name="expectedContentTypes" type="xs:string" />
+
+ <xs:complexType name="base64Binary" >
+ <xs:simpleContent>
+ <xs:extension base="xs:base64Binary" >
+ <xs:attribute ref="xmime:contentType" />
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name="hexBinary" >
+ <xs:simpleContent>
+ <xs:extension base="xs:hexBinary" >
+ <xs:attribute ref="xmime:contentType" />
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+</xs:schema>
\ No newline at end of file
Propchange:
incubator/cxf/trunk/common/schemas/src/main/resources/schemas/wsdl/xmime.xsd
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
incubator/cxf/trunk/common/schemas/src/main/resources/schemas/wsdl/xmime.xsd
------------------------------------------------------------------------------
svn:keywords = Rev Date
Propchange:
incubator/cxf/trunk/common/schemas/src/main/resources/schemas/wsdl/xmime.xsd
------------------------------------------------------------------------------
svn:mime-type = text/xml
Modified:
incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/Context.java
URL:
http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/Context.java?rev=613330&r1=613329&r2=613330&view=diff
==============================================================================
---
incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/Context.java
(original)
+++
incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/Context.java
Fri Jan 18 16:37:33 2008
@@ -38,8 +38,6 @@
private Collection<Attachment> attachments;
private Fault fault;
private Map<Class<?>, Object> properties;
- // this is used as part of dealing with unoptimized base64binary issues.
- private String contentType;
public Context(AegisContext aegisContext) {
this.globalContext = aegisContext;
@@ -90,13 +88,4 @@
public void setProperty(Object value) {
properties.put(value.getClass(), value);
}
-
- public String getContentType() {
- return contentType;
- }
-
- public void setContentType(String contentType) {
- this.contentType = contentType;
- }
-
}
Modified:
incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/databinding/AegisDatabinding.java
URL:
http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/databinding/AegisDatabinding.java?rev=613330&r1=613329&r2=613330&view=diff
==============================================================================
---
incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/databinding/AegisDatabinding.java
(original)
+++
incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/databinding/AegisDatabinding.java
Fri Jan 18 16:37:33 2008
@@ -18,6 +18,7 @@
*/
package org.apache.cxf.aegis.databinding;
+import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
@@ -28,11 +29,14 @@
import java.util.logging.Logger;
import javax.xml.namespace.QName;
+import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
+
import org.apache.cxf.aegis.AegisContext;
import org.apache.cxf.aegis.DatabindingException;
import org.apache.cxf.aegis.type.AbstractTypeCreator.TypeClassInfo;
@@ -40,6 +44,7 @@
import org.apache.cxf.aegis.type.Type;
import org.apache.cxf.aegis.type.TypeCreator;
import org.apache.cxf.aegis.type.TypeMapping;
+import org.apache.cxf.aegis.type.mtom.AbstractXOPType;
import org.apache.cxf.common.classloader.ClassLoaderUtils;
import org.apache.cxf.common.i18n.Message;
import org.apache.cxf.common.logging.LogUtils;
@@ -52,6 +57,7 @@
import org.apache.cxf.frontend.MethodDispatcher;
import org.apache.cxf.frontend.SimpleMethodDispatcher;
import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.service.Service;
import org.apache.cxf.service.factory.ServiceConstructionException;
import org.apache.cxf.service.model.AbstractMessageContainer;
@@ -63,6 +69,8 @@
import org.apache.ws.commons.schema.XmlSchema;
import org.apache.ws.commons.schema.XmlSchemaAnnotated;
import org.apache.ws.commons.schema.utils.NamespaceMap;
+import org.jaxen.JaxenException;
+import org.jaxen.jdom.JDOMXPath;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
@@ -94,6 +102,7 @@
protected static final int FAULT_PARAM = 2;
private static final Logger LOG =
LogUtils.getL7dLogger(AegisDatabinding.class);
+ private static org.w3c.dom.Document xmimeSchemaDocument;
private AegisContext aegisContext;
private Map<MessagePartInfo, Type> part2Type;
@@ -102,10 +111,36 @@
private Set<String> overrideTypes;
private Configuration configuration;
private boolean mtomEnabled;
+ private JDOMXPath importXmimeXpath;
public AegisDatabinding() {
super();
part2Type = new HashMap<MessagePartInfo, Type>();
+ // we have this also in AbstractXOPType. There has to be a better way.
+ importXmimeXpath = AbstractXOPType.getXmimeXpathImport();
+ }
+
+ private boolean schemaImportsXmime(Element schemaElement) {
+ try {
+ return importXmimeXpath.selectSingleNode(schemaElement) != null;
+ } catch (JaxenException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private void ensureXmimeSchemaDocument() {
+ if (xmimeSchemaDocument != null) {
+ return;
+ }
+ try {
+ xmimeSchemaDocument =
DOMUtils.readXml(getClass().getResourceAsStream("/schemas/wsdl/xmime.xsd"));
+ } catch (SAXException e) {
+ throw new RuntimeException(e);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ } catch (ParserConfigurationException e) {
+ throw new RuntimeException(e);
+ }
}
/**
@@ -383,6 +418,7 @@
}
types.add(t);
}
+
for (ServiceInfo si : s.getServiceInfos()) {
SchemaCollection col = si.getXmlSchemaCollection();
if (col.getXmlSchemas().length > 1) {
@@ -392,6 +428,7 @@
}
Map<String, String> namespaceMap = getDeclaredNamespaceMappings();
+ boolean needXmimeSchema = false;
for (Map.Entry<String, Set<Type>> entry : tns2Type.entrySet()) {
String xsdPrefix = SOAPConstants.XSD_PREFIX;
@@ -427,6 +464,10 @@
if (e.getChildren().size() == 0) {
continue;
}
+
+ if (schemaImportsXmime(e)) {
+ needXmimeSchema = true;
+ }
try {
NamespaceMap nsMap = new NamespaceMap();
@@ -457,8 +498,17 @@
} catch (JDOMException e1) {
throw new ServiceConstructionException(e1);
}
+
}
+ if (needXmimeSchema) {
+ ensureXmimeSchemaDocument();
+ for (ServiceInfo si : s.getServiceInfos()) {
+ SchemaCollection col = si.getXmlSchemaCollection();
+ // invented systemId.
+ addSchemaDocument(si, col, xmimeSchemaDocument,
AbstractXOPType.XML_MIME_NS);
+ }
+ }
}
public QName getSuggestedName(Service s, TypeMapping tm, OperationInfo op,
int param) {
Modified:
incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/Type.java
URL:
http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/Type.java?rev=613330&r1=613329&r2=613330&view=diff
==============================================================================
---
incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/Type.java
(original)
+++
incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/Type.java
Fri Jan 18 16:37:33 2008
@@ -36,7 +36,7 @@
public abstract class Type {
protected Class typeClass;
-
+
private QName schemaType;
private TypeMapping typeMapping;
Modified:
incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/basic/Base64Type.java
URL:
http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/basic/Base64Type.java?rev=613330&r1=613329&r2=613330&view=diff
==============================================================================
---
incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/basic/Base64Type.java
(original)
+++
incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/basic/Base64Type.java
Fri Jan 18 16:37:33 2008
@@ -66,12 +66,6 @@
reader.next();
}
- if (reader.isStartElement()) {
- String contentType =
reader.getAttributeValue(AbstractXOPType.XML_MIME_NS,
-
AbstractXOPType.XML_MIME_ATTR_LOCAL_NAME);
- context.setContentType(contentType);
- }
-
if (reader.isStartElement() &&
reader.getName().equals(AbstractXOPType.XOP_INCLUDE)) {
if (mtomEnabled) {
return optimizedType.readMtoM(mreader, context);
Modified:
incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/mtom/AbstractXOPType.java
URL:
http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/mtom/AbstractXOPType.java?rev=613330&r1=613329&r2=613330&view=diff
==============================================================================
---
incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/mtom/AbstractXOPType.java
(original)
+++
incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/mtom/AbstractXOPType.java
Fri Jan 18 16:37:33 2008
@@ -23,6 +23,7 @@
import java.util.Collection;
import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamReader;
import org.apache.cxf.aegis.Context;
import org.apache.cxf.aegis.DatabindingException;
@@ -30,7 +31,11 @@
import org.apache.cxf.aegis.type.basic.Base64Type;
import org.apache.cxf.aegis.xml.MessageReader;
import org.apache.cxf.aegis.xml.MessageWriter;
+import org.apache.cxf.common.util.SOAPConstants;
import org.apache.cxf.message.Attachment;
+import org.jaxen.JaxenException;
+import org.jaxen.XPath;
+import org.jaxen.jdom.JDOMXPath;
import org.jdom.Attribute;
import org.jdom.Element;
import org.jdom.Namespace;
@@ -43,20 +48,37 @@
public static final String XOP_NS =
"http://www.w3.org/2004/08/xop/include";
public static final String XML_MIME_NS =
"http://www.w3.org/2005/05/xmlmime";
public static final String XML_MIME_ATTR_LOCAL_NAME =
"expectedContentTypes";
-
public static final QName XOP_INCLUDE = new QName(XOP_NS, "Include");
+ public static final QName XML_MIME_CONTENT_TYPE = new QName(XML_MIME_NS,
"contentType");
public static final QName XOP_HREF = new QName("href");
private String expectedContentTypes;
// the base64 type knows how to deal with just plain base64 here, which is
essentially always
// what we get in the absence of the optimization. So we need something of
a coroutine.
private Base64Type fallbackDelegate;
+ private XPath importXmimeXpath;
public AbstractXOPType(String expectedContentTypes) {
this.expectedContentTypes = expectedContentTypes;
fallbackDelegate = new Base64Type(this);
+ importXmimeXpath = getXmimeXpathImport();
}
-
+
+ public static JDOMXPath getXmimeXpathImport() {
+ JDOMXPath importXmimeXpath;
+ try {
+ importXmimeXpath = new JDOMXPath("xsd:[EMAIL PROTECTED]'"
+ + XML_MIME_NS
+ + "']");
+ importXmimeXpath.addNamespace(SOAPConstants.XSD_PREFIX,
SOAPConstants.XSD);
+ return importXmimeXpath;
+ } catch (JaxenException e) {
+ throw new RuntimeException(e);
+ }
+
+
+ }
+
/**
* This is called from base64Type when it recognizes an XOP attachment.
* @param reader
@@ -85,12 +107,16 @@
*/
@Override
public Object readObject(MessageReader reader, Context context) throws
DatabindingException {
+ XMLStreamReader xreader = reader.getXMLStreamReader();
+ String contentType =
+ xreader.getAttributeValue(AbstractXOPType.XML_MIME_NS,
+
AbstractXOPType.XML_MIME_CONTENT_TYPE.getLocalPart());
+
Object thingRead = fallbackDelegate.readObject(reader, context);
// If there was actually an attachment, the delegate will have called
back to us and gotten
// the appropriate data type. If there wasn't an attachment, it just
returned the bytes.
// Our subclass have to package them.
if (thingRead.getClass() == (new byte[0]).getClass()) {
- String contentType = context.getContentType();
return wrapBytes((byte[])thingRead, contentType);
}
@@ -119,6 +145,13 @@
@Override
public void writeObject(Object object, MessageWriter writer,
Context context) throws DatabindingException {
+ // add the content type attribute even if we are going to fall back.
+ String contentType = getContentType(object, context);
+ if (contentType != null) {
+ MessageWriter ctWriter =
writer.getAttributeWriter(XML_MIME_CONTENT_TYPE);
+ ctWriter.writeValue(contentType);
+ }
+
if (!context.isMtomEnabled()) {
fallbackDelegate.writeObject(getBytes(object), writer, context);
return;
@@ -135,7 +168,7 @@
Attachment att = createAttachment(object, id);
attachments.add(att);
-
+
MessageWriter include = writer.getElementWriter(XOP_INCLUDE);
MessageWriter href = include.getAttributeWriter(XOP_HREF);
href.writeValue("cid:" + id);
@@ -171,5 +204,20 @@
ns);
schemaElement.setAttribute(expectedContentTypeAttribute);
}
+ }
+
+ @Override
+ public void writeSchema(Element root) {
+ try {
+ Object node = importXmimeXpath.selectSingleNode(root);
+ if (node != null) {
+ return;
+ }
+ } catch (JaxenException e) {
+ throw new RuntimeException(e);
+ }
+ Element element = new Element("import", SOAPConstants.XSD_PREFIX,
SOAPConstants.XSD);
+ root.addContent(0, element);
+ element.setAttribute("namespace", XML_MIME_NS);
}
}
Modified:
incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/mtom/DataHandlerType.java
URL:
http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/mtom/DataHandlerType.java?rev=613330&r1=613329&r2=613330&view=diff
==============================================================================
---
incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/mtom/DataHandlerType.java
(original)
+++
incubator/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/mtom/DataHandlerType.java
Fri Jan 18 16:37:33 2008
@@ -21,11 +21,13 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
import javax.activation.DataHandler;
import org.apache.cxf.aegis.Context;
import org.apache.cxf.attachment.AttachmentImpl;
+import org.apache.cxf.helpers.HttpHeaderHelper;
import org.apache.cxf.helpers.IOUtils;
import org.apache.cxf.message.Attachment;
@@ -57,6 +59,24 @@
@Override
protected Object wrapBytes(byte[] bareBytes, String contentType) {
+ // for the benefit of those who are working with string data, we have
the following
+ // trickery
+ String charset = null;
+ if (contentType != null
+ && contentType.indexOf("text/") != -1
+ && contentType.indexOf("charset") != -1) {
+ charset = contentType.substring(contentType.indexOf("charset") +
8);
+ if (charset.indexOf(";") != -1) {
+ charset = charset.substring(0, charset.indexOf(";"));
+ }
+ }
+ String normalizedEncoding = HttpHeaderHelper.mapCharset(charset);
+ try {
+ String stringData = new String(bareBytes, normalizedEncoding);
+ return new DataHandler(stringData, contentType);
+ } catch (UnsupportedEncodingException e) {
+ // this space intentionally left blank.
+ }
return new DataHandler(bareBytes, contentType);
}
Modified:
incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/aegis/mtom/MtomTest.java
URL:
http://svn.apache.org/viewvc/incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/aegis/mtom/MtomTest.java?rev=613330&r1=613329&r2=613330&view=diff
==============================================================================
---
incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/aegis/mtom/MtomTest.java
(original)
+++
incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/aegis/mtom/MtomTest.java
Fri Jan 18 16:37:33 2008
@@ -104,7 +104,7 @@
assertNotNull(accepted);
Object data = accepted.getDataHandler().getContent();
assertNotNull(data);
- // we would like to see the right content type. However, without
xmime:contentType, we cannot.
+ assertEquals("This is the cereal shot from guns.", data);
}
// we aren't ready for this one ...