You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ws.apache.org by ve...@apache.org on 2015/05/16 01:56:51 UTC
svn commit: r1679662 [1/3] - in /webservices/axiom/trunk:
modules/axiom-api/src/main/java/org/apache/axiom/attachments/
modules/axiom-api/src/main/java/org/apache/axiom/blob/
modules/axiom-api/src/main/java/org/apache/axiom/util/stax/
modules/axiom-api...
Author: veithen
Date: Fri May 15 23:56:49 2015
New Revision: 1679662
URL: http://svn.apache.org/r1679662
Log:
Improve the blob API and use it to implement MIME part handling (instead of the old PartContent code).
Added:
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/LegacyTempFileBlob.java (with props)
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/LegacyTempFileBlobFactory.java (with props)
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/AbstractWritableBlob.java (with props)
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/Blobs.java (with props)
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/IOUtil.java (with props)
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/MemoryBlobImpl.java
- copied, changed from r1678555, webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/MemoryBlob.java
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/OverflowableBlob.java
- copied, changed from r1678555, webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/OverflowBlob.java
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/OverflowableBlobImpl.java
- copied, changed from r1678555, webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/OverflowBlob.java
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/State.java (with props)
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/TempFileBlobFactory.java (with props)
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/TempFileBlobImpl.java (with props)
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/TempFileInputStream.java (with props)
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/WritableBlobFactory.java
- copied, changed from r1678555, webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/WritableBlobFactory.java
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/OverflowableBlobTest.java
- copied, changed from r1678555, webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/OverflowBlobTest.java
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TempFileBlobTest.java (with props)
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/ByteArrayOutputStreamWithReadFromSupport.java (with props)
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/CleanupCallback.java (with props)
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/SizeSensitiveWritableBlobTestCase.java (with props)
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/State.java (with props)
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestAvailable.java (with props)
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestGetInputStreamIllegalState.java
- copied, changed from r1678555, webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestGetInputStreamNew.java
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestGetOutputStreamIllegalState.java
- copied, changed from r1678555, webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestGetOutputStreamCommitted.java
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestGetSizeIllegalState.java (with props)
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestMarkReset.java
- copied, changed from r1678555, webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestMarkReset.java
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestRandomReadWrite.java
- copied, changed from r1678555, webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestRandomReadWrite.java
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadEOF.java (with props)
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadFrom.java
- copied, changed from r1678555, webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestReadFrom.java
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadFromIllegalState.java
- copied, changed from r1678555, webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestReadFromCommitted.java
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadFromSupport.java (with props)
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadFromWithError.java (with props)
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadZeroLength.java (with props)
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReleaseTwice.java (with props)
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestSkip.java (with props)
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestWriteAfterCommit.java (with props)
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestWriteTo.java (with props)
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestWriteToIllegalState.java (with props)
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestWriteToWithError.java (with props)
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/WritableBlobTestCase.java
- copied, changed from r1678555, webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/WritableBlobTestCase.java
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/WritableBlobTestSuiteBuilder.java
- copied, changed from r1678555, webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/WritableBlobTestSuiteBuilder.java
webservices/axiom/trunk/testing/testutils/src/main/java/org/apache/axiom/testutils/io/CloseSensorOutputStream.java (with props)
webservices/axiom/trunk/testing/testutils/src/main/java/org/apache/axiom/testutils/io/ExceptionOutputStream.java (with props)
Removed:
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/PartContent.java
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/PartContentFactory.java
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/PartContentOnFile.java
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/PartContentOnMemory.java
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/BlobOutputStream.java
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/OverflowBlob.java
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/OverflowBlobTest.java
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestGetInputStreamNew.java
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestGetInputStreamUncommitted.java
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestGetOutputStreamCommitted.java
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestGetOutputStreamUncommitted.java
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestMarkReset.java
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestRandomReadWrite.java
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestReadFrom.java
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestReadFromCommitted.java
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/WritableBlobFactory.java
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/WritableBlobTestCase.java
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/WritableBlobTestSuiteBuilder.java
Modified:
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/AttachmentSet.java
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Attachments.java
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/AttachmentsDelegate.java
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/MIMEMessage.java
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/PartImpl.java
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/Blob.java
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/BlobDataSource.java
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/MemoryBlob.java
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/WritableBlob.java
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/package.html
webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/XMLStreamReaderUtils.java
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/attachments/PartOnFileTest.java
webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/MemoryBlobTest.java
webservices/axiom/trunk/modules/axiom-compat/src/main/java/org/apache/axiom/util/blob/BlobOutputStream.java
webservices/axiom/trunk/modules/axiom-compat/src/main/java/org/apache/axiom/util/blob/OverflowBlob.java
webservices/axiom/trunk/systests/integration-tests/src/test/java/org/apache/axiom/om/impl/builder/JAXBCustomBuilderTest.java
webservices/axiom/trunk/testing/testutils/src/main/java/org/apache/axiom/testutils/io/ExceptionInputStream.java
Modified: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/AttachmentSet.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/AttachmentSet.java?rev=1679662&r1=1679661&r2=1679662&view=diff
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/AttachmentSet.java (original)
+++ webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/AttachmentSet.java Fri May 15 23:56:49 2015
@@ -27,7 +27,6 @@ import java.util.Set;
import javax.activation.DataHandler;
-import org.apache.axiom.attachments.lifecycle.LifecycleManager;
import org.apache.axiom.mime.ContentType;
import org.apache.axiom.om.OMException;
@@ -42,14 +41,6 @@ class AttachmentSet extends AttachmentsD
return null;
}
- LifecycleManager getLifecycleManager() {
- return null;
- }
-
- void setLifecycleManager(LifecycleManager manager) {
- // Ignore; only stream based attachments need a lifecycle manager
- }
-
DataHandler getDataHandler(String contentID) {
return (DataHandler)attachmentsMap.get(contentID);
}
Modified: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Attachments.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Attachments.java?rev=1679662&r1=1679661&r2=1679662&view=diff
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Attachments.java (original)
+++ webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Attachments.java Fri May 15 23:56:49 2015
@@ -21,6 +21,10 @@ package org.apache.axiom.attachments;
import org.apache.axiom.attachments.lifecycle.DataHandlerExt;
import org.apache.axiom.attachments.lifecycle.LifecycleManager;
+import org.apache.axiom.attachments.lifecycle.impl.LifecycleManagerImpl;
+import org.apache.axiom.blob.Blobs;
+import org.apache.axiom.blob.WritableBlob;
+import org.apache.axiom.blob.WritableBlobFactory;
import org.apache.axiom.ext.activation.SizeAwareDataSource;
import org.apache.axiom.mime.ContentType;
import org.apache.axiom.om.OMAttachmentAccessor;
@@ -46,12 +50,17 @@ public class Attachments implements OMAt
*/
private String applicationType;
+ private LifecycleManager manager;
+
public LifecycleManager getLifecycleManager() {
- return delegate.getLifecycleManager();
+ if (manager == null) {
+ manager = new LifecycleManagerImpl();
+ }
+ return manager;
}
public void setLifecycleManager(LifecycleManager manager) {
- delegate.setLifecycleManager(manager);
+ this.manager = manager;
}
/**
@@ -84,14 +93,35 @@ public class Attachments implements OMAt
*/
public Attachments(LifecycleManager manager, InputStream inStream, String contentTypeString, boolean fileCacheEnable,
String attachmentRepoDir, String fileThreshold, int contentLength) throws OMException {
- int fileStorageThreshold;
+ this.manager = manager;
+ final int fileStorageThreshold;
if (fileThreshold != null && (!"".equals(fileThreshold))) {
fileStorageThreshold = Integer.parseInt(fileThreshold);
} else {
- fileStorageThreshold = 1;
+ fileStorageThreshold = 0;
+ }
+ WritableBlobFactory attachmentBlobFactory;
+ if (fileCacheEnable) {
+ final WritableBlobFactory tempFileBlobFactory = new LegacyTempFileBlobFactory(this, attachmentRepoDir);
+ if (fileStorageThreshold > 0) {
+ attachmentBlobFactory = new WritableBlobFactory() {
+ public WritableBlob createBlob() {
+ return Blobs.createOverflowableBlob(fileStorageThreshold, tempFileBlobFactory);
+ }
+ };
+ } else {
+ attachmentBlobFactory = tempFileBlobFactory;
+ }
+ } else {
+ attachmentBlobFactory = new WritableBlobFactory() {
+ public WritableBlob createBlob() {
+ return Blobs.createMemoryBlob();
+ }
+ };
}
- delegate = new MIMEMessage(manager, inStream, contentTypeString, fileCacheEnable,
- attachmentRepoDir, fileStorageThreshold, contentLength);
+
+ delegate = new MIMEMessage(inStream, contentTypeString, attachmentBlobFactory,
+ contentLength);
}
/**
Modified: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/AttachmentsDelegate.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/AttachmentsDelegate.java?rev=1679662&r1=1679661&r2=1679662&view=diff
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/AttachmentsDelegate.java (original)
+++ webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/AttachmentsDelegate.java Fri May 15 23:56:49 2015
@@ -25,7 +25,6 @@ import java.util.Set;
import javax.activation.DataHandler;
-import org.apache.axiom.attachments.lifecycle.LifecycleManager;
import org.apache.axiom.mime.ContentType;
import org.apache.axiom.om.OMException;
@@ -50,8 +49,6 @@ import org.apache.axiom.om.OMException;
*/
abstract class AttachmentsDelegate {
abstract ContentType getContentType();
- abstract LifecycleManager getLifecycleManager();
- abstract void setLifecycleManager(LifecycleManager manager);
abstract DataHandler getDataHandler(String contentID);
abstract void addDataHandler(String contentID, DataHandler dataHandler);
abstract void removeDataHandler(String blobContentID);
Added: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/LegacyTempFileBlob.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/LegacyTempFileBlob.java?rev=1679662&view=auto
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/LegacyTempFileBlob.java (added)
+++ webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/LegacyTempFileBlob.java Fri May 15 23:56:49 2015
@@ -0,0 +1,63 @@
+/*
+ * 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;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.activation.DataSource;
+
+import org.apache.axiom.attachments.lifecycle.LifecycleManager;
+import org.apache.axiom.attachments.lifecycle.impl.FileAccessor;
+import org.apache.axiom.blob.AbstractWritableBlob;
+
+final class LegacyTempFileBlob extends AbstractWritableBlob {
+ private final LifecycleManager lifecycleManager;
+ private final String attachmentDir;
+ private FileAccessor fileAccessor;
+
+ LegacyTempFileBlob(LifecycleManager lifecycleManager, String attachmentDir) {
+ this.lifecycleManager = lifecycleManager;
+ this.attachmentDir = attachmentDir;
+ }
+
+ public OutputStream getOutputStream() throws IOException {
+ fileAccessor = lifecycleManager.create(attachmentDir);
+ return fileAccessor.getOutputStream();
+ }
+
+ public InputStream getInputStream() throws IOException {
+ return fileAccessor.getInputStream();
+ }
+
+ DataSource getDataSource(String contentType) {
+ CachedFileDataSource ds = new CachedFileDataSource(fileAccessor.getFile());
+ ds.setContentType(contentType);
+ return ds;
+ }
+
+ public long getSize() {
+ return fileAccessor.getSize();
+ }
+
+ public void release() throws IOException {
+ lifecycleManager.delete(fileAccessor.getFile());
+ }
+}
Propchange: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/LegacyTempFileBlob.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/LegacyTempFileBlobFactory.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/LegacyTempFileBlobFactory.java?rev=1679662&view=auto
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/LegacyTempFileBlobFactory.java (added)
+++ webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/LegacyTempFileBlobFactory.java Fri May 15 23:56:49 2015
@@ -0,0 +1,36 @@
+/*
+ * 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;
+
+import org.apache.axiom.blob.WritableBlob;
+import org.apache.axiom.blob.WritableBlobFactory;
+
+final class LegacyTempFileBlobFactory implements WritableBlobFactory {
+ private final Attachments attachments;
+ private final String attachmentDir;
+
+ LegacyTempFileBlobFactory(Attachments attachments, String attachmentDir) {
+ this.attachments = attachments;
+ this.attachmentDir = attachmentDir;
+ }
+
+ public WritableBlob createBlob() {
+ return new LegacyTempFileBlob(attachments.getLifecycleManager(), attachmentDir);
+ }
+}
Propchange: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/LegacyTempFileBlobFactory.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/MIMEMessage.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/MIMEMessage.java?rev=1679662&r1=1679661&r2=1679662&view=diff
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/MIMEMessage.java (original)
+++ webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/MIMEMessage.java Fri May 15 23:56:49 2015
@@ -31,8 +31,9 @@ import java.util.Set;
import javax.activation.DataHandler;
import org.apache.axiom.attachments.lifecycle.DataHandlerExt;
-import org.apache.axiom.attachments.lifecycle.LifecycleManager;
-import org.apache.axiom.attachments.lifecycle.impl.LifecycleManagerImpl;
+import org.apache.axiom.blob.Blobs;
+import org.apache.axiom.blob.WritableBlob;
+import org.apache.axiom.blob.WritableBlobFactory;
import org.apache.axiom.mime.ContentType;
import org.apache.axiom.mime.Header;
import org.apache.axiom.om.OMException;
@@ -53,6 +54,12 @@ import org.apache.james.mime4j.stream.Re
*/
class MIMEMessage extends AttachmentsDelegate {
private static final Log log = LogFactory.getLog(MIMEMessage.class);
+
+ private static final WritableBlobFactory rootPartBlobFactory = new WritableBlobFactory() {
+ public WritableBlob createBlob() {
+ return Blobs.createMemoryBlob();
+ }
+ };
/** <code>ContentType</code> of the MIME message */
private final ContentType contentType;
@@ -88,24 +95,15 @@ class MIMEMessage extends AttachmentsDel
private String firstPartId;
- private final boolean fileCacheEnable;
-
- private final String attachmentRepoDir;
-
- private final int fileStorageThreshold;
+ private final WritableBlobFactory attachmentBlobFactory;
- private LifecycleManager manager;
-
- MIMEMessage(LifecycleManager manager, InputStream inStream, String contentTypeString, boolean fileCacheEnable,
- String attachmentRepoDir, int fileStorageThreshold, int contentLength) throws OMException {
- this.manager = manager;
+ MIMEMessage(InputStream inStream, String contentTypeString,
+ WritableBlobFactory attachmentBlobFactory, int contentLength) throws OMException {
this.contentLength = contentLength;
- this.attachmentRepoDir = attachmentRepoDir;
- this.fileCacheEnable = fileCacheEnable;
+ this.attachmentBlobFactory = attachmentBlobFactory;
if (log.isDebugEnabled()) {
log.debug("Attachments contentLength=" + contentLength + ", contentTypeString=" + contentTypeString);
}
- this.fileStorageThreshold = fileStorageThreshold;
try {
contentType = new ContentType(contentTypeString);
} catch (ParseException e) {
@@ -153,17 +151,6 @@ class MIMEMessage extends AttachmentsDel
return contentType;
}
- LifecycleManager getLifecycleManager() {
- if(manager == null) {
- manager = new LifecycleManagerImpl();
- }
- return manager;
- }
-
- void setLifecycleManager(LifecycleManager manager) {
- this.manager = manager;
- }
-
DataHandler getDataHandler(String contentID) {
do {
DataHandler dataHandler = (DataHandler)attachmentsMap.get(contentID);
@@ -357,7 +344,7 @@ class MIMEMessage extends AttachmentsDel
List headers = readHeaders();
partIndex++;
- currentPart = new PartImpl(this, isRootPart, headers, parser);
+ currentPart = new PartImpl(isRootPart ? rootPartBlobFactory : attachmentBlobFactory, headers, parser);
return currentPart;
} catch (IOException ex) {
throw new OMException(ex);
@@ -366,18 +353,6 @@ class MIMEMessage extends AttachmentsDel
}
}
- int getThreshold() {
- return fileCacheEnable ? fileStorageThreshold : 0;
- }
-
- String getAttachmentRepoDir() {
- return attachmentRepoDir;
- }
-
- int getContentLengthIfKnown() {
- return contentLength;
- }
-
private List readHeaders() throws IOException, MimeException {
if(log.isDebugEnabled()){
log.debug("readHeaders");
Modified: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/PartImpl.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/PartImpl.java?rev=1679662&r1=1679661&r2=1679662&view=diff
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/PartImpl.java (original)
+++ webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/attachments/PartImpl.java Fri May 15 23:56:49 2015
@@ -20,6 +20,10 @@
package org.apache.axiom.attachments;
import org.apache.axiom.attachments.Part;
+import org.apache.axiom.blob.OverflowableBlob;
+import org.apache.axiom.blob.WritableBlob;
+import org.apache.axiom.blob.WritableBlobFactory;
+import org.apache.axiom.ext.io.StreamCopyException;
import org.apache.axiom.mime.Header;
import org.apache.axiom.om.OMException;
import org.apache.axiom.om.util.DetachableInputStream;
@@ -66,8 +70,7 @@ final class PartImpl implements Part {
private static final Log log = LogFactory.getLog(PartImpl.class);
- private final MIMEMessage message;
- private final boolean isRootPart;
+ private final WritableBlobFactory blobFactory;
private List/*<Header>*/ headers;
@@ -82,7 +85,7 @@ final class PartImpl implements Part {
/**
* The content of this part. This is only set if the state is {@link #STATE_BUFFERED}.
*/
- private PartContent content;
+ private WritableBlob content;
private final DataHandler dataHandler;
@@ -93,9 +96,8 @@ final class PartImpl implements Part {
* @see org.apache.axiom.attachments.PartContentFactory
* @param headers
*/
- PartImpl(MIMEMessage message, boolean isRootPart, List headers, MimeTokenStream parser) {
- this.message = message;
- this.isRootPart = isRootPart;
+ PartImpl(WritableBlobFactory blobFactory, List headers, MimeTokenStream parser) {
+ this.blobFactory = blobFactory;;
this.headers = headers;
this.parser = parser;
this.dataHandler = new PartDataHandler(this);
@@ -143,7 +145,7 @@ final class PartImpl implements Part {
return getContent().getSize();
}
- private PartContent getContent() {
+ private WritableBlob getContent() {
switch (state) {
case STATE_UNREAD:
fetch();
@@ -176,13 +178,19 @@ final class PartImpl implements Part {
if (log.isDebugEnabled()) {
in = new DebugInputStream(in, log);
}
- // The PartFactory will determine which Part implementation is most appropriate.
- content = PartContentFactory.createPartContent(message.getLifecycleManager(),
- in,
- isRootPart,
- message.getThreshold(),
- message.getAttachmentRepoDir(),
- message.getContentLengthIfKnown()); // content-length for the whole message
+ content = blobFactory.createBlob();
+ if (log.isDebugEnabled()) {
+ log.debug("Using blob of type " + content.getClass().getName());
+ }
+ try {
+ content.readFrom(in);
+ } catch (StreamCopyException ex) {
+ if (ex.getOperation() == StreamCopyException.READ) {
+ throw new OMException("Failed to fetch the MIME part content", ex.getCause());
+ } else {
+ throw new OMException("Failed to write the MIME part content to temporary storage", ex.getCause());
+ }
+ }
moveToNextPart();
state = STATE_BUFFERED;
break;
@@ -225,7 +233,7 @@ final class PartImpl implements Part {
detachableInputStream = new DetachableInputStream(parser.getDecodedInputStream());
return detachableInputStream;
} else {
- PartContent content = getContent();
+ WritableBlob content = getContent();
InputStream stream = content.getInputStream();
if (!preserve) {
stream = new ReadOnceInputStreamWrapper(this, stream);
@@ -235,7 +243,18 @@ final class PartImpl implements Part {
}
DataSource getDataSource() {
- return getContent().getDataSource(getDataSourceContentType());
+ WritableBlob blob = getContent();
+ if (blob instanceof OverflowableBlob) {
+ WritableBlob overflowBlob = ((OverflowableBlob)blob).getOverflowBlob();
+ if (overflowBlob != null) {
+ blob = overflowBlob;
+ }
+ }
+ if (blob instanceof LegacyTempFileBlob) {
+ return ((LegacyTempFileBlob)blob).getDataSource(getDataSourceContentType());
+ } else {
+ return null;
+ }
}
void writeTo(OutputStream out) throws IOException {
@@ -256,7 +275,7 @@ final class PartImpl implements Part {
state = STATE_DISCARDED;
break;
case STATE_BUFFERED:
- content.destroy();
+ content.release();
}
}
}
Added: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/AbstractWritableBlob.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/AbstractWritableBlob.java?rev=1679662&view=auto
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/AbstractWritableBlob.java (added)
+++ webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/AbstractWritableBlob.java Fri May 15 23:56:49 2015
@@ -0,0 +1,68 @@
+/*
+ * 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.blob;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.axiom.ext.io.StreamCopyException;
+
+/**
+ * Partial implementation of the {@link WritableBlob} interface that implements
+ * {@link WritableBlob#readFrom(InputStream)} using {@link WritableBlob#getOutputStream()} and
+ * {@link WritableBlob#writeTo(OutputStream)} using {@link WritableBlob#getInputStream()}.
+ */
+public abstract class AbstractWritableBlob implements WritableBlob {
+ public long readFrom(InputStream in) throws StreamCopyException {
+ OutputStream out;
+ try {
+ out = getOutputStream();
+ } catch (IOException ex) {
+ throw new StreamCopyException(StreamCopyException.WRITE, ex);
+ }
+ try {
+ return IOUtil.copy(in, out, -1);
+ } finally {
+ try {
+ out.close();
+ } catch (IOException ex) {
+ throw new StreamCopyException(StreamCopyException.WRITE, ex);
+ }
+ }
+ }
+
+ public void writeTo(OutputStream out) throws StreamCopyException {
+ InputStream in;
+ try {
+ in = getInputStream();
+ } catch (IOException ex) {
+ throw new StreamCopyException(StreamCopyException.READ, ex);
+ }
+ try {
+ IOUtil.copy(in, out, -1);
+ } finally {
+ try {
+ in.close();
+ } catch (IOException ex) {
+ throw new StreamCopyException(StreamCopyException.READ, ex);
+ }
+ }
+ }
+}
Propchange: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/AbstractWritableBlob.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/Blob.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/Blob.java?rev=1679662&r1=1679661&r2=1679662&view=diff
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/Blob.java (original)
+++ webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/Blob.java Fri May 15 23:56:49 2015
@@ -28,13 +28,18 @@ import org.apache.axiom.ext.io.StreamCop
/**
* Stores binary data.
* <p>
- * Not that blobs are not thread safe. While they support requesting multiple concurrent input
- * streams, these streams must be used in the same thread, unless appropriate synchronization or
- * locking is done.
+ * Blobs are thread safe in the sense that methods defined by this interface may be called
+ * concurrently. In addition, two different threads can safely invoke methods on two different
+ * {@link InputStream} instances retrieved by {@link #getInputStream()} concurrently. However some
+ * blobs (in particular {@link WritableBlob} implementations) may define additional methods and
+ * invoking these methods concurrently with methods defined by this interface is generally not
+ * thread safe.
*/
public interface Blob {
/**
- * Get an input stream to read the data in the blob.
+ * Get an input stream to read the data in the blob. A new {@link InputStream} object is
+ * returned each time this method is called, and the stream is positioned at the beginning of
+ * the data.
*
* @return the input stream to read the data from
* @throws IOException
@@ -42,7 +47,8 @@ public interface Blob {
InputStream getInputStream() throws IOException;
/**
- * Write the data to a given output stream.
+ * Write the data to a given output stream. This method can be called multiple times, i.e. it
+ * doesn't consume the content.
*
* @param out
* The output stream to write the data to. This method will not close the stream.
@@ -54,9 +60,9 @@ public interface Blob {
void writeTo(OutputStream out) throws StreamCopyException;
/**
- * Get the length of the data in the blob, i.e. the number of bytes.
+ * Get the size of the blob.
*
- * @return the length of the data in the blob
+ * @return the number of bytes in the blob
*/
- long getLength();
+ long getSize();
}
\ No newline at end of file
Modified: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/BlobDataSource.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/BlobDataSource.java?rev=1679662&r1=1679661&r2=1679662&view=diff
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/BlobDataSource.java (original)
+++ webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/BlobDataSource.java Fri May 15 23:56:49 2015
@@ -54,6 +54,6 @@ public class BlobDataSource implements S
}
public long getSize() {
- return blob.getLength();
+ return blob.getSize();
}
}
Added: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/Blobs.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/Blobs.java?rev=1679662&view=auto
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/Blobs.java (added)
+++ webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/Blobs.java Fri May 15 23:56:49 2015
@@ -0,0 +1,73 @@
+/*
+ * 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.blob;
+
+import java.io.File;
+
+/**
+ * Contains factory methods to create various types of blobs.
+ */
+public final class Blobs {
+ private Blobs() {}
+
+ /**
+ * Create a {@link MemoryBlob} instance.
+ *
+ * @return the blob
+ */
+ public static MemoryBlob createMemoryBlob() {
+ return new MemoryBlobImpl();
+ }
+
+ /**
+ * Create an {@link OverflowableBlob}.
+ *
+ * @param threshold
+ * the threshold above which data is transferred to the overflow blob
+ * @param overflowBlobFactory
+ * the factory that will be used to create the overflow blob
+ * @return the blob
+ */
+ public static OverflowableBlob createOverflowableBlob(int threshold, WritableBlobFactory overflowBlobFactory) {
+ int numberOfChunks = Math.max(16, Math.min(1, threshold/4096));
+ int chunkSize = threshold/numberOfChunks;
+ return new OverflowableBlobImpl(numberOfChunks, chunkSize, overflowBlobFactory);
+ }
+
+ /**
+ * Create an {@link OverflowableBlob} that overflows to a temporary file. Temporary files are
+ * created using {@link File#createTempFile(String, String, File)}.
+ *
+ * @param threshold
+ * the overflow threshold
+ * @param tempPrefix
+ * the prefix to be used in generating the name of the temporary file
+ * @param tempSuffix
+ * the suffix to be used in generating the name of the temporary file
+ * @param tempDirectory
+ * the directory in which the temporary file is to be created, or <code>null</code>
+ * if the default temporary directory is to be used
+ * @return the blob
+ */
+ public static OverflowableBlob createOverflowableBlob(int threshold, String tempPrefix,
+ String tempSuffix, File tempDirectory) {
+ return createOverflowableBlob(threshold,
+ new TempFileBlobFactory(tempPrefix, tempSuffix, tempDirectory));
+ }
+}
Propchange: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/Blobs.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/IOUtil.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/IOUtil.java?rev=1679662&view=auto
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/IOUtil.java (added)
+++ webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/IOUtil.java Fri May 15 23:56:49 2015
@@ -0,0 +1,59 @@
+/*
+ * 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.blob;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.axiom.ext.io.ReadFromSupport;
+import org.apache.axiom.ext.io.StreamCopyException;
+
+final class IOUtil {
+ private IOUtil() {}
+
+ static long copy(InputStream in, OutputStream out, long length) throws StreamCopyException {
+ if (out instanceof ReadFromSupport) {
+ return ((ReadFromSupport)out).readFrom(in, length);
+ } else {
+ byte[] buffer = new byte[4096];
+ long read = 0;
+ long toRead = length == -1 ? Long.MAX_VALUE : length;
+ while (toRead > 0) {
+ int c;
+ try {
+ c = in.read(buffer, 0, (int)Math.min(toRead, buffer.length));
+ } catch (IOException ex) {
+ throw new StreamCopyException(StreamCopyException.READ, ex);
+ }
+ if (c == -1) {
+ break;
+ }
+ try {
+ out.write(buffer, 0, c);
+ } catch (IOException ex) {
+ throw new StreamCopyException(StreamCopyException.WRITE, ex);
+ }
+ read += c;
+ toRead -= c;
+ }
+ return read;
+ }
+ }
+}
Propchange: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/IOUtil.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/MemoryBlob.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/MemoryBlob.java?rev=1679662&r1=1679661&r2=1679662&view=diff
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/MemoryBlob.java (original)
+++ webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/MemoryBlob.java Fri May 15 23:56:49 2015
@@ -16,244 +16,23 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.axiom.blob;
-import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.axiom.ext.io.StreamCopyException;
/**
- * Blob implementation that stores data in memory.
+ * Blob that stores data in memory.
+ * <p>
+ * This interface redefines several methods from {@link Blob} and {@link WritableBlob} to not throw
+ * {@link IOException}. Also note that since data is stored in memory, calling
+ * {@link WritableBlob#release()} is not required.
+ * <p>
+ * Instances are created with {@link Blobs#createMemoryBlob()}.
*/
-public final class MemoryBlob implements WritableBlob {
- // TODO: this should be configurable
- final static int BUFFER_SIZE = 4096;
-
- class OutputStreamImpl extends BlobOutputStream {
- public WritableBlob getBlob() {
- return MemoryBlob.this;
- }
-
- public void write(byte[] b, int off, int len) throws IOException {
- int total = 0;
- while (total < len) {
- int copy = Math.min(len-total, BUFFER_SIZE-index);
- System.arraycopy(b, off, currBuffer, index, copy);
- total += copy;
- index += copy;
- off += copy;
- if (index >= BUFFER_SIZE) {
- addBuffer();
- }
- }
- }
-
- public void write(byte[] b) throws IOException {
- this.write(b, 0, b.length);
- }
-
- byte[] writeByte = new byte[1];
- public void write(int b) throws IOException {
- writeByte[0] = (byte) b;
- this.write(writeByte, 0, 1);
- }
-
- public void close() throws IOException {
- committed = true;
- }
- }
-
- class InputStreamImpl extends InputStream {
- private int i;
- private int currIndex;
- private int totalIndex;
- private int mark;
- private byte[] currBuffer;
- private byte[] read_byte = new byte[1];
-
- public InputStreamImpl() {
- }
-
- public int read() throws IOException {
- int read = read(read_byte);
-
- if (read < 0) {
- return -1;
- } else {
- return read_byte[0] & 0xFF;
- }
- }
-
- public int available() throws IOException {
- return (int)getLength() - totalIndex;
- }
-
-
- public synchronized void mark(int readlimit) {
- mark = totalIndex;
- }
-
- public boolean markSupported() {
- return true;
- }
-
- public int read(byte[] b, int off, int len) throws IOException {
- int size = (int)getLength();
- int total = 0;
- if (totalIndex >= size) {
- return -1;
- }
- while (total < len && totalIndex < size) {
- if (currBuffer == null) {
- currBuffer = (byte[]) data.get(i);
- }
- int copy = Math.min(len - total, BUFFER_SIZE - currIndex);
- copy = Math.min(copy, size - totalIndex);
- System.arraycopy(currBuffer, currIndex, b, off, copy);
- total += copy;
- currIndex += copy;
- totalIndex += copy;
- off += copy;
- if (currIndex >= BUFFER_SIZE) {
- if (i+1 < data.size()) {
- i++;
- currIndex = 0;
- } else {
- currIndex = BUFFER_SIZE;
- }
- currBuffer = null;
- }
- }
- return total;
- }
-
- public int read(byte[] b) throws IOException {
- return this.read(b, 0, b.length);
- }
-
- public synchronized void reset() throws IOException {
- i = mark / BUFFER_SIZE;
- currIndex = mark - (i * BUFFER_SIZE);
- currBuffer = (byte[]) data.get(i);
- totalIndex = mark;
- }
- }
-
- List data; // null here indicates the blob is in state NEW
- int index;
- byte[] currBuffer;
- boolean committed;
-
- private void init() {
- data = new ArrayList();
- addBuffer();
- }
-
- void addBuffer() {
- currBuffer = new byte[BUFFER_SIZE];
- data.add(currBuffer);
- index = 0;
- }
-
- public boolean isSupportingReadUncommitted() {
- return true;
- }
-
- public long getLength() {
- if (data == null) {
- return 0;
- } else {
- return (BUFFER_SIZE * (data.size()-1)) + index;
- }
- }
-
- public BlobOutputStream getOutputStream() {
- if (data != null) {
- throw new IllegalStateException();
- } else {
- init();
- return new OutputStreamImpl();
- }
- }
-
- public long readFrom(InputStream in, long length, boolean commit) throws StreamCopyException {
- if (committed) {
- throw new IllegalStateException();
- }
- if (data == null) {
- init();
- }
-
- if (length == -1) {
- length = Long.MAX_VALUE;
- }
- long bytesReceived = 0;
-
- // Now directly write to the buffers
- boolean done = false;
- while (!done) {
-
- // Don't get more than will fit in the current buffer
- int len = (int) Math.min(BUFFER_SIZE - index, length-bytesReceived);
-
- // Now get the bytes
- int bytesRead;
- try {
- bytesRead = in.read(currBuffer, index, len);
- } catch (IOException ex) {
- throw new StreamCopyException(StreamCopyException.READ, ex);
- }
- if (bytesRead >= 0) {
- bytesReceived += bytesRead;
- index += bytesRead;
- if (index >= BUFFER_SIZE) {
- addBuffer();
- }
- if (bytesReceived >= length) {
- done = true;
- }
- } else {
- done = true;
- }
- }
-
- committed = commit;
-
- return bytesReceived;
- }
-
- public long readFrom(InputStream in, long length) throws StreamCopyException {
- return readFrom(in, length, data == null);
- }
-
- public InputStream getInputStream() {
- return new InputStreamImpl();
- }
-
- public void writeTo(OutputStream os) throws StreamCopyException {
- int size = (int)getLength();
- if (data != null) {
- try {
- int numBuffers = data.size();
- for (int j = 0; j < numBuffers-1; j ++) {
- os.write( (byte[]) data.get(j), 0, BUFFER_SIZE);
- }
- if (numBuffers > 0) {
- int writeLimit = size - ((numBuffers-1) * BUFFER_SIZE);
- os.write( (byte[]) data.get(numBuffers-1), 0, writeLimit);
- }
- } catch (IOException ex) {
- throw new StreamCopyException(StreamCopyException.WRITE, ex);
- }
- }
- }
-
- public void release() {
- // no-op
- }
+public interface MemoryBlob extends WritableBlob {
+ InputStream getInputStream();
+ OutputStream getOutputStream();
+ long getSize();
+ void release();
}
Copied: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/MemoryBlobImpl.java (from r1678555, webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/MemoryBlob.java)
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/MemoryBlobImpl.java?p2=webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/MemoryBlobImpl.java&p1=webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/MemoryBlob.java&r1=1678555&r2=1679662&rev=1679662&view=diff
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/MemoryBlob.java (original)
+++ webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/MemoryBlobImpl.java Fri May 15 23:56:49 2015
@@ -25,32 +25,29 @@ import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
+import org.apache.axiom.ext.io.ReadFromSupport;
import org.apache.axiom.ext.io.StreamCopyException;
-/**
- * Blob implementation that stores data in memory.
- */
-public final class MemoryBlob implements WritableBlob {
+final class MemoryBlobImpl implements MemoryBlob {
// TODO: this should be configurable
final static int BUFFER_SIZE = 4096;
- class OutputStreamImpl extends BlobOutputStream {
- public WritableBlob getBlob() {
- return MemoryBlob.this;
- }
-
+ class OutputStreamImpl extends OutputStream implements ReadFromSupport {
public void write(byte[] b, int off, int len) throws IOException {
- int total = 0;
- while (total < len) {
- int copy = Math.min(len-total, BUFFER_SIZE-index);
- System.arraycopy(b, off, currBuffer, index, copy);
- total += copy;
- index += copy;
- off += copy;
- if (index >= BUFFER_SIZE) {
- addBuffer();
- }
- }
+ if (committed) {
+ throw new IllegalStateException();
+ }
+ int total = 0;
+ while (total < len) {
+ int copy = Math.min(len-total, BUFFER_SIZE-index);
+ System.arraycopy(b, off, currBuffer, index, copy);
+ total += copy;
+ index += copy;
+ off += copy;
+ if (index >= BUFFER_SIZE) {
+ addBuffer();
+ }
+ }
}
public void write(byte[] b) throws IOException {
@@ -66,6 +63,10 @@ public final class MemoryBlob implements
public void close() throws IOException {
committed = true;
}
+
+ public long readFrom(InputStream in, long length) throws StreamCopyException {
+ return MemoryBlobImpl.this.readFrom(in, length, false);
+ }
}
class InputStreamImpl extends InputStream {
@@ -90,7 +91,7 @@ public final class MemoryBlob implements
}
public int available() throws IOException {
- return (int)getLength() - totalIndex;
+ return (int)getSize() - totalIndex;
}
@@ -103,7 +104,7 @@ public final class MemoryBlob implements
}
public int read(byte[] b, int off, int len) throws IOException {
- int size = (int)getLength();
+ int size = (int)getSize();
int total = 0;
if (totalIndex >= size) {
return -1;
@@ -119,13 +120,9 @@ public final class MemoryBlob implements
currIndex += copy;
totalIndex += copy;
off += copy;
- if (currIndex >= BUFFER_SIZE) {
- if (i+1 < data.size()) {
- i++;
- currIndex = 0;
- } else {
- currIndex = BUFFER_SIZE;
- }
+ if (currIndex == BUFFER_SIZE) {
+ i++;
+ currIndex = 0;
currBuffer = null;
}
}
@@ -160,20 +157,16 @@ public final class MemoryBlob implements
index = 0;
}
- public boolean isSupportingReadUncommitted() {
- return true;
- }
-
- public long getLength() {
- if (data == null) {
- return 0;
+ public long getSize() {
+ if (data == null || !committed) {
+ throw new IllegalStateException();
} else {
return (BUFFER_SIZE * (data.size()-1)) + index;
}
}
- public BlobOutputStream getOutputStream() {
- if (data != null) {
+ public OutputStream getOutputStream() {
+ if (data != null || committed) {
throw new IllegalStateException();
} else {
init();
@@ -181,7 +174,7 @@ public final class MemoryBlob implements
}
}
- public long readFrom(InputStream in, long length, boolean commit) throws StreamCopyException {
+ long readFrom(InputStream in, long length, boolean commit) throws StreamCopyException {
if (committed) {
throw new IllegalStateException();
}
@@ -227,33 +220,38 @@ public final class MemoryBlob implements
return bytesReceived;
}
- public long readFrom(InputStream in, long length) throws StreamCopyException {
- return readFrom(in, length, data == null);
+ public long readFrom(InputStream in) throws StreamCopyException {
+ if (data != null) {
+ throw new IllegalStateException();
+ }
+ return readFrom(in, -1, true);
}
public InputStream getInputStream() {
+ if (data == null || !committed) {
+ throw new IllegalStateException();
+ }
return new InputStreamImpl();
}
public void writeTo(OutputStream os) throws StreamCopyException {
- int size = (int)getLength();
- if (data != null) {
- try {
- int numBuffers = data.size();
- for (int j = 0; j < numBuffers-1; j ++) {
- os.write( (byte[]) data.get(j), 0, BUFFER_SIZE);
- }
- if (numBuffers > 0) {
- int writeLimit = size - ((numBuffers-1) * BUFFER_SIZE);
- os.write( (byte[]) data.get(numBuffers-1), 0, writeLimit);
- }
- } catch (IOException ex) {
- throw new StreamCopyException(StreamCopyException.WRITE, ex);
- }
+ if (data == null || !committed) {
+ throw new IllegalStateException();
+ }
+ int size = (int)getSize();
+ try {
+ int numBuffers = data.size();
+ for (int j = 0; j < numBuffers-1; j ++) {
+ os.write( (byte[]) data.get(j), 0, BUFFER_SIZE);
+ }
+ int writeLimit = size - ((numBuffers-1) * BUFFER_SIZE);
+ os.write( (byte[]) data.get(numBuffers-1), 0, writeLimit);
+ } catch (IOException ex) {
+ throw new StreamCopyException(StreamCopyException.WRITE, ex);
}
}
public void release() {
- // no-op
+ data = null;
}
}
Copied: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/OverflowableBlob.java (from r1678555, webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/OverflowBlob.java)
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/OverflowableBlob.java?p2=webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/OverflowableBlob.java&p1=webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/OverflowBlob.java&r1=1678555&r2=1679662&rev=1679662&view=diff
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/OverflowBlob.java (original)
+++ webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/OverflowableBlob.java Fri May 15 23:56:49 2015
@@ -16,453 +16,23 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.axiom.blob;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import org.apache.axiom.ext.io.ReadFromSupport;
-import org.apache.axiom.ext.io.StreamCopyException;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
/**
- * Blob implementation that stores data in a temporary file if the size exceeds a configurable
- * threshold. The data is first stored into a fixed size buffer. Once this buffer overflows, it is
- * transferred to a temporary file. The buffer is divided into a given number of fixed size chunks
- * that are allocated on demand. Since a temporary file may be created it is mandatory to call
- * {@link #release()} to discard the blob.
+ * Blob that accumulates data in memory and transfers it to a different type of blob if the size
+ * exceeds a certain threshold. Typically the overflow blob (i.e. the blob that is created if the
+ * memory buffer overflows) stores data in a temporary file. It is therefore mandatory to call
+ * {@link WritableBlob#release()} to discard the blob.
+ * <p>
+ * Instances are created with {@link Blobs#createOverflowableBlob(int, WritableBlobFactory)} or any
+ * of the other methods returning {@link OverflowableBlob}.
*/
-public final class OverflowBlob implements WritableBlob {
- private static final Log log = LogFactory.getLog(OverflowBlob.class);
-
- static final int STATE_NEW = 0;
- static final int STATE_UNCOMMITTED = 1;
- static final int STATE_COMMITTED = 2;
-
- class OutputStreamImpl extends BlobOutputStream {
-
- private FileOutputStream fileOutputStream;
-
- public WritableBlob getBlob() {
- return OverflowBlob.this;
- }
-
- public void write(byte[] b, int off, int len) throws IOException {
-
- if (fileOutputStream != null) {
- fileOutputStream.write(b, off, len);
- } else if (len > (chunks.length-chunkIndex)*chunkSize - chunkOffset) {
-
- // The buffer will overflow. Switch to a temporary file.
- fileOutputStream = switchToTempFile();
-
- // Write the new data to the temporary file.
- fileOutputStream.write(b, off, len);
-
- } else {
-
- // The data will fit into the buffer.
- while (len > 0) {
-
- byte[] chunk = getCurrentChunk();
-
- // Determine number of bytes that can be copied to the current chunk.
- int c = Math.min(len, chunkSize-chunkOffset);
- // Copy data to the chunk.
- System.arraycopy(b, off, chunk, chunkOffset, c);
-
- // Update variables.
- len -= c;
- off += c;
- chunkOffset += c;
- if (chunkOffset == chunkSize) {
- chunkIndex++;
- chunkOffset = 0;
- }
- }
- }
- }
-
- public void write(byte[] b) throws IOException {
- write(b, 0, b.length);
- }
-
- public void write(int b) throws IOException {
- write(new byte[] { (byte)b }, 0, 1);
- }
-
- public void flush() throws IOException {
- if (fileOutputStream != null) {
- fileOutputStream.flush();
- }
- }
-
- public void close() throws IOException {
- if (fileOutputStream != null) {
- fileOutputStream.close();
- }
- state = STATE_COMMITTED;
- }
- }
-
- class InputStreamImpl extends InputStream {
-
- private int currentChunkIndex;
- private int currentChunkOffset;
- private int markChunkIndex;
- private int markChunkOffset;
-
- public int available() throws IOException {
- return (chunkIndex-currentChunkIndex)*chunkSize + chunkOffset - currentChunkOffset;
- }
-
- public int read(byte[] b, int off, int len) throws IOException {
-
- if (len == 0) {
- return 0;
- }
-
- int read = 0;
- while (len > 0 && !(currentChunkIndex == chunkIndex
- && currentChunkOffset == chunkOffset)) {
-
- int c;
- if (currentChunkIndex == chunkIndex) {
- // The current chunk is the last one => take into account the offset
- c = Math.min(len, chunkOffset-currentChunkOffset);
- } else {
- c = Math.min(len, chunkSize-currentChunkOffset);
- }
-
- // Copy the data.
- System.arraycopy(chunks[currentChunkIndex], currentChunkOffset, b, off, c);
-
- // Update variables
- len -= c;
- off += c;
- currentChunkOffset += c;
- read += c;
- if (currentChunkOffset == chunkSize) {
- currentChunkIndex++;
- currentChunkOffset = 0;
- }
- }
-
- if (read == 0) {
- // We didn't read anything (and the len argument was not 0) => we reached the end of the buffer.
- return -1;
- } else {
- return read;
- }
- }
-
- public int read(byte[] b) throws IOException {
- return read(b, 0, b.length);
- }
-
- public int read() throws IOException {
- byte[] b = new byte[1];
- return read(b) == -1 ? -1 : b[0] & 0xFF;
- }
-
- public boolean markSupported() {
- return true;
- }
-
- public void mark(int readlimit) {
- markChunkIndex = currentChunkIndex;
- markChunkOffset = currentChunkOffset;
- }
-
- public void reset() throws IOException {
- currentChunkIndex = markChunkIndex;
- currentChunkOffset = markChunkOffset;
- }
-
- public long skip(long n) throws IOException {
-
- int available = available();
- int c = n < available ? (int)n : available;
- int newOffset = currentChunkOffset + c;
- int chunkDelta = newOffset/chunkSize;
- currentChunkIndex += chunkDelta;
- currentChunkOffset = newOffset - (chunkDelta*chunkSize);
- return c;
- }
-
- public void close() throws IOException {
- }
- }
-
- /**
- * Size of the chunks that will be allocated in the buffer.
- */
- final int chunkSize;
-
- /**
- * The prefix to be used in generating the name of the temporary file.
- */
- final String tempPrefix;
-
- /**
- * The suffix to be used in generating the name of the temporary file.
- */
- final String tempSuffix;
-
- /**
- * Array of <code>byte[]</code> representing the chunks of the buffer.
- * A chunk is only allocated when the first byte is written to it.
- * This attribute is set to <code>null</code> when the buffer overflows and
- * is written out to a temporary file.
- */
- byte[][] chunks;
-
- /**
- * Index of the chunk the next byte will be written to.
- */
- int chunkIndex;
-
- /**
- * Offset into the chunk where the next byte will be written.
- */
- int chunkOffset;
-
+public interface OverflowableBlob extends WritableBlob {
/**
- * The handle of the temporary file. This is only set when the memory buffer
- * overflows and is written out to a temporary file.
- */
- File temporaryFile;
-
- /**
- * The state of the blob.
- */
- int state = STATE_NEW;
-
- public OverflowBlob(int numberOfChunks, int chunkSize, String tempPrefix, String tempSuffix) {
- this.chunkSize = chunkSize;
- this.tempPrefix = tempPrefix;
- this.tempSuffix = tempSuffix;
- chunks = new byte[numberOfChunks][];
- }
-
- public boolean isSupportingReadUncommitted() {
- // This is actually a limitation of the implementation, not an intrinsic limitation
- return false;
- }
-
- /**
- * Get the current chunk to write to, allocating it if necessary.
+ * Get a reference to the overflow blob. The overflow blob is created only if the size of the
+ * blob exceeds the threshold. The method returns <code>null</code> if that's not the case.
*
- * @return the current chunk to write to (never null)
+ * @return the overflow blob, or <code>null</code> if this blob hasn't overflown
*/
- byte[] getCurrentChunk() {
- if (chunkOffset == 0) {
- // We will write the first byte to the current chunk. Allocate it.
- byte[] chunk = new byte[chunkSize];
- chunks[chunkIndex] = chunk;
- return chunk;
- } else {
- // The chunk has already been allocated.
- return chunks[chunkIndex];
- }
- }
-
- /**
- * Create a temporary file and write the existing in memory data to it.
- *
- * @return an open FileOutputStream to the temporary file
- * @throws IOException
- */
- FileOutputStream switchToTempFile() throws IOException {
- temporaryFile = File.createTempFile(tempPrefix, tempSuffix);
- if (log.isDebugEnabled()) {
- log.debug("Using temporary file " + temporaryFile);
- }
- temporaryFile.deleteOnExit();
-
- FileOutputStream fileOutputStream = new FileOutputStream(temporaryFile);
- // Write the buffer to the temporary file.
- for (int i=0; i<chunkIndex; i++) {
- fileOutputStream.write(chunks[i]);
- }
-
- if (chunkOffset > 0) {
- fileOutputStream.write(chunks[chunkIndex], 0, chunkOffset);
- }
-
- // Release references to the buffer so that it can be garbage collected.
- chunks = null;
-
- return fileOutputStream;
- }
-
- public BlobOutputStream getOutputStream() {
- if (state != STATE_NEW) {
- throw new IllegalStateException();
- } else {
- state = STATE_UNCOMMITTED;
- return new OutputStreamImpl();
- }
- }
-
- public long readFrom(InputStream in, long length, boolean commit) throws StreamCopyException {
- if (state == STATE_COMMITTED) {
- throw new IllegalStateException();
- }
- // TODO: this will not work if the blob is in state UNCOMMITTED and we have already switched to a temporary file
- long read = 0;
- long toRead = length == -1 ? Long.MAX_VALUE : length;
- while (true) {
- int c;
- try {
- int len = chunkSize-chunkOffset;
- if (len > toRead) {
- len = (int)toRead;
- }
- c = in.read(getCurrentChunk(), chunkOffset, len);
- } catch (IOException ex) {
- throw new StreamCopyException(StreamCopyException.READ, ex);
- }
- if (c == -1) {
- break;
- }
- read += c;
- toRead -= c;
- chunkOffset += c;
- if (chunkOffset == chunkSize) {
- chunkIndex++;
- chunkOffset = 0;
- if (chunkIndex == chunks.length) {
- FileOutputStream fileOutputStream;
- try {
- fileOutputStream = switchToTempFile();
- } catch (IOException ex) {
- throw new StreamCopyException(StreamCopyException.WRITE, ex);
- }
- byte[] buf = new byte[4096];
- while (true) {
- int c2;
- try {
- c2 = in.read(buf, 0, (int)Math.min(toRead, 4096));
- } catch (IOException ex) {
- throw new StreamCopyException(StreamCopyException.READ, ex);
- }
- if (c2 == -1) {
- break;
- }
- try {
- fileOutputStream.write(buf, 0, c2);
- } catch (IOException ex) {
- throw new StreamCopyException(StreamCopyException.WRITE, ex);
- }
- read += c2;
- toRead -= c2;
- }
- try {
- fileOutputStream.close();
- } catch (IOException ex) {
- throw new StreamCopyException(StreamCopyException.WRITE, ex);
- }
- break;
- }
- }
- }
- state = commit ? STATE_COMMITTED : STATE_UNCOMMITTED;
- return read;
- }
-
- public long readFrom(InputStream in, long length) throws StreamCopyException {
- return readFrom(in, length, state == STATE_NEW);
- }
-
- public InputStream getInputStream() throws IOException {
- if (state != STATE_COMMITTED) {
- throw new IllegalStateException();
- } else if (temporaryFile != null) {
- return new FileInputStream(temporaryFile);
- } else {
- return new InputStreamImpl();
- }
- }
-
- public void writeTo(OutputStream out) throws StreamCopyException {
- if (temporaryFile != null) {
- FileInputStream in;
- try {
- in = new FileInputStream(temporaryFile);
- } catch (IOException ex) {
- throw new StreamCopyException(StreamCopyException.READ, ex);
- }
- try {
- if (out instanceof ReadFromSupport) {
- ((ReadFromSupport)out).readFrom(in, -1);
- } else {
- byte[] buf = new byte[4096];
- while (true) {
- int c;
- try {
- c = in.read(buf);
- } catch (IOException ex) {
- throw new StreamCopyException(StreamCopyException.READ, ex);
- }
- if (c == -1) {
- break;
- }
- try {
- out.write(buf, 0, c);
- } catch (IOException ex) {
- throw new StreamCopyException(StreamCopyException.WRITE, ex);
- }
- }
- }
- } finally {
- try {
- in.close();
- } catch (IOException ex) {
- throw new StreamCopyException(StreamCopyException.READ, ex);
- }
- }
- } else {
- try {
- for (int i=0; i<chunkIndex; i++) {
- out.write(chunks[i]);
- }
- if (chunkOffset > 0) {
- out.write(chunks[chunkIndex], 0, chunkOffset);
- }
- } catch (IOException ex) {
- throw new StreamCopyException(StreamCopyException.WRITE, ex);
- }
- }
- }
-
- public long getLength() {
- if (temporaryFile != null) {
- return temporaryFile.length();
- } else {
- return chunkIndex*chunkSize + chunkOffset;
- }
- }
-
- public void release() {
- if (temporaryFile != null) {
- if (log.isDebugEnabled()) {
- log.debug("Deleting temporary file " + temporaryFile);
- }
- temporaryFile.delete();
- }
- }
-
- protected void finalize() throws Throwable {
- if (temporaryFile != null) {
- log.warn("Cleaning up unreleased temporary file " + temporaryFile);
- temporaryFile.delete();
- }
- }
+ WritableBlob getOverflowBlob();
}