Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/Bundle.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/Bundle.java?rev=922398&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/Bundle.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/Bundle.java Fri Mar 12 19:13:39 2010
@@ -0,0 +1,584 @@
+/*
+ * 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.j3.mc;
+
+import javax.jcr.PropertyType;
+
+public class Bundle {
+
+ // types 0 (PropertyType.UNDEFINED) - 12 (PropertyType.DECIMAL) are used
+
+ private static final int BACK_POINTER = 42;
+ private static final int MULTI_VALUE = 43;
+ private static final int BINARY_REFERENCE = 44;
+ private static final int BOOLEAN_FALSE = 45;
+ private static final int BOOLEAN_TRUE = 46;
+ private static final int LONG_NEGATIVE = 47;
+ private static final int STRING_LEN_0_15 = 48;
+ private static final int INDEXED = 64;
+
+ /**
+ * The data itself.
+ */
+ private byte[] data;
+
+ /**
+ * Used while writing: back pointers.
+ */
+ private final int[] last = new int[64];
+
+ /**
+ * The current write or read position.
+ */
+ private int pos;
+
+ private Bundle(byte[] data) {
+ this.data = data;
+ }
+
+ /**
+ * Get the length of a String value.
+ *
+ * @param s the value
+ * @return the length
+ */
+ private int getStringLen(String s) {
+ int len = s.length();
+ return getStringWithoutLengthLen(s, len) + getVarIntLen(len);
+ }
+
+ private int getStringWithoutLengthLen(String s, int len) {
+ int plus = 0;
+ for (int i = 0; i < len; i++) {
+ char c = s.charAt(i);
+ if (c >= 0x800) {
+ plus += 2;
+ } else if (c >= 0x80) {
+ plus++;
+ }
+ }
+ return len + plus;
+ }
+
+ /**
+ * Read a String value.
+ * The current position is incremented.
+ *
+ * @return the value
+ */
+ private String readString() {
+ int len = readVarInt();
+ return readString(len);
+ }
+
+ private String readString(int len) {
+ byte[] buff = data;
+ int p = pos;
+ char[] chars = new char[len];
+ for (int i = 0; i < len; i++) {
+ int x = buff[p++] & 0xff;
+ if (x < 0x80) {
+ chars[i] = (char) x;
+ } else if (x >= 0xe0) {
+ chars[i] = (char) (((x & 0xf) << 12) + ((buff[p++] & 0x3f) << 6) + (buff[p++] & 0x3f));
+ } else {
+ chars[i] = (char) (((x & 0x1f) << 6) + (buff[p++] & 0x3f));
+ }
+ }
+ pos = p;
+ return new String(chars);
+ }
+
+ /**
+ * Write a String value.
+ * The current position is incremented.
+ *
+ * @param s the value
+ */
+ private void writeString(String s) {
+ int len = s.length();
+ checkCapacity(5 + len * 3);
+ writeVarInt(len);
+ writeStringWithoutLength(s, len);
+ }
+
+ private void writeStringWithoutLength(String s, int len) {
+ int p = pos;
+ byte[] buff = data;
+ for (int i = 0; i < len; i++) {
+ int c = s.charAt(i);
+ if (c < 0x80) {
+ buff[p++] = (byte) c;
+ } else if (c >= 0x800) {
+ buff[p++] = (byte) (0xe0 | (c >> 12));
+ buff[p++] = (byte) (((c >> 6) & 0x3f));
+ buff[p++] = (byte) (c & 0x3f);
+ } else {
+ buff[p++] = (byte) (0xc0 | (c >> 6));
+ buff[p++] = (byte) (c & 0x3f);
+ }
+ }
+ pos = p;
+ }
+
+ /**
+ * Create a new buffer.
+ *
+ * @param capacity the initial capacity of the buffer
+ * @return the buffer
+ */
+ public static Bundle create(int capacity) {
+ return new Bundle(new byte[capacity]);
+ }
+
+ /**
+ * Create a new buffer.
+ *
+ * @param data the data
+ * @return the buffer
+ */
+ public static Bundle create(byte[] data) {
+ return new Bundle(data);
+ }
+
+ /**
+ * Get the current write position of this buffer, which is the current
+ * length.
+ *
+ * @return the length
+ */
+ public int length() {
+ return pos;
+ }
+
+ /**
+ * Get the byte array used for this bundle.
+ *
+ * @return the byte array
+ */
+ public byte[] getBytes() {
+ byte[] b = new byte[pos];
+ System.arraycopy(data, 0, b, 0, pos);
+ return b;
+ }
+
+ /**
+ * Set the position to 0.
+ */
+ public void reset() {
+ pos = 0;
+ }
+
+ /**
+ * Append a number of bytes to this buffer.
+ *
+ * @param buff the data
+ * @param off the offset in the data
+ * @param len the length in bytes
+ */
+ private void write(byte[] buff, int off, int len) {
+ checkCapacity(len);
+ System.arraycopy(buff, off, data, pos, len);
+ pos += len;
+ }
+
+ /**
+ * Copy a number of bytes to the given buffer from the current position. The
+ * current position is incremented accordingly.
+ *
+ * @param buff the output buffer
+ * @param off the offset in the output buffer
+ * @param len the number of bytes to copy
+ */
+ private void read(byte[] buff, int off, int len) {
+ System.arraycopy(data, pos, buff, off, len);
+ pos += len;
+ }
+
+ /**
+ * Append one single byte.
+ *
+ * @param x the value
+ */
+ private void writeByte(byte x) {
+ data[pos++] = x;
+ }
+
+ /**
+ * Append a value.
+ *
+ * @param v the value
+ */
+ public Bundle writeVal(Val v) {
+ checkCapacity(16);
+ if (v.getIndex() > 0) {
+ writeVarInt(INDEXED + v.getIndex());
+ return this;
+ }
+ int start = pos;
+ int type = v.getType();
+ switch (type) {
+ case Val.TYPE_MULTI_VALUE: {
+ writeByte((byte) MULTI_VALUE);
+ writeVarInt(v.getArray().length);
+ for (Val x : v.getArray()) {
+ writeVal(x);
+ }
+ break;
+ }
+ case Val.TYPE_BINARY_REFERENCE:
+ writeByte((byte) BINARY_REFERENCE);
+ writeString(v.getString());
+ break;
+ case PropertyType.BOOLEAN:
+ writeByte((byte) (v == Val.TRUE ? BOOLEAN_TRUE : BOOLEAN_FALSE));
+ break;
+ case PropertyType.BINARY: {
+ writeByte((byte) type);
+ byte[] x = v.getBytes();
+ writeVarInt(x.length);
+ write(x, 0, x.length);
+ break;
+ }
+ case PropertyType.DOUBLE:
+ writeByte((byte) type);
+ writeVarLong(Long.reverseBytes(Double.doubleToLongBits(v.getDouble())));
+ break;
+ case PropertyType.LONG: {
+ long x = v.getLong();
+ if (x < 0) {
+ writeByte((byte) LONG_NEGATIVE);
+ writeVarLong(-x);
+ } else {
+ writeByte((byte) type);
+ writeVarLong(x);
+ }
+ break;
+ }
+ case PropertyType.STRING: {
+ String s = v.getString();
+ int len = s.length();
+ if (len < 16) {
+ writeByte((byte) (STRING_LEN_0_15 + len));
+ writeStringWithoutLength(s, len);
+ } else {
+ writeByte((byte) type);
+ writeString(s);
+ }
+ break;
+ }
+ case PropertyType.DATE:
+ case PropertyType.DECIMAL:
+ case PropertyType.NAME:
+ case PropertyType.PATH:
+ case PropertyType.REFERENCE:
+ case PropertyType.URI:
+ case PropertyType.WEAKREFERENCE:
+ writeByte((byte) type);
+ writeString(v.getString());
+ break;
+ default:
+ throw new IllegalArgumentException("type:" + v.getType());
+ }
+ int len = pos - start;
+ if (len > 8) {
+ int hash = data[start] ^ data[start + 1] ^ data[start + 2];
+ hash = hash & (last.length - 1);
+ int test = last[hash];
+ if (test <= 0 || test >= start) {
+ last[hash] = start + 1;
+ } else {
+ test--;
+ int i = 0;
+ for (; i < len; i++) {
+ if (data[i + start] != data[test + i]) {
+ break;
+ }
+ }
+ if (i == len) {
+ // write back pointer instead of the data
+ pos = start;
+ writeByte((byte) BACK_POINTER);
+ writeVarInt(start - test);
+ }
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Calculate the number of bytes required to encode the given value.
+ *
+ * @param v the value
+ * @return the number of bytes required to store this value
+ */
+ public int getValLen(Val v) {
+ if (v.getIndex() > 0) {
+ return getVarIntLen(INDEXED + v.getIndex());
+ }
+ int type = v.getType();
+ switch (type) {
+ case Val.TYPE_MULTI_VALUE: {
+ Val[] array = v.getArray();
+ int len = 1 + getVarLongLen(array.length);
+ for (Val x : array) {
+ len += getValLen(x);
+ }
+ return len;
+ }
+ case Val.TYPE_BINARY_REFERENCE:
+ return 1 + getStringLen(v.getString());
+ case PropertyType.BOOLEAN:
+ return 1;
+ case PropertyType.BINARY: {
+ byte[] x = v.getBytes();
+ return 1 + getVarIntLen(x.length) + x.length;
+ }
+ case PropertyType.DOUBLE: {
+ double x = v.getDouble();
+ return 1 + getVarLongLen(Long.reverseBytes(Double.doubleToLongBits(x)));
+ }
+ case PropertyType.LONG: {
+ long x = v.getLong();
+ if (x < 0) {
+ return 1 + getVarLongLen(-x);
+ } else {
+ return 1 + getVarLongLen(x);
+ }
+ }
+ case PropertyType.STRING: {
+ String s = v.getString();
+ int len = s.length();
+ if (len < 16) {
+ return 1 + getStringWithoutLengthLen(s, len);
+ } else {
+ return 1 + getStringLen(s);
+ }
+ }
+ case PropertyType.DATE:
+ case PropertyType.DECIMAL:
+ case PropertyType.NAME:
+ case PropertyType.PATH:
+ case PropertyType.REFERENCE:
+ case PropertyType.URI:
+ case PropertyType.WEAKREFERENCE:
+ return 1 + getStringLen(v.getString());
+ default:
+ throw new IllegalArgumentException("type:" + v.getType());
+ }
+ }
+
+ /**
+ * Read a value.
+ *
+ * @return the value
+ */
+ public Val readVal() {
+ int type = data[pos] & 255;
+ if (type >= INDEXED) {
+ return Val.getIndexed(readVarInt() - INDEXED);
+ }
+ pos++;
+ switch (type) {
+ case BACK_POINTER: {
+ int start = pos - 1;
+ int offset = readVarInt();
+ int old = pos;
+ pos = start - offset;
+ Val v = readVal();
+ pos = old;
+ return v;
+ }
+ case MULTI_VALUE: {
+ int len = readVarInt();
+ Val array[] = new Val[len];
+ for (int i=0; i<len; i++) {
+ array[i] = readVal();
+ }
+ return Val.get(array);
+ }
+ case BINARY_REFERENCE:
+ return Val.get(PropertyType.BINARY, readString());
+ case BOOLEAN_TRUE:
+ return Val.TRUE;
+ case BOOLEAN_FALSE:
+ return Val.FALSE;
+ case PropertyType.BINARY: {
+ byte[] x = new byte[readVarInt()];
+ read(x, 0, x.length);
+ return Val.get(x);
+ }
+ case PropertyType.DOUBLE: {
+ long x = Long.reverseBytes(readVarLong());
+ return Val.get(Double.longBitsToDouble(x));
+ }
+ case PropertyType.LONG:
+ return Val.get(readVarLong());
+ case LONG_NEGATIVE:
+ return Val.get(-readVarLong());
+ case PropertyType.STRING:
+ case PropertyType.DATE:
+ case PropertyType.DECIMAL:
+ case PropertyType.NAME:
+ case PropertyType.PATH:
+ case PropertyType.REFERENCE:
+ case PropertyType.URI:
+ case PropertyType.WEAKREFERENCE:
+ return Val.get(type, readString());
+ default:
+ if (type >= STRING_LEN_0_15 && type < STRING_LEN_0_15 + 16) {
+ return Val.get(readString(type - STRING_LEN_0_15));
+ }
+ throw new IllegalArgumentException("type:" + type);
+ }
+ }
+
+ /**
+ * The number of bytes required for a variable size int.
+ *
+ * @param x the value
+ * @return the len
+ */
+ private int getVarIntLen(int x) {
+ if ((x & (-1 << 7)) == 0) {
+ return 1;
+ } else if ((x & (-1 << 14)) == 0) {
+ return 2;
+ } else if ((x & (-1 << 21)) == 0) {
+ return 3;
+ } else if ((x & (-1 << 28)) == 0) {
+ return 4;
+ }
+ return 5;
+ }
+
+ /**
+ * Write a variable size int.
+ *
+ * @param x the value
+ */
+ public void writeVarInt(int x) {
+ while ((x & ~0x7f) != 0) {
+ data[pos++] = (byte) (0x80 | (x & 0x7f));
+ x >>>= 7;
+ }
+ data[pos++] = (byte) x;
+ }
+
+ /**
+ * Read a variable size int.
+ *
+ * @return the value
+ */
+ public int readVarInt() {
+ int b = data[pos];
+ if (b >= 0) {
+ pos++;
+ return b;
+ }
+ int x = b & 0x7f;
+ b = data[pos + 1];
+ if (b >= 0) {
+ pos += 2;
+ return x | (b << 7);
+ }
+ x |= (b & 0x7f) << 7;
+ b = data[pos + 2];
+ if (b >= 0) {
+ pos += 3;
+ return x | (b << 14);
+ }
+ x |= (b & 0x7f) << 14;
+ b = data[pos + 3];
+ if (b >= 0) {
+ pos += 4;
+ return x | b << 21;
+ }
+ x |= ((b & 0x7f) << 21) | (data[pos + 4] << 28);
+ pos += 5;
+ return x;
+ }
+
+ /**
+ * The number of bytes required for a variable size long.
+ *
+ * @param x the value
+ * @return the len
+ */
+ private int getVarLongLen(long x) {
+ int i = 1;
+ while (true) {
+ x >>>= 7;
+ if (x == 0) {
+ return i;
+ }
+ i++;
+ }
+ }
+
+ /**
+ * Write a variable size long.
+ *
+ * @param x the value
+ */
+ public void writeVarLong(long x) {
+ while ((x & ~0x7f) != 0) {
+ data[pos++] = (byte) ((x & 0x7f) | 0x80);
+ x >>>= 7;
+ }
+ data[pos++] = (byte) x;
+ }
+
+ /**
+ * Read a variable size long.
+ *
+ * @return the value
+ */
+ public long readVarLong() {
+ long x = data[pos++];
+ if (x >= 0) {
+ return x;
+ }
+ x &= 0x7f;
+ for (int s = 7;; s += 7) {
+ long b = data[pos++];
+ x |= (b & 0x7f) << s;
+ if (b >= 0) {
+ return x;
+ }
+ }
+ }
+
+ /**
+ * Check if there is still enough capacity in the buffer.
+ * This method extends the buffer if required.
+ *
+ * @param plus the number of additional bytes required
+ */
+ private void checkCapacity(int plus) {
+ if (pos + plus >= data.length) {
+ expand(plus);
+ }
+ }
+
+ private void expand(int plus) {
+ byte[] d = new byte[(data.length + plus) * 2];
+ System.arraycopy(data, 0, d, 0, data.length);
+ data = d;
+ }
+
+}
Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/McException.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/McException.java?rev=922398&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/McException.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/McException.java Fri Mar 12 19:13:39 2010
@@ -0,0 +1,29 @@
+/*
+ * 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.j3.mc;
+
+public class McException extends RuntimeException {
+
+ public McException(String message) {
+ super(message);
+ }
+
+ public McException(Exception e) {
+ super(e);
+ }
+
+}
Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/NodeData.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/NodeData.java?rev=922398&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/NodeData.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/NodeData.java Fri Mar 12 19:13:39 2010
@@ -0,0 +1,242 @@
+/*
+ * 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.j3.mc;
+
+public class NodeData {
+
+ private final Val id;
+ private final Val primaryParentId;
+ private final long version;
+ private Val[] propertyValuePairs;
+ private Val[] childNameIdPairs;
+ private int cachedParentIndex;
+
+ public NodeData(Val id, Val primaryParentId, long version) {
+ this.id = id;
+ this.primaryParentId = primaryParentId;
+ this.version = version;
+ }
+
+ public NodeData clone() {
+ NodeData copy = new NodeData(id, primaryParentId, version);
+ copy.propertyValuePairs = propertyValuePairs;
+ copy.childNameIdPairs = childNameIdPairs;
+ return copy;
+ }
+
+ public void addChild(Val childName, Val childId) {
+ if (getChildId(childName) != null) {
+ throw new McException("duplicate node");
+ }
+ childNameIdPairs = updatePair(childNameIdPairs, childName, childId);
+ }
+
+ public Val getId() {
+ return id;
+ }
+
+ public Val getName(NodeData parent) {
+ if (parent == null) {
+ return Val.get("");
+ }
+ if (parent.childNameIdPairs == null) {
+ throw new McException("Child not found: " + id);
+ }
+ if (cachedParentIndex > parent.childNameIdPairs.length
+ || !parent.childNameIdPairs[cachedParentIndex + 1].equals(id)) {
+ for (int i = 0; i < parent.childNameIdPairs.length; i += 2) {
+ if (parent.childNameIdPairs[i + 1].equals(id)) {
+ cachedParentIndex = i;
+ break;
+ }
+ }
+ if (!parent.childNameIdPairs[cachedParentIndex + 1].equals(id)) {
+ throw new McException("Child not found: " + id);
+ }
+ }
+ return parent.childNameIdPairs[cachedParentIndex];
+ }
+
+ public Val getChildId(Val name) {
+ if (childNameIdPairs == null) {
+ return null;
+ }
+ int index = search(name, childNameIdPairs);
+ if (index < 0) {
+ return null;
+ }
+ Val childId = childNameIdPairs[index + 1];
+ return childId;
+ }
+
+ public Val getPropertyValue(Val propertyName) {
+ if (propertyValuePairs == null) {
+ return null;
+ }
+ int index = search(propertyName, propertyValuePairs);
+ if (index < 0) {
+ return null;
+ }
+ return propertyValuePairs[index + 1];
+ }
+
+ public void setPropertyValue(Val propertyName, Val newValue) {
+ propertyValuePairs = updatePair(propertyValuePairs, propertyName, newValue);
+ }
+
+ Val[] updatePair(Val[] pairs, Val key, Val value) {
+ if (pairs == null) {
+ if (value == null) {
+ return null;
+ } else {
+ return new Val[] { key, value };
+ }
+ }
+ int index = search(key, pairs);
+ if (index < 0) {
+ if (value == null) {
+ return pairs;
+ }
+ index = -index - 2;
+ Val[] newPairs = new Val[pairs.length + 2];
+ System.arraycopy(pairs, 0, newPairs, 0, index);
+ int len = newPairs.length - index;
+ if (len > 0) {
+ System.arraycopy(pairs, index, newPairs, index + 2, len - 2);
+ }
+ pairs = newPairs;
+ } else if (value == null) {
+ if (pairs.length == 2) {
+ return null;
+ }
+ Val[] newPairs = new Val[pairs.length - 2];
+ System.arraycopy(pairs, 0, newPairs, 0, index);
+ int len = newPairs.length - index;
+ if (len > 0) {
+ System.arraycopy(pairs, index + 2, newPairs, index, len);
+ }
+ return newPairs;
+ }
+ pairs[index] = key;
+ pairs[index + 1] = value;
+ return pairs;
+ }
+
+ private int search(Val key, Val[] pair) {
+ int low = 0;
+ int high = pair.length / 2 - 1;
+ while (low <= high) {
+ int mid = (low + high) >> 1;
+ Val middle = pair[mid * 2];
+ int result = middle.compareTo(key);
+ if (result < 0) {
+ low = mid + 1;
+ } else if (result > 0) {
+ high = mid - 1;
+ } else {
+ return mid * 2;
+ }
+ }
+ // not found
+ return -(low * 2 + 2);
+ }
+
+ int getMemoryUsed() {
+ int memory = 16;
+ if (propertyValuePairs != null) {
+ for (Val v : propertyValuePairs) {
+ memory += v.getMemoryUsed();
+ }
+ }
+ if (childNameIdPairs != null) {
+ for (Val v : childNameIdPairs) {
+ memory += v.getMemoryUsed();
+ }
+ }
+ return memory;
+ }
+
+ public String toString() {
+ StringBuilder buff = new StringBuilder();
+ buff.append("NodeData: id=" + id + " mainParent=" + primaryParentId + " version=" + version);
+ if (propertyValuePairs != null) {
+ buff.append(" { ");
+ for (int i = 0; i < propertyValuePairs.length; i += 2) {
+ if (i > 0) {
+ buff.append(", ");
+ }
+ buff.append(propertyValuePairs[i]).append('=').append(propertyValuePairs[i + 1]);
+ }
+ buff.append(" }");
+ }
+ if (childNameIdPairs != null) {
+ buff.append(" [ ");
+ for (int i = 0; i < childNameIdPairs.length; i += 2) {
+ if (i > 0) {
+ buff.append(", ");
+ }
+ buff.append(childNameIdPairs[i]).append('=').append(childNameIdPairs[i + 1]);
+ }
+ buff.append(" ]");
+ }
+ return buff.toString();
+ }
+
+ public static NodeData readFrom(Bundle bundle) {
+ Val id = bundle.readVal();
+ Val mainParentId = bundle.readVal();
+ if (mainParentId == Val.FALSE) {
+ mainParentId = null;
+ }
+ int version = bundle.readVarInt();
+ NodeData data = new NodeData(id, mainParentId, version);
+ Val children = bundle.readVal();
+ if (children != Val.FALSE) {
+ data.childNameIdPairs = children.getArray();
+ }
+ Val properties = bundle.readVal();
+ if (properties != Val.FALSE) {
+ data.propertyValuePairs = properties.getArray();
+ }
+ return data;
+ }
+
+ public void writeTo(Bundle bundle) {
+ bundle.writeVal(id);
+ bundle.writeVal(primaryParentId == null ? Val.FALSE : primaryParentId);
+ bundle.writeVarLong(version);
+ if (childNameIdPairs == null) {
+ bundle.writeVal(Val.FALSE);
+ } else {
+ bundle.writeVal(Val.get(childNameIdPairs));
+ }
+ if (propertyValuePairs == null) {
+ bundle.writeVal(Val.FALSE);
+ } else {
+ bundle.writeVal(Val.get(propertyValuePairs));
+ }
+ }
+
+ public long getVersion() {
+ return version;
+ }
+
+ public Val getPrimaryParentId() {
+ return primaryParentId;
+ }
+
+}
Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/Storage.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/Storage.java?rev=922398&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/Storage.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/Storage.java Fri Mar 12 19:13:39 2010
@@ -0,0 +1,25 @@
+/*
+ * 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.j3.mc;
+
+public interface Storage {
+
+ StorageSession openSession(String user, String password);
+
+ void close();
+
+}
Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/StorageSession.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/StorageSession.java?rev=922398&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/StorageSession.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/StorageSession.java Fri Mar 12 19:13:39 2010
@@ -0,0 +1,35 @@
+/*
+ * 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.j3.mc;
+
+public interface StorageSession {
+
+ void close();
+
+ Val getRootNodeId();
+
+ NodeData getNode(Val nodeId);
+
+ Val newNodeId(Val parentId);
+
+ void save(NodeData[] changed);
+
+ Val convertIdentifierToNodeId(String id);
+
+ String convertNodeIdToIdentifier(Val nodeId);
+
+}
Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/Val.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/Val.java?rev=922398&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/Val.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/Val.java Fri Mar 12 19:13:39 2010
@@ -0,0 +1,384 @@
+/*
+ * 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.j3.mc;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import javax.jcr.PropertyType;
+
+public class Val implements Comparable<Val> {
+
+ public static final Val TRUE = new Val(PropertyType.BOOLEAN, 0, true);
+ public static final Val FALSE = new Val(PropertyType.BOOLEAN, 0, false);
+
+ public static final int TYPE_MULTI_VALUE = 43;
+ public static final int TYPE_BINARY_REFERENCE = 44;
+
+ private static final int CACHE_SIZE = 1024;
+ private static final Val[] CACHE = new Val[CACHE_SIZE];
+
+ private static final String EMPTY_STRING = "";
+ private static final Val STRING_0 = new Val(PropertyType.STRING, 0, EMPTY_STRING);
+
+ private static final HashMap<Val, Integer> INDEX_MAP = new HashMap<Val, Integer>();
+
+ private static final Val[] INDEXED = new Val[128];
+
+ static {
+ // index 0 is not used
+ Val[] indexed = new Val[] {
+ Val.get(-1),
+ Val.get(0),
+ Val.get(1),
+ Val.get(2),
+ Val.get(3),
+ Val.get(4),
+ Val.get(5),
+ Val.get(6),
+ Val.get(7),
+ Val.get(0.0d),
+ Val.get(1.0d),
+ Val.get("http://www.jcp.org/jcr/1.0"),
+ Val.get("http://www.jcp.org/jcr/mix/1.0"),
+ Val.get("http://www.jcp.org/jcr/nt/1.0"),
+ Val.get("http://www.jcp.org/jcr/sv/1.0"),
+ Val.get("activity"),
+ Val.get("address"),
+ Val.get("autocreated"),
+ Val.get("base"),
+ Val.get("childNodeDefinition"),
+ Val.get("childVersionHistory"),
+ Val.get("configuration"),
+ Val.get("content"),
+ Val.get("copiedFrom"),
+ Val.get("created"),
+ Val.get("createdBy"),
+ Val.get("data"),
+ Val.get("defaultPrimaryType"),
+ Val.get("defaultValues"),
+ Val.get("description"),
+ Val.get("encoding"),
+ Val.get("etag"),
+ Val.get("file"),
+ Val.get("folder"),
+ Val.get("frozenMixinTypes"),
+ Val.get("frozenNode"),
+ Val.get("frozenPrimaryType"),
+ Val.get("frozenUuid"),
+ Val.get("hasOrderableChildNodes"),
+ Val.get("hierarchyNode"),
+ Val.get("host"),
+ Val.get("id"),
+ Val.get("internal"),
+ Val.get("isCheckedOut"),
+ Val.get("jcr"),
+ Val.get("key"),
+ Val.get("language"),
+ Val.get("lastModified"),
+ Val.get("lastModifiedBy"),
+ Val.get("lifecycle"),
+ Val.get("linkedFile"),
+ Val.get("mandatory"),
+ Val.get("mergeFailed"),
+ Val.get("message"),
+ Val.get("mimeType"),
+ Val.get("mixin"),
+ Val.get("mixinTypes"),
+ Val.get("multiple"),
+ Val.get("name"),
+ Val.get("nodeTypeName"),
+ Val.get("nt"),
+ Val.get("onParentVersion"),
+ Val.get("orderable"),
+ Val.get("path"),
+ Val.get("port"),
+ Val.get("predecessors"),
+ Val.get("primaryItemName"),
+ Val.get("primaryType"),
+ Val.get("propertyDefinition"),
+ Val.get("protected"),
+ Val.get("protocol"),
+ Val.get("query"),
+ Val.get("referenceable"),
+ Val.get("repository"),
+ Val.get("requiredPrimaryTypes"),
+ Val.get("requiredType"),
+ Val.get("resource"),
+ Val.get("resourceType"),
+ Val.get("root"),
+ Val.get("rootVersion"),
+ Val.get("sameNameSiblings"),
+ Val.get("share"),
+ Val.get("shareable"),
+ Val.get("simpleVersionable"),
+ Val.get("sling"),
+ Val.get("successors"),
+ Val.get("supertypes"),
+ Val.get("system"),
+ Val.get("text"),
+ Val.get("title"),
+ Val.get("type"),
+ Val.get("unfiled"),
+ Val.get("unstructured"),
+ Val.get("uuid"),
+ Val.get("valueConstraints"),
+ Val.get("version"),
+ Val.get("versionable"),
+ Val.get("versionableUuid"),
+ Val.get("versionedChild"),
+ Val.get("versionHistory"),
+ Val.get("versionLabels"),
+ Val.get("versionStorage"),
+ Val.get("workspace"),
+ Val.get("http://sling.apache.org/jcr/event/1.0"),
+ Val.get("http://sling.apache.org/jcr/sling/1.0"),
+ Val.get("http://www.day.com/crx/1.0"),
+ Val.get("http://www.day.com/crx/replication/1.0"),
+ Val.get("http://www.day.com/dam/1.0"),
+ Val.get("http://www.day.com/jcr/cq/1.0"),
+ Val.get("http://www.day.com/jcr/crxde/1.0"),
+ Val.get("http://www.day.com/jcr/vault/1.0"),
+ Val.get("http://www.day.com/jcr/wiki/1.0"),
+ Val.get("http://www.w3.org/2001/XMLSchema"),
+ Val.get("http://www.w3.org/2004/10/xpath-functions"),
+ Val.get("http://www.w3.org/2005/xpath-functions"),
+ Val.get("http://www.w3.org/XML/1998/namespace"),
+ };
+ int i = 0;
+ for (Val v : indexed) {
+ v.index = (short) i;
+ INDEXED[i] = v;
+ INDEX_MAP.put(v, i);
+ i++;
+ }
+ }
+
+ private final short type;
+ private short index;
+ private final Object value;
+
+ private Val(int type, int index, Object value) {
+ this.type = (short) type;
+ this.index = (short) index;
+ this.value = value;
+ }
+
+ public static Val getIndexed(int index) {
+ return INDEXED[index];
+ }
+
+ private static Val cache(int type, Object value) {
+ Val v = new Val(type, 0, value);
+ Integer index = INDEX_MAP.get(v);
+ if (index != null) {
+ return INDEXED[index];
+ }
+ int hash = v.hashCode();
+ int cacheIndex = hash & (CACHE_SIZE - 1);
+ Val cached = CACHE[cacheIndex];
+ if (cached != null && v.equals(cached)) {
+ return cached;
+ }
+ CACHE[cacheIndex] = v;
+ return v;
+ }
+
+ public static Val get(Val... array) {
+ if (array == null) {
+ throw new NullPointerException();
+ }
+ return new Val(TYPE_MULTI_VALUE, 0, array);
+ }
+
+ public static Val get(boolean x) {
+ return x ? TRUE : FALSE;
+ }
+
+ public static Val get(long x) {
+ return cache(PropertyType.LONG, Long.valueOf(x));
+ }
+
+ public static Val get(double x) {
+ return cache(PropertyType.DOUBLE, Double.valueOf(x));
+ }
+
+ public static Val get(byte[] x) {
+ return new Val(PropertyType.BINARY, 0, x);
+ }
+
+ public static Val get(String x) {
+ if (x.length() == 0) {
+ return STRING_0;
+ }
+ return cache(PropertyType.STRING, x);
+ }
+
+ public static Val get(int type, String x) {
+ if (x.length() == 0) {
+ x = EMPTY_STRING;
+ }
+ switch (type) {
+ case PropertyType.DECIMAL:
+ case PropertyType.DATE:
+ case PropertyType.NAME:
+ case PropertyType.PATH:
+ case PropertyType.REFERENCE:
+ case PropertyType.STRING:
+ case PropertyType.URI:
+ case PropertyType.WEAKREFERENCE:
+ return cache(type, x);
+ case PropertyType.BINARY:
+ return cache(TYPE_BINARY_REFERENCE, x);
+ }
+ throw new IllegalArgumentException("type: " + type + " value: " + x);
+ }
+
+ public int hashCode() {
+ switch (type) {
+ case PropertyType.BINARY:
+ return getType() ^ Arrays.hashCode(getBytes());
+ case TYPE_MULTI_VALUE:
+ return getType() ^ Arrays.hashCode(getArray());
+ }
+ return getType() ^ value.hashCode();
+ }
+
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+ if (other instanceof Val) {
+ Val v = (Val) other;
+ if (v.type != type) {
+ return false;
+ }
+ switch (type) {
+ case PropertyType.BINARY:
+ return Arrays.equals(getBytes(), v.getBytes());
+ case TYPE_MULTI_VALUE:
+ return Arrays.equals(getArray(), v.getArray());
+ }
+ return v.value.equals(value);
+ }
+ return false;
+ }
+
+ public String toString() {
+ switch (type) {
+ case TYPE_MULTI_VALUE: {
+ StringBuilder buff = new StringBuilder("[ ");
+ int i = 0;
+ for (Val v : (Val[]) value) {
+ if (i++ > 0) {
+ buff.append(", ");
+ }
+ buff.append(v.toString());
+ }
+ return buff.append(" ]").toString();
+ }
+ case TYPE_BINARY_REFERENCE: {
+ return "binaryRef:" + value;
+ }
+ default:
+ return value + ":" + PropertyType.nameFromValue(type);
+ }
+ }
+
+ public int getType() {
+ return type;
+ }
+
+ public String getString() {
+ return value.toString();
+ }
+
+ public double getDouble() {
+ return (Double) value;
+ }
+
+ public byte[] getBytes() {
+ return (byte[]) value;
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ public Val[] getArray() {
+ return (Val[]) value;
+ }
+
+ public long getLong() {
+ return (Long) value;
+ }
+
+ public int getMemoryUsed() {
+ if (index == 0) {
+ return 0;
+ }
+ switch (type) {
+ case PropertyType.BINARY:
+ return 32 + getBytes().length;
+ case PropertyType.LONG:
+ case PropertyType.DOUBLE:
+ return 16;
+ }
+ return 32 + getString().length() * 2;
+ }
+
+ public int compareTo(Val o) {
+ int result = compareInt(type, o.type);
+ if (result != 0) {
+ return result;
+ }
+ switch (type) {
+ case PropertyType.BINARY:
+ result = compareNotNull(getBytes(), o.getBytes());
+ break;
+ case PropertyType.LONG:
+ result = compareLong(getLong(), o.getLong());
+ break;
+ case PropertyType.DOUBLE:
+ result = Double.compare(getDouble(), o.getDouble());
+ break;
+ default:
+ result = getString().compareTo(o.getString());
+ }
+ return result;
+ }
+
+ public static int compareInt(int a, int b) {
+ return a == b ? 0 : a < b ? -1 : 1;
+ }
+
+ public static int compareLong(long a, long b) {
+ return a == b ? 0 : a < b ? -1 : 1;
+ }
+
+ public static int compareNotNull(byte[] data1, byte[] data2) {
+ int len = Math.min(data1.length, data2.length);
+ for (int i = 0; i < len; i++) {
+ byte b = data1[i];
+ byte b2 = data2[i];
+ if (b != b2) {
+ return b > b2 ? 1 : -1;
+ }
+ }
+ return Integer.signum(data1.length - data2.length);
+ }
+
+}
Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/jdbc/JdbcStorage.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/jdbc/JdbcStorage.java?rev=922398&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/jdbc/JdbcStorage.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/jdbc/JdbcStorage.java Fri Mar 12 19:13:39 2010
@@ -0,0 +1,83 @@
+/*
+ * 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.j3.mc.jdbc;
+
+import org.apache.jackrabbit.j3.mc.McException;
+import org.apache.jackrabbit.j3.mc.NodeData;
+import org.apache.jackrabbit.j3.mc.Storage;
+import org.apache.jackrabbit.j3.mc.StorageSession;
+import org.apache.jackrabbit.j3.mc.Val;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class JdbcStorage implements Storage {
+
+ private final String url;
+ private boolean initDone;
+ private final static Val rootNodeId = Val.get(0);
+ private AtomicLong nextNodeId;
+
+ public JdbcStorage(String url) {
+ this.url = url;
+ }
+
+ public StorageSession openSession(String user, String password) {
+ try {
+ Connection conn = JdbcUtils.getConnection(null, url, user, password);
+ JdbcStorageSession session = new JdbcStorageSession(this, conn);
+ init(conn, session);
+ return session;
+ } catch (SQLException e) {
+ throw new McException(e);
+ }
+ }
+
+ private synchronized void init(Connection conn, JdbcStorageSession session) {
+ if (initDone) {
+ return;
+ }
+ try {
+ Statement stat = conn.createStatement();
+ stat.execute("create table if not exists bundles(id bigint primary key, version bigint, data binary)");
+ ResultSet rs = stat.executeQuery("select max(id) from bundles");
+ rs.next();
+ nextNodeId = new AtomicLong(rs.getLong(1) + 1);
+ if (rs.wasNull()) {
+ NodeData root = new NodeData(rootNodeId, null, 0);
+ session.save(new NodeData[] { root });
+ }
+ } catch (SQLException e) {
+ throw new McException(e);
+ }
+ initDone = true;
+ }
+
+ public void close() {
+ }
+
+ Val newNodeId() {
+ return Val.get(nextNodeId.getAndIncrement());
+ }
+
+ Val getRootNodeId() {
+ return rootNodeId;
+ }
+
+}
Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/jdbc/JdbcStorageSession.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/jdbc/JdbcStorageSession.java?rev=922398&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/jdbc/JdbcStorageSession.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/jdbc/JdbcStorageSession.java Fri Mar 12 19:13:39 2010
@@ -0,0 +1,111 @@
+/*
+ * 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.j3.mc.jdbc;
+
+import org.apache.jackrabbit.j3.mc.Bundle;
+import org.apache.jackrabbit.j3.mc.McException;
+import org.apache.jackrabbit.j3.mc.NodeData;
+import org.apache.jackrabbit.j3.mc.StorageSession;
+import org.apache.jackrabbit.j3.mc.Val;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashMap;
+
+public class JdbcStorageSession implements StorageSession {
+
+ private final JdbcStorage storage;
+ private final Connection conn;
+ private final HashMap<String, PreparedStatement> prepared = new HashMap<String, PreparedStatement>();
+ private final Bundle bundle = Bundle.create(512);
+
+ JdbcStorageSession(JdbcStorage storage, Connection conn) {
+ this.storage = storage;
+ this.conn = conn;
+ }
+
+ private PreparedStatement prepare(String sql) throws SQLException {
+ PreparedStatement p = prepared.get(sql);
+ if (p == null) {
+ p = conn.prepareStatement(sql);
+ prepared.put(sql, p);
+ }
+ return p;
+ }
+
+ public void close() {
+ try {
+ conn.close();
+ } catch (SQLException e) {
+ throw new McException(e);
+ }
+ }
+
+ public Val getRootNodeId() {
+ return storage.getRootNodeId();
+ }
+
+ public NodeData getNode(Val nodeId) {
+ try {
+ PreparedStatement p = prepare("select data from bundles where id = ?");
+ p.setLong(1, nodeId.getLong());
+ ResultSet rs = p.executeQuery();
+ if (!rs.next()) {
+ rs.close();
+ return null;
+ }
+ byte[] data = rs.getBytes(1);
+ Bundle bundle = Bundle.create(data);
+ NodeData node = NodeData.readFrom(bundle);
+ rs.close();
+ return node;
+ } catch (SQLException e) {
+ throw new McException(e);
+ }
+ }
+
+ public Val newNodeId(Val parentId) {
+ return storage.newNodeId();
+ }
+
+ public void save(NodeData[] changed) {
+ try {
+ PreparedStatement p = prepare("merge into bundles(id, version, data) values(?, ?, ?)");
+ for (NodeData n : changed) {
+ p.setLong(1, n.getId().getLong());
+ p.setLong(2, n.getVersion());
+ bundle.reset();
+ n.writeTo(bundle);
+ p.setBytes(3, bundle.getBytes());
+ p.executeUpdate();
+ }
+ } catch (SQLException e) {
+ throw new McException(e);
+ }
+ }
+
+ public Val convertIdentifierToNodeId(String id) {
+ return Val.get(Long.parseLong(id));
+ }
+
+ public String convertNodeIdToIdentifier(Val nodeId) {
+ return nodeId.getString();
+ }
+
+
+}
Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/jdbc/JdbcUtils.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/jdbc/JdbcUtils.java?rev=922398&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/jdbc/JdbcUtils.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/jdbc/JdbcUtils.java Fri Mar 12 19:13:39 2010
@@ -0,0 +1,186 @@
+/*
+ * 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.j3.mc.jdbc;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Properties;
+import javax.naming.Context;
+import javax.sql.DataSource;
+
+/**
+ * This is a utility class with JDBC helper functions.
+ */
+public class JdbcUtils {
+
+ private static final String[] DRIVERS = {
+ "h2:", "org.h2.Driver",
+ "Cache:", "com.intersys.jdbc.CacheDriver",
+ "daffodilDB://", "in.co.daffodil.db.rmi.RmiDaffodilDBDriver",
+ "daffodil", "in.co.daffodil.db.jdbc.DaffodilDBDriver",
+ "db2:", "COM.ibm.db2.jdbc.net.DB2Driver",
+ "derby:net:", "org.apache.derby.jdbc.ClientDriver",
+ "derby://", "org.apache.derby.jdbc.ClientDriver",
+ "derby:", "org.apache.derby.jdbc.EmbeddedDriver",
+ "FrontBase:", "com.frontbase.jdbc.FBJDriver",
+ "firebirdsql:", "org.firebirdsql.jdbc.FBDriver",
+ "hsqldb:", "org.hsqldb.jdbcDriver",
+ "informix-sqli:", "com.informix.jdbc.IfxDriver",
+ "jtds:", "net.sourceforge.jtds.jdbc.Driver",
+ "microsoft:", "com.microsoft.jdbc.sqlserver.SQLServerDriver",
+ "mimer:", "com.mimer.jdbc.Driver",
+ "mysql:", "com.mysql.jdbc.Driver",
+ "odbc:", "sun.jdbc.odbc.JdbcOdbcDriver",
+ "oracle:", "oracle.jdbc.driver.OracleDriver",
+ "pervasive:", "com.pervasive.jdbc.v2.Driver",
+ "pointbase:micro:", "com.pointbase.me.jdbc.jdbcDriver",
+ "pointbase:", "com.pointbase.jdbc.jdbcUniversalDriver",
+ "postgresql:", "org.postgresql.Driver",
+ "sybase:", "com.sybase.jdbc3.jdbc.SybDriver",
+ "sqlserver:", "com.microsoft.sqlserver.jdbc.SQLServerDriver",
+ "teradata:", "com.ncr.teradata.TeraDriver",
+ };
+
+ private JdbcUtils() {
+ // utility class
+ }
+
+ /**
+ * Close a statement without throwing an exception.
+ *
+ * @param stat the statement or null
+ */
+ public static void closeSilently(Statement stat) {
+ if (stat != null) {
+ try {
+ stat.close();
+ } catch (SQLException e) {
+ // ignore
+ }
+ }
+ }
+
+ /**
+ * Close a connection without throwing an exception.
+ *
+ * @param conn the connection or null
+ */
+ public static void closeSilently(Connection conn) {
+ if (conn != null) {
+ try {
+ conn.close();
+ } catch (SQLException e) {
+ // ignore
+ }
+ }
+ }
+
+ /**
+ * Close a result set without throwing an exception.
+ *
+ * @param rs the result set or null
+ */
+ public static void closeSilently(ResultSet rs) {
+ if (rs != null) {
+ try {
+ rs.close();
+ } catch (SQLException e) {
+ // ignore
+ }
+ }
+ }
+
+ /**
+ * Open a new database connection with the given settings.
+ *
+ * @param driver the driver class name
+ * @param url the database URL
+ * @param user the user name
+ * @param password the password
+ * @return the database connection
+ */
+ public static Connection getConnection(String driver, String url, String user, String password) throws SQLException {
+ Properties prop = new Properties();
+ if (user != null) {
+ prop.setProperty("user", user);
+ }
+ if (password != null) {
+ prop.setProperty("password", password);
+ }
+ return getConnection(driver, url, prop);
+ }
+
+ /**
+ * Open a new database connection with the given settings.
+ *
+ * @param driver the driver class name
+ * @param url the database URL
+ * @param prop the properties containing at least the user name and password
+ * @return the database connection
+ */
+ public static Connection getConnection(String driver, String url, Properties prop) throws SQLException {
+ try {
+ if (driver == null || driver.length() == 0) {
+ driver = getDriver(url);
+ }
+ Class< ? > d = Class.forName(driver);
+ if (java.sql.Driver.class.isAssignableFrom(d)) {
+ return DriverManager.getConnection(url, prop);
+ } else if (javax.naming.Context.class.isAssignableFrom(d)) {
+ // JNDI context
+ Context context = (Context) d.newInstance();
+ DataSource ds = (DataSource) context.lookup(url);
+ String user = prop.getProperty("user");
+ String password = prop.getProperty("password");
+ if (user == null && password == null) {
+ return ds.getConnection();
+ }
+ return ds.getConnection(user, password);
+ } else {
+ return DriverManager.getConnection(url, prop);
+ }
+ } catch (Exception e) {
+ SQLException e2 = new SQLException("Can not open connection for url " + url + " " + prop);
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ /**
+ * Get the driver class name for the given URL, or null if the URL is
+ * unknown.
+ *
+ * @param url the database URL
+ * @return the driver class name
+ */
+ public static String getDriver(String url) {
+ if (url.startsWith("jdbc:")) {
+ url = url.substring("jdbc:".length());
+ for (int i = 0; i < DRIVERS.length; i += 2) {
+ String prefix = DRIVERS[i];
+ if (url.startsWith(prefix)) {
+ return DRIVERS[i + 1];
+ }
+ }
+ }
+ return null;
+ }
+
+}
Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/mem/MemStorage.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/mem/MemStorage.java?rev=922398&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/mem/MemStorage.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/mem/MemStorage.java Fri Mar 12 19:13:39 2010
@@ -0,0 +1,52 @@
+/*
+ * 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.j3.mc.mem;
+
+import org.apache.jackrabbit.j3.mc.Val;
+import org.apache.jackrabbit.j3.mc.NodeData;
+import org.apache.jackrabbit.j3.mc.Storage;
+import org.apache.jackrabbit.j3.mc.StorageSession;
+import java.util.HashMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class MemStorage implements Storage {
+
+ private final static Val rootNodeId = Val.get(0);
+ private final HashMap<Val, NodeData> content = new HashMap<Val, NodeData>();
+ private AtomicLong nextNodeId = new AtomicLong(1);
+
+ public MemStorage() {
+ NodeData root = new NodeData(rootNodeId, null, 0);
+ content.put(rootNodeId, root);
+ }
+
+ public void close() {
+ }
+
+ public StorageSession openSession(String user, String password) {
+ return new MemStorageSession(this, content);
+ }
+
+ public Val newNodeId() {
+ return Val.get(nextNodeId.getAndIncrement());
+ }
+
+ Val getRootNodeId() {
+ return rootNodeId;
+ }
+
+}
Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/mem/MemStorageSession.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/mem/MemStorageSession.java?rev=922398&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/mem/MemStorageSession.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/mc/mem/MemStorageSession.java Fri Mar 12 19:13:39 2010
@@ -0,0 +1,65 @@
+/*
+ * 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.j3.mc.mem;
+
+import java.util.HashMap;
+import org.apache.jackrabbit.j3.mc.NodeData;
+import org.apache.jackrabbit.j3.mc.StorageSession;
+import org.apache.jackrabbit.j3.mc.Val;
+
+public class MemStorageSession implements StorageSession {
+
+ private final MemStorage storage;
+ private final HashMap<Val, NodeData> content;
+
+ MemStorageSession(MemStorage storage, HashMap<Val, NodeData> content) {
+ this.storage = storage;
+ this.content = content;
+ }
+
+ public void close() {
+ }
+
+ public NodeData getNode(Val nodeId) {
+ return content.get(nodeId);
+ }
+
+ public Val getRootNodeId() {
+ return storage.getRootNodeId();
+ }
+
+ public Val newNodeId(Val parentId) {
+ return storage.newNodeId();
+ }
+
+ public void save(NodeData[] changed) {
+ for (NodeData n : changed) {
+ synchronized (storage) {
+ content.put(n.getId(), n);
+ }
+ }
+ }
+
+ public Val convertIdentifierToNodeId(String id) {
+ return Val.get(Long.parseLong(id));
+ }
+
+ public String convertNodeIdToIdentifier(Val nodeId) {
+ return nodeId.getString();
+ }
+
+}
Added: jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventImpl.java?rev=922398&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventImpl.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/main/java/org/apache/jackrabbit/j3/observation/EventImpl.java Fri Mar 12 19:13:39 2010
@@ -0,0 +1,64 @@
+/*
+ * 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.j3.observation;
+
+import java.util.Map;
+import javax.jcr.RepositoryException;
+import javax.jcr.observation.Event;
+import org.apache.jackrabbit.j3.SessionImpl;
+import org.apache.jackrabbit.j3.mc.Val;
+
+public class EventImpl implements Event {
+
+ private SessionImpl session;
+ private int eventType;
+ private Val nodeId;
+ private Val propertyName;
+ private long persistedDate;
+
+ public String getUserID() {
+ return session.getUserID();
+ }
+
+ public int getType() {
+ return eventType;
+ }
+
+ public long getDate() throws RepositoryException {
+ return persistedDate;
+ }
+
+ public String getIdentifier() throws RepositoryException {
+ return session.getStorageSession().convertNodeIdToIdentifier(nodeId);
+ }
+
+ public Map getInfo() throws RepositoryException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public String getPath() throws RepositoryException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public String getUserData() throws RepositoryException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
Added: jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestAll.java?rev=922398&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestAll.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestAll.java Fri Mar 12 19:13:39 2010
@@ -0,0 +1,44 @@
+/*
+ * 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.j3;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class TestAll {
+
+ /**
+ * Returns a <code>Test</code> suite that executes all tests inside this
+ * package.
+ *
+ * @return a <code>Test</code> suite that executes all tests inside this
+ * package.
+ */
+ public static Test suite() {
+ TestSuite suite = new TestSuite("org.apache.jackrabbit.j3");
+
+ suite.addTestSuite(TestBundle.class);
+
+ for (int i=0; i<2; i++) {
+ suite.addTestSuite(TestConcurrentWrite.class);
+ suite.addTestSuite(TestSimple.class);
+ suite.addTestSuite(TestNextConfiguration.class);
+ }
+
+ return suite;
+ }
+}
Added: jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestBase.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestBase.java?rev=922398&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestBase.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestBase.java Fri Mar 12 19:13:39 2010
@@ -0,0 +1,60 @@
+/*
+ * 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.j3;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.jcr.LoginException;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.RepositoryFactory;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import junit.framework.TestCase;
+
+public class TestBase extends TestCase {
+
+ protected static int configurationId;
+
+ private Repository repository;
+ protected Session session;
+ private static final String[] URL = new String[] {
+ "mem:",
+ "jdbc:h2:mem:test"
+ };
+
+ public void setUp() throws Exception {
+ String factoryClass = "org.apache.jackrabbit.j3.RepositoryFactoryImpl";
+ String url = URL[configurationId];
+ RepositoryFactory factory = (RepositoryFactory) Class.forName(factoryClass).newInstance();
+ Map<String, String> parameters = new HashMap<String, String>();
+ parameters.put("url", url);
+ repository = factory.getRepository(parameters);
+
+ session = openSession();
+ }
+
+ public void tearDown() throws Exception {
+ session.logout();
+ }
+
+ protected Session openSession() throws LoginException, RepositoryException {
+ SimpleCredentials credentials = new SimpleCredentials("sa", "sa".toCharArray());
+ return repository.login(credentials);
+ }
+
+}
Added: jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestBundle.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestBundle.java?rev=922398&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestBundle.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestBundle.java Fri Mar 12 19:13:39 2010
@@ -0,0 +1,97 @@
+/*
+ * 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.j3;
+
+import javax.jcr.PropertyType;
+import junit.framework.TestCase;
+import org.apache.jackrabbit.j3.mc.Bundle;
+import org.apache.jackrabbit.j3.mc.Val;
+
+public class TestBundle extends TestCase {
+
+ public void testBundle() {
+ Bundle bundle = Bundle.create(512);
+ bundle.writeVal(Val.get("Hello")).writeVal(Val.get("World"));
+ assertEquals(12, bundle.length());
+ bundle.reset();
+ assertEquals("Hello", bundle.readVal().getString());
+ assertEquals("World", bundle.readVal().getString());
+ testLength(Val.TRUE);
+ testLength(Val.get(false));
+ testLength(Val.get(true));
+ testLength(Val.get(5));
+ testLength(Val.get(10));
+ testLength(Val.get(10000));
+ testLength(Val.get(100000000));
+ testLength(Val.get(10000000000L));
+ testLength(Val.get(1000000000000L));
+ testLength(Val.get(-100));
+ testLength(Val.get(""));
+ testLength(Val.get("unstructured"));
+ testLength(Val.get("lastModifiedBy"));
+ testLength(Val.get("http://www.jcp.org/jcr/mix/1.0"));
+ testLength(Val.get(0.0));
+ testLength(Val.get(1.0));
+ testLength(Val.get(12.0));
+ testLength(Val.get(123.0));
+ testLength(Val.get(1234.0));
+ testLength(Val.get(-1.0));
+ testLength(Val.get(3.1415));
+ testLength(Val.get(new Val[]{Val.get("multi"), Val.get("valued")}));
+ testLength(Val.get(new Val[]{}));
+ testLength(Val.get(new byte[10]));
+ testLength(Val.get(PropertyType.DATE, "2001-01-02"));
+ testLength(Val.get(PropertyType.DECIMAL, "10.00"));
+ testLength(Val.get(PropertyType.NAME, "xyz"));
+ testLength(Val.get(PropertyType.PATH, ""));
+ testLength(Val.get(PropertyType.PATH, "/xyz/abc"));
+ testLength(Val.get(PropertyType.REFERENCE, "abc:def"));
+ testLength(Val.get(PropertyType.WEAKREFERENCE, "abc:def"));
+ testLength(Val.get(PropertyType.BINARY, "0x1234"));
+ testLength(Val.get("long string with strange characters äöü \u1234"));
+ testLength(Val.get(new byte[1024]));
+ testLength(Val.get(new byte[1024 * 1024]));
+ testLength(true, Val.get(new Val[]{Val.get("Hello World 1"), Val.get("Hello World 2"), Val.get("Hello World 3")}));
+ testLength(true, Val.get(new Val[]{Val.get("Hello World 1"), Val.get("Hello World 1"), Val.get("Hello World 1")}));
+ }
+
+ static void testLength(Val v) {
+ testLength(false, v);
+ }
+
+ static void testLength(boolean allowSmaller, Val v) {
+ Bundle bundle = Bundle.create(512);
+ int len = bundle.writeVal(v).length();
+ // System.out.println("length: " + len + ": " + v);
+ bundle.reset();
+ Val v2 = bundle.readVal();
+ if (allowSmaller) {
+ if (len > bundle.getValLen(v)) {
+ throw new AssertionError();
+ }
+ } else {
+ if (len != bundle.getValLen(v)) {
+ throw new AssertionError();
+ }
+ }
+ if (v2.hashCode() != v.hashCode() || !v2.equals(v)) {
+ throw new AssertionError();
+ }
+ }
+
+}
+
Added: jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestConcurrentWrite.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestConcurrentWrite.java?rev=922398&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestConcurrentWrite.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestConcurrentWrite.java Fri Mar 12 19:13:39 2010
@@ -0,0 +1,92 @@
+/*
+ * 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.j3;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+public class TestConcurrentWrite extends TestBase {
+
+ private String parentUUID;
+ private boolean stop;
+
+ public void test() throws Exception {
+
+ Node n = session.getRootNode().addNode("testParent");
+ parentUUID = n.getIdentifier();
+
+ Node node = session.getNodeByIdentifier(parentUUID);
+ node.addNode(UUID.randomUUID().toString());
+ session.save();
+
+ Session s2 = openSession();
+ Node n2 = s2.getNodeByIdentifier(parentUUID);
+ assertEquals("testParent", n2.getName());
+ s2.logout();
+
+ }
+
+ public void tearDown() throws Exception {
+ session.save();
+ session.logout();
+ }
+
+
+
+ public void testConcurrency() throws Exception {
+ int threadCount = 20;
+ final List<Exception> exceptions = new ArrayList<Exception>();
+ final CountDownLatch latch = new CountDownLatch(threadCount);
+ for (int i = 0; i < threadCount; i++) {
+ Thread thread = new Thread() {
+ public void run() {
+ try {
+ while (stop) {
+ Session session = openSession();
+ try {
+ Node node = session.getNodeByIdentifier(parentUUID);
+ node.addNode(UUID.randomUUID().toString());
+ session.save();
+ } finally {
+ session.logout();
+ }
+ }
+ } catch (RepositoryException e) {
+ exceptions.add(e);
+ stop = true;
+ }
+ latch.countDown();
+ }
+
+ };
+ thread.start();
+ }
+ latch.await(10, TimeUnit.SECONDS);
+ stop = true;
+ for (Exception e : exceptions) {
+ e.printStackTrace();
+ }
+ assertEquals(0, exceptions.size());
+ }
+
+}
\ No newline at end of file
Added: jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestNextConfiguration.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestNextConfiguration.java?rev=922398&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestNextConfiguration.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestNextConfiguration.java Fri Mar 12 19:13:39 2010
@@ -0,0 +1,9 @@
+package org.apache.jackrabbit.j3;
+
+public class TestNextConfiguration extends TestBase {
+
+ public void testChange() {
+ configurationId++;
+ }
+
+}
Added: jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestSimple.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestSimple.java?rev=922398&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestSimple.java (added)
+++ jackrabbit/sandbox/jackrabbit-j3/src/test/java/org/apache/jackrabbit/j3/TestSimple.java Fri Mar 12 19:13:39 2010
@@ -0,0 +1,47 @@
+/*
+ * 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.j3;
+
+import javax.jcr.Node;
+import javax.jcr.Session;
+
+public class TestSimple extends TestBase {
+
+ public void test() throws Exception {
+
+ Session session = openSession();
+ Node root = session.getRootNode();
+ if (root.hasNode("test")) {
+ root.getNode("test").remove();
+ session.save();
+ }
+ Node test = root.addNode("test");
+ test.setProperty("name", "Hello");
+ session.save();
+ assertEquals("Hello", test.getProperty("name").getValue().getString());
+
+ Session session2 = openSession();
+ Node root2 = session2.getRootNode();
+ Node test2 = root2.getNode("test");
+ assertEquals("Hello", test2.getProperty("name").getValue().getString());
+ assertEquals("/test", test.getPath());
+ assertEquals("/test", test2.getPath());
+ session2.logout();
+ session.logout();
+
+ }
+}
|