Author: fmui
Date: Wed Mar 21 15:43:33 2012
New Revision: 1303448
URL: http://svn.apache.org/viewvc?rev=1303448&view=rev
Log:
OpenCMIS server: use the same content handling code for AtomPub and Browser
binding
Added:
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/shared/ThresholdOutputStream.java
(with props)
Modified:
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/atompub/AtomEntryParser.java
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/POSTHttpServletRequestWrapper.java
Modified:
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/atompub/AtomEntryParser.java
URL:
http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/atompub/AtomEntryParser.java?rev=1303448&r1=1303447&r2=1303448&view=diff
==============================================================================
---
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/atompub/AtomEntryParser.java
(original)
+++
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/atompub/AtomEntryParser.java
Wed Mar 21 15:43:33 2012
@@ -18,17 +18,10 @@
*/
package org.apache.chemistry.opencmis.server.impl.atompub;
-import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.FilterInputStream;
-import java.io.IOException;
import java.io.InputStream;
-import java.io.OutputStream;
import java.math.BigInteger;
import java.util.Iterator;
import java.util.List;
@@ -61,6 +54,7 @@ import org.apache.chemistry.opencmis.com
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertiesImpl;
import
org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyStringImpl;
import org.apache.chemistry.opencmis.commons.impl.jaxb.CmisObjectType;
+import org.apache.chemistry.opencmis.server.shared.ThresholdOutputStream;
/**
* Parser for Atom Entries.
@@ -389,7 +383,7 @@ public class AtomEntryParser {
* Parses a tag that contains base64 encoded content.
*/
private ThresholdOutputStream readBase64(XMLStreamReader parser) throws
Exception {
- ThresholdOutputStream bufferStream = new ThresholdOutputStream(64 *
1024, tempDir, memoryThreshold);
+ ThresholdOutputStream bufferStream = new
ThresholdOutputStream(tempDir, memoryThreshold);
Base64.OutputStream b64stream = new Base64.OutputStream(bufferStream,
Base64.DECODE);
next(parser);
@@ -582,245 +576,4 @@ public class AtomEntryParser {
return false;
}
-
- private static class ThresholdOutputStream extends OutputStream {
-
- private static final int MAX_GROW = 10 * 1024 * 1024;
- private static final int DEFAULT_THRESHOLD = 4 * 1024 * 1024;
-
- private File tempDir;
- private int memoryThreshold;
-
- private byte[] buf = null;
- private int bufSize = 0;
- private long size;
- private File tempFile;
- private OutputStream tmpStream;
-
- public ThresholdOutputStream(int initSize, File tempDir, int
memoryThreshold) {
- if (initSize < 0) {
- throw new IllegalArgumentException("Negative initial size: " +
initSize);
- }
-
- this.tempDir = tempDir;
- this.memoryThreshold = (memoryThreshold < 0 ? DEFAULT_THRESHOLD :
memoryThreshold);
-
- buf = new byte[initSize];
- }
-
- private void expand(int nextBufferSize) throws IOException {
- if (bufSize + nextBufferSize <= buf.length) {
- return;
- }
-
- if (bufSize + nextBufferSize > memoryThreshold) {
- if (tmpStream == null) {
- tempFile = File.createTempFile("opencmis", null, tempDir);
- tmpStream = new FileOutputStream(tempFile);
- }
- tmpStream.write(buf, 0, bufSize);
-
- if (buf.length != memoryThreshold) {
- buf = new byte[memoryThreshold];
- }
- bufSize = 0;
-
- return;
- }
-
- int newSize = ((bufSize + nextBufferSize) * 2 < MAX_GROW ?
(bufSize + nextBufferSize) * 2 : buf.length
- + nextBufferSize + MAX_GROW);
- byte[] newbuf = new byte[newSize];
- System.arraycopy(buf, 0, newbuf, 0, bufSize);
- buf = newbuf;
- }
-
- public long getSize() {
- return size;
- }
-
- @Override
- public void write(byte[] buffer) throws IOException {
- write(buffer, 0, buffer.length);
- }
-
- @Override
- public void write(byte[] buffer, int offset, int len) throws
IOException {
- if (len == 0) {
- return;
- }
-
- expand(len);
- System.arraycopy(buffer, offset, buf, bufSize, len);
- bufSize += len;
- size += len;
- }
-
- @Override
- public void write(int oneByte) throws IOException {
- if (bufSize == buf.length) {
- expand(1);
- }
-
- buf[bufSize++] = (byte) oneByte;
- size++;
- }
-
- @Override
- public void flush() throws IOException {
- if (tmpStream != null) {
- if (bufSize > 0) {
- tmpStream.write(buf, 0, bufSize);
- bufSize = 0;
- }
- tmpStream.flush();
- }
- }
-
- @Override
- public void close() throws IOException {
- flush();
-
- if (tmpStream != null) {
- tmpStream.close();
- }
- }
-
- public void destroy() {
- try {
- close();
- } catch (Exception e) {
- // ignore
- }
-
- if (tempFile != null) {
- tempFile.delete();
- }
-
- buf = null;
- }
-
- public InputStream getInputStream() throws Exception {
- if (tmpStream != null) {
- close();
- buf = null;
-
- return new InternalTempFileInputStream();
- } else {
- return new InternalBufferInputStream();
- }
- }
-
- private class InternalBufferInputStream extends InputStream {
-
- private int pos = 0;
-
- @Override
- public boolean markSupported() {
- return false;
- }
-
- @Override
- public int available() {
- return bufSize - pos;
- }
-
- @Override
- public int read() {
- return (pos < bufSize) && (buf != null) ? (buf[pos++] & 0xff)
: -1;
- }
-
- @Override
- public int read(byte[] b) throws IOException {
- return read(b, 0, b.length);
- }
-
- @Override
- public int read(byte[] b, int off, int len) {
- if ((pos >= bufSize) || (buf == null)) {
- return -1;
- }
-
- if ((pos + len) > bufSize) {
- len = (bufSize - pos);
- }
-
- System.arraycopy(buf, pos, b, off, len);
- pos += len;
-
- return len;
- }
-
- @Override
- public long skip(long n) {
- if ((pos + n) > bufSize) {
- n = bufSize - pos;
- }
-
- if (n < 0) {
- return 0;
- }
-
- pos += n;
-
- return n;
- }
-
- @Override
- public void close() throws IOException {
- buf = null;
- }
- }
-
- private class InternalTempFileInputStream extends FilterInputStream {
-
- private boolean isDeleted = false;
-
- public InternalTempFileInputStream() throws FileNotFoundException {
- super(new BufferedInputStream(new FileInputStream(tempFile),
64 * 1024));
- }
-
- @Override
- public boolean markSupported() {
- return false;
- }
-
- @Override
- public int read() throws IOException {
- int b = super.read();
-
- if (b == -1 && !isDeleted) {
- super.close();
- isDeleted = tempFile.delete();
- }
-
- return b;
- }
-
- @Override
- public int read(byte[] b) throws IOException {
- return read(b, 0, b.length);
- }
-
- @Override
- public int read(byte[] b, int off, int len) throws IOException {
- int n = super.read(b, off, len);
-
- if (n == -1 && !isDeleted) {
- super.close();
- isDeleted = tempFile.delete();
- }
-
- return n;
- }
-
- @Override
- public void close() throws IOException {
- if (!isDeleted) {
- super.close();
- isDeleted = tempFile.delete();
- }
- }
- }
- }
}
\ No newline at end of file
Modified:
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/POSTHttpServletRequestWrapper.java
URL:
http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/POSTHttpServletRequestWrapper.java?rev=1303448&r1=1303447&r2=1303448&view=diff
==============================================================================
---
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/POSTHttpServletRequestWrapper.java
(original)
+++
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/POSTHttpServletRequestWrapper.java
Wed Mar 21 15:43:33 2012
@@ -18,6 +18,7 @@
*/
package org.apache.chemistry.opencmis.server.impl.browser;
+import java.io.BufferedInputStream;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -26,7 +27,6 @@ import java.net.URLDecoder;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
@@ -34,12 +34,10 @@ import javax.servlet.http.HttpServletReq
import org.apache.chemistry.opencmis.commons.impl.Constants;
import org.apache.chemistry.opencmis.server.shared.HttpUtils;
-import org.apache.commons.fileupload.FileItem;
+import org.apache.chemistry.opencmis.server.shared.ThresholdOutputStream;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
-import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
-import org.apache.commons.fileupload.util.Streams;
public class POSTHttpServletRequestWrapper extends HttpServletRequestWrapper {
private final boolean isMultipart;
@@ -62,58 +60,63 @@ public class POSTHttpServletRequestWrapp
isMultipart = ServletFileUpload.isMultipartContent(request);
if (isMultipart) {
- if (true) {
- // multipart processing - the safe way
- DiskFileItemFactory itemFactory = new
DiskFileItemFactory(memoryThreshold, tempDir);
-
- ServletFileUpload upload = new ServletFileUpload(itemFactory);
- @SuppressWarnings("unchecked")
- List<FileItem> fileItems = upload.parseRequest(request);
-
- for (FileItem item : fileItems) {
- if (item.isFormField()) {
- addParameter(item.getFieldName(), item.getString());
- } else {
- filename = item.getName();
- contentType = (item.getContentType() == null ?
Constants.MEDIATYPE_OCTETSTREAM : item
- .getContentType());
- size = BigInteger.valueOf(item.getSize());
- stream = item.getInputStream();
+ ServletFileUpload upload = new ServletFileUpload();
+ FileItemIterator iter = upload.getItemIterator(request);
+
+ while (iter.hasNext()) {
+ FileItemStream item = iter.next();
+ String name = item.getFieldName();
+ InputStream itemStream = new
BufferedInputStream(item.openStream());
+
+ if (item.isFormField()) {
+ InputStreamReader reader = new
InputStreamReader(itemStream, "UTF-8");
+
+ try {
+ StringBuilder sb = new StringBuilder();
+
+ char[] buffer = new char[64 * 1024];
+ int b = 0;
+ while ((b = reader.read(buffer)) > -1) {
+ sb.append(buffer, 0, b);
+ }
+
+ addParameter(name, sb.toString());
+ } finally {
+ try {
+ reader.close();
+ } catch (Exception e) {
+ // ignore
+ }
}
- }
- } else {
- // multipart processing - optimized but unsafe
- // big content is not buffered on disk but has to be the last
- // part of the request
- // code is parked here until we find a way to make it safe
-
- ServletFileUpload upload = new ServletFileUpload();
- FileItemIterator iter = upload.getItemIterator(request);
-
- while (iter.hasNext()) {
- FileItemStream item = iter.next();
- String name = item.getFieldName();
- InputStream itemStream = item.openStream();
-
- if (item.isFormField()) {
- addParameter(name, Streams.asString(itemStream));
- } else {
- filename = item.getName();
- contentType = (item.getContentType() == null ?
Constants.MEDIATYPE_OCTETSTREAM : item
- .getContentType());
-
- if (item.getHeaders() != null) {
- String lengthStr =
item.getHeaders().getHeader("Content-Length");
- if (lengthStr != null) {
- try {
- size = new BigInteger(lengthStr);
- } catch (NumberFormatException e) {
- }
- }
+ } else {
+ filename = item.getName();
+ contentType = (item.getContentType() == null ?
Constants.MEDIATYPE_OCTETSTREAM : item
+ .getContentType());
+
+ ThresholdOutputStream os = new
ThresholdOutputStream(tempDir, memoryThreshold);
+
+ try {
+ byte[] buffer = new byte[64 * 1024];
+ int b = 0;
+ while ((b = itemStream.read(buffer)) > -1) {
+ os.write(buffer, 0, b);
}
- stream = itemStream;
- break;
+ os.close();
+
+ size = BigInteger.valueOf(os.getSize());
+ stream = os.getInputStream();
+ } catch (Exception e) {
+ // if something went wrong, make sure the temp file
will
+ // be deleted
+ os.destroy();
+ throw e;
+ } finally {
+ try {
+ itemStream.close();
+ } catch (Exception e) {
+ // ignore
+ }
}
}
}
Added:
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/shared/ThresholdOutputStream.java
URL:
http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/shared/ThresholdOutputStream.java?rev=1303448&view=auto
==============================================================================
---
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/shared/ThresholdOutputStream.java
(added)
+++
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/shared/ThresholdOutputStream.java
Wed Mar 21 15:43:33 2012
@@ -0,0 +1,329 @@
+/*
+ * 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.chemistry.opencmis.server.shared;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * An OutputStream that stores the data in main memory until it reaches a
+ * threshold. If the threshold is passed the data is written to a temporary
+ * file.
+ *
+ * It it is important to close this OutputStream before
+ * {@link #getInputStream()} is called or call {@link #destroy()} if the
+ * InputStream isn't required!
+ */
+public class ThresholdOutputStream extends OutputStream {
+ private static final int MAX_GROW = 10 * 1024 * 1024;
+ private static final int DEFAULT_THRESHOLD = 4 * 1024 * 1024;
+
+ private File tempDir;
+ private int memoryThreshold;
+
+ private byte[] buf = null;
+ private int bufSize = 0;
+ private long size;
+ private File tempFile;
+ private OutputStream tmpStream;
+
+ public ThresholdOutputStream(File tempDir, int memoryThreshold) {
+ this(64 * 1024, tempDir, memoryThreshold);
+ }
+
+ public ThresholdOutputStream(int initSize, File tempDir, int
memoryThreshold) {
+ if (initSize < 0) {
+ throw new IllegalArgumentException("Negative initial size: " +
initSize);
+ }
+
+ this.tempDir = tempDir;
+ this.memoryThreshold = (memoryThreshold < 0 ? DEFAULT_THRESHOLD :
memoryThreshold);
+
+ buf = new byte[initSize];
+ }
+
+ private void expand(int nextBufferSize) throws IOException {
+ if (bufSize + nextBufferSize <= buf.length) {
+ return;
+ }
+
+ if (bufSize + nextBufferSize > memoryThreshold) {
+ if (tmpStream == null) {
+ tempFile = File.createTempFile("opencmis", null, tempDir);
+ tmpStream = new BufferedOutputStream(new
FileOutputStream(tempFile));
+ }
+ tmpStream.write(buf, 0, bufSize);
+
+ if (buf.length != memoryThreshold) {
+ buf = new byte[memoryThreshold];
+ }
+ bufSize = 0;
+
+ return;
+ }
+
+ int newSize = ((bufSize + nextBufferSize) * 2 < MAX_GROW ? (bufSize +
nextBufferSize) * 2 : buf.length
+ + nextBufferSize + MAX_GROW);
+ byte[] newbuf = new byte[newSize];
+ System.arraycopy(buf, 0, newbuf, 0, bufSize);
+ buf = newbuf;
+ }
+
+ public long getSize() {
+ return size;
+ }
+
+ @Override
+ public void write(byte[] buffer) throws IOException {
+ write(buffer, 0, buffer.length);
+ }
+
+ @Override
+ public void write(byte[] buffer, int offset, int len) throws IOException {
+ if (len == 0) {
+ return;
+ }
+
+ expand(len);
+ System.arraycopy(buffer, offset, buf, bufSize, len);
+ bufSize += len;
+ size += len;
+ }
+
+ @Override
+ public void write(int oneByte) throws IOException {
+ if (bufSize == buf.length) {
+ expand(1);
+ }
+
+ buf[bufSize++] = (byte) oneByte;
+ size++;
+ }
+
+ @Override
+ public void flush() throws IOException {
+ if (tmpStream != null) {
+ if (bufSize > 0) {
+ tmpStream.write(buf, 0, bufSize);
+ bufSize = 0;
+ }
+ tmpStream.flush();
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ flush();
+
+ if (tmpStream != null) {
+ tmpStream.close();
+ }
+ }
+
+ /**
+ * Destroys the object before it has been read.
+ */
+ public void destroy() {
+ try {
+ close();
+ } catch (Exception e) {
+ // ignore
+ }
+
+ if (tempFile != null) {
+ tempFile.delete();
+ }
+
+ buf = null;
+ }
+
+ /**
+ * Returns the data as an InputStream.
+ */
+ public InputStream getInputStream() throws Exception {
+ if (tmpStream != null) {
+ close();
+ buf = null;
+
+ return new InternalTempFileInputStream();
+ } else {
+ return new InternalBufferInputStream();
+ }
+ }
+
+ /**
+ * Provides information about the input stream.
+ */
+ public interface ThresholdInputStream {
+
+ /**
+ * Returns <code>true</code> if the data is in memory. Returns
+ * <code>false</code> if the data resides in a temporary file.
+ */
+ boolean isInMemory();
+
+ /**
+ * Returns the temporary file if the data stored in a file. Returns
+ * <code>null</code> is the data is stored in memory.
+ */
+ File getTemporaryFile();
+ }
+
+ /**
+ * InputStream for in-memory data.
+ */
+ private class InternalBufferInputStream extends InputStream implements
ThresholdInputStream {
+
+ private int pos = 0;
+
+ public boolean isInMemory() {
+ return true;
+ }
+
+ public File getTemporaryFile() {
+ return null;
+ }
+
+ @Override
+ public boolean markSupported() {
+ return false;
+ }
+
+ @Override
+ public int available() {
+ return bufSize - pos;
+ }
+
+ @Override
+ public int read() {
+ return (pos < bufSize) && (buf != null) ? (buf[pos++] & 0xff) : -1;
+ }
+
+ @Override
+ public int read(byte[] b) throws IOException {
+ return read(b, 0, b.length);
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) {
+ if ((pos >= bufSize) || (buf == null)) {
+ return -1;
+ }
+
+ if ((pos + len) > bufSize) {
+ len = (bufSize - pos);
+ }
+
+ System.arraycopy(buf, pos, b, off, len);
+ pos += len;
+
+ return len;
+ }
+
+ @Override
+ public long skip(long n) {
+ if ((pos + n) > bufSize) {
+ n = bufSize - pos;
+ }
+
+ if (n < 0) {
+ return 0;
+ }
+
+ pos += n;
+
+ return n;
+ }
+
+ @Override
+ public void close() throws IOException {
+ buf = null;
+ }
+ }
+
+ /**
+ * InputStream for file data.
+ */
+ private class InternalTempFileInputStream extends FilterInputStream
implements ThresholdInputStream {
+
+ private boolean isDeleted = false;
+
+ public InternalTempFileInputStream() throws FileNotFoundException {
+ super(new BufferedInputStream(new FileInputStream(tempFile),
memoryThreshold));
+ }
+
+ public boolean isInMemory() {
+ return false;
+ }
+
+ public File getTemporaryFile() {
+ return tempFile;
+ }
+
+ @Override
+ public boolean markSupported() {
+ return false;
+ }
+
+ @Override
+ public int read() throws IOException {
+ int b = super.read();
+
+ if (b == -1 && !isDeleted) {
+ super.close();
+ isDeleted = tempFile.delete();
+ }
+
+ return b;
+ }
+
+ @Override
+ public int read(byte[] b) throws IOException {
+ return read(b, 0, b.length);
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ int n = super.read(b, off, len);
+
+ if (n == -1 && !isDeleted) {
+ super.close();
+ isDeleted = tempFile.delete();
+ }
+
+ return n;
+ }
+
+ @Override
+ public void close() throws IOException {
+ if (!isDeleted) {
+ super.close();
+ isDeleted = tempFile.delete();
+ }
+ }
+ }
+}
Propchange:
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/shared/ThresholdOutputStream.java
------------------------------------------------------------------------------
svn:eol-style = native