You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by fm...@apache.org on 2014/02/03 13:41:56 UTC
svn commit: r1563862 - in
/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src:
main/java/org/apache/chemistry/opencmis/server/shared/
test/java/org/apache/chemistry/opencmis/server/impl/
Author: fmui
Date: Mon Feb 3 12:41:56 2014
New Revision: 1563862
URL: http://svn.apache.org/r1563862
Log:
Corrected ThresholdOutputStream (the rewind and mark/reset behaviors of in-memory and temp file storage should be the same)
Added:
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/test/java/org/apache/chemistry/opencmis/server/impl/ThresholdOutputStreamTest.java (with props)
Modified:
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/shared/ThresholdOutputStream.java
Modified: 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=1563862&r1=1563861&r2=1563862&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/shared/ThresholdOutputStream.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/shared/ThresholdOutputStream.java Mon Feb 3 12:41:56 2014
@@ -78,8 +78,7 @@ public class ThresholdOutputStream exten
* Constructor.
*
* @param tempDir
- * temp directory or <code>null</code> for the default temp
- * directory
+ * temp directory or {@code null} for the default temp directory
* @param memoryThreshold
* memory threshold in bytes
* @param maxContentSize
@@ -93,8 +92,7 @@ public class ThresholdOutputStream exten
* Constructor.
*
* @param tempDir
- * temp directory or <code>null</code> for the default temp
- * directory
+ * temp directory or {@code null} for the default temp directory
* @param memoryThreshold
* memory threshold in bytes
* @param maxContentSize
@@ -110,8 +108,7 @@ public class ThresholdOutputStream exten
* @param initSize
* initial internal buffer size
* @param tempDir
- * temp directory or <code>null</code> for the default temp
- * directory
+ * temp directory or {@code null} for the default temp directory
* @param memoryThreshold
* memory threshold in bytes
* @param maxContentSize
@@ -139,27 +136,7 @@ public class ThresholdOutputStream exten
if (bufSize + nextBufferSize > memoryThreshold) {
if (tmpStream == null) {
- tempFile = File.createTempFile("opencmis", null, tempDir);
- if (encrypt) {
-
- Cipher cipher;
- try {
- KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM);
- keyGenerator.init(KEY_SIZE);
- key = keyGenerator.generateKey();
-
- cipher = Cipher.getInstance(TRANSFORMATION);
- cipher.init(Cipher.ENCRYPT_MODE, key);
-
- iv = cipher.getIV();
- } catch (Exception e) {
- throw new IOException("Cannot initialize encryption cipher!", e);
- }
-
- tmpStream = new BufferedOutputStream(new CipherOutputStream(new FileOutputStream(tempFile), cipher));
- } else {
- tmpStream = new BufferedOutputStream(new FileOutputStream(tempFile));
- }
+ openTempFile();
}
tmpStream.write(buf, 0, bufSize);
@@ -178,6 +155,30 @@ public class ThresholdOutputStream exten
buf = newbuf;
}
+ private void openTempFile() throws IOException {
+ tempFile = File.createTempFile("opencmis", null, tempDir);
+
+ if (encrypt) {
+ Cipher cipher;
+ try {
+ KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM);
+ keyGenerator.init(KEY_SIZE);
+ key = keyGenerator.generateKey();
+
+ cipher = Cipher.getInstance(TRANSFORMATION);
+ cipher.init(Cipher.ENCRYPT_MODE, key);
+
+ iv = cipher.getIV();
+ } catch (Exception e) {
+ throw new IOException("Cannot initialize encryption cipher!", e);
+ }
+
+ tmpStream = new BufferedOutputStream(new CipherOutputStream(new FileOutputStream(tempFile), cipher));
+ } else {
+ tmpStream = new BufferedOutputStream(new FileOutputStream(tempFile));
+ }
+ }
+
public long getSize() {
return size;
}
@@ -212,7 +213,7 @@ public class ThresholdOutputStream exten
@Override
public void write(int oneByte) throws IOException {
try {
- if ((maxContentSize > -1) && (size + 1 > maxContentSize)) {
+ if (maxContentSize > -1 && size + 1 > maxContentSize) {
destroy();
throw new CmisConstraintException("Content too big!");
}
@@ -231,6 +232,10 @@ public class ThresholdOutputStream exten
@Override
public void flush() throws IOException {
+ if (tmpStream == null && memoryThreshold < bufSize) {
+ openTempFile();
+ }
+
if (tmpStream != null) {
try {
if (bufSize > 0) {
@@ -299,16 +304,16 @@ public class ThresholdOutputStream exten
/**
* Returns if the data is stored in memory.
*
- * @return <code>true</code> if the data is in memory and
- * <code>false</code> if the data resides in a temporary file
+ * @return {@code true} if the data is in memory and {@code false} if
+ * the data resides in a temporary file
*/
public abstract boolean isInMemory();
/**
* Gets the temporary file.
*
- * @return the temporary file or <code>null</code> if the data is stored
- * in memory
+ * @return the temporary file or {@code null} if the data is stored in
+ * memory
*/
public File getTemporaryFile() {
return null;
@@ -317,8 +322,11 @@ public class ThresholdOutputStream exten
/**
* Gets the byte buffer.
*
- * @return the content in a byte array or <code>null</code> if the data
- * is stored in a file
+ * This the underlying byte buffer and might be bigger than then the
+ * total length of the stream.
+ *
+ * @return the content in a byte array or {@code null} if the data is
+ * stored in a file
*/
public byte[] getBytes() {
return null;
@@ -347,11 +355,17 @@ public class ThresholdOutputStream exten
private int pos = 0;
private int mark = -1;
+ @Override
public boolean isInMemory() {
return true;
}
+ @Override
public byte[] getBytes() {
+ if (buf == null) {
+ throw new IllegalStateException("Stream is already closed!");
+ }
+
return buf;
}
@@ -452,7 +466,9 @@ public class ThresholdOutputStream exten
}
/**
- * InputStream for file data.
+ * InputStream for temp file data.
+ *
+ * Call {@link #close()} to delete the temp file.
*/
private class InternalTempFileInputStream extends ThresholdInputStream {
@@ -478,20 +494,31 @@ public class ThresholdOutputStream exten
openStream();
}
+ /**
+ * Opens the temp file stream.
+ */
protected void openStream() throws FileNotFoundException {
+ int bufferSize = (memoryThreshold < 4 * 1024 ? 4 * 1024 : memoryThreshold);
+
if (encrypt) {
stream = new BufferedInputStream(new CipherInputStream(new FileInputStream(tempFile), cipher),
- memoryThreshold);
+ bufferSize);
} else {
- stream = new BufferedInputStream(new FileInputStream(tempFile), memoryThreshold);
+ stream = new BufferedInputStream(new FileInputStream(tempFile), bufferSize);
}
}
+ @Override
public boolean isInMemory() {
return false;
}
+ @Override
public File getTemporaryFile() {
+ if (isDeleted) {
+ throw new IllegalStateException("Temporary file is already deleted!");
+ }
+
return tempFile;
}
@@ -553,10 +580,6 @@ public class ThresholdOutputStream exten
int b = stream.read();
- if (b == -1) {
- delete();
- }
-
return b;
}
@@ -573,10 +596,6 @@ public class ThresholdOutputStream exten
int n = super.read(b, off, len);
- if (n == -1) {
- delete();
- }
-
return n;
}
@@ -585,6 +604,9 @@ public class ThresholdOutputStream exten
delete();
}
+ /**
+ * Closes the temp file stream and then deletes the temp file.
+ */
protected void delete() {
if (!isClosed) {
try {
@@ -598,7 +620,7 @@ public class ThresholdOutputStream exten
if (!isDeleted) {
isDeleted = tempFile.delete();
if (!isDeleted) {
- LOG.warn("Temp file " + tempFile.getAbsolutePath() + " could not be deleted!");
+ LOG.warn("Temp file {} could not be deleted!", tempFile.getAbsolutePath());
}
}
}
Added: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/test/java/org/apache/chemistry/opencmis/server/impl/ThresholdOutputStreamTest.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/test/java/org/apache/chemistry/opencmis/server/impl/ThresholdOutputStreamTest.java?rev=1563862&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/test/java/org/apache/chemistry/opencmis/server/impl/ThresholdOutputStreamTest.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/test/java/org/apache/chemistry/opencmis/server/impl/ThresholdOutputStreamTest.java Mon Feb 3 12:41:56 2014
@@ -0,0 +1,184 @@
+/*
+ * 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.impl;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+
+import org.apache.chemistry.opencmis.server.shared.ThresholdOutputStream;
+import org.apache.chemistry.opencmis.server.shared.ThresholdOutputStream.ThresholdInputStream;
+import org.apache.chemistry.opencmis.server.shared.ThresholdOutputStreamFactory;
+import org.junit.Test;
+
+public class ThresholdOutputStreamTest {
+
+ private static final byte[] CONTENT = "Hello".getBytes();
+
+ @Test
+ public void testInMemory() throws Exception {
+ ThresholdOutputStreamFactory streamFactory = ThresholdOutputStreamFactory.newInstance(null, 1024, 1024, false);
+
+ // set content
+ ThresholdOutputStream tos = streamFactory.newOutputStream();
+ tos.write(CONTENT);
+ tos.close();
+
+ // get and check input stream
+ ThresholdInputStream tis = (ThresholdInputStream) tos.getInputStream();
+
+ assertTrue(tis.isInMemory());
+ assertNull(tis.getTemporaryFile());
+ assertTrue(tis.markSupported());
+ assertEquals(CONTENT.length, tis.length());
+ assertArrayEquals(CONTENT, getBytesFromArray(tis.getBytes(), (int) tis.length()));
+
+ // read stream
+ byte[] buffer = new byte[CONTENT.length];
+ int len = tis.read(buffer);
+ assertEquals(CONTENT.length, len);
+ assertArrayEquals(CONTENT, buffer);
+
+ // rewind and read again
+ tis.rewind();
+ len = tis.read(buffer);
+ assertEquals(CONTENT.length, len);
+ assertArrayEquals(CONTENT, buffer);
+
+ // mark and reset
+ tis.rewind();
+ tis.read();
+ tis.mark(1024);
+ tis.read();
+ tis.read();
+ tis.reset();
+ len = tis.read(buffer);
+ assertEquals(CONTENT.length - 1, len);
+
+ // close and check
+ tis.close();
+
+ assertEquals(-1, tis.read());
+
+ try {
+ tis.getBytes();
+ fail("IllegalStateException expected!");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testTempFile() throws Exception {
+ ThresholdOutputStreamFactory streamFactory = ThresholdOutputStreamFactory.newInstance(null, 0, 1024, false);
+
+ // set content
+ ThresholdOutputStream tos = streamFactory.newOutputStream();
+ tos.write(CONTENT);
+ tos.close();
+
+ // get and check input stream
+ ThresholdInputStream tis = (ThresholdInputStream) tos.getInputStream();
+
+ assertFalse(tis.isInMemory());
+ assertTrue(tis.markSupported());
+ assertNull(tis.getBytes());
+ assertEquals(CONTENT.length, tis.length());
+
+ assertTrue(tis.getTemporaryFile().exists());
+ assertEquals(CONTENT.length, tis.getTemporaryFile().length());
+
+ // read stream
+ byte[] buffer = new byte[CONTENT.length];
+ int len = tis.read(buffer);
+ assertEquals(CONTENT.length, len);
+ assertArrayEquals(CONTENT, buffer);
+ assertTrue(tis.getTemporaryFile().exists());
+
+ // rewind and read again
+ tis.rewind();
+ len = tis.read(buffer);
+ assertEquals(CONTENT.length, len);
+ assertArrayEquals(CONTENT, buffer);
+ assertTrue(tis.getTemporaryFile().exists());
+
+ // mark and reset
+ tis.rewind();
+ tis.read();
+ tis.mark(1024);
+ tis.read();
+ tis.read();
+ tis.reset();
+ len = tis.read(buffer);
+ assertEquals(CONTENT.length - 1, len);
+
+ File tempFile = tis.getTemporaryFile();
+
+ // close and check
+ tis.close();
+
+ assertEquals(-1, tis.read());
+ assertFalse(tempFile.exists());
+
+ try {
+ tis.getTemporaryFile();
+ fail("IllegalStateException expected!");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testThreshold() throws Exception {
+ int threshold = 8;
+
+ ThresholdOutputStreamFactory streamFactory = ThresholdOutputStreamFactory.newInstance(null, threshold, 1024,
+ false);
+
+ for (int i = 0; i < 20; i++) {
+ ThresholdOutputStream tos = streamFactory.newOutputStream();
+ for (int j = 0; j < i; j++) {
+ tos.write('0' + j);
+ }
+ tos.close();
+
+ ThresholdInputStream tis = (ThresholdInputStream) tos.getInputStream();
+ if (i > threshold) {
+ assertFalse(tis.isInMemory());
+ } else {
+ assertTrue(tis.isInMemory());
+ }
+
+ tos.close();
+ }
+ }
+
+ private byte[] getBytesFromArray(byte[] buffer, int len) {
+ byte[] result = new byte[len];
+
+ System.arraycopy(buffer, 0, result, 0, len);
+
+ return result;
+ }
+}
Propchange: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/test/java/org/apache/chemistry/opencmis/server/impl/ThresholdOutputStreamTest.java
------------------------------------------------------------------------------
svn:eol-style = native