You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by st...@apache.org on 2009/05/25 18:01:37 UTC
svn commit: r778445 - in /jackrabbit/trunk:
jackrabbit-core/src/main/java/org/apache/jackrabbit/core/
jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/value/
Author: stefan
Date: Mon May 25 16:01:36 2009
New Revision: 778445
URL: http://svn.apache.org/viewvc?rev=778445&view=rev
Log:
JCR-2056: Binary interfaces (WIP...)
Added:
jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/value/BinaryImpl.java
Modified:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java
jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/value/BaseValue.java
jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/value/BinaryValue.java
jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/value/ValueFactoryImpl.java
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java?rev=778445&r1=778444&r2=778445&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java Mon May 25 16:01:36 2009
@@ -754,10 +754,16 @@
internalSetValue(internalValues, reqType);
}
+ /**
+ * {@inheritDoc}
+ */
public long getLength() throws RepositoryException {
return getLength(internalGetValue());
}
+ /**
+ * {@inheritDoc}
+ */
public long[] getLengths() throws RepositoryException {
InternalValue[] values = internalGetValues();
long[] lengths = new long[values.length];
@@ -777,10 +783,23 @@
return data.getPropertyDefinition();
}
+ /**
+ * {@inheritDoc}
+ */
public int getType() throws RepositoryException {
return getPropertyState().getType();
}
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isMultiple() throws RepositoryException {
+ // check state of this instance
+ sanityCheck();
+
+ return data.getPropertyDefinition().isMultiple();
+ }
+
//-----------------------------------------------------------------< Item >
/**
* {@inheritDoc}
Modified: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/value/BaseValue.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/value/BaseValue.java?rev=778445&r1=778444&r2=778445&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/value/BaseValue.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/value/BaseValue.java Mon May 25 16:01:36 2009
@@ -26,6 +26,7 @@
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
+import java.io.IOException;
import java.math.BigDecimal;
import java.util.Calendar;
@@ -223,8 +224,15 @@
public Binary getBinary()
throws ValueFormatException, IllegalStateException,
RepositoryException {
- // TODO
- throw new UnsupportedRepositoryOperationException("JCR-2056");
+ try {
+ // convert via string
+ return new BinaryImpl(new ByteArrayInputStream(getInternalString().getBytes(DEFAULT_ENCODING)));
+ } catch (UnsupportedEncodingException e) {
+ throw new RepositoryException(DEFAULT_ENCODING
+ + " not supported on this platform", e);
+ } catch (IOException e) {
+ throw new RepositoryException("failed to create Binary instance", e);
+ }
}
/**
Added: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/value/BinaryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/value/BinaryImpl.java?rev=778445&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/value/BinaryImpl.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/value/BinaryImpl.java Mon May 25 16:01:36 2009
@@ -0,0 +1,187 @@
+/*
+ * 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.value;
+
+import org.apache.jackrabbit.util.TransientFileFactory;
+
+import javax.jcr.Binary;
+import javax.jcr.RepositoryException;
+import java.io.File;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.FileOutputStream;
+import java.io.FileInputStream;
+import java.io.RandomAccessFile;
+import java.io.FileNotFoundException;
+import java.io.ByteArrayInputStream;
+
+/**
+ * <code>BinaryImpl</code> implements the <code>Binary</code> interface.
+ */
+public class BinaryImpl implements Binary {
+
+ /**
+ * empty array
+ */
+ private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
+
+ /**
+ * max size for keeping tmp data in memory
+ */
+ private static final int MAX_BUFFER_SIZE = 0x10000;
+
+ /**
+ * underlying tmp file
+ */
+ private final File tmpFile;
+
+ /**
+ * buffer for small-sized data
+ */
+ private byte[] buffer = EMPTY_BYTE_ARRAY;
+
+ /**
+ * Creates a new <code>BinaryImpl</code> instance from an
+ * <code>InputStream</code>. The contents of the stream is spooled
+ * to a temporary file or to a byte buffer if its size is smaller than
+ * {@link #MAX_BUFFER_SIZE}.
+ * <p/>
+ * @param in stream to be represented as a <code>BLOBFileValue</code> instance
+ * @throws IOException if an error occurs while reading from the stream or
+ * writing to the temporary file
+ */
+ public BinaryImpl(InputStream in) throws IOException {
+ byte[] spoolBuffer = new byte[0x2000];
+ int read;
+ int len = 0;
+ OutputStream out = null;
+ File spoolFile = null;
+ try {
+ while ((read = in.read(spoolBuffer)) > 0) {
+ if (out != null) {
+ // spool to temp file
+ out.write(spoolBuffer, 0, read);
+ len += read;
+ } else if (len + read > MAX_BUFFER_SIZE) {
+ // threshold for keeping data in memory exceeded;
+ // create temp file and spool buffer contents
+ TransientFileFactory fileFactory = TransientFileFactory.getInstance();
+ spoolFile = fileFactory.createTransientFile("bin", null, null);
+ out = new FileOutputStream(spoolFile);
+ out.write(buffer, 0, len);
+ out.write(spoolBuffer, 0, read);
+ buffer = null;
+ len += read;
+ } else {
+ // reallocate new buffer and spool old buffer contents
+ byte[] newBuffer = new byte[len + read];
+ System.arraycopy(buffer, 0, newBuffer, 0, len);
+ System.arraycopy(spoolBuffer, 0, newBuffer, len, read);
+ buffer = newBuffer;
+ len += read;
+ }
+ }
+ } finally {
+ if (out != null) {
+ out.close();
+ }
+ }
+
+ // init fields
+ tmpFile = spoolFile;
+ }
+
+ /**
+ * Creates a new <code>BinaryImpl</code> instance from a
+ * <code>byte[]</code> array.
+ *
+ * @param buffer byte array to be represented as a <code>BinaryImpl</code>
+ * instance
+ */
+ public BinaryImpl(byte[] buffer) {
+ if (buffer == null) {
+ throw new IllegalArgumentException("buffer must be non-null");
+ }
+ this.buffer = buffer;
+ tmpFile = null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public InputStream getStream() throws RepositoryException {
+ if (tmpFile != null) {
+ try {
+ // this instance is backed by a temp file
+ return new FileInputStream(tmpFile);
+ } catch (FileNotFoundException e) {
+ throw new RepositoryException("already disposed");
+ }
+ } else {
+ // this instance is backed by an in-memory buffer
+ return new ByteArrayInputStream(buffer);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int read(byte[] b, long position) throws IOException, RepositoryException {
+ if (tmpFile != null) {
+ // this instance is backed by a temp file
+ RandomAccessFile raf = new RandomAccessFile(tmpFile, "r");
+ raf.seek(position);
+ return raf.read(b);
+ } else {
+ // this instance is backed by an in-memory buffer
+ int length = buffer.length - (int) position;
+ System.arraycopy(buffer, (int) position, b, 0, length);
+ return length;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getSize() throws RepositoryException {
+ if (tmpFile != null) {
+ // this instance is backed by a temp file
+ if (tmpFile.exists()) {
+ return tmpFile.length();
+ } else {
+ return -1;
+ }
+ } else {
+ // this instance is backed by an in-memory buffer
+ return buffer.length;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void dispose() {
+ if (tmpFile != null) {
+ // this instance is backed by a temp file
+ tmpFile.delete();
+ } else {
+ // this instance is backed by an in-memory buffer
+ buffer = EMPTY_BYTE_ARRAY;
+ }
+ }
+}
Modified: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/value/BinaryValue.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/value/BinaryValue.java?rev=778445&r1=778444&r2=778445&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/value/BinaryValue.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/value/BinaryValue.java Mon May 25 16:01:36 2009
@@ -19,8 +19,8 @@
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.ValueFormatException;
+import javax.jcr.Binary;
import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
@@ -33,8 +33,7 @@
public static final int TYPE = PropertyType.BINARY;
- // those fields are mutually exclusive, i.e. only one can be non-null
- private byte[] streamData = null;
+ private Binary bin = null;
private String text = null;
/**
@@ -48,23 +47,37 @@
}
/**
+ * Constructs a <code>BinaryValue</code> object based on a <code>Binary</code>.
+ *
+ * @param bin the bytes this <code>BinaryValue</code> should represent
+ */
+ public BinaryValue(Binary bin) {
+ super(TYPE);
+ this.bin = bin;
+ }
+
+ /**
* Constructs a <code>BinaryValue</code> object based on a stream.
*
* @param stream the stream this <code>BinaryValue</code> should represent
*/
public BinaryValue(InputStream stream) {
super(TYPE);
- this.stream = stream;
+ try {
+ bin = new BinaryImpl(stream);
+ } catch (IOException e) {
+ throw new IllegalArgumentException("specified stream cannot be read", e);
+ }
}
/**
- * Constructs a <code>BinaryValue</code> object based on a stream.
+ * Constructs a <code>BinaryValue</code> object based on a byte array.
*
- * @param data the stream this <code>BinaryValue</code> should represent
+ * @param data the bytes this <code>BinaryValue</code> should represent
*/
public BinaryValue(byte[] data) {
super(TYPE);
- streamData = data;
+ bin = new BinaryImpl(data);
}
/**
@@ -85,18 +98,11 @@
if (obj instanceof BinaryValue) {
BinaryValue other = (BinaryValue) obj;
if (text == other.text && stream == other.stream
- && streamData == other.streamData) {
+ && bin == other.bin) {
return true;
}
- // stream, streamData and text are mutually exclusive,
- // i.e. only one of them can be non-null
- if (stream != null) {
- return stream.equals(other.stream);
- } else if (streamData != null) {
- return streamData.equals(other.streamData);
- } else {
- return text.equals(other.text);
- }
+ return (text != null && text.equals(other.text))
+ || (bin != null && bin.equals(other.bin));
}
return false;
}
@@ -124,46 +130,20 @@
public String getInternalString()
throws ValueFormatException, RepositoryException {
// build text value if necessary
- if (streamData != null) {
+ if (text == null) {
try {
- text = new String(streamData, DEFAULT_ENCODING);
- } catch (UnsupportedEncodingException e) {
- throw new RepositoryException(DEFAULT_ENCODING
- + " not supported on this platform", e);
- }
- streamData = null;
- } else if (stream != null) {
- try {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- byte[] buffer = new byte[8192];
- int read;
- while ((read = stream.read(buffer)) > 0) {
- out.write(buffer, 0, read);
- }
- byte[] data = out.toByteArray();
- text = new String(data, DEFAULT_ENCODING);
+ byte[] bytes = new byte[(int) bin.getSize()];
+ bin.read(bytes, 0);
+ text = new String(bytes, DEFAULT_ENCODING);
} catch (UnsupportedEncodingException e) {
throw new RepositoryException(DEFAULT_ENCODING
+ " not supported on this platform", e);
} catch (IOException e) {
- throw new RepositoryException("conversion from stream to string failed", e);
- } finally {
- try {
- if (stream != null) {
- stream.close();
- }
- } catch (IOException e) {
- // ignore
- }
+ throw new RepositoryException("failed to retrieve binary data", e);
}
- stream = null;
}
- if (text != null) {
- return text;
- } else {
- throw new ValueFormatException("empty value");
- }
+ return text;
}
//----------------------------------------------------------------< Value >
@@ -174,20 +154,36 @@
throws IllegalStateException, RepositoryException {
setStreamConsumed();
- // build stream value if necessary
- if (streamData != null) {
- stream = new ByteArrayInputStream(streamData);
- streamData = null;
- } else if (text != null) {
+ if (bin != null) {
+ return bin.getStream();
+ } else {
try {
- stream = new ByteArrayInputStream(text.getBytes(DEFAULT_ENCODING));
+ return new ByteArrayInputStream(text.getBytes(DEFAULT_ENCODING));
} catch (UnsupportedEncodingException e) {
throw new RepositoryException(DEFAULT_ENCODING
+ " not supported on this platform", e);
}
- text = null;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Binary getBinary()
+ throws ValueFormatException, IllegalStateException,
+ RepositoryException {
+
+ if (bin == null) {
+ try {
+ bin = new BinaryImpl(new ByteArrayInputStream(text.getBytes(DEFAULT_ENCODING)));
+ } catch (UnsupportedEncodingException e) {
+ throw new RepositoryException(DEFAULT_ENCODING
+ + " not supported on this platform", e);
+ } catch (IOException e) {
+ throw new RepositoryException("failed to retrieve binary data", e);
+ }
}
- return super.getStream();
+ return bin;
}
}
Modified: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/value/ValueFactoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/value/ValueFactoryImpl.java?rev=778445&r1=778444&r2=778445&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/value/ValueFactoryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/value/ValueFactoryImpl.java Mon May 25 16:01:36 2009
@@ -17,6 +17,7 @@
package org.apache.jackrabbit.value;
import java.io.InputStream;
+import java.io.IOException;
import java.math.BigDecimal;
import java.util.Calendar;
@@ -151,12 +152,22 @@
return val;
}
+ /**
+ * {@inheritDoc}
+ */
public Binary createBinary(InputStream stream) throws RepositoryException {
- throw new UnsupportedRepositoryOperationException("JCR-2056");
+ try {
+ return new BinaryImpl(stream);
+ } catch (IOException e) {
+ throw new RepositoryException("failed to create Binary instance", e);
+ }
}
+ /**
+ * {@inheritDoc}
+ */
public Value createValue(Binary value) {
- throw new UnsupportedOperationException("JCR-2056");
+ return new BinaryValue(value);
}
/**