snichol 2002/11/20 13:34:43
Modified: java/src/org/apache/soap/providers RPCJavaProvider.java
java/src/org/apache/soap/rpc Call.java SOAPContext.java
java/src/org/apache/soap/server ServerUtils.java
java/src/org/apache/soap/server/http RPCRouterServlet.java
java/src/org/apache/soap/transport TransportMessage.java
Log:
Submitted by: Pavel Ausianik <[EMAIL PROTECTED]>
thinking more on the current code I have found interesting
thing. Most requests we have a simple, straight SOAP envelopes, without any
attachments. Looking how it is processed I have found following (traced
from httpconnection):
In SOAPHTTPConnection.send() we call TransportMessage.save().
Let's look into it (see my comment how I understand it...
Seems like we are doing wonderful job of running a lot unnecessary
operations, involving a lot of memory allocations... It could be most
advanced improvement we ever done!
I think I managed make it compatible to existing code and yet still
much faster (8-10 sec of 60 I had in the morning ). The Mime
part will be created as soon as it requested, otherwise plain Envelope used
Also I set up initial buffer in couple of classes...
Revision Changes Path
1.6 +1 -1 xml-soap/java/src/org/apache/soap/providers/RPCJavaProvider.java
Index: RPCJavaProvider.java
===================================================================
RCS file:
/home/cvs/xml-soap/java/src/org/apache/soap/providers/RPCJavaProvider.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- RPCJavaProvider.java 17 May 2001 17:45:46 -0000 1.5
+++ RPCJavaProvider.java 20 Nov 2002 21:34:42 -0000 1.6
@@ -129,7 +129,7 @@
Response resp = RPCRouter.invoke( dd, call, targetObject,
reqContext, resContext );
Envelope env = resp.buildEnvelope();
- StringWriter sw = new StringWriter();
+ StringWriter sw = new StringWriter(1024);
env.marshall( sw, call.getSOAPMappingRegistry(), resContext );
resContext.setRootPart( sw.toString(),
Constants.HEADERVAL_CONTENT_TYPE_UTF8);
}
1.23 +2 -4 xml-soap/java/src/org/apache/soap/rpc/Call.java
Index: Call.java
===================================================================
RCS file: /home/cvs/xml-soap/java/src/org/apache/soap/rpc/Call.java,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- Call.java 19 Nov 2002 02:47:38 -0000 1.22
+++ Call.java 20 Nov 2002 21:34:42 -0000 1.23
@@ -271,15 +271,13 @@
BufferedReader in = null;
String payloadStr = null;
- MimeBodyPart rootPart = respCtx.getRootPart();
- String ctype = rootPart.getContentType();
+ String ctype = respCtx.getRootPartContentType();
ContentType type = null;
type = MimeUtils.getContentType(ctype);
if (type != null && Constants.CTYPE_TEXT_ALL.match(type)) {
// Get the input stream to read the response envelope from.
- in = st.receive();
- payloadStr = IOUtils.getStringFromReader(in);
+ payloadStr = respCtx.getEnvelope();
}
// Check Content-Type of root part of response to see if it's
1.16 +109 -17 xml-soap/java/src/org/apache/soap/rpc/SOAPContext.java
Index: SOAPContext.java
===================================================================
RCS file: /home/cvs/xml-soap/java/src/org/apache/soap/rpc/SOAPContext.java,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- SOAPContext.java 19 Nov 2002 02:47:38 -0000 1.15
+++ SOAPContext.java 20 Nov 2002 21:34:42 -0000 1.16
@@ -78,17 +78,22 @@
*
* @author Wouter Cloetens ([EMAIL PROTECTED])
* @author Scott Nichol ([EMAIL PROTECTED])
+ * @author Pavel Ausianik ([EMAIL PROTECTED])
*/
public class SOAPContext {
protected MimeMultipart parts;
protected Hashtable bag = new Hashtable();
protected ClassLoader loader = null ;
- protected Vector multiRef = new Vector();
- protected Hashtable deserializedMultiRef = new Hashtable();
+ protected List multiRef = null;
+ protected Map deserializedMultiRef = null;
protected String currentId = null;
protected boolean docLitSerialization = false;
protected Boolean gzip = null;
protected Boolean acceptGzip = null;
+
+ protected boolean isRootPartEnvelope = false;
+ protected String rootPartString = null;
+ protected String rootPartContentType = "";
protected boolean oneWay = false;
// Constants for checking type for base64 encoding
@@ -160,6 +165,7 @@
* @return the Part, or null if no such part exists.
*/
public MimeBodyPart getBodyPart(int index) {
+ fillRootPart();
/* Actually, this method never throws a MessagingException. In case a
* future implementation does, catch it and throw an
* IndexOutOfBoundsException
@@ -189,6 +195,7 @@
* @return the Part, or null if no such part exists.
*/
public MimeBodyPart getBodyPart(String CID) {
+ fillRootPart();
if (parts == null) {
return null;
}
@@ -222,6 +229,7 @@
* @return the Part or null if not found
*/
public MimeBodyPart findBodyPart(String uri) {
+ fillRootPart();
if (parts == null || uri == null) {
return null;
}
@@ -420,10 +428,12 @@
* @exception MessagingException
*/
public void setRootPart(MimeBodyPart part) throws MessagingException {
+ if (rootPartSet && !isRootPartEnvelope)
+ parts.removeBodyPart(getRootPart());
+ isRootPartEnvelope = false;
+
String rootCid = '<' + MimeUtils.getUniqueValue() + '>';
part.setHeader(Constants.HEADER_CONTENT_ID, rootCid);
- if (rootPartSet)
- parts.removeBodyPart(getRootPart());
addBodyPart(part, 0);
rootPartSet = true;
}
@@ -438,7 +448,10 @@
*/
public void setRootPart(String s, String contentType)
throws MessagingException, IOException {
- setRootPart(s.getBytes("UTF8"), contentType);
+ isRootPartEnvelope = true;
+ rootPartContentType = contentType;
+ rootPartString = s;
+ rootPartSet = true;
}
/**
@@ -458,7 +471,6 @@
bp.setDataHandler(dh);
bp.setHeader(Constants.HEADER_CONTENT_LENGTH,
String.valueOf(ds.getSize()));
-
// Avoid letting JavaMail determine a transfer-encoding of
// quoted-printable or base64... Force 8-bit encoding.
bp.setHeader("Content-Transfer-Encoding", "8bit");
@@ -467,6 +479,60 @@
}
/**
+ * In case MimePart is requested converts Envelope to MimePart
+ */
+ private void fillRootPart() {
+ if (isRootPartEnvelope) {
+ try {
+ byte[] rootPartBytes = rootPartString.getBytes(
+ MimeUtils.getEncoding(rootPartContentType, "UTF8"));
+
+ ByteArrayDataSource ds =
+ new ByteArrayDataSource(rootPartBytes, rootPartContentType);
+ DataHandler dh = new DataHandler(ds);
+ MimeBodyPart bp = new MimeBodyPart();
+ bp.setDataHandler(dh);
+ bp.setHeader(Constants.HEADER_CONTENT_LENGTH,
+ String.valueOf(ds.getSize()));
+
+ // Avoid letting JavaMail determine a transfer-encoding of
+ // quoted-printable or base64... Force 8-bit encoding.
+ bp.setHeader("Content-Transfer-Encoding", "8bit");
+ bp.setHeader(Constants.HEADERVAL_CONTENT_TYPE, rootPartContentType);
+ setRootPart(bp);
+ }
+ catch (MessagingException e) {} // Should never happen
+ catch (UnsupportedEncodingException e) {} // Should never happen
+ }
+ }
+
+ /**
+ * Return Envelope String set up as setRootPart(String)
+ * or converted from MimeBodyPart
+ *
+ * @return Envelope String
+ */
+ public String getEnvelope() {
+ if (isRootPartEnvelope) {
+ return rootPartString;
+ }
+ // Envelope was set up as MimeBodyPart - let's get a text from it
+ try {
+ MimeBodyPart rootPart = getRootPart();
+ if (rootPart != null) {
+ String ctype = rootPart.getContentType();
+ ContentType type = MimeUtils.getContentType(ctype);
+ if (type != null && Constants.CTYPE_TEXT_ALL.match(type)) {
+ ByteArrayDataSource ds = new ByteArrayDataSource(
+ rootPart.getInputStream(), ctype);
+ return ds.getText();
+ }
+ }
+ } catch (Exception e) {}
+ return null;
+ }
+
+ /**
* Find the root part. For multipart, search for a "start" Content-Type
* header modifier, if not present or invalid, assume the first part is
* the root.
@@ -475,9 +541,10 @@
* @exception MessagingException
*/
public MimeBodyPart getRootPart() throws MessagingException {
+ fillRootPart();
MimeBodyPart rootPart = null;
if (getCount() > 1) {
- String startCid = MimeUtils.getContentType(
+ String startCid = new ContentType(
parts.getContentType()).getParameter("start");
if (startCid != null)
rootPart = getBodyPart(MimeUtils.decode(startCid));
@@ -488,6 +555,22 @@
}
/**
+ * Returns root part ContentType.
+ *
+ * @return root BodyPart ContentType
+ * @exception MessagingException
+ */
+ public String getRootPartContentType() throws MessagingException {
+ if (isRootPartEnvelope)
+ return rootPartContentType;
+ else {
+ MimeBodyPart rootPart = getRootPart();
+ return rootPart == null ? null : rootPart.getContentType();
+ }
+ }
+
+
+ /**
* Set the MultiPart Mime subtype. This method should be invoked only on
* a new MimeMultipart object created by the client. The default subtype
* of such a multipart object is "related".<p>
@@ -515,10 +598,11 @@
* @return number of parts
*/
public int getCount() throws MessagingException {
+ int countRoot = isRootPartEnvelope ? 1 : 0;
if (parts == null)
- return 0;
+ return countRoot;
else
- return parts.getCount();
+ return parts.getCount() + countRoot;
}
/**
@@ -530,7 +614,7 @@
*/
public String getContentType() throws MessagingException {
if (parts == null)
- return null;
+ return isRootPartEnvelope ? rootPartContentType : null;
else
if (parts.getCount() == 1)
return getRootPart().getContentType();
@@ -554,6 +638,8 @@
getRootPart().writeTo(os);
}
else {
+ // fill Root part first
+ fillRootPart();
Session session = Session.getDefaultInstance(new Properties(), null);
MimeMessage msg = new MimeMessage(session);
msg.setContent(parts);
@@ -691,14 +777,16 @@
* @return The id of the element.
*/
public int addMultiRef(Object obj, Serializer ser) {
+ if (multiRef == null)
+ multiRef = new ArrayList();
// While a Hashtable might seem a better choice than a vector here,
// a Vector is easier to work with during serialization, since
// multiRefs may be added during the serialization of other multiRefs.
for (int i = 0; i < multiRef.size(); i++) {
- if (((MultiRefInfo) multiRef.elementAt(i)).obj == obj)
+ if (((MultiRefInfo) multiRef.get(i)).obj == obj)
return i;
}
- multiRef.addElement(new MultiRefInfo(obj, ser));
+ multiRef.add(new MultiRefInfo(obj, ser));
return multiRef.size() - 1;
}
@@ -709,7 +797,7 @@
* @return The multiRef object for the id.
*/
public Object getMultiRefObject(int id) {
- return ((MultiRefInfo) multiRef.elementAt(id)).obj;
+ return multiRef != null ? ((MultiRefInfo) multiRef.get(id)).obj : null;
}
/**
@@ -719,7 +807,7 @@
* @return The multiRef serializer for the id.
*/
public Serializer getMultiRefSerializer(int id) {
- return ((MultiRefInfo) multiRef.elementAt(id)).ser;
+ return multiRef != null ? ((MultiRefInfo) multiRef.get(id)).ser : null;
}
/**
@@ -728,7 +816,7 @@
* @return The number of multiRefs.
*/
public int getMultiRefCount() {
- return multiRef.size();
+ return multiRef != null ? multiRef.size() : 0;
}
/**
@@ -738,6 +826,8 @@
* @param o The deserialized object.
*/
public void addDeserializedMultiRef(String id, Object o) {
+ if (deserializedMultiRef == null)
+ deserializedMultiRef = new HashMap();
deserializedMultiRef.put(id, o);
}
@@ -748,7 +838,7 @@
* @return The multiRef for the id.
*/
public Object getDeserializedMultiRef(String id) {
- return deserializedMultiRef.get(id);
+ return deserializedMultiRef == null ? null :deserializedMultiRef.get(id);
}
/**
@@ -794,7 +884,9 @@
pw.print("}]");
- pw.print(" multiRefs: " + multiRef.size() + " deserializedMultiRefs: " +
deserializedMultiRef.size());
+ pw.print(" multiRefs: " + (multiRef != null ? multiRef.size() : '0') +
+ " deserializedMultiRefs: " +
+ (deserializedMultiRef != null ? deserializedMultiRef.size() : '0'));
return sw.toString();
}
1.11 +5 -3 xml-soap/java/src/org/apache/soap/server/ServerUtils.java
Index: ServerUtils.java
===================================================================
RCS file: /home/cvs/xml-soap/java/src/org/apache/soap/server/ServerUtils.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- ServerUtils.java 5 Sep 2002 16:50:52 -0000 1.10
+++ ServerUtils.java 20 Nov 2002 21:34:42 -0000 1.11
@@ -147,11 +147,13 @@
reqMsg.read();
// Check Content-Type of root part of request to see if it's
// consistent with a SOAP envelope (text/xml).
- MimeBodyPart rootPart = ctx.getRootPart();
- if (!rootPart.isMimeType(Constants.HEADERVAL_CONTENT_TYPE))
+ String ctype = ctx.getRootPartContentType();
+ ContentType type = null;
+ type = MimeUtils.getContentType(ctype);
+ if (type == null || !Constants.CTYPE_TEXT_XML.match(type))
throw new SOAPException(Constants.FAULT_CODE_PROTOCOL,
"Unsupported content type \"" +
- rootPart.getContentType() + "\", must be: \"" +
+ ctype + "\", must be: \"" +
Constants.HEADERVAL_CONTENT_TYPE + "\".");
// Apply Transport-Hook-Extension
reqMsg.editIncoming(editor);
1.43 +1 -1
xml-soap/java/src/org/apache/soap/server/http/RPCRouterServlet.java
Index: RPCRouterServlet.java
===================================================================
RCS file:
/home/cvs/xml-soap/java/src/org/apache/soap/server/http/RPCRouterServlet.java,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -r1.42 -r1.43
--- RPCRouterServlet.java 10 Sep 2002 07:27:25 -0000 1.42
+++ RPCRouterServlet.java 20 Nov 2002 21:34:42 -0000 1.43
@@ -409,7 +409,7 @@
(call != null) ? call.getSOAPMappingRegistry ()
: ServerHTTPUtils.getSMRFromContext (context);
Envelope env = resp.buildEnvelope();
- StringWriter sw = new StringWriter();
+ StringWriter sw = new StringWriter(1024);
env.marshall(sw, smr, resp.getSOAPContext());
resp.getSOAPContext().setRootPart( sw.toString(),
Constants.HEADERVAL_CONTENT_TYPE_UTF8);
1.23 +24 -34
xml-soap/java/src/org/apache/soap/transport/TransportMessage.java
Index: TransportMessage.java
===================================================================
RCS file:
/home/cvs/xml-soap/java/src/org/apache/soap/transport/TransportMessage.java,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- TransportMessage.java 20 Nov 2002 07:29:32 -0000 1.22
+++ TransportMessage.java 20 Nov 2002 21:34:42 -0000 1.23
@@ -330,13 +330,22 @@
} else {
rootBytes = bytes;
rootContentType = cType;
- // Set the single part as the root part of SOAPContext.
- ByteArrayDataSource ds = new ByteArrayDataSource(bytes,
- contentType);
- DataHandler dh = new DataHandler(ds);
- rootPart = new MimeBodyPart();
- rootPart.setDataHandler(dh);
- ctx.addBodyPart(rootPart);
+
+ // If the root part is text, extract it as a String.
+ // Note that we could use JAF's help to do this (see save())
+ // but implementing it ourselves is safer and faster.
+ if (Constants.CTYPE_TEXT_ALL.match(rootContentType)) {
+ String charset = rootContentType.getParameter("charset");
+ // Hmm, risky, the default charset is transport-specific...
+ if (charset == null || charset.equals(""))
+ charset = Constants.HEADERVAL_DEFAULT_CHARSET;
+ envelope = new String(rootBytes, MimeUtility.javaCharset(charset));
+ // Set the envelope as a String.
+ ctx.setRootPart(envelope, contentType);
+ } else
+ // Set the single part as the root part of SOAPContext.
+ ctx.setRootPart(bytes, contentType);
+ return envelope;
}
// If the root part is text, extract it as a String.
@@ -394,20 +403,14 @@
* and try to use it as the envelope.
*/
String rootContentType = null;
- if (ctx.isRootPartSet()) {
- MimeBodyPart rootPart = ctx.getRootPart();
- if (rootPart != null)
- // Note: don't call MimeBodyPart.getContent() because it will
- // default to "text/plain" if the Content-Type header isn't
- // set.
- rootContentType = rootPart.getHeader(
- Constants.HEADER_CONTENT_TYPE, null);
- }
- if (rootContentType == null)
- rootContentType = Constants.HEADERVAL_CONTENT_TYPE_UTF8;
if (getEnvelope() != null && !rootPartIsEnvelope) {
- ctx.setRootPart(envelope, rootContentType);
+ rootContentType = Constants.HEADERVAL_CONTENT_TYPE_UTF8;
+ ctx.setRootPart(envelope, Constants.HEADERVAL_CONTENT_TYPE_UTF8);
rootPartIsEnvelope = true;
+ } else {
+ rootContentType = ctx.getRootPartContentType();
+ if (rootContentType == null)
+ rootContentType = Constants.HEADERVAL_CONTENT_TYPE_UTF8;
}
// If we only have one part, it is the envelope, so handle
@@ -511,21 +514,8 @@
*/
public String getEnvelope() {
if (envelope == null) {
- // Assign the root part, if any, to the envelope.
- try {
- MimeBodyPart rootPart = ctx.getRootPart();
- if (rootPart != null) {
- String ctype = rootPart.getContentType();
- ContentType type = MimeUtils.getContentType(ctype);
- if (type != null && Constants.CTYPE_TEXT_ALL.match(type)) {
- ByteArrayDataSource ds = new ByteArrayDataSource(
- rootPart.getInputStream(), ctype);
- envelope = ds.getText();
- }
- rootPartIsEnvelope = true;
- }
- } catch (Exception e) {
- }
+ // get an enveope from SOAPContext
+ envelope = ctx.getEnvelope();
}
return envelope;
}
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>