Index: src/main/java/org/apache/jackrabbit/util/PipedStream.java =================================================================== --- src/main/java/org/apache/jackrabbit/util/PipedStream.java (revision 0) +++ src/main/java/org/apache/jackrabbit/util/PipedStream.java (revision 0) @@ -0,0 +1,131 @@ +/* + * 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.jackrabbit.util; + +import java.io.PipedInputStream; +import java.io.IOException; +import java.io.PipedOutputStream; +import java.io.OutputStream; +import java.io.InputStream; + +import javax.jcr.Node; +import javax.jcr.ValueFactory; + +/** + * PipedStream is a utility class that allows you to + * {@link #write(OutputStream)} data into an output stream, which is then piped + * into an input stream that can be consumed by the repository implementation in + * a call to {@link Node#setProperty(String, InputStream)} or + * {@link ValueFactory#createBinary(InputStream)}. + */ +public abstract class PipedStream extends PipedInputStream { + + /** + * Set when an exception is thrown while writing data into the output + * stream. This exception is picked up by the piped input stream when read + * methods are called. + */ + private volatile IOException exception; + + /** + * Creates a new BinaryStream instance. + * + * @throws IOException if an I/O error occurs. + */ + public PipedStream() throws IOException { + super(); + final PipedOutputStream out = new PipedOutputStream(); + connect(out); + new Thread(new Runnable() { + public void run() { + try { + PipedStream.this.write(out); + } catch (Throwable e) { + if (e instanceof IOException) { + exception = (IOException) e; + } else { + exception = (IOException) new IOException(e.getMessage()).initCause(e); + } + } finally { + try { + out.close(); + } catch (IOException e) { + // do not overwrite existing exception + if (exception == null) { + exception = e; + } + } + } + } + }).start(); + } + + /** + * Sub class responsiblity. This is where the data is written and piped to + * the input stream. The calling thread guarantees that the output stream + * is closed when this method returns successfully as well as when this + * method throws an exception. + * + * @param out where the data must be written to. + * @throws IOException if an I/O error occurs. + */ + public abstract void write(OutputStream out) throws IOException; + + /** + * {@inheritDoc} + */ + public int read(byte b[], int off, int len) throws IOException { + checkException(); + return super.read(b, off, len); + } + + /** + * {@inheritDoc} + */ + public int read() throws IOException { + checkException(); + return super.read(); + } + + /** + * {@inheritDoc} + */ + public int available() throws IOException { + checkException(); + return super.available(); + } + + /** + * {@inheritDoc} + */ + public void close() throws IOException { + checkException(); + super.close(); + } + + /** + * Checks if there was an exception while data was written to the piped + * output stream. + * + * @throws IOException if an I/O error occurs. + */ + protected void checkException() throws IOException { + if (exception != null) { + throw exception; + } + } +} Property changes on: src\main\java\org\apache\jackrabbit\util\PipedStream.java ___________________________________________________________________ Added: svn:eol-style + native Index: src/test/java/org/apache/jackrabbit/util/PipedStreamTest.java =================================================================== --- src/test/java/org/apache/jackrabbit/util/PipedStreamTest.java (revision 0) +++ src/test/java/org/apache/jackrabbit/util/PipedStreamTest.java (revision 0) @@ -0,0 +1,72 @@ +/* + * 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.jackrabbit.util; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import java.util.Random; + +import junit.framework.TestCase; + +/** + * PipedStreamTest contains test cases for {@link PipedStream}. + */ +public class PipedStreamTest extends TestCase { + + public void testStream() throws Exception { + Random rand = new Random(); + final byte[] data = new byte[10 * 1024]; + rand.nextBytes(data); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + InputStream in = new PipedStream() { + public void write(OutputStream out) throws IOException { + for (byte b : data) { + out.write(new byte[]{b}); + } + } + }; + byte[] buf = new byte[1024]; + int num; + while ((num = in.read(buf)) != -1) { + out.write(buf, 0, num); + } + // check data + byte[] result = out.toByteArray(); + assertEquals(data.length, result.length); + for (int i = 0; i < data.length; i++) { + assertEquals(data[i], result[i]); + } + } + + public void testException() throws Exception { + InputStream in = new PipedStream() { + public void write(OutputStream out) throws IOException { + out.write("test".getBytes("UTF-8")); + throw new IOException(); + } + }; + try { + while (in.read() != -1) { + } + fail("IOException expected"); + } catch (IOException e) { + // expected + } + } +} Property changes on: src\test\java\org\apache\jackrabbit\util\PipedStreamTest.java ___________________________________________________________________ Added: svn:eol-style + native