Return-Path: Delivered-To: apmail-jackrabbit-commits-archive@www.apache.org Received: (qmail 97726 invoked from network); 8 Jul 2009 13:59:14 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 8 Jul 2009 13:59:14 -0000 Received: (qmail 39964 invoked by uid 500); 8 Jul 2009 13:59:24 -0000 Delivered-To: apmail-jackrabbit-commits-archive@jackrabbit.apache.org Received: (qmail 39925 invoked by uid 500); 8 Jul 2009 13:59:24 -0000 Mailing-List: contact commits-help@jackrabbit.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@jackrabbit.apache.org Delivered-To: mailing list commits@jackrabbit.apache.org Received: (qmail 39916 invoked by uid 99); 8 Jul 2009 13:59:24 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 08 Jul 2009 13:59:24 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 08 Jul 2009 13:59:12 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 6068A23889C5; Wed, 8 Jul 2009 13:58:17 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r792142 [13/35] - in /jackrabbit/sandbox/JCR-1456: ./ jackrabbit-api/src/main/java/org/apache/jackrabbit/api/ jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/ jackrabbit-core/ jackrabbit-core/src/main/java/org/apache/jackrab... Date: Wed, 08 Jul 2009 13:57:46 -0000 To: commits@jackrabbit.apache.org From: jukka@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090708135817.6068A23889C5@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInDataStore.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInDataStore.java?rev=792142&r1=792141&r2=792142&view=diff ============================================================================== --- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInDataStore.java (original) +++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInDataStore.java Wed Jul 8 13:57:13 2009 @@ -30,7 +30,7 @@ /** * Represents binary data which is stored in the data store. */ -public class BLOBInDataStore extends BLOBFileValue { +class BLOBInDataStore extends BLOBFileValue { private final DataStore store; private final DataIdentifier identifier; @@ -53,22 +53,19 @@ this.identifier = identifier; } - public void delete(boolean pruneEmptyParentDirs) { + void delete(boolean pruneEmptyParentDirs) { // do nothing } - public void discard() { + void discard() { // do nothing } - - public DataIdentifier getDataIdentifier() { + + DataIdentifier getDataIdentifier() { return identifier; } - /** - * {@inheritDoc} - */ - public boolean isImmutable() { + boolean isImmutable() { return true; } @@ -91,11 +88,11 @@ return 0; } - public long getLength() { + public long getSize() { try { return getDataRecord().getLength(); } catch (DataStoreException e) { - log.warn("getLength for " + identifier + " failed", e); + log.warn("getSize for " + identifier + " failed", e); return -1; } } @@ -113,7 +110,7 @@ DataIdentifier identifier = new DataIdentifier(id); return new BLOBInDataStore(store, identifier); } - + static BLOBInDataStore getInstance(DataStore store, DataIdentifier identifier) { return new BLOBInDataStore(store, identifier); } @@ -138,8 +135,4 @@ return store.getRecord(identifier); } - public boolean isSmall() { - return false; - } - } Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInMemory.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInMemory.java?rev=792142&r1=792141&r2=792142&view=diff ============================================================================== --- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInMemory.java (original) +++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInMemory.java Wed Jul 8 13:57:13 2009 @@ -29,7 +29,7 @@ /** * Represents binary data which is backed by a byte[] (in memory). */ -public class BLOBInMemory extends BLOBFileValue { +class BLOBInMemory extends BLOBFileValue { /** * Logger instance for this class @@ -117,49 +117,31 @@ return BLOBInMemory.getInstance(data); } - /** - * {@inheritDoc} - */ - public void delete(boolean pruneEmptyParentDirs) { + void delete(boolean pruneEmptyParentDirs) { // do nothing // this object could still be referenced // the data will be garbage collected } - /** - * {@inheritDoc} - */ - public void discard() { + void discard() { // do nothing // this object could still be referenced // the data will be garbage collected } - /** - * {@inheritDoc} - */ - public boolean isImmutable() { + boolean isImmutable() { return true; } - /** - * {@inheritDoc} - */ - public long getLength() { + public long getSize() { return data.length; } - /** - * {@inheritDoc} - */ public InputStream getStream() { return new ByteArrayInputStream(data); } - /** - * {@inheritDoc} - */ - public String getString() throws RepositoryException { + String getString() throws RepositoryException { try { return new String(data, "UTF-8"); } catch (UnsupportedEncodingException e) { @@ -167,9 +149,6 @@ } } - /** - * {@inheritDoc} - */ public String toString() { StringBuilder buff = new StringBuilder(PREFIX.length() + 2 * data.length); buff.append(PREFIX); @@ -182,9 +161,6 @@ return buff.toString(); } - /** - * {@inheritDoc} - */ public boolean equals(Object obj) { if (this == obj) { return true; @@ -207,8 +183,4 @@ return 0; } - public boolean isSmall() { - return true; - } - } Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInResource.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInResource.java?rev=792142&r1=792141&r2=792142&view=diff ============================================================================== --- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInResource.java (original) +++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInResource.java Wed Jul 8 13:57:13 2009 @@ -29,7 +29,7 @@ /** * Represents binary data which is stored in a file system resource. */ -public class BLOBInResource extends BLOBFileValue { +class BLOBInResource extends BLOBFileValue { /** * The default logger @@ -82,10 +82,7 @@ return new BLOBInResource(fsResource); } - /** - * {@inheritDoc} - */ - public void delete(boolean pruneEmptyParentDirs) { + void delete(boolean pruneEmptyParentDirs) { try { fsResource.delete(pruneEmptyParentDirs); } catch (FileSystemException fse) { @@ -95,31 +92,19 @@ } - /** - * {@inheritDoc} - */ - public void discard() { + void discard() { // this instance is not backed by temporarily allocated resource/buffer } - /** - * {@inheritDoc} - */ - public boolean isImmutable() { + boolean isImmutable() { // delete will modify the state. return false; } - /** - * {@inheritDoc} - */ - public long getLength() { + public long getSize() { return length; } - /** - * {@inheritDoc} - */ public InputStream getStream() throws RepositoryException { try { return fsResource.getInputStream(); @@ -129,16 +114,10 @@ } } - /** - * {@inheritDoc} - */ public String toString() { return PREFIX + fsResource.toString(); } - /** - * {@inheritDoc} - */ public boolean equals(Object obj) { if (this == obj) { return true; @@ -161,11 +140,4 @@ return 0; } - /** - * {@inheritDoc} - */ - public boolean isSmall() { - return false; - } - } Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInTempFile.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInTempFile.java?rev=792142&r1=792141&r2=792142&view=diff ============================================================================== --- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInTempFile.java (original) +++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BLOBInTempFile.java Wed Jul 8 13:57:13 2009 @@ -26,13 +26,14 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.RandomAccessFile; import javax.jcr.RepositoryException; /** * Represents binary data which is stored in a temporary file. */ -public class BLOBInTempFile extends BLOBFileValue { +class BLOBInTempFile extends BLOBFileValue { /** * the prefix of the string representation of this value @@ -104,42 +105,27 @@ return new BLOBInTempFile(file, temp); } - /** - * {@inheritDoc} - */ - public void delete(boolean pruneEmptyParentDirs) { + void delete(boolean pruneEmptyParentDirs) { file.delete(); length = -1; file = null; } - /** - * {@inheritDoc} - */ - public void discard() { + void discard() { if (temp) { delete(true); } } - /** - * {@inheritDoc} - */ - public boolean isImmutable() { + boolean isImmutable() { // discard and delete can modify the state. return false; } - /** - * {@inheritDoc} - */ - public long getLength() { + public long getSize() { return length; } - /** - * {@inheritDoc} - */ public InputStream getStream() throws IllegalStateException, RepositoryException { try { return new LazyFileInputStream(file); @@ -148,16 +134,10 @@ } } - /** - * {@inheritDoc} - */ public String toString() { return PREFIX + file.toString(); } - /** - * {@inheritDoc} - */ public boolean equals(Object obj) { if (this == obj) { return true; @@ -180,11 +160,13 @@ return 0; } - /** - * {@inheritDoc} - */ - public boolean isSmall() { - return false; + public int read(byte[] b, long position) throws IOException, RepositoryException { + RandomAccessFile raf = new RandomAccessFile(file, "r"); + try { + raf.seek(position); + return raf.read(b); + } finally { + raf.close(); + } } - } Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BinaryValueImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BinaryValueImpl.java?rev=792142&r1=792141&r2=792142&view=diff ============================================================================== --- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BinaryValueImpl.java (original) +++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/BinaryValueImpl.java Wed Jul 8 13:57:13 2009 @@ -24,40 +24,28 @@ /** * Represents a binary value that is backed by a blob file value. */ -public class BinaryValueImpl extends BinaryValue implements JackrabbitValue { - +class BinaryValueImpl extends BinaryValue implements JackrabbitValue { + private final BLOBFileValue blob; /** * Construct a new object from the given blob. - * + * * @param blob the blob */ BinaryValueImpl(BLOBFileValue blob) throws RepositoryException { - super(blob.getStream()); + super(blob); this.blob = blob; } - /** - * {@inheritDoc} - */ public String getContentIdentity() { DataIdentifier id = blob.getDataIdentifier(); return id == null ? null : id.toString(); } /** - * Get the wrapped blob file value - * - * @return the blob file value - */ - BLOBFileValue getBlob() { - return blob; - } - - /** * Get the data identifier if one is available. - * + * * @return the data identifier or null */ DataIdentifier getDataIdentifier() { Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/InternalValue.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/InternalValue.java?rev=792142&r1=792141&r2=792142&view=diff ============================================================================== --- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/InternalValue.java (original) +++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/InternalValue.java Wed Jul 8 13:57:13 2009 @@ -16,43 +16,39 @@ */ package org.apache.jackrabbit.core.value; -import org.apache.commons.io.IOUtils; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.SequenceInputStream; +import java.io.UnsupportedEncodingException; +import java.math.BigDecimal; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Calendar; + +import javax.jcr.Binary; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Value; +import javax.jcr.ValueFormatException; + import org.apache.jackrabbit.core.data.DataIdentifier; import org.apache.jackrabbit.core.data.DataStore; +import org.apache.jackrabbit.core.data.DataStoreException; import org.apache.jackrabbit.core.fs.FileSystemResource; +import org.apache.jackrabbit.spi.Name; +import org.apache.jackrabbit.spi.Path; +import org.apache.jackrabbit.spi.QValue; import org.apache.jackrabbit.spi.commons.conversion.MalformedPathException; import org.apache.jackrabbit.spi.commons.conversion.NameException; import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver; -import org.apache.jackrabbit.spi.Path; -import org.apache.jackrabbit.spi.Name; -import org.apache.jackrabbit.spi.QValue; -import org.apache.jackrabbit.util.ISO8601; -import org.apache.jackrabbit.uuid.UUID; -import org.apache.jackrabbit.value.StringValue; -import org.apache.jackrabbit.value.URIValue; -import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl; import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl; -import org.apache.jackrabbit.spi.commons.value.ValueFactoryQImpl; +import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl; import org.apache.jackrabbit.spi.commons.value.AbstractQValue; +import org.apache.jackrabbit.spi.commons.value.AbstractQValueFactory; import org.apache.jackrabbit.spi.commons.value.QValueValue; - -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.Value; -import javax.jcr.ValueFormatException; -import javax.jcr.Session; -import javax.jcr.ValueFactory; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.SequenceInputStream; -import java.io.UnsupportedEncodingException; -import java.util.Calendar; -import java.net.URI; -import java.net.URISyntaxException; -import java.math.BigDecimal; +import org.apache.jackrabbit.util.ISO8601; +import org.apache.jackrabbit.uuid.UUID; /** * InternalValue represents the internal format of a property value. @@ -84,12 +80,6 @@ private static final InternalValue BOOLEAN_FALSE = new InternalValue(false); /** - * If set to 'true', the data store is used when configured in repository.xml - */ - public static final boolean USE_DATA_STORE = - Boolean.valueOf(System.getProperty("org.jackrabbit.useDataStore", "true")).booleanValue(); - - /** * Temporary binary values smaller or equal this size are kept in memory */ private static final int MIN_BLOB_FILE_SIZE = 1024; @@ -102,6 +92,8 @@ * @param value the JCR value * @param resolver * @return the created internal value + * @throws RepositoryException + * @throws ValueFormatException */ public static InternalValue create(Value value, NamePathResolver resolver) throws ValueFormatException, RepositoryException { @@ -116,41 +108,32 @@ * @param resolver * @param store the data store * @return the created internal value + * @throws RepositoryException + * @throws ValueFormatException */ public static InternalValue create(Value value, NamePathResolver resolver, DataStore store) throws ValueFormatException, RepositoryException { switch (value.getType()) { case PropertyType.BINARY: InternalValue result; - if (USE_DATA_STORE) { - BLOBFileValue blob = null; - if (value instanceof BinaryValueImpl) { - BinaryValueImpl bin = (BinaryValueImpl) value; - DataIdentifier identifier = bin.getDataIdentifier(); - if (identifier != null) { - // access the record to ensure it is not garbage collected - if (store.getRecordIfStored(identifier) != null) { - // it exists - so we don't need to stream it again - // but we need to create a new object because the original - // one might be in a different data store (repository) - blob = BLOBInDataStore.getInstance(store, identifier); - } + BLOBFileValue blob = null; + if (value instanceof BinaryValueImpl) { + BinaryValueImpl bin = (BinaryValueImpl) value; + DataIdentifier identifier = bin.getDataIdentifier(); + if (identifier != null) { + // access the record to ensure it is not garbage collected + if (store.getRecordIfStored(identifier) != null) { + // it exists - so we don't need to stream it again + // but we need to create a new object because the original + // one might be in a different data store (repository) + blob = BLOBInDataStore.getInstance(store, identifier); } } - if (blob == null) { - blob = getBLOBFileValue(store, value.getStream(), true); - } - result = new InternalValue(blob); - } else if (value instanceof BLOBFileValue) { - result = new InternalValue((BLOBFileValue) value); - } else { - InputStream stream = value.getStream(); - try { - result = createTemporary(stream); - } finally { - IOUtils.closeQuietly(stream); - } } + if (blob == null) { + blob = getBLOBFileValue(store, value.getBinary().getStream(), true); + } + result = new InternalValue(blob); return result; case PropertyType.BOOLEAN: return create(value.getBoolean()); @@ -209,6 +192,54 @@ } } + public static InternalValue create(QValue value) + throws RepositoryException { + switch (value.getType()) { + case PropertyType.BINARY: + try { + return create(value.getString().getBytes(AbstractQValueFactory.DEFAULT_ENCODING)); + } catch (UnsupportedEncodingException e) { + throw new InternalError(AbstractQValueFactory.DEFAULT_ENCODING + " not supported"); + } + case PropertyType.BOOLEAN: + return new InternalValue(value.getBoolean()); + case PropertyType.DATE: + return new InternalValue(value.getCalendar()); + case PropertyType.DOUBLE: + return new InternalValue(value.getDouble()); + case PropertyType.DECIMAL: + return new InternalValue(value.getDecimal()); + case PropertyType.LONG: + return new InternalValue(value.getLong()); + case PropertyType.REFERENCE: + return create(new UUID(value.getString())); + case PropertyType.WEAKREFERENCE: + return create(new UUID(value.getString()), true); + case PropertyType.URI: + return new InternalValue(value.getURI()); + case PropertyType.NAME: + return new InternalValue(value.getName()); + case PropertyType.PATH: + return new InternalValue(value.getPath()); + case PropertyType.STRING: + return new InternalValue(value.getString()); + default: + throw new IllegalArgumentException("illegal value"); + } + } + + static InternalValue getInternalValue(DataIdentifier identifier, DataStore store) throws DataStoreException { + // access the record to ensure it is not garbage collected + if (store.getRecordIfStored(identifier) != null) { + // it exists - so we don't need to stream it again + // but we need to create a new object because the original + // one might be in a different data store (repository) + BLOBFileValue blob = BLOBInDataStore.getInstance(store, identifier); + return new InternalValue(blob); + } + return null; + } + /** * @param value * @return the created value @@ -253,7 +284,7 @@ * @param value * @return the created value */ - public static InternalValue create(URI value) { + static InternalValue create(URI value) { return new InternalValue(value); } @@ -270,10 +301,7 @@ * @return the created value */ public static InternalValue create(byte[] value) { - if (USE_DATA_STORE) { - return new InternalValue(BLOBInMemory.getInstance(value)); - } - return new InternalValue(new BLOBValue(value)); + return new InternalValue(BLOBInMemory.getInstance(value)); } /** @@ -281,52 +309,32 @@ * * @param value the stream * @return the internal value + * @throws RepositoryException */ public static InternalValue createTemporary(InputStream value) throws RepositoryException { - if (USE_DATA_STORE) { - return new InternalValue(getBLOBFileValue(null, value, true)); - } - try { - return new InternalValue(new BLOBValue(value, true)); - } catch (IOException e) { - throw new RepositoryException("Error creating temporary file", e); - } + return new InternalValue(getBLOBFileValue(null, value, true)); } /** - * Create an internal value that is backed by a temporary file - * (if data store usage is disabled or the store is null) - * or in the data store if it is not null and enabled. + * Create an internal value that is stored in the data store (if enabled). * - * @param value the stream - * @param store the data store or null to use a temporary file + * @param value the input stream + * @param store * @return the internal value + * @throws RepositoryException */ - public static InternalValue createTemporary(InputStream value, DataStore store) throws RepositoryException { - if (USE_DATA_STORE) { - return new InternalValue(getBLOBFileValue(store, value, true)); - } - try { - return new InternalValue(new BLOBValue(value, true)); - } catch (IOException e) { - throw new RepositoryException("Error creating temporary file", e); - } + static InternalValue create(InputStream value, DataStore store) throws RepositoryException { + return new InternalValue(getBLOBFileValue(store, value, false)); } /** * @param value * @return * @throws IOException + * @throws RepositoryException */ public static InternalValue create(InputStream value) throws RepositoryException { - if (USE_DATA_STORE) { - return new InternalValue(getBLOBFileValue(null, value, false)); - } - try { - return new InternalValue(new BLOBValue(value, false)); - } catch (IOException e) { - throw new RepositoryException("Error creating file", e); - } + return new InternalValue(getBLOBFileValue(null, value, false)); } /** @@ -335,20 +343,7 @@ * @throws IOException */ public static InternalValue create(FileSystemResource value) throws IOException { - if (USE_DATA_STORE) { - return new InternalValue(BLOBInResource.getInstance(value)); - } - return new InternalValue(new BLOBValue(value)); - } - - /** - * @param value - * @return - * @throws IOException - */ - public static InternalValue create(File value) throws IOException { - assert !USE_DATA_STORE; - return new InternalValue(new BLOBValue(value)); + return new InternalValue(BLOBInResource.getInstance(value)); } /** @@ -359,7 +354,6 @@ * @return the value */ public static InternalValue create(DataStore store, String id) { - assert USE_DATA_STORE && store != null; return new InternalValue(getBLOBFileValue(store, id)); } @@ -384,18 +378,6 @@ } /** - * @param values - * @return the created value - */ - public static InternalValue[] create(String[] values) { - InternalValue[] ret = new InternalValue[values.length]; - for (int i = 0; i < values.length; i++) { - ret[i] = new InternalValue(values[i]); - } - return ret; - } - - /** * @param value * @return the created value */ @@ -421,78 +403,17 @@ } //----------------------------------------------------< conversions, etc. > - /** - * @param resolver - * @return - * @throws RepositoryException - * @deprecated - */ - public Value toJCRValue(NamePathResolver resolver) - throws RepositoryException { - ValueFactory vf; - if (resolver instanceof Session) { - vf = ((Session) resolver).getValueFactory(); - } else { - vf = new ValueFactoryImpl(resolver); - } - - if (vf instanceof ValueFactoryQImpl) { - return ((ValueFactoryQImpl) vf).createValue(this); - } else { - switch (type) { - case PropertyType.BINARY: - return vf.createValue(((BLOBFileValue) val).getStream()); - case PropertyType.BOOLEAN: - return vf.createValue(((Boolean) val).booleanValue()); - case PropertyType.DATE: - return vf.createValue((Calendar) val); - case PropertyType.DOUBLE: - return vf.createValue(((Double) val).doubleValue()); - case PropertyType.LONG: - return vf.createValue(((Long) val).longValue()); - case PropertyType.DECIMAL: - return vf.createValue((BigDecimal) val); - case PropertyType.REFERENCE: - return vf.createValue(val.toString(), PropertyType.REFERENCE); - case PropertyType.WEAKREFERENCE: - return vf.createValue(val.toString(), PropertyType.WEAKREFERENCE); - case PropertyType.URI: - return new URIValue((URI) val); - case PropertyType.PATH: - return vf.createValue(resolver.getJCRPath((Path) val), PropertyType.PATH); - case PropertyType.NAME: - return vf.createValue(resolver.getJCRName((Name) val), PropertyType.NAME); - case PropertyType.STRING: - return new StringValue((String) val); - default: - throw new RepositoryException("illegal internal value type"); - } - } - } - - /** - * @deprecated - * @return the internal object - */ - public Object internalValue() { - return val; - } - public BLOBFileValue getBLOBFileValue() { + BLOBFileValue getBLOBFileValue() { assert val != null && type == PropertyType.BINARY; return (BLOBFileValue) val; } public UUID getUUID() { - assert val != null && type == PropertyType.REFERENCE; + assert val != null && (type == PropertyType.REFERENCE || type == PropertyType.WEAKREFERENCE); return (UUID) val; } - public Name getQName() { - assert val != null && type == PropertyType.NAME; - return (Name) val; - } - public Calendar getDate() { assert val != null && type == PropertyType.DATE; return (Calendar) val; @@ -512,10 +433,8 @@ return this; } BLOBFileValue v = (BLOBFileValue) val; - if (USE_DATA_STORE) { - if (v.isImmutable()) { - return this; - } + if (v.isImmutable()) { + return this; } // return a copy since the wrapped BLOBFileValue instance is mutable InputStream stream = v.getStream(); @@ -547,7 +466,7 @@ public static InternalValue valueOf(String s, int type) { switch (type) { case PropertyType.BOOLEAN: - return create(Boolean.valueOf(s).booleanValue()); + return create(Boolean.valueOf(s)); case PropertyType.DATE: return create(ISO8601.parse(s)); case PropertyType.DOUBLE: @@ -602,11 +521,11 @@ } private InternalValue(long value) { - super(Long.valueOf(value)); + super(value); } private InternalValue(double value) { - super(Double.valueOf(value)); + super(value); } private InternalValue(Calendar value) { @@ -614,15 +533,15 @@ } private InternalValue(boolean value) { - super(Boolean.valueOf(value)); + super(value); } private InternalValue(URI value) { - super(value, PropertyType.URI); + super(value); } private InternalValue(BigDecimal value) { - super(value, PropertyType.DECIMAL); + super(value); } private InternalValue(BLOBFileValue value) { @@ -633,10 +552,6 @@ super(value); } - private InternalValue(UUID value) { - super(value, PropertyType.REFERENCE); - } - private InternalValue(UUID value, boolean weak) { super(value, weak ? PropertyType.WEAKREFERENCE : PropertyType.REFERENCE); } @@ -649,6 +564,7 @@ * @param in the input stream * @param temporary if the file should be deleted when discard is called (ignored if a data store is used) * @return the value + * @throws RepositoryException */ private static BLOBFileValue getBLOBFileValue(DataStore store, InputStream in, boolean temporary) throws RepositoryException { int maxMemorySize; @@ -705,22 +621,16 @@ * @param dataStore the data store * @throws RepositoryException */ - public void store(DataStore dataStore) throws RepositoryException, IOException { - assert USE_DATA_STORE; + public void store(DataStore dataStore) throws RepositoryException { assert dataStore != null; assert type == PropertyType.BINARY; BLOBFileValue v = (BLOBFileValue) val; if (v instanceof BLOBInDataStore) { // already in the data store, OK return; - } else if (v instanceof BLOBInMemory) { - if (v.getLength() < dataStore.getMinRecordLength()) { - // in memory and does not make sense to store, OK - return; - } } - // store the temp file to the data store, or (theoretically) load it in memory - val = getBLOBFileValue(dataStore, v.getStream(), false); + // store it in the data store + val = BLOBInDataStore.getInstance(dataStore, getStream()); } //-------------------------------------------------------------< QValue >--- @@ -729,7 +639,7 @@ */ public long getLength() throws RepositoryException { if (PropertyType.BINARY == type) { - return ((BLOBFileValue) val).getLength(); + return ((BLOBFileValue) val).getSize(); } else { return super.getLength(); } @@ -763,4 +673,45 @@ } } } + + /** + * @see org.apache.jackrabbit.spi.QValue#getBinary() + */ + public Binary getBinary() throws RepositoryException { + if (type == PropertyType.BINARY) { + return (BLOBFileValue) val; + } else { + try { + // convert via string + byte[] data = getString().getBytes(InternalValueFactory.DEFAULT_ENCODING); + return BLOBInMemory.getInstance(data); + } catch (UnsupportedEncodingException e) { + throw new RepositoryException(InternalValueFactory.DEFAULT_ENCODING + " is not supported encoding on this platform", e); + } + } + } + + /** + * @see org.apache.jackrabbit.spi.QValue#discard() + */ + public void discard() { + if (type == PropertyType.BINARY) { + BLOBFileValue bfv = (BLOBFileValue) val; + bfv.discard(); + } else { + super.discard(); + } + } + + /** + * Delete persistent binary objects. This method does not delete objects in + * the data store. + */ + public void deleteBinaryResource() { + if (type == PropertyType.BINARY) { + BLOBFileValue bfv = (BLOBFileValue) val; + bfv.delete(true); + } + } + } Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/InternalValueFactory.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/InternalValueFactory.java?rev=792142&r1=792141&r2=792142&view=diff ============================================================================== --- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/InternalValueFactory.java (original) +++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/InternalValueFactory.java Wed Jul 8 13:57:13 2009 @@ -16,6 +16,7 @@ */ package org.apache.jackrabbit.core.value; +import org.apache.jackrabbit.core.data.DataStore; import org.apache.jackrabbit.spi.Name; import org.apache.jackrabbit.spi.Path; import org.apache.jackrabbit.spi.QValue; @@ -50,9 +51,12 @@ */ private static final Logger log = LoggerFactory.getLogger(InternalValueFactory.class); - private static final QValueFactory INSTANCE = new InternalValueFactory(); + private static final QValueFactory INSTANCE = new InternalValueFactory(null); - private InternalValueFactory() { + private final DataStore store; + + InternalValueFactory(DataStore store) { + this.store = store; } public static QValueFactory getInstance() { @@ -133,20 +137,24 @@ return InternalValue.create(value); } + public QValue create(URI value) throws RepositoryException { + return InternalValue.create(value); + } + + public QValue create(BigDecimal value) throws RepositoryException { + return InternalValue.create(value); + } + public QValue create(byte[] value) throws RepositoryException { return InternalValue.create(value); } public QValue create(InputStream value) throws RepositoryException, IOException { - return InternalValue.create(value); + return InternalValue.create(value, store); } public QValue create(File value) throws RepositoryException, IOException { - if (InternalValue.USE_DATA_STORE) { - InputStream in = new FileInputStream(value); - return InternalValue.createTemporary(in); - } else { - return InternalValue.create(value); - } + InputStream in = new FileInputStream(value); + return InternalValue.createTemporary(in); } } \ No newline at end of file Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/ValueFactoryImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/ValueFactoryImpl.java?rev=792142&r1=792141&r2=792142&view=diff ============================================================================== --- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/ValueFactoryImpl.java (original) +++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/value/ValueFactoryImpl.java Wed Jul 8 13:57:13 2009 @@ -16,12 +16,15 @@ */ package org.apache.jackrabbit.core.value; +import org.apache.jackrabbit.core.data.DataIdentifier; +import org.apache.jackrabbit.core.data.DataStore; import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver; import org.apache.jackrabbit.spi.commons.value.ValueFactoryQImpl; import org.apache.jackrabbit.spi.QValue; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.jcr.Binary; import javax.jcr.Value; import javax.jcr.PropertyType; import javax.jcr.ValueFormatException; @@ -39,6 +42,8 @@ */ private static final Logger log = LoggerFactory.getLogger(ValueFactoryImpl.class); + private final DataStore store; + /** * Constructs a new ValueFactoryQImpl based * on an existing SPI QValueFactory and a @@ -46,8 +51,9 @@ * * @param resolver wrapped NamePathResolver */ - public ValueFactoryImpl(NamePathResolver resolver) { - super(InternalValueFactory.getInstance(), resolver); + public ValueFactoryImpl(NamePathResolver resolver, DataStore store) { + super(new InternalValueFactory(store), resolver); + this.store = store; } public Value createValue(QValue qvalue) { @@ -56,12 +62,30 @@ return new BinaryValueImpl(((InternalValue) qvalue).getBLOBFileValue()); } catch (RepositoryException e) { // should not get here - log.error(e.getMessage()); + log.error(e.getMessage(), e); } } return super.createValue(qvalue); } + public Value createValue(Binary binary) { + try { + if (binary instanceof BLOBInDataStore) { + DataIdentifier identifier = ((BLOBInDataStore) binary).getDataIdentifier(); + InternalValue value = InternalValue.getInternalValue(identifier, store); + if (value != null) { + // if the value is already in this data store + return new BinaryValueImpl(value.getBLOBFileValue()); + } + } + return createValue(binary.getStream()); + } catch (RepositoryException e) { + log.error(e.getMessage(), e); + // ignore - the super method may be smarter + } + return super.createValue(binary); + } + public Value createValue(InputStream value) { try { InternalValue qvalue = (InternalValue) getQValueFactory().create(value); @@ -76,7 +100,7 @@ public Value createValue(String value, int type) throws ValueFormatException { if (PropertyType.BINARY == type) { try { - InternalValue qvalue = (InternalValue) getQValueFactory().create(value, type); + InternalValue qvalue = (InternalValue) getQValueFactory().create(value, type); return new BinaryValueImpl(qvalue.getBLOBFileValue()); } catch (RepositoryException e) { throw new ValueFormatException(e); Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/AbstractVersionManager.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/AbstractVersionManager.java?rev=792142&r1=792141&r2=792142&view=diff ============================================================================== --- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/AbstractVersionManager.java (original) +++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/AbstractVersionManager.java Wed Jul 8 13:57:13 2009 @@ -16,32 +16,36 @@ */ package org.apache.jackrabbit.core.version; +import javax.jcr.ItemNotFoundException; +import javax.jcr.ReferentialIntegrityException; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.Value; +import javax.jcr.version.VersionException; + import org.apache.jackrabbit.core.NodeId; import org.apache.jackrabbit.core.NodeImpl; import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry; import org.apache.jackrabbit.core.state.DefaultISMLocking; +import org.apache.jackrabbit.core.state.ISMLocking.ReadLock; +import org.apache.jackrabbit.core.state.ISMLocking.WriteLock; import org.apache.jackrabbit.core.state.ItemStateException; import org.apache.jackrabbit.core.state.LocalItemStateManager; +import org.apache.jackrabbit.core.state.NodeReferences; +import org.apache.jackrabbit.core.state.NodeReferencesId; import org.apache.jackrabbit.core.state.NodeState; -import org.apache.jackrabbit.core.state.ISMLocking.ReadLock; -import org.apache.jackrabbit.core.state.ISMLocking.WriteLock; import org.apache.jackrabbit.spi.Name; import org.apache.jackrabbit.spi.commons.name.NameConstants; import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl; +import org.apache.jackrabbit.uuid.UUID; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.Value; -import javax.jcr.ItemNotFoundException; -import javax.jcr.version.VersionException; - /** * Base implementation of the {@link VersionManager} interface. *

- * All read operations must aquire the read lock before reading, all write - * operations must aquire the write lock. + * All read operations must acquire the read lock before reading, all write + * operations must acquire the write lock. */ abstract class AbstractVersionManager implements VersionManager { @@ -66,6 +70,11 @@ protected NodeStateEx historyRoot; /** + * Persistent root node of the activities. + */ + protected NodeStateEx activitiesRoot; + + /** * the lock on this version manager */ private final DefaultISMLocking rwLock = new DefaultISMLocking(); @@ -91,6 +100,18 @@ /** * {@inheritDoc} */ + public InternalActivity getActivity(NodeId id) throws RepositoryException { + // lock handling via getItem() + InternalActivity v = (InternalActivity) getItem(id); + if (v == null) { + log.warn("Versioning item not found: " + id); + } + return v; + } + + /** + * {@inheritDoc} + */ public InternalVersionHistory getVersionHistory(NodeId id) throws RepositoryException { // lock handling via getItem() @@ -107,7 +128,7 @@ String uuid = id.getUUID().toString(); Name name = getName(uuid); - NodeStateEx parent = getParentNode(uuid, false); + NodeStateEx parent = getParentNode(historyRoot, uuid, null); if (parent != null && parent.hasNode(name)) { NodeStateEx history = parent.getNode(name, 1); return getVersionHistory(history.getNodeId()); @@ -137,6 +158,7 @@ /** * Acquires the write lock on this version manager. + * @return returns the write lock */ protected WriteLock acquireWriteLock() { while (true) { @@ -150,6 +172,7 @@ /** * acquires the read lock on this version manager. + * @return returns the read lock */ protected ReadLock acquireReadLock() { while (true) { @@ -246,7 +269,8 @@ /** * {@inheritDoc} */ - public VersionHistoryInfo getVersionHistory(Session session, NodeState node) + public VersionHistoryInfo getVersionHistory(Session session, NodeState node, + NodeId copiedFrom) throws RepositoryException { VersionHistoryInfo info = null; @@ -255,7 +279,7 @@ String uuid = node.getNodeId().getUUID().toString(); Name name = getName(uuid); - NodeStateEx parent = getParentNode(uuid, false); + NodeStateEx parent = getParentNode(historyRoot, uuid, null); if (parent != null && parent.hasNode(name)) { NodeStateEx history = parent.getNode(name, 1); Name root = NameConstants.JCR_ROOTVERSION; @@ -268,7 +292,7 @@ } if (info == null) { - info = createVersionHistory(session, node); + info = createVersionHistory(session, node, copiedFrom); } return info; @@ -279,19 +303,22 @@ * a new 'mix:versionable' node or when adding the 'mix:versionable' mixin * to a node. * - * @param session - * @param node NodeState + * @param session repository session + * @param node versionable node state + * @param copiedFrom node id for the jcr:copiedFrom property * @return identifier of the new version history node - * @throws RepositoryException - * @see #getVersionHistory(Session, NodeState) + * @throws RepositoryException if an error occurrs + * @see #getVersionHistory(Session, NodeState, NodeId) */ - protected abstract VersionHistoryInfo createVersionHistory( - Session session, NodeState node) throws RepositoryException; + protected abstract VersionHistoryInfo createVersionHistory(Session session, + NodeState node, + NodeId copiedFrom) + throws RepositoryException; /** * Returns the item with the given persistent id. Subclass responsibility. *

- * Please note, that the overridden method must aquire the readlock before + * Please note, that the overridden method must acquire the readlock before * reading the state manager. * * @param id the id of the item @@ -312,34 +339,48 @@ /** * Checks if there are item references (from outside the version storage) - * that reference the given version item. Subclass responsiblity. + * that reference the given node. Subclass responsibility. *

- * Please note, that the overridden method must aquire the readlock before + * Please note, that the overridden method must acquire the readlock before * reading the state manager. * - * @param item version item + * @param id the id of the node * @return true if there are item references from outside the * version storage; false otherwise. * @throws RepositoryException if an error occurs while reading from the * repository. */ - protected abstract boolean hasItemReferences(InternalVersionItem item) + protected abstract boolean hasItemReferences(NodeId id) + throws RepositoryException; + + /** + * Returns the node with the given persistent id. Subclass responsibility. + *

+ * Please note, that the overridden method must acquire the readlock before + * reading the state manager. + * + * @param id the id of the node + * @throws RepositoryException if an error occurs while reading from the + * repository. + */ + protected abstract NodeStateEx getNodeStateEx(NodeId id) throws RepositoryException; /** * Creates a new Version History. * * @param node the node for which the version history is to be initialized + * @param copiedFrom node id for the jcr:copiedFrom parameter * @return the identifiers of the newly created version history and root version - * @throws javax.jcr.RepositoryException + * @throws RepositoryException if an error occurs */ - NodeStateEx createVersionHistory(NodeState node) + NodeStateEx internalCreateVersionHistory(NodeState node, NodeId copiedFrom) throws RepositoryException { WriteOperation operation = startWriteOperation(); try { // create deep path String uuid = node.getNodeId().getUUID().toString(); - NodeStateEx parent = getParentNode(uuid, true); + NodeStateEx parent = getParentNode(historyRoot, uuid, NameConstants.REP_VERSIONSTORAGE); Name name = getName(uuid); if (parent.hasNode(name)) { // already exists @@ -348,7 +389,7 @@ // create new history node in the persistent state NodeStateEx history = - InternalVersionHistoryImpl.create(this, parent, name, node); + InternalVersionHistoryImpl.create(this, parent, name, node, copiedFrom); // end update operation.save(); @@ -365,11 +406,89 @@ } /** + * Creates a new activity. + * + * @param title title of the new activity + * @return the id of the newly created activity + * @throws RepositoryException if an error occurs + */ + NodeStateEx internalCreateActivity(String title) + throws RepositoryException { + WriteOperation operation = startWriteOperation(); + try { + // create deep path + NodeId activityId = new NodeId(UUID.randomUUID()); + NodeStateEx parent = getParentNode(activitiesRoot, activityId.toString(), NameConstants.REP_ACTIVITIES); + Name name = getName(activityId.toString()); + + // create new activity node in the persistent state + NodeStateEx pNode = InternalActivityImpl.create(parent, name, activityId, title); + + // end update + operation.save(); + + log.debug("Created new activity " + activityId + + " with title " + title + "."); + return pNode; + } catch (ItemStateException e) { + throw new RepositoryException(e); + } finally { + operation.close(); + } + } + + /** + * Removes the specified activity + * + * @param activity the acitvity to remove + * @throws javax.jcr.RepositoryException if any other error occurs. + */ + protected void internalRemoveActivity(InternalActivityImpl activity) + throws RepositoryException { + WriteOperation operation = startWriteOperation(); + try { + // check if the activity has any references in the workspaces + NodeId nodeId = activity.getId(); + NodeReferencesId refId = new NodeReferencesId(nodeId); + if (stateMgr.hasNodeReferences(refId)) { + NodeReferences refs = stateMgr.getNodeReferences(refId); + if (refs.hasReferences()) { + throw new ReferentialIntegrityException("Unable to delete activity. still referenced."); + } + } + // TODO: + // check if the activity is used in anywhere in the version storage + // and reject removal + + // remove activity and possible empty parent directories + NodeStateEx act = getNodeStateEx(nodeId); + NodeId parentId = act.getParentId(); + Name name = act.getName(); + while (parentId != null) { + NodeStateEx parent = getNodeStateEx(parentId); + parent.removeNode(name); + parent.store(); + if (parent.getChildNodes().length == 0 && !parentId.equals(activitiesRoot.getNodeId())) { + name = parent.getName(); + parentId = parent.getParentId(); + } else { + parentId = null; + } + } + operation.save(); + } catch (ItemStateException e) { + log.error("Error while storing: " + e.toString()); + } finally { + operation.close(); + } + } + + /** * Utility method that returns the given string as a name in the default * namespace. * * @param name string name - * @return qualified name + * @return A Name object. */ private Name getName(String name) { return NameFactoryImpl.getInstance().create(Name.NS_DEFAULT_URI, name); @@ -378,24 +497,26 @@ /** * Utility method that returns the parent node under which the version * history of the identified versionable node is or will be stored. If - * the create flag is set, then the returned parent node and any ancestor - * nodes are automatically created if they do not already exist. Otherwise + * the interNT is not null then the returned + * parent node and any ancestor nodes are automatically created if they do + * not already exist. Otherwise * null is returned if the parent node does not exist. * + * @param parent the parent node * @param uuid UUID of a versionable node - * @param create whether to create missing nodes + * @param interNT intermediate nodetype. * @return parent node of the version history, or null * @throws RepositoryException if an error occurs */ - private NodeStateEx getParentNode(String uuid, boolean create) + private NodeStateEx getParentNode(NodeStateEx parent, String uuid, Name interNT) throws RepositoryException { - NodeStateEx n = historyRoot; + NodeStateEx n = parent; for (int i = 0; i < 3; i++) { Name name = getName(uuid.substring(i * 2, i * 2 + 2)); if (n.hasNode(name)) { n = n.getNode(name, 1); - } else if (create) { - n.addNode(name, NameConstants.REP_VERSIONSTORAGE, null, false); + } else if (interNT != null) { + n.addNode(name, interNT, null, false); n.store(); n = n.getNode(name, 1); } else { @@ -415,13 +536,21 @@ * @throws javax.jcr.RepositoryException if an error occurs * @see javax.jcr.Node#checkin() */ - protected InternalVersion checkin(InternalVersionHistoryImpl history, + protected InternalVersion internalCheckin(InternalVersionHistoryImpl history, NodeImpl node, boolean simple) throws RepositoryException { WriteOperation operation = startWriteOperation(); try { String versionName = calculateCheckinVersionName(history, node, simple); InternalVersionImpl v = history.checkin(NameFactoryImpl.getInstance().create("", versionName), node); + + // check for jcr:activity + if (node.hasProperty(NameConstants.JCR_ACTIVITY)) { + NodeId actId = new NodeId(node.getProperty(NameConstants.JCR_ACTIVITY).internalGetValue().getUUID()); + InternalActivityImpl act = (InternalActivityImpl) getItem(actId); + act.addVersion(v); + } + operation.save(); return v; } catch (ItemStateException e) { @@ -484,8 +613,8 @@ } else { // 1. search a predecessor, suitable for generating the new name Value[] values = node.getProperty(NameConstants.JCR_PREDECESSORS).getValues(); - for (int i = 0; i < values.length; i++) { - InternalVersion pred = history.getVersion(NodeId.valueOf(values[i].getString())); + for (Value value: values) { + InternalVersion pred = history.getVersion(NodeId.valueOf(value.getString())); if (best == null || pred.getName().getLocalName().length() < best.getName().getLocalName().length()) { best = pred; @@ -518,7 +647,7 @@ * not have a version with name. * @throws javax.jcr.RepositoryException if any other error occurs. */ - protected void removeVersion(InternalVersionHistoryImpl history, Name name) + protected void internalRemoveVersion(InternalVersionHistoryImpl history, Name name) throws VersionException, RepositoryException { WriteOperation operation = startWriteOperation(); try { @@ -577,7 +706,7 @@ * Invoked by the internal version item itself, when it's underlying * persistence state was discarded. * - * @param item + * @param item item that was discarded */ protected void itemDiscarded(InternalVersionItem item) { } @@ -609,6 +738,8 @@ return ((InternalVersionHistory) parent).getVersion(id); } else if (ntName.equals(NameConstants.NT_VERSIONHISTORY)) { return new InternalVersionHistoryImpl(this, pNode); + } else if (ntName.equals(NameConstants.NT_ACTIVITY)) { + return new InternalActivityImpl(this, pNode); } else { return null; } Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalFrozenNodeImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalFrozenNodeImpl.java?rev=792142&r1=792141&r2=792142&view=diff ============================================================================== --- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalFrozenNodeImpl.java (original) +++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalFrozenNodeImpl.java Wed Jul 8 13:57:13 2009 @@ -123,7 +123,7 @@ } } else if (prop.getName().equals(NameConstants.JCR_FROZENPRIMARYTYPE)) { // special property - frozenPrimaryType = node.getPropertyValue(NameConstants.JCR_FROZENPRIMARYTYPE).getQName(); + frozenPrimaryType = node.getPropertyValue(NameConstants.JCR_FROZENPRIMARYTYPE).getName(); } else if (prop.getName().equals(NameConstants.JCR_FROZENMIXINTYPES)) { // special property InternalValue[] values = node.getPropertyValues(NameConstants.JCR_FROZENMIXINTYPES); @@ -132,7 +132,7 @@ } else { frozenMixinTypes = new Name[values.length]; for (int j = 0; j < values.length; j++) { - frozenMixinTypes[j] = values[j].getQName(); + frozenMixinTypes[j] = values[j].getName(); } } } else if (prop.getName().equals(NameConstants.JCR_PRIMARYTYPE)) { Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionHistoryImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionHistoryImpl.java?rev=792142&r1=792141&r2=792142&view=diff ============================================================================== --- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionHistoryImpl.java (original) +++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionHistoryImpl.java Wed Jul 8 13:57:13 2009 @@ -39,6 +39,7 @@ import java.util.Iterator; import java.util.Set; import java.util.LinkedHashMap; +import java.util.Map; /** * Implements a InternalVersionHistory @@ -61,7 +62,7 @@ * key = version label (String) * value = version name */ - private HashMap labelCache = new HashMap(); + private Map labelCache = new HashMap(); /** * the root version of this history @@ -73,19 +74,19 @@ * key = version name * value = version id (NodeId) */ - private LinkedHashMap/**/ nameCache = new LinkedHashMap/**/(); + private Map nameCache = new LinkedHashMap(); /** * the hashmap of all versions * key = version id (NodeId) * value = version */ - private HashMap/**/ versionCache = new HashMap/**/(); + private Map versionCache = new HashMap(); /** * Temporary version cache, used on a refresh. */ - private HashMap/**/ tempVersionCache = new HashMap/**/(); + private Map tempVersionCache = new HashMap(); /** * the node that holds the label nodes @@ -136,8 +137,7 @@ // init label cache try { PropertyState[] labels = labelNode.getProperties(); - for (int i = 0; i < labels.length; i++) { - PropertyState pState = labels[i]; + for (PropertyState pState : labels) { if (pState.getType() == PropertyType.REFERENCE) { Name labelName = pState.getName(); UUID ref = pState.getValues()[0].getUUID(); @@ -159,8 +159,7 @@ // get version entries ChildNodeEntry[] children = (ChildNodeEntry[]) node.getState().getChildNodeEntries().toArray(); - for (int i = 0; i < children.length; i++) { - ChildNodeEntry child = children[i]; + for (ChildNodeEntry child : children) { if (child.getName().equals(NameConstants.JCR_VERSIONLABELS)) { continue; } @@ -169,9 +168,7 @@ // fix legacy if (rootVersion.getSuccessors().length == 0) { - Iterator iter = nameCache.keySet().iterator(); - while (iter.hasNext()) { - Name versionName = (Name) iter.next(); + for (Name versionName : nameCache.keySet()) { InternalVersionImpl v = createVersionInstance(versionName); v.legacyResolveSuccessors(); } @@ -188,9 +185,8 @@ init(); // invalidate all versions that are not referenced any more - Iterator iter = tempVersionCache.values().iterator(); - while (iter.hasNext()) { - InternalVersionImpl v = (InternalVersionImpl) iter.next(); + for (Object o : tempVersionCache.values()) { + InternalVersionImpl v = (InternalVersionImpl) o; v.invalidate(); } tempVersionCache.clear(); @@ -210,10 +206,8 @@ vMgr.versionCreated(v); // add labels - Iterator iter = labelCache.keySet().iterator(); - while (iter.hasNext()) { - Name labelName = (Name) iter.next(); - Name versionName = (Name) labelCache.get(labelName); + for (Name labelName: labelCache.keySet()) { + Name versionName = labelCache.get(labelName); if (v.getName().equals(versionName)) { v.internalAddLabel(labelName); } @@ -265,12 +259,12 @@ * {@inheritDoc} */ public InternalVersion getVersion(Name versionName) throws VersionException { - NodeId versionId = (NodeId) nameCache.get(versionName); + NodeId versionId = nameCache.get(versionName); if (versionId == null) { throw new VersionException("Version " + versionName + " does not exist."); } - InternalVersion v = (InternalVersion) versionCache.get(versionId); + InternalVersion v = versionCache.get(versionId); if (v == null) { v = createVersionInstance(versionName); } @@ -288,11 +282,9 @@ * {@inheritDoc} */ public InternalVersion getVersion(NodeId id) { - InternalVersion v = (InternalVersion) versionCache.get(id); + InternalVersion v = versionCache.get(id); if (v == null) { - Iterator iter = nameCache.keySet().iterator(); - while (iter.hasNext()) { - Name versionName = (Name) iter.next(); + for (Name versionName : nameCache.keySet()) { if (nameCache.get(versionName).equals(id)) { v = createVersionInstance(versionName); break; @@ -306,13 +298,13 @@ * {@inheritDoc} */ public InternalVersion getVersionByLabel(Name label) { - Name versionName = (Name) labelCache.get(label); + Name versionName = labelCache.get(label); if (versionName == null) { return null; } - NodeId id = (NodeId) nameCache.get(versionName); - InternalVersion v = (InternalVersion) versionCache.get(id); + NodeId id = nameCache.get(versionName); + InternalVersion v = versionCache.get(id); if (v == null) { v = createVersionInstance(versionName); } @@ -323,7 +315,7 @@ * {@inheritDoc} */ public Name[] getVersionNames() { - return (Name[]) nameCache.keySet().toArray(new Name[nameCache.size()]); + return nameCache.keySet().toArray(new Name[nameCache.size()]); } /** @@ -344,7 +336,7 @@ * {@inheritDoc} */ public Name[] getVersionLabels() { - return (Name[]) labelCache.keySet().toArray(new Name[labelCache.size()]); + return labelCache.keySet().toArray(new Name[labelCache.size()]); } /** @@ -375,19 +367,25 @@ throw new VersionException(msg); } // check if any references (from outside the version storage) exist on this version - if (vMgr.hasItemReferences(v)) { + if (vMgr.hasItemReferences(v.getId())) { throw new ReferentialIntegrityException("Unable to remove version. At least once referenced."); } // unregister from labels Name[] labels = v.internalGetLabels(); - for (int i = 0; i < labels.length; i++) { - v.internalRemoveLabel(labels[i]); - labelNode.removeProperty(labels[i]); + for (Name label : labels) { + v.internalRemoveLabel(label); + labelNode.removeProperty(label); } // detach from the version graph v.internalDetach(); + // check if referenced by an activity + InternalActivityImpl activity = v.getActivity(); + if (activity != null) { + activity.removeVersion(v); + } + // remove from persistence state node.removeNode(v.getName()); @@ -396,12 +394,29 @@ nameCache.remove(versionName); vMgr.versionDestroyed(v); - // store changes - node.store(); + // Check if this was the last version in addition to the root version + if (!vMgr.hasItemReferences(node.getNodeId())) { + log.debug("Current version history has no references"); + NodeStateEx[] childNodes = node.getChildNodes(); + + // Check if there is only root version and version labels nodes + if (childNodes.length == 2) { + log.debug("Removing orphan version history as it contains only two children"); + NodeStateEx parentNode = vMgr.getNodeStateEx(node.getParentId()); + // Remove version history node + parentNode.removeNode(node.getName()); + // store changes for this node and his children + parentNode.store(); + } + } else { + log.debug("Current version history has at least one reference"); + // store changes + node.store(); + } // now also remove from labelCache - for (int i = 0; i < labels.length; i++) { - labelCache.remove(labels[i]); + for (Name label : labels) { + labelCache.remove(label); } } @@ -426,7 +441,7 @@ if (versionName != null && version == null) { throw new VersionException("Version " + versionName + " does not exist in this version history."); } - Name prevName = (Name) labelCache.get(label); + Name prevName = labelCache.get(label); InternalVersionImpl prev = null; if (prevName == null) { if (version == null) { @@ -509,6 +524,12 @@ NodeId versionId = new NodeId(UUID.randomUUID()); NodeStateEx vNode = node.addNode(name, NameConstants.NT_VERSION, versionId, true); + // check for jcr:activity + if (src.hasProperty(NameConstants.JCR_ACTIVITY)) { + InternalValue act = src.getProperty(NameConstants.JCR_ACTIVITY).internalGetValue(); + vNode.setPropertyValue(NameConstants.JCR_ACTIVITY, act); + } + // initialize 'created', 'predecessors' and 'successors' vNode.setPropertyValue(NameConstants.JCR_CREATED, InternalValue.create(getCurrentTime())); vNode.setPropertyValues(NameConstants.JCR_PREDECESSORS, PropertyType.REFERENCE, predecessors); @@ -541,12 +562,13 @@ * @param parent parent node * @param name history name * @param nodeState node state + * @param copiedFrom the id of the base version * @return new node state * @throws RepositoryException if an error occurs */ static NodeStateEx create( AbstractVersionManager vMgr, NodeStateEx parent, Name name, - NodeState nodeState) throws RepositoryException { + NodeState nodeState, NodeId copiedFrom) throws RepositoryException { // create history node NodeId historyId = new NodeId(UUID.randomUUID()); @@ -559,6 +581,11 @@ // create label node pNode.addNode(NameConstants.JCR_VERSIONLABELS, NameConstants.NT_VERSIONLABELS, null, false); + // initialize the 'jcr:copiedFrom' property + if (copiedFrom != null) { + pNode.setPropertyValue(NameConstants.JCR_COPIEDFROM, InternalValue.create(copiedFrom.getUUID(), true)); + } + // create root version NodeId versionId = new NodeId(UUID.randomUUID()); NodeStateEx vNode = pNode.addNode(NameConstants.JCR_ROOTVERSION, NameConstants.NT_VERSION, versionId, true); Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionImpl.java?rev=792142&r1=792141&r2=792142&view=diff ============================================================================== --- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionImpl.java (original) +++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionImpl.java Wed Jul 8 13:57:13 2009 @@ -25,11 +25,11 @@ import javax.jcr.PropertyType; import javax.jcr.RepositoryException; -import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.HashSet; import java.util.List; +import java.util.ArrayList; /** * Implements a InternalVersion @@ -45,7 +45,7 @@ /** * the set of version labes of this history (values == String) */ - private HashSet labelCache = null; + private HashSet labelCache = null; /** * specifies if this is the root version @@ -208,8 +208,7 @@ */ public boolean isMoreRecent(InternalVersion v) { InternalVersion[] preds = getPredecessors(); - for (int i = 0; i < preds.length; i++) { - InternalVersion pred = preds[i]; + for (InternalVersion pred : preds) { if (pred.equals(v) || pred.isMoreRecent(v)) { return true; } @@ -281,14 +280,14 @@ void internalDetach() throws RepositoryException { // detach this from all successors InternalVersion[] succ = getSuccessors(); - for (int i = 0; i < succ.length; i++) { - ((InternalVersionImpl) succ[i]).internalDetachPredecessor(this, true); + for (InternalVersion aSucc : succ) { + ((InternalVersionImpl) aSucc).internalDetachPredecessor(this, true); } // detach cached successors from predecessors InternalVersion[] preds = getPredecessors(); - for (int i = 0; i < preds.length; i++) { - ((InternalVersionImpl) preds[i]).internalDetachSuccessor(this, true); + for (InternalVersion pred : preds) { + ((InternalVersionImpl) pred).internalDetachSuccessor(this, true); } // clear properties @@ -303,8 +302,8 @@ */ void internalAttach() throws RepositoryException { InternalVersion[] preds = getPredecessors(); - for (int i = 0; i < preds.length; i++) { - ((InternalVersionImpl) preds[i]).internalAddSuccessor(this, true); + for (InternalVersion pred : preds) { + ((InternalVersionImpl) pred).internalAddSuccessor(this, true); } } @@ -317,7 +316,7 @@ */ private void internalAddSuccessor(InternalVersionImpl succ, boolean store) throws RepositoryException { - List l = new ArrayList(Arrays.asList(getSuccessors())); + List l = new ArrayList(Arrays.asList(getSuccessors())); if (!l.contains(succ)) { l.add(succ); storeXCessors(l, NameConstants.JCR_SUCCESSORS, store); @@ -337,7 +336,7 @@ private void internalDetachPredecessor(InternalVersionImpl v, boolean store) throws RepositoryException { // remove 'v' from predecessor list - List l = new ArrayList(Arrays.asList(getPredecessors())); + List l = new ArrayList(Arrays.asList(getPredecessors())); l.remove(v); // attach V's predecessors @@ -358,7 +357,7 @@ private void internalDetachSuccessor(InternalVersionImpl v, boolean store) throws RepositoryException { // remove 'v' from successors list - List l = new ArrayList(Arrays.asList(getSuccessors())); + List l = new ArrayList(Arrays.asList(getSuccessors())); l.remove(v); // attach V's successors @@ -374,7 +373,7 @@ */ boolean internalAddLabel(Name label) { if (labelCache == null) { - labelCache = new HashSet(); + labelCache = new HashSet(); } return labelCache.add(label); } @@ -408,7 +407,7 @@ if (labelCache == null) { return new Name[0]; } else { - return (Name[]) labelCache.toArray(new Name[labelCache.size()]); + return labelCache.toArray(new Name[labelCache.size()]); } } @@ -427,8 +426,8 @@ void legacyResolveSuccessors() throws RepositoryException { InternalValue[] values = node.getPropertyValues(NameConstants.JCR_PREDECESSORS); if (values != null) { - for (int i = 0; i < values.length; i++) { - NodeId vId = new NodeId(values[i].getUUID()); + for (InternalValue value : values) { + NodeId vId = new NodeId(value.getUUID()); InternalVersionImpl v = (InternalVersionImpl) versionHistory.getVersion(vId); v.internalAddSuccessor(this, false); } @@ -455,4 +454,18 @@ public int hashCode() { return getId().hashCode(); } + + /** + * Returns the activity of this version or null if not defined + * @return the activity or null + * @throws RepositoryException if an error occurs + */ + public InternalActivityImpl getActivity() throws RepositoryException { + if (node.hasProperty(NameConstants.JCR_ACTIVITY)) { + NodeId actId = new NodeId(node.getPropertyValue(NameConstants.JCR_ACTIVITY).getUUID()); + return (InternalActivityImpl) vMgr.getItem(actId); + } else { + return null; + } + } } Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/JcrVersionManagerImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/JcrVersionManagerImpl.java?rev=792142&r1=792141&r2=792142&view=diff ============================================================================== --- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/JcrVersionManagerImpl.java (original) +++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/JcrVersionManagerImpl.java Wed Jul 8 13:57:13 2009 @@ -16,15 +16,25 @@ */ package org.apache.jackrabbit.core.version; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.jcr.ItemNotFoundException; import javax.jcr.Node; import javax.jcr.NodeIterator; import javax.jcr.RepositoryException; import javax.jcr.UnsupportedRepositoryOperationException; +import javax.jcr.version.Version; +import javax.jcr.version.VersionHistory; +import org.apache.jackrabbit.core.ItemId; +import org.apache.jackrabbit.core.LazyItemIterator; +import org.apache.jackrabbit.core.NodeId; import org.apache.jackrabbit.core.NodeImpl; import org.apache.jackrabbit.core.SessionImpl; -import javax.jcr.version.Version; -import javax.jcr.version.VersionHistory; +import org.apache.jackrabbit.spi.commons.name.NameConstants; import org.slf4j.LoggerFactory; import org.slf4j.Logger; @@ -47,6 +57,12 @@ private final SessionImpl session; /** + * the node id of the current activity + */ + private NodeId currentActivity; + + + /** * Creates a new version manager for the given session * @param session workspace sesion */ @@ -58,7 +74,7 @@ * {@inheritDoc} */ public Version checkin(String absPath) throws RepositoryException { - return (Version) session.getNode(absPath).checkin(); + return session.getNode(absPath).checkin(); } /** @@ -75,7 +91,7 @@ // this is not quite correct, since the entire checkpoint operation // should be atomic Node node = session.getNode(absPath); - Version v = (Version) node.checkin(); + Version v = node.checkin(); node.checkout(); return v; } @@ -92,7 +108,7 @@ */ public VersionHistory getVersionHistory(String absPath) throws RepositoryException { - return (VersionHistory) session.getNode(absPath).getVersionHistory(); + return session.getNode(absPath).getVersionHistory(); } /** @@ -100,7 +116,7 @@ */ public Version getBaseVersion(String absPath) throws RepositoryException { - return (Version) session.getNode(absPath).getBaseVersion(); + return session.getNode(absPath).getBaseVersion(); } /** @@ -193,34 +209,142 @@ * {@inheritDoc} */ public Node setActivity(Node activity) throws RepositoryException { - throw new UnsupportedRepositoryOperationException("comming soon..."); + Node oldActivity = getActivity(); + if (activity == null) { + currentActivity = null; + } else { + NodeImpl actNode = (NodeImpl) activity; + if (!actNode.isNodeType(NameConstants.NT_ACTIVITY)) { + throw new UnsupportedRepositoryOperationException("Given node is not an activity."); + } + currentActivity = actNode.getNodeId(); + } + return oldActivity; } /** * {@inheritDoc} */ public Node getActivity() throws RepositoryException { - throw new UnsupportedRepositoryOperationException("comming soon..."); + if (currentActivity == null) { + return null; + } else { + return session.getNodeById(currentActivity); + } } /** * {@inheritDoc} */ public Node createActivity(String title) throws RepositoryException { - throw new UnsupportedRepositoryOperationException("comming soon..."); + NodeId id = session.getVersionManager().createActivity(session, title); + return session.getNodeById(id); } /** * {@inheritDoc} */ - public Node removeActivity(String title) throws RepositoryException { - throw new UnsupportedRepositoryOperationException("comming soon..."); + public void removeActivity(Node node) throws RepositoryException { + NodeImpl actNode = (NodeImpl) node; + if (!actNode.isNodeType(NameConstants.NT_ACTIVITY)) { + throw new UnsupportedRepositoryOperationException("Given node is not an activity."); + } + NodeId actId = actNode.getNodeId(); + session.getVersionManager().removeActivity(session, actId); + if (actId.equals(currentActivity)) { + currentActivity = null; + } } /** * {@inheritDoc} */ public NodeIterator merge(Node activityNode) throws RepositoryException { - throw new UnsupportedRepositoryOperationException("comming soon..."); + NodeImpl actNode = (NodeImpl) activityNode; + if (!actNode.isNodeType(NameConstants.NT_ACTIVITY)) { + throw new UnsupportedRepositoryOperationException("Given node is not an activity."); + } + InternalActivity activity = session.getVersionManager().getActivity(actNode.getNodeId()); + if (activity == null) { + throw new UnsupportedRepositoryOperationException("Given activity not found."); + } + boolean success = false; + try { + NodeIterator ret = internalMerge(activity); + session.save(); + success = true; + return ret; + } finally { + if (!success) { + // revert session + try { + log.debug("reverting changes applied during merge..."); + session.refresh(false); + } catch (RepositoryException e) { + log.error("Error while reverting changes applied merge restore.", e); + } + } + } + } + + /** + * Internally does the merge without saving the changes. + * @param activity internal activity + * @throws RepositoryException if an error occurs + * @return a node iterator of all failed nodes + */ + private NodeIterator internalMerge(InternalActivity activity) + throws RepositoryException { + List failedIds = new ArrayList(); + Map changeSet = activity.getChangeSet(); + ChangeSetVersionSelector vsel = new ChangeSetVersionSelector(changeSet); + Iterator iter = changeSet.keySet().iterator(); + while (iter.hasNext()) { + InternalVersion v = changeSet.remove(iter.next()); + NodeId nodeId = new NodeId(v.getVersionHistory().getVersionableUUID()); + try { + NodeImpl node = session.getNodeById(nodeId); + InternalVersion base = ((VersionImpl) node.getBaseVersion()).getInternalVersion(); + VersionImpl version = (VersionImpl) session.getNodeById(v.getId()); + // if base version is newer than version, add to failed list + // but merge it anyways + if (base.isMoreRecent(version.getInternalVersion())) { + failedIds.add(node.getNodeId()); + // should we add it to the jcr:mergeFailed property ? + } else { + Version[] vs = node.internalRestore(version, vsel, true); + for (Version restored: vs) { + changeSet.remove(((VersionImpl) restored).getNodeId()); + } + } + } catch (ItemNotFoundException e) { + // ignore nodes not present in this workspace (not best practice) + } + + // reset iterator + iter = changeSet.keySet().iterator(); + } + return new LazyItemIterator(session.getItemManager(), failedIds); + } + + /** + * Internal version selector that selects the version in the changeset. + */ + private class ChangeSetVersionSelector implements VersionSelector { + + private final Map changeSet; + + private ChangeSetVersionSelector(Map changeSet) { + this.changeSet = changeSet; + } + + public Version select(VersionHistory vh) throws RepositoryException { + InternalVersion v = changeSet.get(((VersionHistoryImpl) vh).getNodeId()); + if (v != null) { + return (Version) session.getNodeById(v.getId()); + } else { + return null; + } + } } } \ No newline at end of file Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/NodeStateEx.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/NodeStateEx.java?rev=792142&r1=792141&r2=792142&view=diff ============================================================================== --- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/NodeStateEx.java (original) +++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/NodeStateEx.java Wed Jul 8 13:57:13 2009 @@ -40,6 +40,7 @@ import java.util.Set; import javax.jcr.RepositoryException; +import javax.jcr.PropertyType; import javax.jcr.nodetype.ConstraintViolationException; import javax.jcr.nodetype.NoSuchNodeTypeException; @@ -436,6 +437,19 @@ } /** + * Sets the given mixin types + * @param mixinTypeNames the mixin type names + * @throws RepositoryException if an error occurs + */ + public void setMixins(Set mixinTypeNames) throws RepositoryException { + nodeState.setMixinTypeNames(mixinTypeNames); + // update jcr:mixinTypes property + setPropertyValues(NameConstants.JCR_MIXINTYPES, PropertyType.NAME, + InternalValue.create( + mixinTypeNames.toArray(new Name[mixinTypeNames.size()])) + ); + } + /** * creates a new child node * * @param name