You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commons-dev@ws.apache.org by sc...@apache.org on 2008/01/14 22:37:00 UTC
svn commit: r611943 - in
/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments:
./ impl/ part/
Author: scheu
Date: Mon Jan 14 13:36:58 2008
New Revision: 611943
URL: http://svn.apache.org/viewvc?rev=611943&view=rev
Log:
WSCOMMONS-292
Contributor:Rich Scheuerle
Introduced PartFactory to control the logic to createPart objects. This logic is moved out of Attachments.getPart. In addition, I added new PartOnFile and PartOnMemory objects that are more buffer sensitive. Removed the legacy PartOnFile, PartOnMemory, PartOnByteArray, etc. classes
Added:
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/AbstractPart.java
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/BufferUtils.java
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartFactory.java
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnFile.java
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnMemory.java
Removed:
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/PartOnFile.java
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/PartOnMemory.java
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/PushbackFilePartInputStream.java
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/part/
Modified:
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Attachments.java
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/MIMEBodyPartInputStream.java
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Part.java
Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Attachments.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Attachments.java?rev=611943&r1=611942&r2=611943&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Attachments.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Attachments.java Mon Jan 14 13:36:58 2008
@@ -19,6 +19,18 @@
package org.apache.axiom.attachments;
+import org.apache.axiom.attachments.impl.PartFactory;
+import org.apache.axiom.om.OMException;
+import org.apache.axiom.om.impl.MTOMConstants;
+import org.apache.axiom.om.util.UUIDGenerator;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.activation.DataHandler;
+import javax.mail.MessagingException;
+import javax.mail.internet.ContentType;
+import javax.mail.internet.ParseException;
+
import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
@@ -28,18 +40,6 @@
import java.util.Set;
import java.util.TreeMap;
-import javax.activation.DataHandler;
-import javax.mail.MessagingException;
-import javax.mail.internet.ContentType;
-import javax.mail.internet.ParseException;
-
-import org.apache.axiom.attachments.part.DynamicPart;
-import org.apache.axiom.om.OMException;
-import org.apache.axiom.om.impl.MTOMConstants;
-import org.apache.axiom.om.util.UUIDGenerator;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
public class Attachments {
/** <code>ContentType</code> of the MIME message */
@@ -549,56 +549,22 @@
partsRequested = true;
- Part part;
+ boolean isSOAPPart = (partIndex == 0);
+ int threshhold = (fileCacheEnable) ? fileStorageThreshold : 0;
- try {
- if (fileCacheEnable) {
- try {
- //If Content-Length defined.
- if(contentLength!=0){
- if (log.isDebugEnabled()) {
- log.debug("Fixed Content-Length Data");
- }
- MIMEBodyPartInputStream partStream =
- new MIMEBodyPartInputStream(pushbackInStream,
- boundary,
- this,
- PUSHBACK_SIZE);
-
- part = DynamicPart.createPart(contentLength, partIndex, partStream, attachmentRepoDir, fileStorageThreshold);
-
- } else {
- if (log.isDebugEnabled()) {
- log.debug("Chunked Data");
- }
- // Read chunks of data to determine the size
- // of the attachment. This can wasteful because we need to gc the buffers.
- // TODO We could look at the content-length of the individual attachment; however
- // this is seldom provided.
-
- MIMEBodyPartInputStream partStream;
-
- partStream =
- new MIMEBodyPartInputStream(pushbackInStream,
- boundary,
- this,
- PUSHBACK_SIZE);
- part = DynamicPart.createPart(partStream, attachmentRepoDir, fileStorageThreshold);
-
- }
- } catch (Exception e) {
- throw new OMException("Error creating temporary File.", e);
- }
- } else {
- MIMEBodyPartInputStream partStream;
- partStream =
- new MIMEBodyPartInputStream(pushbackInStream, boundary, this, PUSHBACK_SIZE);
- part = new PartOnMemory(partStream);
- }
-
- } catch (MessagingException e) {
- throw new OMException(e);
- }
+ // Create a MIMEBodyPartInputStream that simulates a single stream for this MIME body part
+ MIMEBodyPartInputStream partStream =
+ new MIMEBodyPartInputStream(pushbackInStream,
+ boundary,
+ this,
+ PUSHBACK_SIZE);
+
+ // The PartFactory will determine which Part implementation is most appropriate.
+ Part part = PartFactory.createPart(partStream,
+ isSOAPPart,
+ threshhold,
+ attachmentRepoDir,
+ contentLength); // content-length for the whole message
partIndex++;
return part;
}
Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/MIMEBodyPartInputStream.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/MIMEBodyPartInputStream.java?rev=611943&r1=611942&r2=611943&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/MIMEBodyPartInputStream.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/MIMEBodyPartInputStream.java Mon Jan 14 13:36:58 2008
@@ -24,7 +24,7 @@
import java.io.PushbackInputStream;
/**
- * @author scheu
+ * MIMEBodyPartInputStream
*
*/
public class MIMEBodyPartInputStream extends InputStream {
Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Part.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Part.java?rev=611943&r1=611942&r2=611943&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Part.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Part.java Mon Jan 14 13:36:58 2008
@@ -25,25 +25,80 @@
import java.io.InputStream;
import java.util.Enumeration;
+/**
+ * Abstract for Part. A Part can be the SOAP Part or an Attachment Part.
+ * There are several implementations for part, which are optimized for
+ * space and time.
+ *
+ * A Part is created with the PartFactory.
+ *
+ * @see org.apache.axiom.attachments.impl.PartFactory
+ */
public interface Part {
+ /**
+ * @return DataHandler representing this part
+ * @throws MessagingException
+ */
+ public DataHandler getDataHandler() throws MessagingException;
+
+ /**
+ * @return size
+ * @throws MessagingException
+ */
public int getSize() throws MessagingException;
+ /**
+ * @return content type of the part
+ * @throws MessagingException
+ */
public String getContentType() throws MessagingException;
+ /**
+ * @return content id of the part
+ * @throws MessagingException
+ */
public String getContentID() throws MessagingException;
+ /**
+ * The part may be backed by a file. If that is the case,
+ * this method returns the file name.
+ *
+ * @return
+ * @throws MessagingException
+ * @deprecated The callers should not no how the part
+ * is implemented.
+ */
public String getFileName() throws MessagingException;
+ /**
+ * @return Get the part data as an input stream
+ * @throws IOException
+ * @throws MessagingException
+ */
public InputStream getInputStream() throws IOException, MessagingException;
- public DataHandler getDataHandler() throws MessagingException;
-
- public void addHeader(String arg0, String arg1) throws MessagingException;
-
- public String getHeader(String arg0) throws MessagingException;
-
+ /**
+ * Add a Header (name, value) to the part
+ * @param name
+ * @param value
+ * @throws MessagingException
+ */
+ public void addHeader(String name, String value) throws MessagingException;
+
+ /**
+ * Get the value of a specific header
+ * @param name
+ * @return value or null
+ * @throws MessagingException
+ */
+ public String getHeader(String name) throws MessagingException;
+
+ /**
+ * @return Enumeration of javax.mail.Header
+ * @throws MessagingException
+ */
public Enumeration getAllHeaders() throws MessagingException;
}
Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/AbstractPart.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/AbstractPart.java?rev=611943&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/AbstractPart.java (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/AbstractPart.java Mon Jan 14 13:36:58 2008
@@ -0,0 +1,153 @@
+/*
+ * 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.attachments.impl;
+
+import org.apache.axiom.attachments.Part;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.activation.DataHandler;
+import javax.mail.Header;
+import javax.mail.MessagingException;
+import javax.mail.internet.HeaderTokenizer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+/**
+ * AbstractPart is a base class for the actual
+ * Part implementations. The primary purpose of AbstractPart is
+ * to define some of the common methods to promote code reuse.
+ */
+abstract class AbstractPart implements Part {
+
+ private static Log log = LogFactory.getLog(AbstractPart.class);
+
+ // Key is the lower-case name.
+ // Value is a javax.mail.Header object
+ private Hashtable headers;
+
+
+ /**
+ * The actual parts are constructed with the PartFactory.
+ * @see org.apache.axiom.attachments.impl.PartFactory
+ * @param headers
+ */
+ AbstractPart(Hashtable in) {
+ headers = in;
+ if (headers == null) {
+ headers = new Hashtable();
+ }
+ }
+
+ public void addHeader(String name, String value) {
+ if (log.isDebugEnabled()){
+ log.debug("addHeader: (" + name + ") value=(" + value +")");
+ }
+ Header headerObj = new Header(name, value);
+
+ // Use the lower case name as the key
+ String key = name.toLowerCase();
+ headers.put(key, headerObj);
+ }
+
+ public Enumeration getAllHeaders() throws MessagingException {
+ if(log.isDebugEnabled()){
+ log.debug("getAllHeaders");
+ }
+ return headers.elements();
+ }
+
+ public String getHeader(String name) {
+ String key = name.toLowerCase();
+ Header header = (Header) headers.get(key);
+ String value = header == null ? null : header.getValue();
+ if(log.isDebugEnabled()){
+ log.debug("getHeader name=(" + name + ") value=(" + value +")");
+ }
+ return value;
+ }
+
+ public String getContentID() throws MessagingException {
+ return getHeader("content-id");
+ }
+
+ public String getContentType() throws MessagingException {
+ return getHeader("content-type");
+ }
+
+ /**
+ * @return contentTransferEncoding
+ * @throws MessagingException
+ */
+ public String getContentTransferEncoding() throws MessagingException {
+ if(log.isDebugEnabled()){
+ log.debug("getContentTransferEncoding()");
+ }
+ String cte = getHeader("content-transfer-encoding");
+
+ if(log.isDebugEnabled()){
+ log.debug(" CTE =" + cte);
+ }
+
+ if(cte!=null){
+ cte = cte.trim();
+
+ if(cte.equalsIgnoreCase("7bit") ||
+ cte.equalsIgnoreCase("8bit") ||
+ cte.equalsIgnoreCase("quoted-printable") ||
+ cte.equalsIgnoreCase("base64")){
+
+ return cte;
+ }
+
+ HeaderTokenizer ht = new HeaderTokenizer(cte, HeaderTokenizer.MIME);
+ boolean done = false;
+ while(!done){
+ HeaderTokenizer.Token token = ht.next();
+ switch(token.getType()){
+ case HeaderTokenizer.Token.EOF:
+ if(log.isDebugEnabled()){
+ log.debug("HeaderTokenizer EOF");
+ }
+ done = true;
+ break;
+ case HeaderTokenizer.Token.ATOM:
+ return token.getValue();
+ }
+ }
+ return cte;
+ }
+ return null;
+
+
+ }
+
+ // The following classes must be implemented by the derived class.
+ public abstract DataHandler getDataHandler() throws MessagingException;
+
+ public abstract String getFileName() throws MessagingException;
+
+ public abstract InputStream getInputStream() throws IOException, MessagingException;
+
+ public abstract int getSize() throws MessagingException;
+
+}
Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/BufferUtils.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/BufferUtils.java?rev=611943&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/BufferUtils.java (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/BufferUtils.java Mon Jan 14 13:36:58 2008
@@ -0,0 +1,87 @@
+/*
+ * 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.attachments.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Attachment processing uses a lot of buffers.
+ * The BufferUtils class attempts to reuse buffers to prevent
+ * excessive GarbageCollection
+ */
+public class BufferUtils {
+
+ public static final int BUFFER_LEN = 16 * 1024;
+
+ /**
+ * Private utility to write the InputStream contents to the OutputStream.
+ * @param is
+ * @param os
+ * @throws IOException
+ */
+ public static void inputStream2OutputStream(InputStream is,
+ OutputStream os)
+ throws IOException {
+
+
+ byte[] buffer = new byte[BUFFER_LEN];
+ int bytesRead = is.read(buffer);
+
+ // Continue reading until no bytes are read and no
+ // bytes are now available.
+ while (bytesRead > 0 || is.available() > 0) {
+ os.write(buffer, 0, bytesRead);
+ bytesRead = is.read(buffer);
+ }
+
+ }
+
+ /**
+ * @param is InputStream
+ * @param os OutputStream
+ * @param limit maximum number of bytes to read
+ * @return total ytes read
+ * @throws IOException
+ */
+ public static int inputStream2OutputStream(InputStream is,
+ OutputStream os,
+ int limit)
+ throws IOException {
+
+ byte[] buffer = new byte[BUFFER_LEN];
+ int totalWritten = 0;
+ int bytesRead = 0;
+
+ do {
+ int len = (limit-totalWritten) > BUFFER_LEN ? BUFFER_LEN : (limit-totalWritten);
+ bytesRead = is.read(buffer, 0, len);
+ if (bytesRead > 0) {
+ os.write(buffer, 0, bytesRead);
+ if (bytesRead > 0) {
+ totalWritten += bytesRead;
+ }
+ }
+ } while (totalWritten < limit && (bytesRead > 0 || is.available() > 0));
+ return totalWritten;
+ }
+
+
+}
Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartFactory.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartFactory.java?rev=611943&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartFactory.java (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartFactory.java Mon Jan 14 13:36:58 2008
@@ -0,0 +1,205 @@
+/*
+ * 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.attachments.impl;
+
+import org.apache.axiom.attachments.MIMEBodyPartInputStream;
+import org.apache.axiom.attachments.Part;
+import org.apache.axiom.om.OMException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.mail.Header;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Hashtable;
+import java.util.Map;
+
+/**
+ * The PartFactory creates an object that represents a Part
+ * (implements the Part interface). There are different ways
+ * to represent a part (backing file or backing array etc.).
+ * These different implementations should not be exposed to the
+ * other layers of the code. The PartFactory helps maintain this
+ * abstraction, and makes it easier to add new implementations.
+ */
+public class PartFactory {
+
+ private static Log log = LogFactory.getLog(PartFactory.class);
+
+ /**
+ * Creates a part from the input stream.
+ * The remaining parameters are used to determine if the
+ * part should be represented in memory (byte buffers) or
+ * backed by a file.
+ *
+ * @param in MIMEBodyPartInputStream
+ * @param isSOAPPart
+ * @param threshholdSize
+ * @param attachmentDir
+ * @param messageContentLength
+ * @return Part
+ * @throws OMException if any exception is encountered while processing.
+ */
+ public static Part createPart(MIMEBodyPartInputStream in,
+ boolean isSOAPPart,
+ int threshholdSize,
+ String attachmentDir,
+ int messageContentLength
+ ) throws OMException {
+ if(log.isDebugEnabled()){
+ log.debug("Start createPart()");
+ log.debug(" isSOAPPart=" + isSOAPPart);
+ log.debug(" threshholdSize= " + threshholdSize);
+ log.debug(" attachmentDir=" + attachmentDir);
+ log.debug(" messageContentLength " + messageContentLength);
+ }
+
+ try {
+ // Read enough of the InputStream to build the headers
+ Hashtable headers = new Hashtable();
+ readHeaders(in, headers);
+
+
+ if (isSOAPPart ||
+ threshholdSize <= 0 ||
+ (messageContentLength > 0 &&
+ messageContentLength < threshholdSize)) {
+ // If the entire message is less than the threshold size,
+ // keep it in memory.
+ // If this is a SOAPPart, keep it in memory.
+
+ // Get the bytes of the data without a lot
+ // of resizing and GC. For now I will write to a
+ // private BAOS and get the byte buffer from it.
+ BAOS baos = new BAOS();
+ BufferUtils.inputStream2OutputStream(in, baos);
+ return new PartOnMemory(headers, baos.toByteArray(), baos.size());
+ } else {
+ // We need to read the input stream to determine whether
+ // the size is bigger or smaller than the threshhold.
+ BAOS baos = new BAOS();
+ int total = BufferUtils.inputStream2OutputStream(in, baos, threshholdSize);
+ if (total < threshholdSize) {
+ return new PartOnMemory(headers, baos.toByteArray(), baos.size());
+ } else {
+ ByteArrayInputStream bais =
+ new ByteArrayInputStream(baos.toByteArray(), 0, baos.size());
+
+ return new PartOnFile(headers,
+ bais,
+ in,
+ attachmentDir);
+ }
+
+ }
+
+ } catch (Exception e) {
+ throw new OMException(e);
+ }
+ }
+
+ /**
+ * The implementing class must call initHeaders prior to using
+ * any of the Part methods.
+ * @param is
+ * @param headers
+ */
+ private static void readHeaders(InputStream in, Map headers) throws IOException {
+ int ch;
+ if(log.isDebugEnabled()){
+ log.debug("initHeaders");
+ }
+ boolean done = false;
+
+ // Read the characters into a StringBuffer and
+ // add each header to the map
+ StringBuffer sb = new StringBuffer(50);
+ while (!done && (ch = in.read()) != -1) {
+ if (ch == 13) {
+ if ((ch = in.read()) == 10) {
+ if ((ch = in.read()) == 13) {
+ if ((ch = in.read()) == 10) {
+ // Blank line indicates we are done.
+ readHeader(sb, headers);
+ sb.delete(0, sb.length()); // Clear the buffer for reuse
+ done = true;
+ }
+ } else {
+ // now parse and add the header String
+ readHeader(sb, headers);
+ sb.delete(0, sb.length()); // Clear the buffer for reuse
+ sb.append((char) ch);
+ }
+ } else {
+ sb.append(13);
+ sb.append((char) ch);
+ }
+ } else {
+ sb.append((char) ch);
+ }
+ }
+ if(log.isDebugEnabled()){
+ log.debug("End initHeaders");
+ }
+ return;
+ }
+
+ /**
+ * Parse the header into a name and value pair.
+ * Add the name value pair to the map.
+ * @param header StringBuffer
+ * @param headers Map
+ */
+ private static void readHeader(StringBuffer header, Map headers) {
+ int delimiter = header.indexOf(":");
+ String name = header.substring(0, delimiter).trim();
+ String value = header.substring(delimiter + 1, header.length()).trim();
+
+ if (log.isDebugEnabled()){
+ log.debug("addHeader: (" + name + ") value=(" + value +")");
+ }
+ Header headerObj = new Header(name, value);
+
+ // Use the lower case name as the key
+ String key = name.toLowerCase();
+ headers.put(key, headerObj);
+ }
+
+ /**
+ * A normal ByteArrayOutputStream, except that it returns the buffer
+ * directly instead of returning a copy of the buffer.
+ */
+ static class BAOS extends ByteArrayOutputStream {
+
+ /**
+ * Create a BAOS with a decent sized buffer
+ */
+ public BAOS() {
+ super(16 * 1024);
+ }
+
+ public byte[] toByteArray() {
+ return buf;
+ }
+
+ }
+}
Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnFile.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnFile.java?rev=611943&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnFile.java (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnFile.java Mon Jan 14 13:36:58 2008
@@ -0,0 +1,128 @@
+/*
+ * 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.attachments.impl;
+
+import org.apache.axiom.attachments.CachedFileDataSource;
+import org.apache.axiom.om.util.UUIDGenerator;
+
+import javax.activation.DataHandler;
+import javax.mail.MessagingException;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Hashtable;
+
+/**
+ * PartOnFile stores that attachment in a file.
+ * This implementation is used for very large attachments to reduce
+ * the in-memory footprint.
+ *
+ * The PartOnFile object is created by the PartFactory
+ * @see org.apache.axiom.attachments.impl.PartFactory.
+ */
+public class PartOnFile extends AbstractPart {
+
+ File backingFile;
+
+
+ /**
+ * Create a PartOnFile from the specified InputStream
+ * @param headers Hashtable of javax.mail.Headers
+ * @param in1 InputStream containing data
+ * @param in2 InputStream containing data
+ * @param attachmentDir String
+ */
+ PartOnFile(Hashtable headers, InputStream is1, InputStream is2, String attachmentDir) throws IOException {
+ super(headers);
+ backingFile = createFile(attachmentDir);
+
+
+ // Now write the data to the backing file
+ FileOutputStream fos = new FileOutputStream(backingFile);
+ BufferUtils.inputStream2OutputStream(is1, fos);
+ BufferUtils.inputStream2OutputStream(is2, fos);
+ fos.flush();
+ fos.close();
+ }
+
+ /**
+ * Create a unique file in the designated directory
+ * @param attachmentDir
+ * @return File
+ * @throws IOException
+ */
+ private static File createFile(String attachmentDir) throws IOException {
+ File file = null;
+ File dir = null;
+ if (attachmentDir != null) {
+ dir = new File(attachmentDir);
+ if (!dir.exists()) {
+ dir.mkdirs();
+ }
+ }
+ if (!dir.isDirectory()) {
+ throw new IllegalArgumentException("Given Axis2 Attachment File Cache Location "
+ + dir + " should be a directory.");
+ }
+ // Generate unique id. The UUID generator is used so that we can limit
+ // synchronization with the java random number generator.
+ String id = UUIDGenerator.getUUID();
+
+ //Replace colons with underscores
+ id = id.replaceAll(":", "_");
+
+ String fileString = "Axis2" + id + ".att";
+ file = new File(dir, fileString);
+ return file;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.axiom.attachments.impl.AbstractPart#getDataHandler()
+ */
+ public DataHandler getDataHandler() throws MessagingException {
+ CachedFileDataSource dataSource = new CachedFileDataSource(backingFile);
+ dataSource.setContentType(getContentType());
+ return new DataHandler(dataSource);
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.axiom.attachments.impl.AbstractPart#getFileName()
+ */
+ public String getFileName() throws MessagingException {
+ return backingFile.getAbsolutePath();
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.axiom.attachments.impl.AbstractPart#getInputStream()
+ */
+ public InputStream getInputStream() throws IOException, MessagingException {
+ return new FileInputStream(backingFile);
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.axiom.attachments.impl.AbstractPart#getSize()
+ */
+ public int getSize() {
+ return (int) backingFile.length();
+ }
+
+}
Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnMemory.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnMemory.java?rev=611943&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnMemory.java (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnMemory.java Mon Jan 14 13:36:58 2008
@@ -0,0 +1,140 @@
+/*
+ * 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.attachments.impl;
+
+import org.apache.axiom.om.OMException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.activation.DataHandler;
+import javax.activation.DataSource;
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeUtility;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Hashtable;
+
+/**
+ * PartOnMemory stores that attachment in memory (in byte arrays)
+ * This implementation is used for smaller attachments to enhance
+ * performance.
+ *
+ * The PartOnMemory object is created by the PartFactory
+ * @see org.apache.axiom.attachments.impl.PartFactory.
+ */
+public class PartOnMemory extends AbstractPart {
+
+ private static Log log = LogFactory.getLog(PartOnMemory.class);
+ byte[] bytes;
+ int length;
+
+ /**
+ * Construct a PartOnMemory
+ * @param headers
+ * @param bytes
+ * @param length (length of data in bytes)
+ */
+ PartOnMemory(Hashtable headers, byte[] bytes, int length) {
+ super(headers);
+ this.bytes = bytes;
+ this.length = length;
+ }
+
+ public DataHandler getDataHandler() throws MessagingException {
+ DataSource ds = new MyByteArrayDataSource();
+ return new DataHandler(ds);
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.axiom.attachments.impl.AbstractPart#getFileName()
+ */
+ public String getFileName() throws MessagingException {
+ // There is no file name
+ return null;
+ }
+
+ public InputStream getInputStream() throws IOException, MessagingException {
+ return new ByteArrayInputStream(bytes, 0, length);
+ }
+
+ public int getSize() throws MessagingException {
+ return length;
+ }
+
+
+ /**
+ * A DataSource that is backed by the byte[] and
+ * headers map.
+ */
+ class MyByteArrayDataSource implements DataSource {
+
+ /* (non-Javadoc)
+ * @see javax.activation.DataSource#getContentType()
+ */
+ public String getContentType() {
+ String ct = getHeader("content-type");
+ return (ct == null) ?
+ "application/octet-stream" :
+ ct;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.activation.DataSource#getInputStream()
+ */
+ public InputStream getInputStream() throws IOException {
+ InputStream is = new ByteArrayInputStream(bytes, 0, length);
+ String cte = null;
+ try {
+ cte = getContentTransferEncoding();
+ if(cte != null){
+ if(log.isDebugEnabled()){
+ log.debug("Start Decoding stream");
+ }
+ return MimeUtility.decode(is, cte);
+
+ }
+ } catch (MessagingException e) {
+ if(log.isDebugEnabled()){
+ log.debug("Stream Failed decoding");
+ }
+ throw new OMException(e);
+ }
+ return is;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.activation.DataSource#getName()
+ */
+ public String getName() {
+ return "MyByteArrayDataSource";
+ }
+
+ /* (non-Javadoc)
+ * @see javax.activation.DataSource#getOutputStream()
+ */
+ public OutputStream getOutputStream() throws IOException {
+ throw new IOException("Not Supported");
+ }
+
+ }
+
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: commons-dev-help@ws.apache.org