blob: 0a548447a77c78e83b0af9d7acb9b17a024c04a3 [file] [log] [blame]
/*
* 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.rmi.value;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import javax.jcr.Binary;
import javax.jcr.Node;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import javax.jcr.ValueFormatException;
/**
* The <code>SerialValueFactory</code> class is used in the RMI infrastructure
* to create serializable <code>Value</code> instances on the client side.
* <p>
* This class works in conjunction with the implementations of the
* <code>javax.jcr.Value</code> interface found in this package.
* <p>
* This class may be extended to overwrite any of the
* <code>createXXXValue</code> methods to create instances of the respective
* type of {@link Value} implementation. The
* methods of the <code>ValueFactory</code> interface are declared final to
* guard against breaking the rules.
*/
public class SerialValueFactory implements ValueFactory {
/** The singleton value factory instance */
private static final SerialValueFactory INSTANCE = new SerialValueFactory();
/**
* Returns the <code>ValueFactory</code> instance, which currently is a
* singleton instance of this class.
* <p>
* Future revisions will support some kind of configuration to specify
* which concrete class should be used.
*/
public static final SerialValueFactory getInstance() {
return INSTANCE;
}
/**
* Utility method for decorating an array of values. The returned array will
* contain serializable value decorators for all the given values. Note that
* the contents of the original values will only be copied when the
* decorators are serialized.
* <p>
* If the given array is <code>null</code>, then an empty array is
* returned.
*
* @param values the values to be decorated
* @return array of decorated values
* @throws RepositoryException if the values can not be serialized
*/
public static Value[] makeSerialValueArray(Value[] values)
throws RepositoryException {
List<Value> serials = new ArrayList<Value>();
if (values != null) {
for (Value value : values) {
if (value != null) {
serials.add(makeSerialValue(value));
}
}
}
return serials.toArray(new Value[serials.size()]);
}
/**
* Utility method for decorating a value. Note that the contents of the
* original values will only be copied when the decorators are serialized.
* Null referenced and already serializable values are passed as-is.
*
* @param value the value to be decorated, or <code>null</code>
* @return the decorated value, or <code>null</code>
* @throws RepositoryException if the value can not be serialized
*/
public static Value makeSerialValue(Value value) throws RepositoryException {
// if the value is null or already serializable, just return it
if (value == null || value instanceof Serializable) {
return value;
} else {
return INSTANCE.createValue(value);
}
}
/**
* Utility method for converting an array of strings to serializable
* string values.
* <p>
* If the given array is <code>null</code>, then an empty array is
* returned.
*
* @param values the string array
* @return array of string values
*/
public static Value[] makeSerialValueArray(String[] values) {
List<Value> serials = new ArrayList<Value>();
if (values != null) {
for (String value : values) {
if (value != null) {
serials.add(INSTANCE.createValue(value));
}
}
}
return serials.toArray(new Value[serials.size()]);
}
/**
* Default constructor only visible to extensions of this class. See
* class comments for details.
*/
protected SerialValueFactory() {
}
/** {@inheritDoc} */
public Value createValue(String value) {
return new StringValue(value);
}
/** {@inheritDoc} */
public final Value createValue(String value, int type)
throws ValueFormatException {
try {
return createValue(new StringValue(value), type);
} catch (ValueFormatException e) {
throw e;
} catch (RepositoryException e) {
throw new ValueFormatException(
"Unexpected error when creating value: " + value, e);
}
}
private Value createValue(Value value) throws RepositoryException {
return createValue(value, value.getType());
}
private Value createValue(Value value, int type)
throws RepositoryException {
switch (type) {
case PropertyType.BINARY:
Binary binary = value.getBinary();
try {
return createValue(binary.getStream());
} finally {
binary.dispose();
}
case PropertyType.BOOLEAN:
return createValue(value.getBoolean());
case PropertyType.DATE:
return createValue(value.getDate());
case PropertyType.DECIMAL:
return createValue(value.getDecimal());
case PropertyType.DOUBLE:
return createValue(value.getDouble());
case PropertyType.LONG:
return createValue(value.getLong());
case PropertyType.NAME:
return new NameValue(value.getString());
case PropertyType.PATH:
return new PathValue(value.getString());
case PropertyType.REFERENCE:
return new ReferenceValue(value.getString());
case PropertyType.STRING:
return createValue(value.getString());
default:
throw new ValueFormatException("Unknown value type " + type);
}
}
/** {@inheritDoc} */
public final Value createValue(long value) {
return new LongValue(value);
}
/** {@inheritDoc} */
public final Value createValue(double value) {
return new DoubleValue(value);
}
/** {@inheritDoc} */
public final Value createValue(boolean value) {
return new BooleanValue(value);
}
/** {@inheritDoc} */
public Value createValue(BigDecimal value) {
return new DecimalValue(value);
}
/** {@inheritDoc} */
public final Value createValue(Calendar value) {
return new DateValue(value);
}
/** {@inheritDoc} */
public final Value createValue(InputStream value) {
try {
return createValue(createBinary(value));
} catch (RepositoryException e) {
throw new RuntimeException("Unable to create a binary value", e);
}
}
/** {@inheritDoc} */
public final Value createValue(Node value) throws RepositoryException {
return createValue(value.getUUID(), PropertyType.REFERENCE);
}
public Binary createBinary(InputStream stream) throws RepositoryException {
try {
try {
return new SerializableBinary(stream);
} finally {
stream.close();
}
} catch (IOException e) {
throw new RepositoryException("Unable to read binary stream", e);
}
}
public Value createValue(Binary value) {
return new BinaryValue(value);
}
public Value createValue(Node value, boolean weak)
throws RepositoryException {
return new ReferenceValue(value.getUUID());
}
}