Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/util/uuid/Bytes.java ------------------------------------------------------------------------------ svn = Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/util/uuid/Bytes.java ------------------------------------------------------------------------------ svn:eol-style = native Added: incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/util/uuid/Constants.java URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/util/uuid/Constants.java?rev=180346&view=auto ============================================================================== --- incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/util/uuid/Constants.java (added) +++ incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/util/uuid/Constants.java Mon Jun 6 10:36:09 2005 @@ -0,0 +1,191 @@ +/* + * Copyright 2004-2005 The Apache Software Foundation or its licensors, + * as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.util.uuid; + +/** + *

Constant values commonly needed in the uuid classes.

+ *

+ *

Copied from the Jakarta Commons-Id project

+ *

+ * todo remove and use official commons-id release as soon as it is available + */ +public interface Constants { + + //** Magic number constants + /** + * Bits in a UUID. + */ + int UUID_BIT_LENGTH = 128; + + /** + * Number of bytes in a UUID. + */ + int UUID_BYTE_LENGTH = 16; + + + //** Formatting and validation constants + /** + * Chars in a UUID String. + */ + int UUID_UNFORMATTED_LENGTH = 32; + + /** + * Chars in a UUID String. + */ + int UUID_FORMATTED_LENGTH = 36; + + /** + * Token length of '-' separated tokens. + */ + int TOKENS_IN_UUID = 5; + + /** + * Array to check tokenized UUID's segment lengths + */ + int[] TOKEN_LENGTHS = {8, 4, 4, 4, 12}; + + /** + * Insertion point 1 for dashes in the string format + */ + int FORMAT_POSITION1 = 8; + + /** + * Insertion point 2 for dashes in the string format + */ + int FORMAT_POSITION2 = 13; + + /** + * Insertion point 3 for dashes in the string format + */ + int FORMAT_POSITION3 = 18; + + /** + * Insertion point 4 for dashes in the string format + */ + int FORMAT_POSITION4 = 23; + + /** + * The string prefix for a urn UUID identifier. + */ + String URN_PREFIX = "urn:uuid:"; + + + //** UUID Variant QueryConstants + /** + * UUID variant bits described in the IETF Draft MSB order, + * this is the "Reserved, NCS backward compatibility field" 0 x x with unknown bits as 0 + */ + int VARIANT_NCS_COMPAT = 0; + + /** + * UUID variant bits described in the IETF Draft MSB order, + * this is the IETF Draft memo variant field 1 0 x with unknown bits as 0 + */ + int VARIANT_IETF_DRAFT = 2; + + /** + * UUID variant bits described in the IETF Draft MSB order, + * this is the IETF Draft "Microsoft Corporation" field variant 1 1 0 x with unknown bits as 0 + */ + int VARIANT_MS = (byte) 6; + + /** + * UUID variant bits described in the IETF Draft MSB order, + * this is the "Future Reserved variant 1 1 1 x with unknown bits as 0 + */ + int VARIANT_FUTURE = 7; + + + //** UUID Version QueryConstants + /** + * Version one constant for UUID version one of four + */ + int VERSION_ONE = 1; + + /** + * Version two constant for UUID version two of four + */ + int VERSION_TWO = 2; + + /** + * Version three constant for UUID version three of four + */ + int VERSION_THREE = 3; + + /** + * Version four constant for UUID version four of four + */ + int VERSION_FOUR = 4; + + //** Exception message constants + /** + * Message indicating this is not a version one UUID + */ + String WRONG_VAR_VER_MSG = "Not a ietf variant 2 or version 1 (time-based UUID)"; + + // ** Array positions and lengths of UUID fields ** // + /** + * Byte length of time low field + */ + int TIME_LOW_BYTE_LEN = 4; + /** + * Byte length of time low field + */ + int TIME_MID_BYTE_LEN = 2; + /** + * Byte length of time low field + */ + int TIME_HI_BYTE_LEN = 2; + /** + * Timestamp byte[] position of time low field + */ + int TIME_LOW_TS_POS = 4; + /** + * Timestamp byte[] position mid field + */ + int TIME_MID_TS_POS = 2; + /** + * Timestamp byte[] position hi field + */ + int TIME_HI_TS_POS = 0; + /** + * uuid array position start of time low field + */ + int TIME_LOW_START_POS = 0; + /** + * uuid array position start of mid field + */ + int TIME_MID_START_POS = 4; + /** + * uuid array position start of hi field + */ + int TIME_HI_START_POS = 6; + /** + * Byte position of the clock sequence and reserved field + */ + short TIME_HI_AND_VERSION_BYTE_6 = 6; + /** + * Byte position of the clock sequence and reserved field + */ + short CLOCK_SEQ_HI_AND_RESERVED_BYTE_8 = 8; + + /** + * XXX added by stefan@apache.org: + * hexdigits for converting numerics to hex + */ + char[] hexDigits = "0123456789abcdef".toCharArray(); +} Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/util/uuid/Constants.java ------------------------------------------------------------------------------ svn = Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/util/uuid/Constants.java ------------------------------------------------------------------------------ svn:eol-style = native Added: incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/util/uuid/UUID.java URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/util/uuid/UUID.java?rev=180346&view=auto ============================================================================== --- incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/util/uuid/UUID.java (added) +++ incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/util/uuid/UUID.java Mon Jun 6 10:36:09 2005 @@ -0,0 +1,511 @@ +/* + * Copyright 2004-2005 The Apache Software Foundation or its licensors, + * as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.util.uuid; + +import java.io.DataInput; +import java.io.IOException; +import java.io.Serializable; +import java.util.StringTokenizer; + +/** XXX begin modification by stefan@apache.org */ +/*import org.apache.commons.id.IdentifierUtils; +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.binary.Hex; +import org.apache.commons.codec.digest.DigestUtils;*/ +/** XXX end modification by stefan@apache.org */ + +/** + *

UUID represents a Universally Unique Identifier per IETF + * Draft specification. For more information regarding the IETF Draft UUID + * specification

+ *

+ *

See: http://www.ietf.org/internet-drafts/draft-mealling-uuid-urn-01.txt

+ *

+ *

Copied from the Jakarta Commons-Id project

+ *

+ * todo remove and use official commons-id release as soon as it is available + */ + +public class UUID implements Constants, Serializable, Comparable { + + /** + * byte array to store 128-bits composing this UUID + */ + private byte[] rawBytes = new byte[UUID_BYTE_LENGTH]; + + /** + * Holds node identifier for this UUID + */ + private Long node = null; + + /** + * Holds timestamp for this UUID + */ + private long timestamp = -1; + + /** + * Holds the clock sequence field + */ + private Short clockSq = null; + + /** + * Holds the version field of this UUID + */ + private int version = -1; + + /** + * Holds the variant field of this UUID + */ + private int variant = -1; + + /** + * Holds the internal string value of the UUID + */ + private String stringValue = null; + + /** + * XXX begin modification by stefan@apache.org + */ + private static VersionFourGenerator versionFourGenereator = new VersionFourGenerator(); + /** XXX end modification by stefan@apache.org */ + + /** + * Constructs a nil UUID + */ + public UUID() { + super(); + } + + /** + *

Constructs a UUID from a 128 bit java.math.BigInteger.

+ *

Method is protected as their is no standard as to the internal representation of a UUID. + * In this case a BigInteger is used with signum always positive.

+ * + * @param bigIntValue the 128 bit BigInteger to construct this UUID from. + * @throws IllegalArgumentException argument must be 128 bit + */ + /* protected UUID(BigInteger bigIntValue) throws IllegalArgumentException { + super(); + if (bigIntValue.bitLength() > UUID.UUID_BIT_LENGTH) { + throw new IllegalArgumentException("UUID must be contructed using a 128 bit BigInteger"); + } + numberValue = bigIntValue; + } */ + + /** + *

Copy constructor.

+ * + * @param copyFrom the UUID to copy to create this UUID. + */ + public UUID(UUID copyFrom) { + super(); + rawBytes = copyFrom.getRawBytes(); + } + + /** + *

Constructs a UUID from a 16 byte array.

+ * + * @param byteArray the 16 byte array to construct this UUID from. + * @throws IllegalArgumentException argument must be 16 bytes + */ + public UUID(byte[] byteArray) throws IllegalArgumentException { + super(); + if (byteArray.length != UUID_BYTE_LENGTH) { + throw new IllegalArgumentException("UUID must be contructed using a 16 byte array."); + } + // UUID must be immutable so a copy is used. + System.arraycopy(byteArray, 0, rawBytes, 0, UUID_BYTE_LENGTH); + } + + /** + *

Constructs a UUID from a DataInput. Note if 16 bytes are not available this method will block.

+ * + * @param input the datainput with 16 bytes to read in from. + * @throws IOException exception if there is an IO problem also argument must contain 16 bytes. + */ + public UUID(DataInput input) throws IOException { + super(); + input.readFully(rawBytes, 0, UUID_BYTE_LENGTH); + } + + /** + *

Constructs a UUID from two long values in most significant byte, and least significant bytes order.

+ * + * @param mostSignificant - the most significant 8 bytes of the uuid to be constructed. + * @param leastSignificant - the least significant 8 bytes of the uuid to be constructed. + */ + public UUID(long mostSignificant, long leastSignificant) { + rawBytes = Bytes.append(Bytes.toBytes(mostSignificant), Bytes.toBytes(leastSignificant)); + } + + /** XXX begin modification by stefan@apache.org */ + /** + *

Constructs a UUID from a UUID formatted String.

+ * + * @param uuidString the String representing a UUID to construct this UUID + * @throws UUIDFormatException String must be a properly formatted UUID string + */ + //public UUID(String uuidString) throws UUIDFormatException { + public UUID(String uuidString) { + //Calls the copy constructor + this(UUID.fromString(uuidString)); + } + /** XXX end modification by stefan@apache.org */ + + /** XXX begin modification by stefan@apache.org */ + /** + *

Parses a string for a UUID.

+ * + * @param uuidString the UUID formatted String to parse. + * XXX begin modification by stefan@apache.org + * @return Returns a UUID or null if the formatted string could not be parsed. + * @throws IllegalArgumentException the String must be a properly formatted UUID String. + * XXX end modification by stefan@apache.org + */ + //public static UUID fromString(String uuidString) throws UUIDFormatException { + public static UUID fromString(String uuidString) throws IllegalArgumentException { + String leanString = uuidString.toLowerCase(); + UUID tmpUUID = null; + + //Handle prefixed UUIDs + // e.g. urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6 + int pos = uuidString.lastIndexOf(":"); + if (pos > 1) { + leanString = uuidString.substring(++pos, uuidString.length()); + } + + //Check for 36 char length + if (leanString.length() != UUID_FORMATTED_LENGTH) { + //throw new UUIDFormatException(); + throw new IllegalArgumentException(); + } + + //Check for 5 fields + StringTokenizer tok = new StringTokenizer(leanString, "-"); + if (tok.countTokens() != TOKENS_IN_UUID) { + //throw new UUIDFormatException(); + throw new IllegalArgumentException(); + } + + //Remove the "-" from the formatted string and test token sizes + StringBuffer buf = new StringBuffer(UUID_UNFORMATTED_LENGTH); + String token = null; + int count = 0; + while (tok.hasMoreTokens()) { + token = tok.nextToken(); + if (token.length() != TOKEN_LENGTHS[count++]) { + //throw new UUIDFormatException(); + throw new IllegalArgumentException(); + } + buf.append(token); + } + + //Create from the hex value + /** XXX begin modification by stefan@apache.org */ +/* + try { + char[] chars = buf.toString().toCharArray(); + tmpUUID = new UUID(Hex.decodeHex(chars)); + } catch (DecoderException de) { + throw new UUIDFormatException(de.getMessage()); + } +*/ + String s = buf.toString(); + byte[] bytes = new byte[UUID_BYTE_LENGTH]; + for (int i = 0, j = 0; i < (UUID_BYTE_LENGTH * 2); i += 2) { + bytes[j++] = (byte) Integer.parseInt(s.substring(i, i + 2), 16); + } + tmpUUID = new UUID(bytes); + /** XXX end modification by stefan@apache.org */ + + return tmpUUID; + } + /** XXX end modification by stefan@apache.org */ + + /** + *

Returns a string representation of the UUID.

+ * + * @return a string representation of the UUID formatted according to the specification. + */ + public String toString() { + //set string value if not set + if (stringValue == null) { + /** XXX begin modification by stefan@apache.org */ +/* + StringBuffer buf = new StringBuffer(new String(Hex.encodeHex(rawBytes))); + while (buf.length() != UUID_UNFORMATTED_LENGTH) { + buf.insert(0, "0"); + } + buf.ensureCapacity(UUID_FORMATTED_LENGTH); + buf.insert(FORMAT_POSITION1, '-'); + buf.insert(FORMAT_POSITION2, '-'); + buf.insert(FORMAT_POSITION3, '-'); + buf.insert(FORMAT_POSITION4, '-'); + stringValue = buf.toString(); +*/ + char[] chars = new char[UUID_FORMATTED_LENGTH]; + for (int i = 0, j = 0; i < 16; i++) { + chars[j++] = hexDigits[(rawBytes[i] >> 4) & 0x0f]; + chars[j++] = hexDigits[rawBytes[i] & 0x0f]; + if (i == 3 || i == 5 || i == 7 || i == 9) { + chars[j++] = '-'; + } + } + stringValue = new String(chars); + /** XXX end modification by stefan@apache.org */ + } + return stringValue; + } + + /** + *

Returns a urn representation of the UUID. This is same as the + * toString() value prefixed with urn:uuid:

+ * + * @return Returns the urn string representation of the UUID + */ + public String toUrn() { + return URN_PREFIX + this.toString(); + } + + /** + *

Compares two UUID for equality.

+ * + * @see java.lang.Object#equals(Object) + */ + + public boolean equals(Object obj) { + if (!(obj instanceof UUID)) { + return false; + } + return Bytes.areEqual(((UUID) obj).getRawBytes(), rawBytes); + } + + /** + *

Returns a hash code value for the object.

+ * + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + int iConstant = 37; + int iTotal = 17; + for (int i = 0; i < rawBytes.length; i++) { + iTotal = iTotal * iConstant + rawBytes[i]; + } + return iTotal; + } + + /** + *

Compares two UUID's for equality

+ * + * @see Comparable#compareTo(Object) + */ + public int compareTo(Object compareTo) throws ClassCastException { + if (!(compareTo instanceof UUID)) { + throw new ClassCastException(); + } + return (Bytes.compareTo(rawBytes, ((UUID) compareTo).getRawBytes())); + } + + /** + *

Returns the clock sequence value in the UUID. The clock sequence is a random assigned to a particular clock instance that + * generated the time in the timestamp of a time based UUID.

+ * + * @return the clock sequence value in the UUID. + * @throws UnsupportedOperationException thrown if this is not a IETF variant or not a time-based UUID. + */ + public int clockSequence() throws UnsupportedOperationException { + //if variant is not mealling leach salz throw unsupported operation exception + if (variant() != VARIANT_IETF_DRAFT || version() != VERSION_ONE) { + throw new UnsupportedOperationException(WRONG_VAR_VER_MSG); + } + if (clockSq == null) { + byte[] b = {((byte) (rawBytes[8] & 0x3F)), rawBytes[9]}; + clockSq = new Short(Bytes.toShort(b)); + } + return clockSq.intValue(); + } + + /** + *

Returns the version of the UUID. + *

+ *

+ * + * @return the version of the UUID. + */ + public int version() { + if (version == -1) { + version = ((rawBytes[6] >>> 4) & 0x0F); + } + return version; + } + + /** + *

Returns the variant field of the UUID.

+ * + * @return Returns the variant field of the UUID. + * @see UUID#VARIANT_NCS_COMPAT + * @see UUID#VARIANT_IETF_DRAFT + * @see UUID#VARIANT_MS + * @see UUID#VARIANT_FUTURE + */ + public int variant() { + if (variant == -1) { + if ((rawBytes[8] & 0x80) == 0x0) { + variant = VARIANT_NCS_COMPAT; + } else if ((rawBytes[8] & 0x40) == 0x0) { + variant = VARIANT_IETF_DRAFT; + } else if ((rawBytes[8] & 0x20) == 0x0) { + variant = VARIANT_MS; + } else { + variant = VARIANT_FUTURE; + } + } + return variant; + } + + /** + *

Returns the node identifier found in this UUID. The specification was written such that this value holds the IEEE 802 MAC + * address. The specification permits this value to be calculated from other sources other than the MAC.

+ * + * @return the node identifier found in this UUID. + * @throws UnsupportedOperationException thrown if this is not a IETF variant or not a time-based UUID. + */ + public long node() throws UnsupportedOperationException { + //if variant is not mealling leach salz throw unsupported operation exception + if (variant() != VARIANT_IETF_DRAFT || version() != VERSION_ONE) { + throw new UnsupportedOperationException(WRONG_VAR_VER_MSG); + } + if (node == null) { + byte[] b = new byte[8]; + System.arraycopy(rawBytes, 10, b, 2, 6); + node = new Long((Bytes.toLong(b) & 0xFFFFFFFFFFFFL)); + } + return node.longValue(); + } + + /** + *

Returns the timestamp value of the UUID as 100-nano second intervals since the Gregorian change offset (00:00:00.00, 15 + * October 1582 ).

+ * + * @return the timestamp value of the UUID as 100-nano second intervals since the Gregorian change offset. + * @throws UnsupportedOperationException thrown if this is not a IETF variant or not a time-based UUID. + */ + public long timestamp() throws UnsupportedOperationException { + //if variant is not mealling leach salz throw unsupported operation exception + if (variant() != VARIANT_IETF_DRAFT || version() != VERSION_ONE) { + throw new UnsupportedOperationException(WRONG_VAR_VER_MSG); + } + if (timestamp == -1) { + byte[] longVal = new byte[8]; + System.arraycopy(rawBytes, TIME_HI_START_POS, longVal, TIME_HI_TS_POS, TIME_HI_BYTE_LEN); + System.arraycopy(rawBytes, TIME_MID_START_POS, longVal, TIME_MID_TS_POS, TIME_MID_BYTE_LEN); + System.arraycopy(rawBytes, TIME_LOW_START_POS, longVal, TIME_LOW_TS_POS, TIME_LOW_BYTE_LEN); + longVal[TIME_HI_TS_POS] &= 0x0F; + timestamp = Bytes.toLong(longVal); + } + return timestamp; + } + + /** + *

Returns the least significant bits stored in the uuid's internal structure.

+ * + * @return the least significant bits stored in the uuid's internal structure. + */ + long getLeastSignificantBits() { + byte[] lsb = new byte[8]; + System.arraycopy(rawBytes, 8, lsb, 0, 8); + return Bytes.toLong(lsb); + } + + /** + *

Returns the least significant bits stored in the uuid's internal structure.

+ * + * @return the least significant bits stored in the uuid's internal structure. + */ + long getMostSignificantBits() { + byte[] msb = new byte[8]; + System.arraycopy(rawBytes, 0, msb, 0, 8); + return Bytes.toLong(msb); + } + + /** + *

Returns a copy of the byte values contained in this UUID. + * + * @return a copy of the byte values contained in this UUID. + */ + public byte[] getRawBytes() { + byte[] ret = new byte[UUID_BYTE_LENGTH]; + System.arraycopy(rawBytes, 0, ret, 0, UUID_BYTE_LENGTH); + return ret; + } + + /** + *

Returns a new version 4 UUID, based upon Random bits.

+ * + * @return a new version 4 UUID, based upon Random bits. + */ + /** + * XXX begin modification by stefan@apache.org + */ + //static UUID randomUUID() { + public static UUID randomUUID() { + //return (UUID) IdentifierUtils.UUID_VERSION_FOUR_GENERATOR.nextIdentifier(); + return (UUID) versionFourGenereator.nextIdentifier(); + } + /** XXX end modification by stefan@apache.org */ + + /** XXX begin modification by stefan@apache.org */ + /** + *

Returns a new version 1 UUID, based upon node identifier and time stamp.

+ * + * @return a new version 1 UUID, based upon node identifier and time stamp. + */ +/* static UUID timeUUID() { + return (UUID) IdentifierUtils.UUID_VERSION_ONE_GENERATOR.nextIdentifier(); + }*/ + /** XXX end modification by stefan@apache.org */ + + /** XXX begin modification by stefan@apache.org */ + /** + *

Returns a new version three UUID given a name and the namespace's UUID.

+ * + * @param name String the name to calculate the UUID for. + * @param namespace UUID assigned to this namespace. + * @return a new version three UUID given a name and the namespace's UUID. + */ +/* static UUID nameUUIDFromString(String name, UUID namespace) { + byte[] nameAsBytes = name.getBytes(); + byte[] concat = new byte[UUID_BYTE_LENGTH + nameAsBytes.length]; + System.arraycopy(namespace.getRawBytes(), 0, concat, 0, UUID_BYTE_LENGTH); + System.arraycopy(nameAsBytes, 0, concat, UUID_BYTE_LENGTH, nameAsBytes.length); + byte[] raw = DigestUtils.md5(concat); + //Set version + raw[TIME_HI_AND_VERSION_BYTE_6] &= 0x0F; + raw[TIME_HI_AND_VERSION_BYTE_6] |= (UUID.VERSION_THREE << 4); + //Set variant + raw[CLOCK_SEQ_HI_AND_RESERVED_BYTE_8] &= 0x3F; //0011 1111 + raw[CLOCK_SEQ_HI_AND_RESERVED_BYTE_8] |= 0x80; //1000 0000 + + return new UUID(raw); + }*/ + /** XXX end modification by stefan@apache.org */ +} Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/util/uuid/UUID.java ------------------------------------------------------------------------------ svn = Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/util/uuid/UUID.java ------------------------------------------------------------------------------ svn:eol-style = native Added: incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/util/uuid/VersionFourGenerator.java URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/util/uuid/VersionFourGenerator.java?rev=180346&view=auto ============================================================================== --- incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/util/uuid/VersionFourGenerator.java (added) +++ incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/util/uuid/VersionFourGenerator.java Mon Jun 6 10:36:09 2005 @@ -0,0 +1,168 @@ +/* + * Copyright 2004-2005 The Apache Software Foundation or its licensors, + * as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.util.uuid; + +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.SecureRandom; +import java.util.Random; + +/** XXX begin modification by stefan@apache.org */ +//import org.apache.commons.id.IdentifierGenerator; +/** XXX end modification by stefan@apache.org */ + +/** + *

Class is responsible for generating version 4 UUID's per the IETF draft + * specification. This class attempts to use a java.security.SecureRandom with + * the following instantiation + * SecureRandom.getInstance("SHA1PRNG", "SUN"). If neither secure + * random implementation is avialable or an Exception is raised a java.util.Random + * is used.

+ *

Note: Instantiation of SecureRandom is an expensive operation. The + * constructor therefore creates a static member to hold the SecureRandom. + * The first call to getInstance may take time; subsequent calls should return + * quickly.

+ * + *

Copied from the Jakarta Commons-Id project

+ *

+ * todo remove and use official commons-id release as soon as it is available + * + * + */ + +/** + * XXX begin modification by stefan@apache.org + */ +//public final class VersionFourGenerator implements IdentifierGenerator, QueryConstants { +public final class VersionFourGenerator implements Constants { + /** XXX end modification by stefan@apache.org */ + + /** + * Random used to generate UUID's + */ + private static final Random regularRandom = new Random(); + + /** + * SecureRandom used to generate UUID's + */ + private static Random secureRandom; + + /** + * The pseudo-random number generator to use + */ + private static String usePRNG = "SHA1PRNG"; + + /** + * The pseudo-random number generator package name to use + */ + private static String usePRNGPackage = "SUN"; + + /** + *

Constructs a new VersionFourGenerator.

+ */ + public VersionFourGenerator() { + super(); + } + + /** + *

Returns a new version four UUID.

+ * + * @return Object a new version 4 UUID. + */ + public Object nextIdentifier() { + return nextUUID(false); + } + + /** + *

Returns a new version four UUID.

+ *

This overloaded method may produce both UUID's using a SecureRandom as well as using normal + * Random + *

+ * + * @param secure indicates whether or not to use SecureRandom in generating the random bits. + * @return a new version four UUID that was generated by either a Random or SecureRandom. + */ + public Object nextIdentifier(boolean secure) { + if (secure) { + return nextUUID(true); + } + return nextUUID(false); + } + + /** + *

Returns a new version four UUID.

+ * + * @return Object a new version 4 UUID. + */ + private UUID nextUUID() { + //Call nextUUID with secure = false + return nextUUID(false); + } + + /** + *

Returns a new version four UUID using either SecureRandom or Random.

+ * + * @param secure boolean flag indicating whether to use SecureRandom or Random. + * @return a new version four UUID using either SecureRandom or Random. + */ + private UUID nextUUID(boolean secure) { + byte[] raw = new byte[UUID_BYTE_LENGTH]; + if (secure) { + //Initialize the secure random if null. + if (secureRandom == null) { + try { + if (usePRNGPackage != null) { + secureRandom = SecureRandom.getInstance(usePRNG, usePRNGPackage); + } else { + secureRandom = SecureRandom.getInstance(usePRNG); + } + } catch (NoSuchAlgorithmException nsae) { + secure = false; //Fail back to default PRNG/Random + } catch (NoSuchProviderException nspe) { + secure = false; //Fail back to default PRNG/Random + } + secureRandom.nextBytes(raw); + } + } + + if (!secure) { + regularRandom.nextBytes(raw); + } + + raw[TIME_HI_AND_VERSION_BYTE_6] &= 0x0F; + raw[TIME_HI_AND_VERSION_BYTE_6] |= (UUID.VERSION_FOUR << 4); + + raw[CLOCK_SEQ_HI_AND_RESERVED_BYTE_8] &= 0x3F; //0011 1111 + raw[CLOCK_SEQ_HI_AND_RESERVED_BYTE_8] |= 0x80; //1000 0000 + + return new UUID(raw); + } + + /** + *

Allows clients to set the pseudo-random number generator implementation used when generating a version four uuid with + * the secure option. The secure option uses a SecureRandom. The packageName string may be null to specify + * no preferred package.

+ * + * @param prngName the pseudo-random number generator implementation name. For example "SHA1PRNG". + * @param packageName the package name for the PRNG provider. For example "SUN". + */ + public static void setPRNGProvider(String prngName, String packageName) { + VersionFourGenerator.usePRNG = prngName; + VersionFourGenerator.usePRNGPackage = packageName; + VersionFourGenerator.secureRandom = null; + } +} Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/util/uuid/VersionFourGenerator.java ------------------------------------------------------------------------------ svn = Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/util/uuid/VersionFourGenerator.java ------------------------------------------------------------------------------ svn:eol-style = native Added: incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/util/uuid/package.html URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/util/uuid/package.html?rev=180346&view=auto ============================================================================== --- incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/util/uuid/package.html (added) +++ incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/util/uuid/package.html Mon Jun 6 10:36:09 2005 @@ -0,0 +1,14 @@ + +

+

+ This package contains a UUID (Universally Unique Identifier) version 4 + generator implementation copied from from the + + Jakarta Commons-Id project. +

+

+ TODO: Replace with commons-id.jar as soon as official release is + available. +

+

+ \ No newline at end of file Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/util/uuid/package.html ------------------------------------------------------------------------------ svn:eol-style = native Added: incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/value/ValueHelper.java URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/value/ValueHelper.java?rev=180346&view=auto ============================================================================== --- incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/value/ValueHelper.java (added) +++ incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/value/ValueHelper.java Mon Jun 6 10:36:09 2005 @@ -0,0 +1,208 @@ +/* + * Copyright 2004-2005 The Apache Software Foundation or its licensors, + * as applicable. + * + * Licensed 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.Base64; +import org.apache.jackrabbit.util.Text; + +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Value; +import javax.jcr.ValueFormatException; +import javax.jcr.ValueFactory; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.io.StringWriter; +import java.io.Writer; +import java.io.ByteArrayInputStream; + +/** + * The ValueHelper class provides several Value + * related utility methods. + */ +public class ValueHelper { + + /** + * Empty private constructor (avoid instanciation). + */ + private ValueHelper() { + } + + /** + * Serializes the given value to a String. The serialization + * format is the same as used by Document & System View XML, i.e. + * binary values will be Base64-encoded whereas for all others + * {@link javax.jcr.Value#getString()} will be used. + * + * @param value the value to be serialized + * @param encodeBlanks if true space characters will be encoded + * as "_x0020_" within he output string. + * @return a string representation of the given value. + * @throws IllegalStateException if the given value is in an illegal state + * @throws RepositoryException if an error occured during the serialization. + */ + public static String serialize(Value value, boolean encodeBlanks) + throws IllegalStateException, RepositoryException { + StringWriter writer = new StringWriter(); + try { + serialize(value, encodeBlanks, writer); + } catch (IOException ioe) { + throw new RepositoryException("failed to serialize value", + ioe); + } + return writer.toString(); + } + + /** + * Outputs the serialized value to a Writer. The serialization + * format is the same as used by Document & System View XML, i.e. + * binary values will be Base64-encoded whereas for all others + * {@link javax.jcr.Value#getString()} will be used for + * serialization. + * + * @param value the value to be serialized + * @param encodeBlanks if true space characters will be encoded + * as "_x0020_" within he output string. + * @param writer writer to output the encoded data + * @throws IllegalStateException if the given value is in an illegal state + * @throws IOException if an i/o error occured during the + * serialization + * @throws RepositoryException if an error occured during the serialization. + */ + public static void serialize(Value value, boolean encodeBlanks, + Writer writer) + throws IllegalStateException, IOException, RepositoryException { + if (value.getType() == PropertyType.BINARY) { + // binary data, base64 encoding required; + // the encodeBlanks flag can be ignored since base64-encoded + // data cannot contain space characters + InputStream in = value.getStream(); + try { + Base64.encode(in, writer); + // no need to close StringWriter + //writer.close(); + } finally { + try { + in.close(); + } catch (IOException e) { + // ignore + } + } + } else { + String textVal = value.getString(); + if (encodeBlanks) { + // enocde blanks in string + textVal = Text.replace(textVal, " ", "_x0020_"); + } + writer.write(textVal); + } + } + + /** + * Deserializes the given string to a Value of the given type. + * + * @param factory the factory used to create the {@link Value} object of the + * specified type. + * @param value string to be deserialized + * @param type type of value + * @param decodeBlanks if true "_x0020_" character + * sequences will be decoded to single space characters each. + * @return the deserialized Value + * @throws ValueFormatException if the string data is not of the required + * format + * @throws RepositoryException if an error occured during the deserialization. + */ + public static Value deserialize(ValueFactory factory, String value, int type, + boolean decodeBlanks) + throws ValueFormatException, RepositoryException { + if (type == PropertyType.BINARY) { + // base64 encoded binary value; + // the encodeBlanks flag can be ignored since base64-encoded + // data cannot contain encoded space characters + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + Base64.decode(value, baos); + // no need to close ByteArrayOutputStream + //baos.close(); + } catch (IOException ioe) { + throw new RepositoryException("failed to decode binary value", + ioe); + } + return factory.createValue(new ByteArrayInputStream(baos.toByteArray())); + } else { + if (decodeBlanks) { + // decode encoded blanks in value + value = Text.replace(value, "_x0020_", " "); + } + return factory.createValue(value, type); + } + } + + /** + * Deserializes the string data read from the given reader to a + * Value of the given type. + * + * @param factory the factory used to create the {@link Value} object of the + * specified type. + * @param reader reader for the string data to be deserialized + * @param type type of value + * @param decodeBlanks if true "_x0020_" character + * sequences will be decoded to single space characters each. + * @return the deserialized Value + * @throws IOException if an i/o error occured during the serialization + * @throws ValueFormatException if the string data is not of the required + * format + * @throws RepositoryException if an error occured during the deserialization. + */ + public static Value deserialize(ValueFactory factory, Reader reader, int type, + boolean decodeBlanks) + throws IOException, ValueFormatException, RepositoryException { + if (type == PropertyType.BINARY) { + // base64 encoded binary value; + // the encodeBlanks flag can be ignored since base64-encoded + // data cannot contain encoded space characters +/* + // @todo decode to temp file and pass FileInputStream to BinaryValue constructor + File tmpFile = File.createTempFile("bin", null); + FileOutputStream out = new FileOutputStream(tmpFile); + tmpFile.deleteOnExit(); + Base64.decode(reader, out); + out.close(); + return new BinaryValue(new FileInputStream(tmpFile)); +*/ + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + Base64.decode(reader, baos); + // no need to close ByteArrayOutputStream + return factory.createValue(new ByteArrayInputStream(baos.toByteArray())); + } else { + char[] chunk = new char[8192]; + int read; + StringBuffer buf = new StringBuffer(); + while ((read = reader.read(chunk)) > -1) { + buf.append(chunk, 0, read); + } + String value = buf.toString(); + if (decodeBlanks) { + // decode encoded blanks in value + value = Text.replace(value, "_x0020_", " "); + } + return factory.createValue(value, type); + } + } +} Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/value/ValueHelper.java ------------------------------------------------------------------------------ svn = Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/commons/src/java/org/apache/jackrabbit/value/ValueHelper.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: incubator/jackrabbit/trunk/contrib/jcr-server/project.properties URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/project.properties?rev=180346&r1=180345&r2=180346&view=diff ============================================================================== --- incubator/jackrabbit/trunk/contrib/jcr-server/project.properties (original) +++ incubator/jackrabbit/trunk/contrib/jcr-server/project.properties Mon Jun 6 10:36:09 2005 @@ -1,2 +1,7 @@ maven.javadoc.links=http://java.sun.com/j2se/1.4.2/docs/api/,http://www.day.com/maven/jsr170/javadocs/jcr-0.16.1-pfd/ maven.repo.remote = http://www.ibiblio.org/maven/,http://www.day.com/maven/ + +#------------------------------------------------------- +jackrabbit.build.version.jcr=1.0 +jackrabbit.build.version.jackrabbit=0.16.4.1-dev +jackrabbit.build.version.jcr.rmi=0.16.4.1 Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/server/ ------------------------------------------------------------------------------ --- svn:ignore (original) +++ svn:ignore Mon Jun 6 10:36:09 2005 @@ -1 +1,2 @@ target +*.iml Modified: incubator/jackrabbit/trunk/contrib/jcr-server/server/project.xml URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/project.xml?rev=180346&r1=180345&r2=180346&view=diff ============================================================================== --- incubator/jackrabbit/trunk/contrib/jcr-server/server/project.xml (original) +++ incubator/jackrabbit/trunk/contrib/jcr-server/server/project.xml Mon Jun 6 10:36:09 2005 @@ -29,29 +29,26 @@ + jcr-webdav jcr-server ${pom.currentVersion} - jcr-client + commons-jcr jcr-server ${pom.currentVersion} - - true - + + jsr170 jcr - 0.16.4.1 - http://www.day.com/maven/jsr170/jars/jcr-0.16.4.1.jar - - - jackrabbit - 0.16.4.1-dev + ${jackrabbit.build.version.jcr} + + jdom 1.0 @@ -63,10 +60,6 @@ servletapi 2.3 - - - jcr-rmi - 0.16.4.1 commons-chain Modified: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/AbstractWebdavServlet.java URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/AbstractWebdavServlet.java?rev=180346&r1=180345&r2=180346&view=diff ============================================================================== --- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/AbstractWebdavServlet.java (original) +++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/AbstractWebdavServlet.java Mon Jun 6 10:36:09 2005 @@ -15,59 +15,268 @@ */ package org.apache.jackrabbit.server; -import org.apache.log4j.Logger; -import org.apache.jackrabbit.webdav.*; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.DavLocatorFactory; +import org.apache.jackrabbit.webdav.DavMethods; +import org.apache.jackrabbit.webdav.DavResource; +import org.apache.jackrabbit.webdav.DavResourceFactory; +import org.apache.jackrabbit.webdav.DavServletResponse; +import org.apache.jackrabbit.webdav.DavSessionProvider; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.WebdavRequest; +import org.apache.jackrabbit.webdav.WebdavRequestImpl; +import org.apache.jackrabbit.webdav.WebdavResponse; +import org.apache.jackrabbit.webdav.WebdavResponseImpl; +import org.apache.jackrabbit.webdav.lock.ActiveLock; +import org.apache.jackrabbit.webdav.lock.LockInfo; +import org.apache.jackrabbit.webdav.observation.EventDiscovery; import org.apache.jackrabbit.webdav.observation.ObservationResource; -import org.apache.jackrabbit.webdav.observation.SubscriptionInfo; import org.apache.jackrabbit.webdav.observation.Subscription; -import org.apache.jackrabbit.webdav.observation.EventDiscovery; -import org.apache.jackrabbit.webdav.ordering.OrderingResource; +import org.apache.jackrabbit.webdav.observation.SubscriptionInfo; import org.apache.jackrabbit.webdav.ordering.OrderPatch; +import org.apache.jackrabbit.webdav.ordering.OrderingResource; +import org.apache.jackrabbit.webdav.property.DavProperty; +import org.apache.jackrabbit.webdav.property.DavPropertyIterator; +import org.apache.jackrabbit.webdav.property.DavPropertyName; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.property.DavPropertySet; +import org.apache.jackrabbit.webdav.search.SearchConstants; +import org.apache.jackrabbit.webdav.search.SearchInfo; +import org.apache.jackrabbit.webdav.search.SearchResource; import org.apache.jackrabbit.webdav.transaction.TransactionInfo; import org.apache.jackrabbit.webdav.transaction.TransactionResource; -import org.apache.jackrabbit.webdav.lock.LockInfo; -import org.apache.jackrabbit.webdav.lock.ActiveLock; -import org.apache.jackrabbit.webdav.version.*; -import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.jackrabbit.webdav.version.DeltaVConstants; +import org.apache.jackrabbit.webdav.version.DeltaVResource; +import org.apache.jackrabbit.webdav.version.LabelInfo; +import org.apache.jackrabbit.webdav.version.MergeInfo; +import org.apache.jackrabbit.webdav.version.OptionsInfo; +import org.apache.jackrabbit.webdav.version.OptionsResponse; +import org.apache.jackrabbit.webdav.version.UpdateInfo; +import org.apache.jackrabbit.webdav.version.VersionControlledResource; +import org.apache.jackrabbit.webdav.version.VersionResource; +import org.apache.jackrabbit.webdav.version.VersionableResource; import org.apache.jackrabbit.webdav.version.report.Report; -import org.apache.jackrabbit.webdav.property.*; -import org.apache.jackrabbit.webdav.search.SearchResource; -import org.apache.jackrabbit.webdav.search.SearchConstants; -import org.apache.jackrabbit.webdav.search.SearchInfo; - +import org.apache.jackrabbit.webdav.version.report.ReportInfo; +import org.apache.log4j.Logger; import org.jdom.Document; +import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.util.List; import java.util.ArrayList; import java.util.Iterator; +import java.util.List; /** * AbstractWebdavServlet - * - * todo respect Position header + *

+ * todo respect Position header */ abstract public class AbstractWebdavServlet extends HttpServlet implements DavConstants { - /** default logger */ + /** + * default logger + */ private static Logger log = Logger.getLogger(AbstractWebdavServlet.class); /** - * Create a new DavResource + * Default value for the 'WWW-Authenticate' header, that is set, if request + * results in a {@link DavServletResponse#SC_UNAUTHORIZED 401 (Unauthorized)} + * error. + * + * @see #getAuthenticateHeaderValue() + */ + public static final String DEFAULT_AUTHENTICATE_HEADER = "Basic Realm=Jackrabbit Webdav Server"; + + /** + * Checks if the precondition for this request and resource is valid. + * + * @param request + * @param resource + * @return + */ + abstract protected boolean isPreconditionValid(WebdavRequest request, DavResource resource); + + /** + * Returns the DavSessionProvider. + * + * @return the session provider + */ + abstract public DavSessionProvider getSessionProvider(); + + /** + * Returns the DavLocatorFactory. + * + * @return the locator factory + */ + abstract public DavLocatorFactory getLocatorFactory(); + + /** + * Returns the DavResourceFactory. + * + * @return the resource factory + */ + abstract public DavResourceFactory getResourceFactory(); + + /** + * Returns the value of the 'WWW-Authenticate' header, that is returned in + * case of 401 error. + * + * @return value of the 'WWW-Authenticate' header + */ + abstract public String getAuthenticateHeaderValue(); + + /** + * Service the given request. * - * @param locator * @param request * @param response - * @return resource for the given locator - * @throws DavException + * @throws ServletException + * @throws IOException */ - abstract protected DavResource createResource(DavResourceLocator locator, - WebdavRequest request, - WebdavResponse response) throws DavException; + protected void service(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + WebdavRequest webdavRequest = new WebdavRequestImpl(request, getLocatorFactory()); + WebdavResponse webdavResponse = new WebdavResponseImpl(response); + try { + // make sure there is a authenticated user + if (!getSessionProvider().attachSession(webdavRequest)) { + return; + } + + // check matching if=header for lock-token relevant operations + DavResource resource = getResourceFactory().createResource(webdavRequest.getRequestLocator(), webdavRequest, webdavResponse); + if (!isPreconditionValid(webdavRequest, resource)) { + webdavResponse.sendError(DavServletResponse.SC_PRECONDITION_FAILED); + return; + } + + int methodCode = DavMethods.getMethodCode(webdavRequest.getMethod()); + if (!execute(webdavRequest, webdavResponse, methodCode, resource)) { + super.service(request, response); + } + + } catch (DavException e) { + if (e.getErrorCode() == HttpServletResponse.SC_UNAUTHORIZED) { + webdavResponse.setHeader("WWW-Authenticate", getAuthenticateHeaderValue()); + webdavResponse.sendError(e.getErrorCode(), e.getStatusPhrase()); + } else { + webdavResponse.sendErrorResponse(e); + } + } finally { + getSessionProvider().releaseSession(webdavRequest); + } + } + + /** + * Executes the respective method in the given webdav context + * + * @param request + * @param response + * @param method + * @param resource + * @throws ServletException + * @throws IOException + * @throws DavException + */ + protected boolean execute(WebdavRequest request, WebdavResponse response, + int method, DavResource resource) + throws ServletException, IOException, DavException { + + switch (method) { + case DavMethods.DAV_GET: + doGet(request, response, resource); + break; + case DavMethods.DAV_HEAD: + doHead(request, response, resource); + break; + case DavMethods.DAV_PROPFIND: + doPropFind(request, response, resource); + break; + case DavMethods.DAV_PROPPATCH: + doPropPatch(request, response, resource); + break; + case DavMethods.DAV_POST: + doPost(request, response, resource); + break; + case DavMethods.DAV_PUT: + doPut(request, response, resource); + break; + case DavMethods.DAV_DELETE: + doDelete(request, response, resource); + break; + case DavMethods.DAV_COPY: + doCopy(request, response, resource); + break; + case DavMethods.DAV_MOVE: + doMove(request, response, resource); + break; + case DavMethods.DAV_MKCOL: + doMkCol(request, response, resource); + break; + case DavMethods.DAV_OPTIONS: + doOptions(request, response, resource); + break; + case DavMethods.DAV_LOCK: + doLock(request, response, resource); + break; + case DavMethods.DAV_UNLOCK: + doUnlock(request, response, resource); + break; + case DavMethods.DAV_ORDERPATCH: + doOrderPatch(request, response, resource); + break; + case DavMethods.DAV_SUBSCRIBE: + doSubscribe(request, response, resource); + break; + case DavMethods.DAV_UNSUBSCRIBE: + doUnsubscribe(request, response, resource); + break; + case DavMethods.DAV_POLL: + doPoll(request, response, resource); + break; + case DavMethods.DAV_SEARCH: + doSearch(request, response, resource); + break; + case DavMethods.DAV_VERSION_CONTROL: + doVersionControl(request, response, resource); + break; + case DavMethods.DAV_LABEL: + doLabel(request, response, resource); + break; + case DavMethods.DAV_REPORT: + doReport(request, response, resource); + break; + case DavMethods.DAV_CHECKIN: + doCheckin(request, response, resource); + break; + case DavMethods.DAV_CHECKOUT: + doCheckout(request, response, resource); + break; + case DavMethods.DAV_UNCHECKOUT: + doUncheckout(request, response, resource); + break; + case DavMethods.DAV_MERGE: + doMerge(request, response, resource); + break; + case DavMethods.DAV_UPDATE: + doUpdate(request, response, resource); + break; + case DavMethods.DAV_MKWORKSPACE: + doMkWorkspace(request, response, resource); + break; + default: + // any other method + return false; + } + return true; + } /** * The OPTION method @@ -82,7 +291,7 @@ response.addHeader("Allow", resource.getSupportedMethods()); response.addHeader("MS-Author-Via", DavConstants.HEADER_DAV); if (resource instanceof SearchResource) { - String[] langs = ((SearchResource)resource).getQueryGrammerSet().getQueryLanguages(); + String[] langs = ((SearchResource) resource).getQueryGrammerSet().getQueryLanguages(); for (int i = 0; i < langs.length; i++) { response.addHeader(SearchConstants.HEADER_DASL, "<" + langs[i] + ">"); } @@ -91,7 +300,7 @@ OptionsResponse oR = null; OptionsInfo oInfo = request.getOptionsInfo(); if (oInfo != null && resource instanceof DeltaVResource) { - oR = ((DeltaVResource)resource).getOptionResponse(oInfo); + oR = ((DeltaVResource) resource).getOptionResponse(oInfo); } if (oR == null) { response.setStatus(DavServletResponse.SC_OK); @@ -168,7 +377,7 @@ DavProperty contentLength = resource.getProperty(DavPropertyName.GETCONTENTLENGTH); if (contentLength != null) { try { - int length = Integer.parseInt(contentLength.getValue()+""); + int length = Integer.parseInt(contentLength.getValue() + ""); if (length > 0) { response.setIntHeader("Content-Length", length); } @@ -178,16 +387,26 @@ } // spool content in case of 'GET' request - if (sendContent) { - InputStream in = resource.getStream(); + InputStream in = resource.getStream(); + try { + if (sendContent) { + if (in != null) { + OutputStream out = response.getOutputStream(); + byte[] buffer = new byte[8192]; + int read; + while ((read = in.read(buffer)) >= 0) { + out.write(buffer, 0, read); + } + } + } + } finally { + // also close stream if not sending content if (in != null) { - OutputStream out = response.getOutputStream(); - byte[] buffer = new byte[8192]; - int read; - while ((read = in.read(buffer)) >= 0 ) { - out.write(buffer, 0, read); + try { + in.close(); + } catch (IOException e) { + // ignore } - in.close(); } } response.flushBuffer(); @@ -241,7 +460,7 @@ // TODO: not correct resolution of merge conflicts are immediately perstisted // TODO: rfc 2518 requires, that no changes must only be persisted if the complete proppatch-req succeeds if (resource instanceof VersionControlledResource) { - ((VersionControlledResource)resource).resolveMergeConflict(setProperties, removeProperties); + ((VersionControlledResource) resource).resolveMergeConflict(setProperties, removeProperties); } // complete any other property setting or removing @@ -261,6 +480,20 @@ } /** + * The POST method. Delegate to PUT + * + * @param request + * @param response + * @param resource + * @throws IOException + * @throws DavException + */ + protected void doPost(WebdavRequest request, WebdavResponse response, + DavResource resource) throws IOException, DavException { + doPut(request, response, resource); + } + + /** * The PUT method * * @param request @@ -281,7 +514,7 @@ int status; // test if resource already exists - if (resource.exists()){ + if (resource.exists()) { status = DavServletResponse.SC_NO_CONTENT; } else { status = DavServletResponse.SC_CREATED; @@ -357,7 +590,7 @@ return; } - DavResource destResource = createResource(request.getDestinationLocator(), request, response); + DavResource destResource = getResourceFactory().createResource(request.getDestinationLocator(), request, response); int status = validateDestination(destResource, request); if (status > DavServletResponse.SC_NO_CONTENT) { response.sendError(status); @@ -380,7 +613,7 @@ protected void doMove(WebdavRequest request, WebdavResponse response, DavResource resource) throws IOException, DavException { - DavResource destResource = createResource(request.getDestinationLocator(), request, response); + DavResource destResource = getResourceFactory().createResource(request.getDestinationLocator(), request, response); int status = validateDestination(destResource, request); if (status > DavServletResponse.SC_NO_CONTENT) { response.sendError(status); @@ -390,7 +623,7 @@ resource.move(destResource); response.setStatus(status); } - + /** * Validate the given destination resource and return the proper status * code: Any return value greater/equal than {@link DavServletResponse#SC_NO_CONTENT} @@ -401,10 +634,10 @@ * @return status code indicating whether the destination is valid. */ private int validateDestination(DavResource destResource, WebdavRequest request) - throws DavException { + throws DavException { String destHeader = request.getHeader(HEADER_DESTINATION); - if (destHeader == null || "".equals(destHeader)){ + if (destHeader == null || "".equals(destHeader)) { return DavServletResponse.SC_BAD_REQUEST; } if (destResource.getLocator().equals(request.getRequestLocator())) { @@ -419,7 +652,7 @@ return DavServletResponse.SC_PRECONDITION_FAILED; } else { // overwrite existing resource - destResource.getCollection().removeMember(destResource); + destResource.getCollection().removeMember(destResource); status = DavServletResponse.SC_NO_CONTENT; } } else { @@ -489,7 +722,7 @@ String lockToken = request.getLockToken(); TransactionInfo tInfo = request.getTransactionInfo(); if (tInfo != null) { - ((TransactionResource)resource).unlock(lockToken, tInfo); + ((TransactionResource) resource).unlock(lockToken, tInfo); } else { resource.unlock(lockToken); } @@ -521,7 +754,7 @@ return; } // perform reordering of internal members - ((OrderingResource)resource).orderMembers(op); + ((OrderingResource) resource).orderMembers(op); response.setStatus(DavServletResponse.SC_OK); //TODO: in case of failure Multistatus is required... @@ -551,7 +784,7 @@ response.sendError(DavServletResponse.SC_UNSUPPORTED_MEDIA_TYPE); return; } - Subscription subs = ((ObservationResource)resource).subscribe(info, request.getSubscriptionId()); + Subscription subs = ((ObservationResource) resource).subscribe(info, request.getSubscriptionId()); response.sendSubscriptionResponse(subs); } @@ -573,7 +806,7 @@ response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); return; } - ((ObservationResource)resource).unsubscribe(request.getSubscriptionId()); + ((ObservationResource) resource).unsubscribe(request.getSubscriptionId()); response.setStatus(DavServletResponse.SC_NO_CONTENT); } @@ -595,7 +828,7 @@ response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); return; } - EventDiscovery ed = ((ObservationResource)resource).poll(request.getSubscriptionId()); + EventDiscovery ed = ((ObservationResource) resource).poll(request.getSubscriptionId()); response.sendPollResponse(ed); } @@ -615,7 +848,7 @@ response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); return; } - ((VersionableResource)resource).addVersionControl(); + ((VersionableResource) resource).addVersionControl(); } /** @@ -633,9 +866,9 @@ LabelInfo labelInfo = request.getLabelInfo(); if (resource instanceof VersionResource) { - ((VersionResource)resource).label(labelInfo); + ((VersionResource) resource).label(labelInfo); } else if (resource instanceof VersionControlledResource) { - ((VersionControlledResource)resource).label(labelInfo); + ((VersionControlledResource) resource).label(labelInfo); } else { // any other resource type that does not support a LABEL request response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); @@ -659,7 +892,7 @@ return; } ReportInfo info = request.getReportInfo(); - Report report = ((DeltaVResource)resource).getReport(info); + Report report = ((DeltaVResource) resource).getReport(info); response.sendXmlResponse(report.toXml(), DavServletResponse.SC_OK); } @@ -680,7 +913,7 @@ response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); return; } - String versionHref = ((VersionControlledResource)resource).checkin(); + String versionHref = ((VersionControlledResource) resource).checkin(); response.setHeader(DeltaVConstants.HEADER_LOCATION, versionHref); } @@ -700,7 +933,7 @@ response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); return; } - ((VersionControlledResource)resource).checkout(); + ((VersionControlledResource) resource).checkout(); } /** @@ -713,13 +946,13 @@ * @throws IOException */ protected void doUncheckout(WebdavRequest request, WebdavResponse response, - DavResource resource) + DavResource resource) throws DavException, IOException { if (!(resource instanceof VersionControlledResource)) { response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); return; } - ((VersionControlledResource)resource).uncheckout(); + ((VersionControlledResource) resource).uncheckout(); } /** @@ -734,12 +967,12 @@ protected void doMerge(WebdavRequest request, WebdavResponse response, DavResource resource) throws DavException, IOException { - if (!(resource instanceof VersionControlledResource)) { + if (!(resource instanceof VersionControlledResource)) { response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); return; } MergeInfo info = request.getMergeInfo(); - MultiStatus ms = ((VersionControlledResource)resource).merge(info); + MultiStatus ms = ((VersionControlledResource) resource).merge(info); response.sendMultiStatusResponse(ms); } @@ -760,7 +993,7 @@ return; } UpdateInfo info = request.getUpdateInfo(); - MultiStatus ms = ((VersionControlledResource)resource).update(info); + MultiStatus ms = ((VersionControlledResource) resource).update(info); response.sendMultiStatusResponse(ms); } @@ -774,7 +1007,7 @@ * @throws IOException */ protected void doMkWorkspace(WebdavRequest request, WebdavResponse response, - DavResource resource) throws DavException, IOException { + DavResource resource) throws DavException, IOException { if (resource.exists()) { log.warn("Cannot create a new workspace. Resource already exists."); response.sendError(DavServletResponse.SC_FORBIDDEN); @@ -791,13 +1024,13 @@ response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED); return; } - ((DeltaVResource)parentResource).addWorkspace(resource); + ((DeltaVResource) parentResource).addWorkspace(resource); response.setStatus(DavServletResponse.SC_CREATED); } /** * The SEARCH method - * + * * @param request * @param response * @param resource @@ -815,11 +1048,11 @@ Document doc = request.getRequestDocument(); if (doc != null) { SearchInfo sR = new SearchInfo(doc); - response.sendMultiStatusResponse(((SearchResource)resource).search(sR)); + response.sendMultiStatusResponse(((SearchResource) resource).search(sR)); } else { // request without request body is valid if requested resource // is a 'query' resource. - response.sendMultiStatusResponse(((SearchResource)resource).search(null)); + response.sendMultiStatusResponse(((SearchResource) resource).search(null)); } } catch (IllegalArgumentException e) { response.sendError(DavServletResponse.SC_BAD_REQUEST); Added: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/CredentialsProvider.java URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/CredentialsProvider.java?rev=180346&view=auto ============================================================================== --- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/CredentialsProvider.java (added) +++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/CredentialsProvider.java Mon Jun 6 10:36:09 2005 @@ -0,0 +1,39 @@ +/* + * Copyright 2004-2005 The Apache Software Foundation or its licensors, + * as applicable. + * + * Licensed 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.server; + +import javax.jcr.Credentials; +import javax.jcr.LoginException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.ServletException; + +/** + * This Interface defines a provider for the credentials. + */ +public interface CredentialsProvider { + + /** + * Extracts the credentials from the given servlet request. + * + * @param request + * @return the credentials or null + * @throws LoginException if the credentials are invalid + * @throws ServletException if an error occurrs + */ + public Credentials getCredentials(HttpServletRequest request) + throws LoginException, ServletException; +} Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/CredentialsProvider.java ------------------------------------------------------------------------------ svn = Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/CredentialsProvider.java ------------------------------------------------------------------------------ svn:eol-style = native Added: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/SessionProvider.java URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/SessionProvider.java?rev=180346&view=auto ============================================================================== --- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/SessionProvider.java (added) +++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/SessionProvider.java Mon Jun 6 10:36:09 2005 @@ -0,0 +1,44 @@ +/* + * Copyright 2004-2005 The Apache Software Foundation or its licensors, + * as applicable. + * + * Licensed 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.server; + +import javax.jcr.LoginException; +import javax.jcr.Session; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; + +/** + * This Interface defines a provider for repository sessions + */ +public interface SessionProvider { + + /** + * Provides the repository session suitable for the given request. + * + * @param request + * @param rep the repository to login + * @param workspace the workspace name + * @return the session or null + * @throws LoginException if the credentials are invalid + * @throws ServletException if an error occurrs + */ + public Session getSession(HttpServletRequest request, Repository rep, String workspace) + throws LoginException, ServletException, RepositoryException; + +} Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/SessionProvider.java ------------------------------------------------------------------------------ svn = Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/SessionProvider.java ------------------------------------------------------------------------------ svn:eol-style = native Added: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/SessionProviderImpl.java URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/SessionProviderImpl.java?rev=180346&view=auto ============================================================================== --- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/SessionProviderImpl.java (added) +++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/SessionProviderImpl.java Mon Jun 6 10:36:09 2005 @@ -0,0 +1,54 @@ +/* + * Copyright 2004-2005 The Apache Software Foundation or its licensors, + * as applicable. + * + * Licensed 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.server; + +import javax.jcr.Repository; +import javax.jcr.Session; +import javax.jcr.LoginException; +import javax.jcr.Credentials; +import javax.jcr.RepositoryException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.ServletException; + +/** + * This Class implements a default session provider uses a credentials provider. + */ +public class SessionProviderImpl implements SessionProvider { + + /** + * the credentials provider + */ + private CredentialsProvider cp; + + /** + * Creates a new SessionProvider + * @param cp + */ + public SessionProviderImpl(CredentialsProvider cp) { + this.cp = cp; + } + + /** + * {@inheritDoc } + */ + public Session getSession(HttpServletRequest request, Repository repository, + String workspace) + throws LoginException, RepositoryException, ServletException { + Credentials creds = cp.getCredentials(request); + return repository.login(creds, workspace); + } +} Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/SessionProviderImpl.java ------------------------------------------------------------------------------ svn = Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/SessionProviderImpl.java ------------------------------------------------------------------------------ svn:eol-style = native Added: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/io/AbstractCommand.java URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/io/AbstractCommand.java?rev=180346&view=auto ============================================================================== --- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/io/AbstractCommand.java (added) +++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/io/AbstractCommand.java Mon Jun 6 10:36:09 2005 @@ -0,0 +1,91 @@ +/* + * Copyright 2004-2005 The Apache Software Foundation or its licensors, + * as applicable. + * + * Licensed 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.server.io; + +import org.apache.commons.chain.Command; +import org.apache.commons.chain.Context; +import org.apache.jackrabbit.JcrConstants; + +/** + * This Class implements an abstract command + */ +public abstract class AbstractCommand implements Command, JcrConstants { + + /** + * the id of the command + */ + private String id; + + /** + * flag, indicating if this command is enabled + */ + private boolean enabled = true; + + /** + * Executes this command by calling {@link #execute(AbstractContext)} if + * this command is not disabled by the context properties. + * + * @param context the (import) context. + * @return the return value of the delegated method or false; + * @throws Exception in an error occurrs + */ + final public boolean execute(Context context) throws Exception { + if (context instanceof AbstractContext) { + AbstractContext ctx = (AbstractContext) context; + if (!ctx.isCommandEnabled(getId(), enabled)) { + // ignore if this command is disabled by context property + return false; + } + return execute(ctx); + } else { + return false; + } + } + + /** + * Sets the enabled flag. + * @param enabled + */ + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + /** + * Executes this command + * + * @param context + * @return + * @throws Exception + */ + public abstract boolean execute(AbstractContext context) throws Exception; + + /** + * Gets the id of this command + * @return + */ + public String getId() { + return id; + } + + /** + * Sets the id of this command + * @param id + */ + public void setId(String id) { + this.id = id; + } +} Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/io/AbstractCommand.java ------------------------------------------------------------------------------ svn = Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/io/AbstractCommand.java ------------------------------------------------------------------------------ svn:eol-style = native Added: incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/io/AbstractContext.java URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/io/AbstractContext.java?rev=180346&view=auto ============================================================================== --- incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/io/AbstractContext.java (added) +++ incubator/jackrabbit/trunk/contrib/jcr-server/server/src/java/org/apache/jackrabbit/server/io/AbstractContext.java Mon Jun 6 10:36:09 2005 @@ -0,0 +1,93 @@ +/* + * Copyright 2004-2005 The Apache Software Foundation or its licensors, + * as applicable. + * + * Licensed 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.server.io; + +import org.apache.commons.chain.Context; + +import java.util.Properties; + +/** + */ +public class AbstractContext extends Properties implements Context { + + /** + * Creates a new AbstractContext that used the given properties as default + * @param defaults + */ + public AbstractContext(Properties defaults) { + super(defaults); + } + + /** + * Returns the value of the property or def if the property + * does not exist. + * @param name the name of the property + * @param def the default value to return if the property does not exist. + * @return the value of the property or def + */ + public String getProperty(String name, String def) { + String val = getProperty(name); + return val == null ? def : val; + } + + /** + * Returns the value of the property or def if the property + * does not exist. + * @param name the name of the property + * @param def the default value to return if the property does not exist. + * @return the value of the property or def + */ + public boolean getProperty(String name, boolean def) { + String val = getProperty(name); + return val == null ? def : Boolean.valueOf(getProperty(name)).booleanValue(); + } + + /** + * Enables or disables a command by setting the <id>.enabled property + * to enabled + * + * @param id + * @param enable + */ + public void enableCommand(String id, boolean enable) { + setProperty(id + ".enabled", Boolean.toString(enable)); + } + + /** + * Enables or disables a command by setting the <id>.enabled property + * to enabled + * + * @param id + * @param enable + */ + public void enableCommand(String id, String enable) { + setProperty(id + ".enabled", enable); + } + + /** + * Checks if this command is enabled. if the respective property does not + * exist, the value of def is returned. + * + * @param id + * @param def + * @return + */ + public boolean isCommandEnabled(String id, boolean def) { + return getProperty(id + ".enabled", def); + } + +}