DNA SVN: r765 - trunk/dna-common/src/main/java/org/jboss/dna/common/util.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-03-10 12:18:31 -0400 (Tue, 10 Mar 2009)
New Revision: 765
Modified:
trunk/dna-common/src/main/java/org/jboss/dna/common/util/Base64.java
Log:
Cleaned up the Base64 code to eliminate many warnings, fix some coding errors, and improve error handling.
Modified: trunk/dna-common/src/main/java/org/jboss/dna/common/util/Base64.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/util/Base64.java 2009-03-10 15:17:23 UTC (rev 764)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/util/Base64.java 2009-03-10 16:18:31 UTC (rev 765)
@@ -23,7 +23,17 @@
*/
package org.jboss.dna.common.util;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.util.zip.GZIPInputStream;
+import org.jboss.dna.common.SystemFailureException;
/**
* <p>
@@ -318,7 +328,7 @@
else if ((options & ORDERED) == ORDERED) return _ORDERED_ALPHABET;
else return _STANDARD_ALPHABET;
- } // end getAlphabet
+ }
/**
* Returns one of the _SOMETHING_DECODABET byte arrays depending on the options specified. It's possible, though silly, to
@@ -328,12 +338,12 @@
* @param options The options to use in this operation
* @return the appropriate decodabets
*/
- private final static byte[] getDecodabet( int options ) {
+ protected final static byte[] getDecodabet( int options ) {
if ((options & URL_SAFE) == URL_SAFE) return _URL_SAFE_DECODABET;
else if ((options & ORDERED) == ORDERED) return _ORDERED_DECODABET;
else return _STANDARD_DECODABET;
- } // end getAlphabet
+ }
/** Defeats instantiation. */
private Base64() {
@@ -351,15 +361,14 @@
* @param numSigBytes the number of significant bytes in your array
* @param options The options to use in this operation
* @return four byte array in Base64 notation.
- * @since 1.5.1
*/
- private static byte[] encode3to4( byte[] b4,
- byte[] threeBytes,
- int numSigBytes,
- int options ) {
+ protected static byte[] encode3to4( byte[] b4,
+ byte[] threeBytes,
+ int numSigBytes,
+ int options ) {
encode3to4(threeBytes, 0, numSigBytes, b4, 0, options);
return b4;
- } // end encode3to4
+ }
/**
* <p>
@@ -380,14 +389,13 @@
* @param destOffset the index where output will be put
* @param options The options to use in this operation
* @return the <var>destination</var> array
- * @since 1.3
*/
- private static byte[] encode3to4( byte[] source,
- int srcOffset,
- int numSigBytes,
- byte[] destination,
- int destOffset,
- int options ) {
+ protected static byte[] encode3to4( byte[] source,
+ int srcOffset,
+ int numSigBytes,
+ byte[] destination,
+ int destOffset,
+ int options ) {
byte[] ALPHABET = getAlphabet(options);
// 1 2 3
@@ -429,8 +437,8 @@
default:
return destination;
- } // end switch
- } // end encode3to4
+ }
+ }
/**
* Serializes an object and returns the Base64-encoded version of that serialized object. If the object cannot be serialized
@@ -438,11 +446,11 @@
*
* @param serializableObject The object to encode
* @return The Base64-encoded object
- * @since 1.4
+ * @throws IOException if there is an IOException while serializing
*/
- public static String encodeObject( java.io.Serializable serializableObject ) {
+ public static String encodeObject( java.io.Serializable serializableObject ) throws IOException {
return encodeObject(serializableObject, NO_OPTIONS);
- } // end encodeObject
+ }
/**
* Serializes an object and returns the Base64-encoded version of that serialized object. If the object cannot be serialized
@@ -465,77 +473,60 @@
* @return The Base64-encoded object
* @see Base64#GZIP
* @see Base64#DONT_BREAK_LINES
- * @since 2.0
+ * @throws IOException if there is an IOException while serializing
*/
public static String encodeObject( java.io.Serializable serializableObject,
- int options ) {
- // Streams
- java.io.ByteArrayOutputStream baos = null;
- java.io.OutputStream b64os = null;
+ int options ) throws IOException {
+ // ObjectOutputStream -> (GZIP) -> Base64 -> ByteArrayOutputStream
+ java.io.ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ java.io.OutputStream b64os = new Base64.OutputStream(baos, ENCODE | options);
java.io.ObjectOutputStream oos = null;
java.util.zip.GZIPOutputStream gzos = null;
// Isolate options
int gzip = (options & GZIP);
- int dontBreakLines = (options & DONT_BREAK_LINES);
-
+ boolean error = false;
try {
- // ObjectOutputStream -> (GZIP) -> Base64 -> ByteArrayOutputStream
- baos = new java.io.ByteArrayOutputStream();
- b64os = new Base64.OutputStream(baos, ENCODE | options);
-
// GZip?
if (gzip == GZIP) {
gzos = new java.util.zip.GZIPOutputStream(b64os);
oos = new java.io.ObjectOutputStream(gzos);
- } // end if: gzip
- else oos = new java.io.ObjectOutputStream(b64os);
+ } else {
+ oos = new java.io.ObjectOutputStream(b64os);
+ }
oos.writeObject(serializableObject);
- } // end try
- catch (IOException e) {
- e.printStackTrace();
- return null;
- } // end catch
- finally {
- try {
- oos.close();
- } catch (Exception e) {
+ } catch (IOException e) {
+ error = true;
+ throw e;
+ } finally {
+ if (oos != null) {
+ try {
+ oos.close();
+ } catch (IOException e) {
+ if (!error) throw e;
+ }
}
- try {
- gzos.close();
- } catch (Exception e) {
- }
- try {
- b64os.close();
- } catch (Exception e) {
- }
- try {
- baos.close();
- } catch (Exception e) {
- }
- } // end finally
+ }
// Return value according to relevant encoding.
try {
return new String(baos.toByteArray(), PREFERRED_ENCODING);
- } // end try
- catch (java.io.UnsupportedEncodingException uue) {
+ } catch (java.io.UnsupportedEncodingException uue) {
return new String(baos.toByteArray());
- } // end catch
+ }
- } // end encode
+ }
/**
* Encodes a byte array into Base64 notation. Does not GZip-compress data.
*
* @param source The data to convert
* @return the encoded bytes
- * @since 1.4
*/
public static String encodeBytes( byte[] source ) {
return encodeBytes(source, 0, source.length, NO_OPTIONS);
- } // end encodeBytes
+ }
/**
* Encodes a byte array into Base64 notation.
@@ -557,12 +548,11 @@
* @return the encoded bytes
* @see Base64#GZIP
* @see Base64#DONT_BREAK_LINES
- * @since 2.0
*/
public static String encodeBytes( byte[] source,
int options ) {
return encodeBytes(source, 0, source.length, options);
- } // end encodeBytes
+ }
/**
* Encodes a byte array into Base64 notation. Does not GZip-compress data.
@@ -571,13 +561,12 @@
* @param off Offset in array where conversion should begin
* @param len Length of data
* @return the encoded bytes
- * @since 1.4
*/
public static String encodeBytes( byte[] source,
int off,
int len ) {
return encodeBytes(source, off, len, NO_OPTIONS);
- } // end encodeBytes
+ }
/**
* Encodes a byte array into Base64 notation.
@@ -601,7 +590,6 @@
* @return the encoded bytes
* @see Base64#GZIP
* @see Base64#DONT_BREAK_LINES
- * @since 2.0
*/
public static String encodeBytes( byte[] source,
int off,
@@ -613,88 +601,76 @@
// Compress?
if (gzip == GZIP) {
- java.io.ByteArrayOutputStream baos = null;
+ // GZip -> Base64 -> ByteArray
+ java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
+ Base64.OutputStream b64os = new Base64.OutputStream(baos, ENCODE | options);
java.util.zip.GZIPOutputStream gzos = null;
- Base64.OutputStream b64os = null;
+ boolean error = false;
try {
- // GZip -> Base64 -> ByteArray
- baos = new java.io.ByteArrayOutputStream();
- b64os = new Base64.OutputStream(baos, ENCODE | options);
gzos = new java.util.zip.GZIPOutputStream(b64os);
gzos.write(source, off, len);
gzos.close();
- } // end try
- catch (IOException e) {
- e.printStackTrace();
- return null;
- } // end catch
- finally {
- try {
- gzos.close();
- } catch (Exception e) {
+ } catch (IOException e) {
+ error = true;
+ throw new SystemFailureException(e); // error using reading from byte array!
+ } finally {
+ if (gzos != null) {
+ try {
+ gzos.close();
+ } catch (IOException e) {
+ if (!error) new SystemFailureException(e); // error closing streams over byte array!
+ }
}
- try {
- b64os.close();
- } catch (Exception e) {
- }
- try {
- baos.close();
- } catch (Exception e) {
- }
- } // end finally
+ }
// Return value according to relevant encoding.
try {
return new String(baos.toByteArray(), PREFERRED_ENCODING);
- } // end try
- catch (java.io.UnsupportedEncodingException uue) {
+ } catch (java.io.UnsupportedEncodingException uue) {
return new String(baos.toByteArray());
- } // end catch
- } // end if: compress
+ }
+ }
- // Else, don't compress. Better not to use streams at all then.
- else {
- // Convert option to boolean in way that code likes it.
- boolean breakLines = dontBreakLines == 0;
+ // Otherwise, don't compress. Better not to use streams at all then.
+ // Convert option to boolean in way that code likes it.
+ boolean breakLines = dontBreakLines == 0;
- int len43 = len * 4 / 3;
- byte[] outBuff = new byte[(len43) // Main 4:3
- + ((len % 3) > 0 ? 4 : 0) // Account for padding
- + (breakLines ? (len43 / MAX_LINE_LENGTH) : 0)]; // New lines
- int d = 0;
- int e = 0;
- int len2 = len - 2;
- int lineLength = 0;
- for (; d < len2; d += 3, e += 4) {
- encode3to4(source, d + off, 3, outBuff, e, options);
+ int len43 = len * 4 / 3;
+ byte[] outBuff = new byte[(len43) // Main 4:3
+ + ((len % 3) > 0 ? 4 : 0) // Account for padding
+ + (breakLines ? (len43 / MAX_LINE_LENGTH) : 0)]; // New lines
+ int d = 0;
+ int e = 0;
+ int len2 = len - 2;
+ int lineLength = 0;
+ for (; d < len2; d += 3, e += 4) {
+ encode3to4(source, d + off, 3, outBuff, e, options);
- lineLength += 4;
- if (breakLines && lineLength == MAX_LINE_LENGTH) {
- outBuff[e + 4] = NEW_LINE;
- e++;
- lineLength = 0;
- } // end if: end of line
- } // en dfor: each piece of array
+ lineLength += 4;
+ if (breakLines && lineLength == MAX_LINE_LENGTH) {
+ outBuff[e + 4] = NEW_LINE;
+ e++;
+ lineLength = 0;
+ }
+ }
- if (d < len) {
- encode3to4(source, d + off, len - d, outBuff, e, options);
- e += 4;
- } // end if: some padding needed
+ if (d < len) {
+ // Padding is needed
+ encode3to4(source, d + off, len - d, outBuff, e, options);
+ e += 4;
+ }
- // Return value according to relevant encoding.
- try {
- return new String(outBuff, 0, e, PREFERRED_ENCODING);
- } // end try
- catch (java.io.UnsupportedEncodingException uue) {
- return new String(outBuff, 0, e);
- } // end catch
+ // Return value according to relevant encoding.
+ try {
+ return new String(outBuff, 0, e, PREFERRED_ENCODING);
+ } catch (java.io.UnsupportedEncodingException uue) {
+ return new String(outBuff, 0, e);
+ }
- } // end else: don't compress
+ }
- } // end encodeBytes
-
/* ******** D E C O D I N G M E T H O D S ******** */
/**
@@ -713,13 +689,12 @@
* @param destOffset the index where output will be put
* @param options alphabet type is pulled from this (standard, url-safe, ordered)
* @return the number of decoded bytes converted
- * @since 1.3
*/
- private static int decode4to3( byte[] source,
- int srcOffset,
- byte[] destination,
- int destOffset,
- int options ) {
+ protected static int decode4to3( byte[] source,
+ int srcOffset,
+ byte[] destination,
+ int destOffset,
+ int options ) {
byte[] DECODABET = getDecodabet(options);
// Example: Dk==
@@ -764,14 +739,15 @@
return 3;
} catch (Exception e) {
- System.out.println("" + source[srcOffset] + ": " + (DECODABET[source[srcOffset]]));
- System.out.println("" + source[srcOffset + 1] + ": " + (DECODABET[source[srcOffset + 1]]));
- System.out.println("" + source[srcOffset + 2] + ": " + (DECODABET[source[srcOffset + 2]]));
- System.out.println("" + source[srcOffset + 3] + ": " + (DECODABET[source[srcOffset + 3]]));
- return -1;
- } // end catch
+ StringBuilder sb = new StringBuilder();
+ sb.append("" + source[srcOffset] + ": " + (DECODABET[source[srcOffset]]) + "\n");
+ sb.append("" + source[srcOffset + 1] + ": " + (DECODABET[source[srcOffset + 1]]) + "\n");
+ sb.append("" + source[srcOffset + 2] + ": " + (DECODABET[source[srcOffset + 2]]) + "\n");
+ sb.append("" + source[srcOffset + 3] + ": " + (DECODABET[source[srcOffset + 3]]) + "\n");
+ throw new SystemFailureException(sb.toString(), e);
+ }
}
- } // end decodeToBytes
+ }
/**
* Very low-level access to decoding ASCII characters in the form of a byte array. Does not support automatically gunzipping
@@ -782,7 +758,6 @@
* @param len The length of characters to decode
* @param options The options to use in this operation
* @return decoded data
- * @since 1.3
*/
public static byte[] decode( byte[] source,
int off,
@@ -803,38 +778,37 @@
sbiCrop = (byte)(source[i] & 0x7f); // Only the low seven bits
sbiDecode = DECODABET[sbiCrop];
- if (sbiDecode >= WHITE_SPACE_ENC) // White space, Equals sign or better
- {
+ if (sbiDecode >= WHITE_SPACE_ENC) {
+ // White space, Equals sign or better
if (sbiDecode >= EQUALS_SIGN_ENC) {
+ // Equal sign or better
b4[b4Posn++] = sbiCrop;
if (b4Posn > 3) {
+ // build a quartet
outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn, options);
b4Posn = 0;
// If that was the equals sign, break out of 'for' loop
if (sbiCrop == EQUALS_SIGN) break;
- } // end if: quartet built
+ }
- } // end if: equals sign or better
+ }
- } // end if: white space, equals sign or better
- else {
- System.err.println("Bad Base64 input character at " + i + ": " + source[i] + "(decimal)");
- return null;
- } // end else:
- } // each input character
+ } else {
+ throw new SystemFailureException("Bad Base64 input character at " + i + ": " + source[i] + "(decimal)");
+ }
+ }
byte[] out = new byte[outBuffPosn];
System.arraycopy(outBuff, 0, out, 0, outBuffPosn);
return out;
- } // end decode
+ }
/**
* Decodes data from Base64 notation, automatically detecting gzip-compressed data and decompressing it.
*
* @param s the string to decode
* @return the decoded data
- * @since 1.4
*/
public static byte[] decode( String s ) {
return decode(s, NO_OPTIONS);
@@ -846,18 +820,15 @@
* @param s the string to decode
* @param options encode options such as URL_SAFE
* @return the decoded data
- * @since 1.4
*/
public static byte[] decode( String s,
int options ) {
byte[] bytes;
try {
bytes = s.getBytes(PREFERRED_ENCODING);
- } // end try
- catch (java.io.UnsupportedEncodingException uee) {
+ } catch (java.io.UnsupportedEncodingException uee) {
bytes = s.getBytes();
- } // end catch
- // </change>
+ }
// Decode
bytes = decode(bytes, 0, bytes.length, options);
@@ -866,93 +837,86 @@
// GZIP Magic Two-Byte Number: 0x8b1f (35615)
if (bytes != null && bytes.length >= 4) {
- int head = ((int)bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00);
- if (java.util.zip.GZIPInputStream.GZIP_MAGIC == head) {
- java.io.ByteArrayInputStream bais = null;
- java.util.zip.GZIPInputStream gzis = null;
- java.io.ByteArrayOutputStream baos = null;
+ int head = (bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00);
+ if (GZIPInputStream.GZIP_MAGIC == head) {
+ ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+ GZIPInputStream gzis = null;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[2048];
int length = 0;
try {
- baos = new java.io.ByteArrayOutputStream();
- bais = new java.io.ByteArrayInputStream(bytes);
gzis = new java.util.zip.GZIPInputStream(bais);
-
while ((length = gzis.read(buffer)) >= 0) {
baos.write(buffer, 0, length);
- } // end while: reading input
+ }
// No error? Get new bytes.
bytes = baos.toByteArray();
- } // end try
- catch (IOException e) {
+ } catch (IOException e) {
// Just return originally-decoded bytes
} // end catch
finally {
+ boolean error = false;
try {
- baos.close();
- } catch (Exception e) {
+ if (gzis != null) {
+ try {
+ gzis.close();
+ } catch (IOException e) {
+ throw new SystemFailureException(e); // bad problems with JRE if this doesn't work
+ }
+ }
+ } finally {
+ try {
+ bais.close();
+ } catch (Exception e) {
+ if (!error) throw new SystemFailureException(e); // bad problems with JRE if this doesn't work
+ }
}
- try {
- gzis.close();
- } catch (Exception e) {
- }
- try {
- bais.close();
- } catch (Exception e) {
- }
- } // end finally
+ }
- } // end if: gzipped
- } // end if: bytes.length >= 2
+ }
+ }
return bytes;
- } // end decode
+ }
/**
* Attempts to decode Base64 data and deserialize a Java Object within. Returns <tt>null</tt> if there was an error.
*
* @param encodedObject The Base64 data to decode
* @return The decoded and deserialized object
- * @since 1.5
+ * @throws IOException if there is an error deserializing the encoded object
+ * @throws ClassNotFoundException if the class for the deserialized object could not be found
*/
- public static Object decodeToObject( String encodedObject ) {
+ public static Object decodeToObject( String encodedObject ) throws IOException, ClassNotFoundException {
// Decode and gunzip if necessary
byte[] objBytes = decode(encodedObject);
- java.io.ByteArrayInputStream bais = null;
- java.io.ObjectInputStream ois = null;
+ ByteArrayInputStream bais = new ByteArrayInputStream(objBytes);
+ ObjectInputStream ois = new ObjectInputStream(bais);
Object obj = null;
+ boolean error = false;
try {
- bais = new java.io.ByteArrayInputStream(objBytes);
- ois = new java.io.ObjectInputStream(bais);
-
obj = ois.readObject();
- } // end try
- catch (IOException e) {
- e.printStackTrace();
- obj = null;
- } // end catch
- catch (java.lang.ClassNotFoundException e) {
- e.printStackTrace();
- obj = null;
- } // end catch
- finally {
+ } catch (IOException e) {
+ error = true;
+ throw e;
+ } catch (java.lang.ClassNotFoundException e) {
+ error = true;
+ throw e;
+ } finally {
try {
- bais.close();
- } catch (Exception e) {
- }
- try {
ois.close();
- } catch (Exception e) {
+ } catch (IOException e) {
+ if (!error) throw e;
}
- } // end finally
+ }
return obj;
- } // end decodeObject
+ }
/**
* Convenience method for encoding data to a file.
@@ -960,227 +924,212 @@
* @param dataToEncode byte array of data to encode in base64 form
* @param filename Filename for saving encoded data
* @return <tt>true</tt> if successful, <tt>false</tt> otherwise
- * @since 2.1
+ * @throws IOException if there is a problem writing to the file
*/
public static boolean encodeToFile( byte[] dataToEncode,
- String filename ) {
- boolean success = false;
- Base64.OutputStream bos = null;
+ String filename ) throws IOException {
+ boolean error = false;
+ Base64.OutputStream bos = new Base64.OutputStream(new java.io.FileOutputStream(filename), Base64.ENCODE);
+
try {
- bos = new Base64.OutputStream(new java.io.FileOutputStream(filename), Base64.ENCODE);
bos.write(dataToEncode);
- success = true;
- } // end try
- catch (IOException e) {
-
- success = false;
- } // end catch: IOException
- finally {
+ return true;
+ } catch (IOException e) {
+ error = true;
+ throw e;
+ } finally {
try {
bos.close();
- } catch (Exception e) {
+ } catch (IOException e) {
+ if (!error) throw e;
}
- } // end finally
+ }
+ }
- return success;
- } // end encodeToFile
-
/**
* Convenience method for decoding data to a file.
*
* @param dataToDecode Base64-encoded data as a string
* @param filename Filename for saving decoded data
* @return <tt>true</tt> if successful, <tt>false</tt> otherwise
- * @since 2.1
+ * @throws IOException if there is a problem writing to the file
*/
public static boolean decodeToFile( String dataToDecode,
- String filename ) {
- boolean success = false;
- Base64.OutputStream bos = null;
+ String filename ) throws IOException {
+ boolean error = false;
+ Base64.OutputStream bos = new Base64.OutputStream(new FileOutputStream(filename), Base64.DECODE);
try {
- bos = new Base64.OutputStream(new java.io.FileOutputStream(filename), Base64.DECODE);
bos.write(dataToDecode.getBytes(PREFERRED_ENCODING));
- success = true;
- } // end try
- catch (IOException e) {
- success = false;
- } // end catch: IOException
- finally {
+ return true;
+ } catch (IOException e) {
+ error = true;
+ throw e;
+ } finally {
try {
bos.close();
- } catch (Exception e) {
+ } catch (IOException e) {
+ if (!error) throw e;
}
- } // end finally
+ }
+ }
- return success;
- } // end decodeToFile
-
/**
* Convenience method for reading a base64-encoded file and decoding it.
*
* @param filename Filename for reading encoded data
* @return decoded byte array or null if unsuccessful
- * @since 2.1
+ * @throws IOException if there is a problem reading from the file
*/
- public static byte[] decodeFromFile( String filename ) {
- byte[] decodedData = null;
- Base64.InputStream bis = null;
- try {
- // Set up some useful variables
- java.io.File file = new java.io.File(filename);
- byte[] buffer = null;
- int length = 0;
- int numBytes = 0;
+ public static byte[] decodeFromFile( String filename ) throws IOException {
+ // Set up some useful variables
+ byte[] buffer = null;
+ int length = 0;
+ int numBytes = 0;
- // Check for size of file
- if (file.length() > Integer.MAX_VALUE) {
- System.err.println("File is too big for this convenience method (" + file.length() + " bytes).");
- return null;
- } // end if: file too big for int index
+ File file = new File(filename);
+ Base64.InputStream bis = new Base64.InputStream(new BufferedInputStream(new FileInputStream(file)), Base64.DECODE);
+
+ boolean error = false;
+ try {
buffer = new byte[(int)file.length()];
- // Open a stream
- bis = new Base64.InputStream(new java.io.BufferedInputStream(new java.io.FileInputStream(file)), Base64.DECODE);
-
// Read until done
- while ((numBytes = bis.read(buffer, length, 4096)) >= 0)
+ while ((numBytes = bis.read(buffer, length, 4096)) >= 0) {
length += numBytes;
+ }
// Save in a variable to return
- decodedData = new byte[length];
+ byte[] decodedData = new byte[length];
System.arraycopy(buffer, 0, decodedData, 0, length);
-
- } // end try
- catch (IOException e) {
- System.err.println("Error decoding from file " + filename);
- } // end catch: IOException
- finally {
+ return decodedData;
+ } catch (IOException e) {
+ error = true;
+ throw e;
+ } finally {
try {
bis.close();
- } catch (Exception e) {
+ } catch (IOException e) {
+ if (!error) throw e;
}
- } // end finally
+ }
+ }
- return decodedData;
- } // end decodeFromFile
-
/**
* Convenience method for reading a binary file and base64-encoding it.
*
* @param filename Filename for reading binary data
* @return base64-encoded string or null if unsuccessful
- * @since 2.1
+ * @throws IOException if there is a problem reading from the file
*/
- public static String encodeFromFile( String filename ) {
- String encodedData = null;
- Base64.InputStream bis = null;
- try {
- // Set up some useful variables
- java.io.File file = new java.io.File(filename);
- byte[] buffer = new byte[Math.max((int)(file.length() * 1.4), 40)]; // Need max() for math on small files (v2.2.1)
- int length = 0;
- int numBytes = 0;
+ public static String encodeFromFile( String filename ) throws IOException {
+ File file = new File(filename);
+ Base64.InputStream bis = new Base64.InputStream(new BufferedInputStream(new FileInputStream(file)), Base64.ENCODE);
- // Open a stream
- bis = new Base64.InputStream(new java.io.BufferedInputStream(new java.io.FileInputStream(file)), Base64.ENCODE);
+ // Set up some useful variables
+ byte[] buffer = new byte[Math.max((int)(file.length() * 1.4), 40)]; // Need max() for math on small files (v2.2.1)
+ int length = 0;
+ int numBytes = 0;
+ boolean error = false;
+ try {
// Read until done
- while ((numBytes = bis.read(buffer, length, 4096)) >= 0)
+ while ((numBytes = bis.read(buffer, length, 4096)) >= 0) {
length += numBytes;
-
- // Save in a variable to return
- encodedData = new String(buffer, 0, length, Base64.PREFERRED_ENCODING);
-
- } // end try
- catch (IOException e) {
- System.err.println("Error encoding from file " + filename);
- } // end catch: IOException
- finally {
+ }
+ return new String(buffer, 0, length, Base64.PREFERRED_ENCODING);
+ } catch (IOException e) {
+ error = true;
+ throw e;
+ } finally {
try {
bis.close();
- } catch (Exception e) {
+ } catch (IOException e) {
+ if (!error) throw e;
}
- } // end finally
+ }
+ }
- return encodedData;
- } // end encodeFromFile
-
/**
* Reads <tt>infile</tt> and encodes it to <tt>outfile</tt>.
*
* @param infile Input file
* @param outfile Output file
* @return true if the operation is successful
- * @since 2.2
+ * @throws IOException if there is a problem reading or writing either file
*/
public static boolean encodeFileToFile( String infile,
- String outfile ) {
- boolean success = false;
- java.io.InputStream in = null;
- java.io.OutputStream out = null;
+ String outfile ) throws IOException {
+ InputStream in = new Base64.InputStream(new BufferedInputStream(new FileInputStream(infile)), Base64.ENCODE);
+ java.io.OutputStream out = new BufferedOutputStream(new FileOutputStream(outfile));
+
+ boolean error = false;
try {
- in = new Base64.InputStream(new java.io.BufferedInputStream(new java.io.FileInputStream(infile)), Base64.ENCODE);
- out = new java.io.BufferedOutputStream(new java.io.FileOutputStream(outfile));
byte[] buffer = new byte[65536]; // 64K
int read = -1;
while ((read = in.read(buffer)) >= 0) {
out.write(buffer, 0, read);
- } // end while: through file
- success = true;
- } catch (IOException exc) {
- exc.printStackTrace();
+ }
+ return true;
+ } catch (IOException e) {
+ error = true;
+ throw e;
} finally {
try {
- in.close();
- } catch (Exception exc) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ if (!error) throw e;
+ }
+ } finally {
+ try {
+ out.close();
+ } catch (IOException e) {
+ if (!error) throw e;
+ }
}
- try {
- out.close();
- } catch (Exception exc) {
- }
- } // end finally
+ }
+ }
- return success;
- } // end encodeFileToFile
-
/**
* Reads <tt>infile</tt> and decodes it to <tt>outfile</tt>.
*
* @param infile Input file
* @param outfile Output file
* @return true if the operation is successful
- * @since 2.2
+ * @throws IOException if there is a problem reading or writing either file
*/
public static boolean decodeFileToFile( String infile,
- String outfile ) {
- boolean success = false;
- java.io.InputStream in = null;
- java.io.OutputStream out = null;
+ String outfile ) throws IOException {
+ java.io.InputStream in = new Base64.InputStream(new BufferedInputStream(new FileInputStream(infile)), Base64.DECODE);
+ java.io.OutputStream out = new java.io.BufferedOutputStream(new FileOutputStream(outfile));
+ boolean error = false;
try {
- in = new Base64.InputStream(new java.io.BufferedInputStream(new java.io.FileInputStream(infile)), Base64.DECODE);
- out = new java.io.BufferedOutputStream(new java.io.FileOutputStream(outfile));
byte[] buffer = new byte[65536]; // 64K
int read = -1;
while ((read = in.read(buffer)) >= 0) {
out.write(buffer, 0, read);
- } // end while: through file
- success = true;
- } catch (IOException exc) {
- exc.printStackTrace();
+ }
+ return true;
+ } catch (IOException e) {
+ error = true;
+ throw e;
} finally {
try {
- in.close();
- } catch (Exception exc) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ if (!error) throw e;
+ }
+ } finally {
+ try {
+ out.close();
+ } catch (IOException e) {
+ if (!error) throw e;
+ }
}
- try {
- out.close();
- } catch (Exception exc) {
- }
- } // end finally
+ }
+ }
- return success;
- } // end decodeFileToFile
-
/* ******** I N N E R C L A S S I N P U T S T R E A M ******** */
/**
@@ -1188,7 +1137,6 @@
* encode/decode to/from Base64 notation on the fly.
*
* @see Base64
- * @since 1.3
*/
public static class InputStream extends java.io.FilterInputStream {
private boolean encode; // Encoding or decoding
@@ -1199,7 +1147,6 @@
private int lineLength;
private boolean breakLines; // Break lines at less than 80 characters
private int options; // Record options used to create the stream.
- private byte[] alphabet; // Local copies to avoid extra method calls
private byte[] decodabet; // Local copies to avoid extra method calls
/**
@@ -1210,7 +1157,7 @@
*/
public InputStream( java.io.InputStream in ) {
this(in, DECODE);
- } // end constructor
+ }
/**
* Constructs a {@link Base64.InputStream} in either ENCODE or DECODE mode.
@@ -1231,7 +1178,6 @@
* @see Base64#ENCODE
* @see Base64#DECODE
* @see Base64#DONT_BREAK_LINES
- * @since 2.0
*/
public InputStream( java.io.InputStream in,
int options ) {
@@ -1243,9 +1189,8 @@
this.position = -1;
this.lineLength = 0;
this.options = options; // Record for later, mostly to determine which alphabet to use
- this.alphabet = getAlphabet(options);
this.decodabet = getDecodabet(options);
- } // end constructor
+ }
/**
* Reads enough of the input stream to convert to/from Base64 and returns the next byte.
@@ -1269,25 +1214,21 @@
if (b >= 0) {
b3[i] = (byte)b;
numBinaryBytes++;
- } // end if: not end of stream
-
- } // end try: read
- catch (IOException e) {
+ }
+ } catch (IOException e) {
// Only a problem if we got no data at all.
if (i == 0) throw e;
-
- } // end catch
- } // end for: each needed input byte
-
+ }
+ }
if (numBinaryBytes > 0) {
+ // got data
encode3to4(b3, 0, numBinaryBytes, buffer, 0, options);
position = 0;
numSigBytes = 4;
- } // end if: got data
- else {
+ } else {
return -1;
- } // end else
- } // end if: encoding
+ }
+ }
// Else decoding
else {
@@ -1303,23 +1244,22 @@
if (b < 0) break; // Reads a -1 if end of stream
b4[i] = (byte)b;
- } // end for: each needed input byte
+ }
if (i == 4) {
+ // got four characters
numSigBytes = decode4to3(b4, 0, buffer, 0, options);
position = 0;
- } // end if: got four characters
- else if (i == 0) {
+ } else if (i == 0) {
+ // padded correctly
return -1;
- } // end else if: also padded correctly
- else {
+ } else {
// Must have broken out from above.
throw new IOException("Improperly padded Base64 input.");
- } // end
+ }
+ }
+ }
- } // end else: decode
- } // end else: get data
-
// Got data?
if (position >= 0) {
// End of relevant data?
@@ -1328,27 +1268,21 @@
if (encode && breakLines && lineLength >= MAX_LINE_LENGTH) {
lineLength = 0;
return '\n';
- } // end if
- else {
- lineLength++; // This isn't important when decoding
- // but throwing an extra "if" seems
- // just as wasteful.
+ }
+ lineLength++; // This isn't important when decoding
+ // but throwing an extra "if" seems
+ // just as wasteful.
- int b = buffer[position++];
+ int b = buffer[position++];
- if (position >= bufferLength) position = -1;
+ if (position >= bufferLength) position = -1;
- return b & 0xFF; // This is how you "cast" a byte that's
- // intended to be unsigned.
- } // end else
- } // end if: position >= 0
+ return b & 0xFF; // This is how you "cast" a byte that's intended to be unsigned.
+ }
- // Else error
- else {
- // When JDK1.4 is more accepted, use an assertion here.
- throw new IOException("Error in Base64 code reading stream.");
- } // end else
- } // end read
+ // When JDK1.4 is more accepted, use an assertion here.
+ throw new IOException("Error in Base64 code reading stream.");
+ }
/**
* Calls {@link #read()} repeatedly until the end of stream is reached or <var>len</var> bytes are read. Returns number of
@@ -1375,12 +1309,12 @@
if (b >= 0) dest[off + i] = (byte)b;
else if (i == 0) return -1;
- else break; // Out of 'for' loop
- } // end for: each byte read
+ else break;
+ }
return i;
- } // end read
+ }
- } // end inner class InputStream
+ }
/* ******** I N N E R C L A S S O U T P U T S T R E A M ******** */
@@ -1401,7 +1335,6 @@
private byte[] b4; // Scratch used in a few places
private boolean suspendEncoding;
private int options; // Record for later
- private byte[] alphabet; // Local copies to avoid extra method calls
private byte[] decodabet; // Local copies to avoid extra method calls
/**
@@ -1447,7 +1380,6 @@
this.suspendEncoding = false;
this.b4 = new byte[4];
this.options = options;
- this.alphabet = getAlphabet(options);
this.decodabet = getDecodabet(options);
} // end constructor
@@ -1465,7 +1397,7 @@
if (suspendEncoding) {
super.out.write(theByte);
return;
- } // end if: supsended
+ }
// Encode?
if (encode) {
@@ -1481,27 +1413,25 @@
} // end if: end of line
position = 0;
- } // end if: enough to output
- } // end if: encoding
+ }
+ }
// Else, Decoding
else {
// Meaningful Base64 character?
if (decodabet[theByte & 0x7f] > WHITE_SPACE_ENC) {
buffer[position++] = (byte)theByte;
- if (position >= bufferLength) // Enough to output.
- {
+ if (position >= bufferLength) { // Enough to output.
int len = Base64.decode4to3(buffer, 0, b4, 0, options);
out.write(b4, 0, len);
// out.write( Base64.decode4to3( buffer ) );
position = 0;
- } // end if: enough to output
- } // end if: meaningful base64 character
- else if (decodabet[theByte & 0x7f] != WHITE_SPACE_ENC) {
+ }
+ } else if (decodabet[theByte & 0x7f] != WHITE_SPACE_ENC) {
throw new IOException("Invalid character in Base64 data.");
- } // end else: not white space either
- } // end else: decoding
- } // end write
+ }
+ }
+ }
/**
* Calls {@link #write(int)} repeatedly until <var>len</var> bytes are written.
@@ -1520,14 +1450,13 @@
if (suspendEncoding) {
super.out.write(theBytes, off, len);
return;
- } // end if: supsended
+ }
for (int i = 0; i < len; i++) {
write(theBytes[off + i]);
- } // end for: each byte written
+ }
+ }
- } // end write
-
/**
* Method added by PHIL. [Thanks, PHIL. -Rob] This pads the buffer without closing the stream.
*
@@ -1538,14 +1467,12 @@
if (encode) {
out.write(encode3to4(b4, buffer, position, options));
position = 0;
- } // end if: encoding
- else {
+ } else {
throw new IOException("Base64 input not properly padded.");
- } // end else: decoding
- } // end if: buffer partially full
+ }
+ }
+ }
- } // end flush
-
/**
* Flushes and closes (I think, in the superclass) the stream.
*
@@ -1554,17 +1481,19 @@
*/
@Override
public void close() throws IOException {
- // 1. Ensure that pending characters are written
- flushBase64();
+ try {
+ // 1. Ensure that pending characters are written
+ flushBase64();
+ } finally {
+ // 2. Actually close the stream
+ // Base class both flushes and closes.
+ super.close();
- // 2. Actually close the stream
- // Base class both flushes and closes.
- super.close();
+ buffer = null;
+ out = null;
+ }
+ }
- buffer = null;
- out = null;
- } // end close
-
/**
* Suspends encoding of the stream. May be helpful if you need to embed a piece of base640-encoded data in a stream.
*
@@ -1574,7 +1503,7 @@
public void suspendEncoding() throws IOException {
flushBase64();
this.suspendEncoding = true;
- } // end suspendEncoding
+ }
/**
* Resumes encoding of the stream. May be helpful if you need to embed a piece of base640-encoded data in a stream.
@@ -1583,8 +1512,6 @@
*/
public void resumeEncoding() {
this.suspendEncoding = false;
- } // end resumeEncoding
-
- } // end inner class OutputStream
-
-} // end class Base64
+ }
+ }
+}
15 years, 1 month
DNA SVN: r764 - in trunk: dna-common/src/main/java/org/jboss/dna/common/util and 5 other directories.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-03-10 11:17:23 -0400 (Tue, 10 Mar 2009)
New Revision: 764
Added:
trunk/dna-common/src/main/java/org/jboss/dna/common/text/XmlValueEncoder.java
trunk/dna-common/src/test/java/org/jboss/dna/common/text/XmlValueEncoderTest.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrExporter.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrDocumentViewExporter.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSystemViewExporter.java
Modified:
trunk/dna-common/src/main/java/org/jboss/dna/common/util/Base64.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaBuiltinNodeTypeSource.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrI18n.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNamespaceRegistry.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeType.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
trunk/dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
trunk/dna-jcr/src/test/resources/repositoryJackrabbitTck.xml
Log:
DNA-295 TCK Tests for Session.export* Methods Fail
Applied the "DNA-295_final.patch" and "DNA-295_namespace2.patch" files, and cleaned up a few very minor things (like changed the repositoryJackrabbitTck.xml file to be more DRY by removing the "jcr:primaryTime" attributes since the importer looks at the element name for the primary type).
Added: trunk/dna-common/src/main/java/org/jboss/dna/common/text/XmlValueEncoder.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/text/XmlValueEncoder.java (rev 0)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/text/XmlValueEncoder.java 2009-03-10 15:17:23 UTC (rev 764)
@@ -0,0 +1,162 @@
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.common.text;
+
+import java.text.CharacterIterator;
+import java.text.StringCharacterIterator;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * An encoder useful for converting text to be used within XML attribute values.
+ * The following translations will be performed:
+ * <table cellspacing="0" cellpadding="1" border="1">
+ * <tr>
+ * <th>Raw (Unencoded)<br/>Character</th>
+ * <th>Translated (Encoded)<br/>Entity</th>
+ * </tr>
+ * <tr>
+ * <td> & </td>
+ * <td> &amp; </td>
+ * </tr>
+ * <tr>
+ * <td> < </td>
+ * <td> &lt; </td>
+ * </tr>
+ * <tr>
+ * <td> > </td>
+ * <td> &gt; </td>
+ * </tr>
+ * <tr>
+ * <td> " </td>
+ * <td> &quot; </td>
+ * </tr>
+ * <tr>
+ * <td> ' </td>
+ * <td> &#039; </td>
+ * </tr>
+ * <tr>
+ * <td>All Others</td>
+ * <td>No Translation</td>
+ * </tr>
+ * </table>
+ * </p>
+ */
+public class XmlValueEncoder implements TextEncoder, TextDecoder {
+
+ private static final Map<String, Character> SPECIAL_ENTITIES;
+
+ static {
+ SPECIAL_ENTITIES = new HashMap<String, Character>();
+
+ SPECIAL_ENTITIES.put("quot", '"');
+ SPECIAL_ENTITIES.put("gt", '>');
+ SPECIAL_ENTITIES.put("lt", '<');
+ SPECIAL_ENTITIES.put("amp", '&');
+
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.common.text.TextEncoder#encode(java.lang.String)
+ */
+ public String encode( String text ) {
+ if (text == null) return null;
+ StringBuilder sb = new StringBuilder();
+ CharacterIterator iter = new StringCharacterIterator(text);
+ for (char c = iter.first(); c != CharacterIterator.DONE; c = iter.next()) {
+ switch (c) {
+ case '&':
+ sb.append("&");
+ break;
+ case '"':
+ sb.append(""");
+ break;
+ case '<':
+ sb.append("<");
+ break;
+ case '>':
+ sb.append(">");
+ break;
+ case '\'':
+ sb.append("'");
+ break;
+ default:
+ sb.append(c);
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.common.text.TextDecoder#decode(java.lang.String)
+ */
+ public String decode( String encodedText ) {
+ if (encodedText == null) return null;
+ StringBuilder sb = new StringBuilder();
+ CharacterIterator iter = new StringCharacterIterator(encodedText);
+ for (char c = iter.first(); c != CharacterIterator.DONE; c = iter.next()) {
+ if (c == '&') {
+ int index = iter.getIndex();
+
+ do {
+ c = iter.next();
+ }
+ while (c != CharacterIterator.DONE && c != ';');
+
+ // We found a closing semicolon
+ if (c == ';') {
+ String s = encodedText.substring(index + 1, iter.getIndex());
+
+ if (SPECIAL_ENTITIES.containsKey(s)) {
+ sb.append(SPECIAL_ENTITIES.get(s));
+ continue;
+
+ }
+
+ if (s.length() > 0 && s.charAt(0) == '#') {
+ try {
+ sb.append((char) Short.parseShort(s.substring(1, s.length())));
+ continue;
+ }
+ catch (NumberFormatException nfe) {
+ // This is possible in malformed encodings, but let it fall through
+ }
+ }
+ }
+
+ // Malformed encoding, restore state and pass poorly encoded data back
+ c = '&';
+ iter.setIndex(index);
+ }
+
+ sb.append(c);
+
+ }
+ return sb.toString();
+ }
+}
Property changes on: trunk/dna-common/src/main/java/org/jboss/dna/common/text/XmlValueEncoder.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/dna-common/src/main/java/org/jboss/dna/common/util/Base64.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/util/Base64.java 2009-03-09 17:57:18 UTC (rev 763)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/util/Base64.java 2009-03-10 15:17:23 UTC (rev 764)
@@ -23,6 +23,8 @@
*/
package org.jboss.dna.common.util;
+import java.io.IOException;
+
/**
* <p>
* Encodes and decodes to and from Base64 notation.
@@ -93,6 +95,37 @@
*/
public class Base64 {
+ /* ******** P U B L I C F I E L D S ******** */
+
+ /** No options specified. Value is zero. */
+ public final static int NO_OPTIONS = 0;
+
+ /** Specify encoding. */
+ public final static int ENCODE = 1;
+
+ /** Specify decoding. */
+ public final static int DECODE = 0;
+
+ /** Specify that data should be gzip-compressed. */
+ public final static int GZIP = 2;
+
+ /** Don't break lines when encoding (violates strict Base64 specification) */
+ public final static int DONT_BREAK_LINES = 8;
+
+ /**
+ * Encode using Base64-like encoding that is URL- and Filename-safe as described in Section 4 of RFC3548: <a
+ * href="http://www.faqs.org/rfcs/rfc3548.html">http://www.faqs.org/rfcs/rfc3548.html</a>. It is important to note that data
+ * encoded this way is <em>not</em> officially valid Base64, or at the very least should not be called Base64 without also
+ * specifying that is was encoded using the URL- and Filename-safe dialect.
+ */
+ public final static int URL_SAFE = 16;
+
+ /**
+ * Encode using the special "ordered" dialect of Base64 described here: <a
+ * href="http://www.faqs.org/qa/rfcc-1940.html">http://www.faqs.org/qa/rfcc-1940.html</a>.
+ */
+ public final static int ORDERED = 32;
+
/* ******** P R I V A T E F I E L D S ******** */
/** Maximum line length (76) of Base64 output. */
@@ -107,12 +140,15 @@
/** Preferred encoding. */
private final static String PREFERRED_ENCODING = "UTF-8";
+ // I think I end up not using the BAD_ENCODING indicator.
+ // private final static byte BAD_ENCODING = -9; // Indicates error in encoding
private final static byte WHITE_SPACE_ENC = -5; // Indicates white space in encoding
private final static byte EQUALS_SIGN_ENC = -1; // Indicates equals sign in encoding
/* ******** S T A N D A R D B A S E 6 4 A L P H A B E T ******** */
/** The 64 valid Base64 values. */
+ // private final static byte[] ALPHABET;
/* Host platform me be something funny like EBCDIC, so we hardcode these values. */
private final static byte[] _STANDARD_ALPHABET = {(byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F',
(byte)'G', (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', (byte)'O', (byte)'P', (byte)'Q',
@@ -158,6 +194,147 @@
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
};
+ /* ******** U R L S A F E B A S E 6 4 A L P H A B E T ******** */
+
+ /**
+ * Used in the URL- and Filename-safe dialect described in Section 4 of RFC3548: <a
+ * href="http://www.faqs.org/rfcs/rfc3548.html">http://www.faqs.org/rfcs/rfc3548.html</a>. Notice that the last two bytes
+ * become "hyphen" and "underscore" instead of "plus" and "slash."
+ */
+ private final static byte[] _URL_SAFE_ALPHABET = {(byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F',
+ (byte)'G', (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', (byte)'O', (byte)'P', (byte)'Q',
+ (byte)'R', (byte)'S', (byte)'T', (byte)'U', (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', (byte)'a', (byte)'b',
+ (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m',
+ (byte)'n', (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', (byte)'v', (byte)'w', (byte)'x',
+ (byte)'y', (byte)'z', (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7', (byte)'8',
+ (byte)'9', (byte)'-', (byte)'_'};
+
+ /**
+ * Used in decoding URL- and Filename-safe dialects of Base64.
+ */
+ private final static byte[] _URL_SAFE_DECODABET = {-9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8
+ -5, -5, // Whitespace: Tab and Linefeed
+ -9, -9, // Decimal 11 - 12
+ -5, // Whitespace: Carriage Return
+ -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26
+ -9, -9, -9, -9, -9, // Decimal 27 - 31
+ -5, // Whitespace: Space
+ -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42
+ -9, // Plus sign at decimal 43
+ -9, // Decimal 44
+ 62, // Minus sign at decimal 45
+ -9, // Decimal 46
+ -9, // Slash at decimal 47
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine
+ -9, -9, -9, // Decimal 58 - 60
+ -1, // Equals sign at decimal 61
+ -9, -9, -9, // Decimal 62 - 64
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N'
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z'
+ -9, -9, -9, -9, // Decimal 91 - 94
+ 63, // Underscore at decimal 95
+ -9, // Decimal 96
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm'
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z'
+ -9, -9, -9, -9 // Decimal 123 - 126
+ /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
+ };
+
+ /* ******** O R D E R E D B A S E 6 4 A L P H A B E T ******** */
+
+ /**
+ * I don't get the point of this technique, but it is described here: <a
+ * href="http://www.faqs.org/qa/rfcc-1940.html">http://www.faqs.org/qa/rfcc-1940.html</a>.
+ */
+ private final static byte[] _ORDERED_ALPHABET = {(byte)'-', (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5',
+ (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
+ (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', (byte)'O', (byte)'P', (byte)'Q', (byte)'R',
+ (byte)'S', (byte)'T', (byte)'U', (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', (byte)'_', (byte)'a', (byte)'b',
+ (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m',
+ (byte)'n', (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', (byte)'v', (byte)'w', (byte)'x',
+ (byte)'y', (byte)'z'};
+
+ /**
+ * Used in decoding the "ordered" dialect of Base64.
+ */
+ private final static byte[] _ORDERED_DECODABET = {-9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8
+ -5, -5, // Whitespace: Tab and Linefeed
+ -9, -9, // Decimal 11 - 12
+ -5, // Whitespace: Carriage Return
+ -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26
+ -9, -9, -9, -9, -9, // Decimal 27 - 31
+ -5, // Whitespace: Space
+ -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42
+ -9, // Plus sign at decimal 43
+ -9, // Decimal 44
+ 0, // Minus sign at decimal 45
+ -9, // Decimal 46
+ -9, // Slash at decimal 47
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, // Numbers zero through nine
+ -9, -9, -9, // Decimal 58 - 60
+ -1, // Equals sign at decimal 61
+ -9, -9, -9, // Decimal 62 - 64
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, // Letters 'A' through 'M'
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, // Letters 'N' through 'Z'
+ -9, -9, -9, -9, // Decimal 91 - 94
+ 37, // Underscore at decimal 95
+ -9, // Decimal 96
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, // Letters 'a' through 'm'
+ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // Letters 'n' through 'z'
+ -9, -9, -9, -9 // Decimal 123 - 126
+ /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
+ };
+
+ /* ******** D E T E R M I N E W H I C H A L H A B E T ******** */
+
+ /**
+ * Returns one of the _SOMETHING_ALPHABET byte arrays depending on the options specified. It's possible, though silly, to
+ * specify ORDERED and URLSAFE in which case one of them will be picked, though there is no guarantee as to which one will be
+ * picked.
+ *
+ * @param options The options to use in this operation
+ * @return the appropriate alphabet
+ */
+ private final static byte[] getAlphabet( int options ) {
+ if ((options & URL_SAFE) == URL_SAFE) return _URL_SAFE_ALPHABET;
+ else if ((options & ORDERED) == ORDERED) return _ORDERED_ALPHABET;
+ else return _STANDARD_ALPHABET;
+
+ } // end getAlphabet
+
+ /**
+ * Returns one of the _SOMETHING_DECODABET byte arrays depending on the options specified. It's possible, though silly, to
+ * specify ORDERED and URL_SAFE in which case one of them will be picked, though there is no guarantee as to which one will be
+ * picked.
+ *
+ * @param options The options to use in this operation
+ * @return the appropriate decodabets
+ */
+ private final static byte[] getDecodabet( int options ) {
+ if ((options & URL_SAFE) == URL_SAFE) return _URL_SAFE_DECODABET;
+ else if ((options & ORDERED) == ORDERED) return _ORDERED_DECODABET;
+ else return _STANDARD_DECODABET;
+
+ } // end getAlphabet
+
/** Defeats instantiation. */
private Base64() {
}
@@ -165,6 +342,26 @@
/* ******** E N C O D I N G M E T H O D S ******** */
/**
+ * Encodes up to the first three bytes of array <var>threeBytes</var> and returns a four-byte array in Base64 notation. The
+ * actual number of significant bytes in your array is given by <var>numSigBytes</var>. The array <var>threeBytes</var> needs
+ * only be as big as <var>numSigBytes</var>. Code can reuse a byte array by passing a four-byte array as <var>b4</var>.
+ *
+ * @param b4 A reusable byte array to reduce array instantiation
+ * @param threeBytes the array to convert
+ * @param numSigBytes the number of significant bytes in your array
+ * @param options The options to use in this operation
+ * @return four byte array in Base64 notation.
+ * @since 1.5.1
+ */
+ private static byte[] encode3to4( byte[] b4,
+ byte[] threeBytes,
+ int numSigBytes,
+ int options ) {
+ encode3to4(threeBytes, 0, numSigBytes, b4, 0, options);
+ return b4;
+ } // end encode3to4
+
+ /**
* <p>
* Encodes up to three bytes of the array <var>source</var> and writes the resulting four Base64 bytes to
* <var>destination</var>. The source and destination arrays can be manipulated anywhere along their length by specifying
@@ -181,6 +378,7 @@
* @param numSigBytes the number of significant bytes in your array
* @param destination the array to hold the conversion
* @param destOffset the index where output will be put
+ * @param options The options to use in this operation
* @return the <var>destination</var> array
* @since 1.3
*/
@@ -188,8 +386,9 @@
int srcOffset,
int numSigBytes,
byte[] destination,
- int destOffset ) {
- byte[] ALPHABET = _STANDARD_ALPHABET;
+ int destOffset,
+ int options ) {
+ byte[] ALPHABET = getAlphabet(options);
// 1 2 3
// 01234567890123456789012345678901 Bit position
@@ -234,50 +433,268 @@
} // end encode3to4
/**
- * Encodes a byte array into Base64 notation. Does not GZip-compress data.
+ * Serializes an object and returns the Base64-encoded version of that serialized object. If the object cannot be serialized
+ * or there is another error, the method will return <tt>null</tt>. The object is not GZip-compressed before being encoded.
*
- * @param source The data to convert
- * @return the encoded data
+ * @param serializableObject The object to encode
+ * @return The Base64-encoded object
* @since 1.4
*/
- public static String encodeBytes( byte[] source ) {
- // Convert option to boolean in way that code likes it.
- boolean breakLines = false;
- int len = source.length;
- int len43 = len * 4 / 3;
- byte[] outBuff = new byte[(len43) // Main 4:3
- + ((len % 3) > 0 ? 4 : 0) // Account for padding
- + (breakLines ? (len43 / MAX_LINE_LENGTH) : 0)]; // New lines
- int d = 0;
- int e = 0;
- int len2 = len - 2;
- int lineLength = 0;
- for (; d < len2; d += 3, e += 4) {
- encode3to4(source, d, 3, outBuff, e);
+ public static String encodeObject( java.io.Serializable serializableObject ) {
+ return encodeObject(serializableObject, NO_OPTIONS);
+ } // end encodeObject
- lineLength += 4;
- if (breakLines && lineLength == MAX_LINE_LENGTH) {
- outBuff[e + 4] = NEW_LINE;
- e++;
- lineLength = 0;
- } // end if: end of line
- } // en dfor: each piece of array
+ /**
+ * Serializes an object and returns the Base64-encoded version of that serialized object. If the object cannot be serialized
+ * or there is another error, the method will return <tt>null</tt>.
+ * <p>
+ * Valid options:
+ *
+ * <pre>
+ * GZIP: gzip-compresses object before encoding it.
+ * DONT_BREAK_LINES: don't break lines at 76 characters
+ * <i>Note: Technically, this makes your encoding non-compliant.</i>
+ * </pre>
+ * <p>
+ * Example: <code>encodeObject( myObj, Base64.GZIP )</code> or
+ * <p>
+ * Example: <code>encodeObject( myObj, Base64.GZIP | Base64.DONT_BREAK_LINES )</code>
+ *
+ * @param serializableObject The object to encode
+ * @param options Specified options
+ * @return The Base64-encoded object
+ * @see Base64#GZIP
+ * @see Base64#DONT_BREAK_LINES
+ * @since 2.0
+ */
+ public static String encodeObject( java.io.Serializable serializableObject,
+ int options ) {
+ // Streams
+ java.io.ByteArrayOutputStream baos = null;
+ java.io.OutputStream b64os = null;
+ java.io.ObjectOutputStream oos = null;
+ java.util.zip.GZIPOutputStream gzos = null;
- if (d < len) {
- encode3to4(source, d, len - d, outBuff, e);
- e += 4;
- } // end if: some padding needed
+ // Isolate options
+ int gzip = (options & GZIP);
+ int dontBreakLines = (options & DONT_BREAK_LINES);
+ try {
+ // ObjectOutputStream -> (GZIP) -> Base64 -> ByteArrayOutputStream
+ baos = new java.io.ByteArrayOutputStream();
+ b64os = new Base64.OutputStream(baos, ENCODE | options);
+
+ // GZip?
+ if (gzip == GZIP) {
+ gzos = new java.util.zip.GZIPOutputStream(b64os);
+ oos = new java.io.ObjectOutputStream(gzos);
+ } // end if: gzip
+ else oos = new java.io.ObjectOutputStream(b64os);
+
+ oos.writeObject(serializableObject);
+ } // end try
+ catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ } // end catch
+ finally {
+ try {
+ oos.close();
+ } catch (Exception e) {
+ }
+ try {
+ gzos.close();
+ } catch (Exception e) {
+ }
+ try {
+ b64os.close();
+ } catch (Exception e) {
+ }
+ try {
+ baos.close();
+ } catch (Exception e) {
+ }
+ } // end finally
+
// Return value according to relevant encoding.
try {
- return new String(outBuff, 0, e, PREFERRED_ENCODING);
+ return new String(baos.toByteArray(), PREFERRED_ENCODING);
} // end try
catch (java.io.UnsupportedEncodingException uue) {
- return new String(outBuff, 0, e);
+ return new String(baos.toByteArray());
} // end catch
- } // end else: don't compress
+ } // end encode
+ /**
+ * Encodes a byte array into Base64 notation. Does not GZip-compress data.
+ *
+ * @param source The data to convert
+ * @return the encoded bytes
+ * @since 1.4
+ */
+ public static String encodeBytes( byte[] source ) {
+ return encodeBytes(source, 0, source.length, NO_OPTIONS);
+ } // end encodeBytes
+
+ /**
+ * Encodes a byte array into Base64 notation.
+ * <p>
+ * Valid options:
+ *
+ * <pre>
+ * GZIP: gzip-compresses object before encoding it.
+ * DONT_BREAK_LINES: don't break lines at 76 characters
+ * <i>Note: Technically, this makes your encoding non-compliant.</i>
+ * </pre>
+ * <p>
+ * Example: <code>encodeBytes( myData, Base64.GZIP )</code> or
+ * <p>
+ * Example: <code>encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES )</code>
+ *
+ * @param source The data to convert
+ * @param options Specified options
+ * @return the encoded bytes
+ * @see Base64#GZIP
+ * @see Base64#DONT_BREAK_LINES
+ * @since 2.0
+ */
+ public static String encodeBytes( byte[] source,
+ int options ) {
+ return encodeBytes(source, 0, source.length, options);
+ } // end encodeBytes
+
+ /**
+ * Encodes a byte array into Base64 notation. Does not GZip-compress data.
+ *
+ * @param source The data to convert
+ * @param off Offset in array where conversion should begin
+ * @param len Length of data
+ * @return the encoded bytes
+ * @since 1.4
+ */
+ public static String encodeBytes( byte[] source,
+ int off,
+ int len ) {
+ return encodeBytes(source, off, len, NO_OPTIONS);
+ } // end encodeBytes
+
+ /**
+ * Encodes a byte array into Base64 notation.
+ * <p>
+ * Valid options:
+ *
+ * <pre>
+ * GZIP: gzip-compresses object before encoding it.
+ * DONT_BREAK_LINES: don't break lines at 76 characters
+ * <i>Note: Technically, this makes your encoding non-compliant.</i>
+ * </pre>
+ * <p>
+ * Example: <code>encodeBytes( myData, Base64.GZIP )</code> or
+ * <p>
+ * Example: <code>encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES )</code>
+ *
+ * @param source The data to convert
+ * @param off Offset in array where conversion should begin
+ * @param len Length of data to convert
+ * @param options Specified options- the alphabet type is pulled from this (standard, url-safe, ordered)
+ * @return the encoded bytes
+ * @see Base64#GZIP
+ * @see Base64#DONT_BREAK_LINES
+ * @since 2.0
+ */
+ public static String encodeBytes( byte[] source,
+ int off,
+ int len,
+ int options ) {
+ // Isolate options
+ int dontBreakLines = (options & DONT_BREAK_LINES);
+ int gzip = (options & GZIP);
+
+ // Compress?
+ if (gzip == GZIP) {
+ java.io.ByteArrayOutputStream baos = null;
+ java.util.zip.GZIPOutputStream gzos = null;
+ Base64.OutputStream b64os = null;
+
+ try {
+ // GZip -> Base64 -> ByteArray
+ baos = new java.io.ByteArrayOutputStream();
+ b64os = new Base64.OutputStream(baos, ENCODE | options);
+ gzos = new java.util.zip.GZIPOutputStream(b64os);
+
+ gzos.write(source, off, len);
+ gzos.close();
+ } // end try
+ catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ } // end catch
+ finally {
+ try {
+ gzos.close();
+ } catch (Exception e) {
+ }
+ try {
+ b64os.close();
+ } catch (Exception e) {
+ }
+ try {
+ baos.close();
+ } catch (Exception e) {
+ }
+ } // end finally
+
+ // Return value according to relevant encoding.
+ try {
+ return new String(baos.toByteArray(), PREFERRED_ENCODING);
+ } // end try
+ catch (java.io.UnsupportedEncodingException uue) {
+ return new String(baos.toByteArray());
+ } // end catch
+ } // end if: compress
+
+ // Else, don't compress. Better not to use streams at all then.
+ else {
+ // Convert option to boolean in way that code likes it.
+ boolean breakLines = dontBreakLines == 0;
+
+ int len43 = len * 4 / 3;
+ byte[] outBuff = new byte[(len43) // Main 4:3
+ + ((len % 3) > 0 ? 4 : 0) // Account for padding
+ + (breakLines ? (len43 / MAX_LINE_LENGTH) : 0)]; // New lines
+ int d = 0;
+ int e = 0;
+ int len2 = len - 2;
+ int lineLength = 0;
+ for (; d < len2; d += 3, e += 4) {
+ encode3to4(source, d + off, 3, outBuff, e, options);
+
+ lineLength += 4;
+ if (breakLines && lineLength == MAX_LINE_LENGTH) {
+ outBuff[e + 4] = NEW_LINE;
+ e++;
+ lineLength = 0;
+ } // end if: end of line
+ } // en dfor: each piece of array
+
+ if (d < len) {
+ encode3to4(source, d + off, len - d, outBuff, e, options);
+ e += 4;
+ } // end if: some padding needed
+
+ // Return value according to relevant encoding.
+ try {
+ return new String(outBuff, 0, e, PREFERRED_ENCODING);
+ } // end try
+ catch (java.io.UnsupportedEncodingException uue) {
+ return new String(outBuff, 0, e);
+ } // end catch
+
+ } // end else: don't compress
+
+ } // end encodeBytes
+
/* ******** D E C O D I N G M E T H O D S ******** */
/**
@@ -293,15 +710,17 @@
* @param source the array to convert
* @param srcOffset the index where conversion begins
* @param destination the array to hold the conversion
- * @param destOffset destination offset
+ * @param destOffset the index where output will be put
+ * @param options alphabet type is pulled from this (standard, url-safe, ordered)
* @return the number of decoded bytes converted
* @since 1.3
*/
private static int decode4to3( byte[] source,
int srcOffset,
byte[] destination,
- int destOffset ) {
- byte[] DECODABET = _STANDARD_DECODABET;
+ int destOffset,
+ int options ) {
+ byte[] DECODABET = getDecodabet(options);
// Example: Dk==
if (source[srcOffset + 2] == EQUALS_SIGN) {
@@ -330,44 +749,49 @@
// Example: DkLE
else {
- // Two ways to do the same thing. Don't know which way I like best.
- // int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 )
- // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 )
- // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 )
- // | ( ( DECODABET[ source[ srcOffset + 3 ] ] << 24 ) >>> 24 );
- int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18) | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12)
- | ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6) | ((DECODABET[source[srcOffset + 3]] & 0xFF));
+ try {
+ // Two ways to do the same thing. Don't know which way I like best.
+ // int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 )
+ // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 )
+ // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 )
+ // | ( ( DECODABET[ source[ srcOffset + 3 ] ] << 24 ) >>> 24 );
+ int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18) | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12)
+ | ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6) | ((DECODABET[source[srcOffset + 3]] & 0xFF));
- destination[destOffset] = (byte)(outBuff >> 16);
- destination[destOffset + 1] = (byte)(outBuff >> 8);
- destination[destOffset + 2] = (byte)(outBuff);
+ destination[destOffset] = (byte)(outBuff >> 16);
+ destination[destOffset + 1] = (byte)(outBuff >> 8);
+ destination[destOffset + 2] = (byte)(outBuff);
- return 3;
+ return 3;
+ } catch (Exception e) {
+ System.out.println("" + source[srcOffset] + ": " + (DECODABET[source[srcOffset]]));
+ System.out.println("" + source[srcOffset + 1] + ": " + (DECODABET[source[srcOffset + 1]]));
+ System.out.println("" + source[srcOffset + 2] + ": " + (DECODABET[source[srcOffset + 2]]));
+ System.out.println("" + source[srcOffset + 3] + ": " + (DECODABET[source[srcOffset + 3]]));
+ return -1;
+ } // end catch
}
} // end decodeToBytes
/**
- * Decodes data from Base64 notation.
+ * Very low-level access to decoding ASCII characters in the form of a byte array. Does not support automatically gunzipping
+ * or any other "fancy" features.
*
- * @param s the string to decode
- * @return the decoded data
- * @since 1.4
+ * @param source The Base64 encoded data
+ * @param off The offset of where to begin decoding
+ * @param len The length of characters to decode
+ * @param options The options to use in this operation
+ * @return decoded data
+ * @since 1.3
*/
- public static byte[] decode( String s ) {
- byte[] source;
- try {
- source = s.getBytes(PREFERRED_ENCODING);
- } // end try
- catch (java.io.UnsupportedEncodingException uee) {
- source = s.getBytes();
- } // end catch
- // </change>
- if (source.length % 4 != 0) {
- throw new IllegalArgumentException("Source bytes are not valid"); //$NON-NLS-1$
- }
- byte[] DECODABET = _STANDARD_DECODABET;
- int len = source.length;
- byte[] outBuff = new byte[len * 3 / 4]; // Upper limit on size of output
+ public static byte[] decode( byte[] source,
+ int off,
+ int len,
+ int options ) {
+ byte[] DECODABET = getDecodabet(options);
+
+ int len34 = len * 3 / 4;
+ byte[] outBuff = new byte[len34]; // Upper limit on size of output
int outBuffPosn = 0;
byte[] b4 = new byte[4];
@@ -375,7 +799,7 @@
int i = 0;
byte sbiCrop = 0;
byte sbiDecode = 0;
- for (i = 0; i < len; i++) {
+ for (i = off; i < off + len; i++) {
sbiCrop = (byte)(source[i] & 0x7f); // Only the low seven bits
sbiDecode = DECODABET[sbiCrop];
@@ -384,7 +808,7 @@
if (sbiDecode >= EQUALS_SIGN_ENC) {
b4[b4Posn++] = sbiCrop;
if (b4Posn > 3) {
- outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn);
+ outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn, options);
b4Posn = 0;
// If that was the equals sign, break out of 'for' loop
@@ -395,7 +819,8 @@
} // end if: white space, equals sign or better
else {
- throw new IllegalArgumentException("Source bytes are not valid"); //$NON-NLS-1$
+ System.err.println("Bad Base64 input character at " + i + ": " + source[i] + "(decimal)");
+ return null;
} // end else:
} // each input character
@@ -403,4 +828,763 @@
System.arraycopy(outBuff, 0, out, 0, outBuffPosn);
return out;
} // end decode
-}
+
+ /**
+ * Decodes data from Base64 notation, automatically detecting gzip-compressed data and decompressing it.
+ *
+ * @param s the string to decode
+ * @return the decoded data
+ * @since 1.4
+ */
+ public static byte[] decode( String s ) {
+ return decode(s, NO_OPTIONS);
+ }
+
+ /**
+ * Decodes data from Base64 notation, automatically detecting gzip-compressed data and decompressing it.
+ *
+ * @param s the string to decode
+ * @param options encode options such as URL_SAFE
+ * @return the decoded data
+ * @since 1.4
+ */
+ public static byte[] decode( String s,
+ int options ) {
+ byte[] bytes;
+ try {
+ bytes = s.getBytes(PREFERRED_ENCODING);
+ } // end try
+ catch (java.io.UnsupportedEncodingException uee) {
+ bytes = s.getBytes();
+ } // end catch
+ // </change>
+
+ // Decode
+ bytes = decode(bytes, 0, bytes.length, options);
+
+ // Check to see if it's gzip-compressed
+ // GZIP Magic Two-Byte Number: 0x8b1f (35615)
+ if (bytes != null && bytes.length >= 4) {
+
+ int head = ((int)bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00);
+ if (java.util.zip.GZIPInputStream.GZIP_MAGIC == head) {
+ java.io.ByteArrayInputStream bais = null;
+ java.util.zip.GZIPInputStream gzis = null;
+ java.io.ByteArrayOutputStream baos = null;
+ byte[] buffer = new byte[2048];
+ int length = 0;
+
+ try {
+ baos = new java.io.ByteArrayOutputStream();
+ bais = new java.io.ByteArrayInputStream(bytes);
+ gzis = new java.util.zip.GZIPInputStream(bais);
+
+ while ((length = gzis.read(buffer)) >= 0) {
+ baos.write(buffer, 0, length);
+ } // end while: reading input
+
+ // No error? Get new bytes.
+ bytes = baos.toByteArray();
+
+ } // end try
+ catch (IOException e) {
+ // Just return originally-decoded bytes
+ } // end catch
+ finally {
+ try {
+ baos.close();
+ } catch (Exception e) {
+ }
+ try {
+ gzis.close();
+ } catch (Exception e) {
+ }
+ try {
+ bais.close();
+ } catch (Exception e) {
+ }
+ } // end finally
+
+ } // end if: gzipped
+ } // end if: bytes.length >= 2
+
+ return bytes;
+ } // end decode
+
+ /**
+ * Attempts to decode Base64 data and deserialize a Java Object within. Returns <tt>null</tt> if there was an error.
+ *
+ * @param encodedObject The Base64 data to decode
+ * @return The decoded and deserialized object
+ * @since 1.5
+ */
+ public static Object decodeToObject( String encodedObject ) {
+ // Decode and gunzip if necessary
+ byte[] objBytes = decode(encodedObject);
+
+ java.io.ByteArrayInputStream bais = null;
+ java.io.ObjectInputStream ois = null;
+ Object obj = null;
+
+ try {
+ bais = new java.io.ByteArrayInputStream(objBytes);
+ ois = new java.io.ObjectInputStream(bais);
+
+ obj = ois.readObject();
+ } // end try
+ catch (IOException e) {
+ e.printStackTrace();
+ obj = null;
+ } // end catch
+ catch (java.lang.ClassNotFoundException e) {
+ e.printStackTrace();
+ obj = null;
+ } // end catch
+ finally {
+ try {
+ bais.close();
+ } catch (Exception e) {
+ }
+ try {
+ ois.close();
+ } catch (Exception e) {
+ }
+ } // end finally
+
+ return obj;
+ } // end decodeObject
+
+ /**
+ * Convenience method for encoding data to a file.
+ *
+ * @param dataToEncode byte array of data to encode in base64 form
+ * @param filename Filename for saving encoded data
+ * @return <tt>true</tt> if successful, <tt>false</tt> otherwise
+ * @since 2.1
+ */
+ public static boolean encodeToFile( byte[] dataToEncode,
+ String filename ) {
+ boolean success = false;
+ Base64.OutputStream bos = null;
+ try {
+ bos = new Base64.OutputStream(new java.io.FileOutputStream(filename), Base64.ENCODE);
+ bos.write(dataToEncode);
+ success = true;
+ } // end try
+ catch (IOException e) {
+
+ success = false;
+ } // end catch: IOException
+ finally {
+ try {
+ bos.close();
+ } catch (Exception e) {
+ }
+ } // end finally
+
+ return success;
+ } // end encodeToFile
+
+ /**
+ * Convenience method for decoding data to a file.
+ *
+ * @param dataToDecode Base64-encoded data as a string
+ * @param filename Filename for saving decoded data
+ * @return <tt>true</tt> if successful, <tt>false</tt> otherwise
+ * @since 2.1
+ */
+ public static boolean decodeToFile( String dataToDecode,
+ String filename ) {
+ boolean success = false;
+ Base64.OutputStream bos = null;
+ try {
+ bos = new Base64.OutputStream(new java.io.FileOutputStream(filename), Base64.DECODE);
+ bos.write(dataToDecode.getBytes(PREFERRED_ENCODING));
+ success = true;
+ } // end try
+ catch (IOException e) {
+ success = false;
+ } // end catch: IOException
+ finally {
+ try {
+ bos.close();
+ } catch (Exception e) {
+ }
+ } // end finally
+
+ return success;
+ } // end decodeToFile
+
+ /**
+ * Convenience method for reading a base64-encoded file and decoding it.
+ *
+ * @param filename Filename for reading encoded data
+ * @return decoded byte array or null if unsuccessful
+ * @since 2.1
+ */
+ public static byte[] decodeFromFile( String filename ) {
+ byte[] decodedData = null;
+ Base64.InputStream bis = null;
+ try {
+ // Set up some useful variables
+ java.io.File file = new java.io.File(filename);
+ byte[] buffer = null;
+ int length = 0;
+ int numBytes = 0;
+
+ // Check for size of file
+ if (file.length() > Integer.MAX_VALUE) {
+ System.err.println("File is too big for this convenience method (" + file.length() + " bytes).");
+ return null;
+ } // end if: file too big for int index
+ buffer = new byte[(int)file.length()];
+
+ // Open a stream
+ bis = new Base64.InputStream(new java.io.BufferedInputStream(new java.io.FileInputStream(file)), Base64.DECODE);
+
+ // Read until done
+ while ((numBytes = bis.read(buffer, length, 4096)) >= 0)
+ length += numBytes;
+
+ // Save in a variable to return
+ decodedData = new byte[length];
+ System.arraycopy(buffer, 0, decodedData, 0, length);
+
+ } // end try
+ catch (IOException e) {
+ System.err.println("Error decoding from file " + filename);
+ } // end catch: IOException
+ finally {
+ try {
+ bis.close();
+ } catch (Exception e) {
+ }
+ } // end finally
+
+ return decodedData;
+ } // end decodeFromFile
+
+ /**
+ * Convenience method for reading a binary file and base64-encoding it.
+ *
+ * @param filename Filename for reading binary data
+ * @return base64-encoded string or null if unsuccessful
+ * @since 2.1
+ */
+ public static String encodeFromFile( String filename ) {
+ String encodedData = null;
+ Base64.InputStream bis = null;
+ try {
+ // Set up some useful variables
+ java.io.File file = new java.io.File(filename);
+ byte[] buffer = new byte[Math.max((int)(file.length() * 1.4), 40)]; // Need max() for math on small files (v2.2.1)
+ int length = 0;
+ int numBytes = 0;
+
+ // Open a stream
+ bis = new Base64.InputStream(new java.io.BufferedInputStream(new java.io.FileInputStream(file)), Base64.ENCODE);
+
+ // Read until done
+ while ((numBytes = bis.read(buffer, length, 4096)) >= 0)
+ length += numBytes;
+
+ // Save in a variable to return
+ encodedData = new String(buffer, 0, length, Base64.PREFERRED_ENCODING);
+
+ } // end try
+ catch (IOException e) {
+ System.err.println("Error encoding from file " + filename);
+ } // end catch: IOException
+ finally {
+ try {
+ bis.close();
+ } catch (Exception e) {
+ }
+ } // end finally
+
+ return encodedData;
+ } // end encodeFromFile
+
+ /**
+ * Reads <tt>infile</tt> and encodes it to <tt>outfile</tt>.
+ *
+ * @param infile Input file
+ * @param outfile Output file
+ * @return true if the operation is successful
+ * @since 2.2
+ */
+ public static boolean encodeFileToFile( String infile,
+ String outfile ) {
+ boolean success = false;
+ java.io.InputStream in = null;
+ java.io.OutputStream out = null;
+ try {
+ in = new Base64.InputStream(new java.io.BufferedInputStream(new java.io.FileInputStream(infile)), Base64.ENCODE);
+ out = new java.io.BufferedOutputStream(new java.io.FileOutputStream(outfile));
+ byte[] buffer = new byte[65536]; // 64K
+ int read = -1;
+ while ((read = in.read(buffer)) >= 0) {
+ out.write(buffer, 0, read);
+ } // end while: through file
+ success = true;
+ } catch (IOException exc) {
+ exc.printStackTrace();
+ } finally {
+ try {
+ in.close();
+ } catch (Exception exc) {
+ }
+ try {
+ out.close();
+ } catch (Exception exc) {
+ }
+ } // end finally
+
+ return success;
+ } // end encodeFileToFile
+
+ /**
+ * Reads <tt>infile</tt> and decodes it to <tt>outfile</tt>.
+ *
+ * @param infile Input file
+ * @param outfile Output file
+ * @return true if the operation is successful
+ * @since 2.2
+ */
+ public static boolean decodeFileToFile( String infile,
+ String outfile ) {
+ boolean success = false;
+ java.io.InputStream in = null;
+ java.io.OutputStream out = null;
+ try {
+ in = new Base64.InputStream(new java.io.BufferedInputStream(new java.io.FileInputStream(infile)), Base64.DECODE);
+ out = new java.io.BufferedOutputStream(new java.io.FileOutputStream(outfile));
+ byte[] buffer = new byte[65536]; // 64K
+ int read = -1;
+ while ((read = in.read(buffer)) >= 0) {
+ out.write(buffer, 0, read);
+ } // end while: through file
+ success = true;
+ } catch (IOException exc) {
+ exc.printStackTrace();
+ } finally {
+ try {
+ in.close();
+ } catch (Exception exc) {
+ }
+ try {
+ out.close();
+ } catch (Exception exc) {
+ }
+ } // end finally
+
+ return success;
+ } // end decodeFileToFile
+
+ /* ******** I N N E R C L A S S I N P U T S T R E A M ******** */
+
+ /**
+ * A {@link Base64.InputStream} will read data from another <tt>java.io.InputStream</tt>, given in the constructor, and
+ * encode/decode to/from Base64 notation on the fly.
+ *
+ * @see Base64
+ * @since 1.3
+ */
+ public static class InputStream extends java.io.FilterInputStream {
+ private boolean encode; // Encoding or decoding
+ private int position; // Current position in the buffer
+ private byte[] buffer; // Small buffer holding converted data
+ private int bufferLength; // Length of buffer (3 or 4)
+ private int numSigBytes; // Number of meaningful bytes in the buffer
+ private int lineLength;
+ private boolean breakLines; // Break lines at less than 80 characters
+ private int options; // Record options used to create the stream.
+ private byte[] alphabet; // Local copies to avoid extra method calls
+ private byte[] decodabet; // Local copies to avoid extra method calls
+
+ /**
+ * Constructs a {@link Base64.InputStream} in DECODE mode.
+ *
+ * @param in the <tt>java.io.InputStream</tt> from which to read data.
+ * @since 1.3
+ */
+ public InputStream( java.io.InputStream in ) {
+ this(in, DECODE);
+ } // end constructor
+
+ /**
+ * Constructs a {@link Base64.InputStream} in either ENCODE or DECODE mode.
+ * <p>
+ * Valid options:
+ *
+ * <pre>
+ * ENCODE or DECODE: Encode or Decode as data is read.
+ * DONT_BREAK_LINES: don't break lines at 76 characters
+ * (only meaningful when encoding)
+ * <i>Note: Technically, this makes your encoding non-compliant.</i>
+ * </pre>
+ * <p>
+ * Example: <code>new Base64.InputStream( in, Base64.DECODE )</code>
+ *
+ * @param in the <tt>java.io.InputStream</tt> from which to read data.
+ * @param options Specified options
+ * @see Base64#ENCODE
+ * @see Base64#DECODE
+ * @see Base64#DONT_BREAK_LINES
+ * @since 2.0
+ */
+ public InputStream( java.io.InputStream in,
+ int options ) {
+ super(in);
+ this.breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES;
+ this.encode = (options & ENCODE) == ENCODE;
+ this.bufferLength = encode ? 4 : 3;
+ this.buffer = new byte[bufferLength];
+ this.position = -1;
+ this.lineLength = 0;
+ this.options = options; // Record for later, mostly to determine which alphabet to use
+ this.alphabet = getAlphabet(options);
+ this.decodabet = getDecodabet(options);
+ } // end constructor
+
+ /**
+ * Reads enough of the input stream to convert to/from Base64 and returns the next byte.
+ *
+ * @return next byte
+ * @throws IOException
+ * @since 1.3
+ */
+ @Override
+ public int read() throws IOException {
+ // Do we need to get data?
+ if (position < 0) {
+ if (encode) {
+ byte[] b3 = new byte[3];
+ int numBinaryBytes = 0;
+ for (int i = 0; i < 3; i++) {
+ try {
+ int b = in.read();
+
+ // If end of stream, b is -1.
+ if (b >= 0) {
+ b3[i] = (byte)b;
+ numBinaryBytes++;
+ } // end if: not end of stream
+
+ } // end try: read
+ catch (IOException e) {
+ // Only a problem if we got no data at all.
+ if (i == 0) throw e;
+
+ } // end catch
+ } // end for: each needed input byte
+
+ if (numBinaryBytes > 0) {
+ encode3to4(b3, 0, numBinaryBytes, buffer, 0, options);
+ position = 0;
+ numSigBytes = 4;
+ } // end if: got data
+ else {
+ return -1;
+ } // end else
+ } // end if: encoding
+
+ // Else decoding
+ else {
+ byte[] b4 = new byte[4];
+ int i = 0;
+ for (i = 0; i < 4; i++) {
+ // Read four "meaningful" bytes:
+ int b = 0;
+ do {
+ b = in.read();
+ } while (b >= 0 && decodabet[b & 0x7f] <= WHITE_SPACE_ENC);
+
+ if (b < 0) break; // Reads a -1 if end of stream
+
+ b4[i] = (byte)b;
+ } // end for: each needed input byte
+
+ if (i == 4) {
+ numSigBytes = decode4to3(b4, 0, buffer, 0, options);
+ position = 0;
+ } // end if: got four characters
+ else if (i == 0) {
+ return -1;
+ } // end else if: also padded correctly
+ else {
+ // Must have broken out from above.
+ throw new IOException("Improperly padded Base64 input.");
+ } // end
+
+ } // end else: decode
+ } // end else: get data
+
+ // Got data?
+ if (position >= 0) {
+ // End of relevant data?
+ if ( /*!encode &&*/position >= numSigBytes) return -1;
+
+ if (encode && breakLines && lineLength >= MAX_LINE_LENGTH) {
+ lineLength = 0;
+ return '\n';
+ } // end if
+ else {
+ lineLength++; // This isn't important when decoding
+ // but throwing an extra "if" seems
+ // just as wasteful.
+
+ int b = buffer[position++];
+
+ if (position >= bufferLength) position = -1;
+
+ return b & 0xFF; // This is how you "cast" a byte that's
+ // intended to be unsigned.
+ } // end else
+ } // end if: position >= 0
+
+ // Else error
+ else {
+ // When JDK1.4 is more accepted, use an assertion here.
+ throw new IOException("Error in Base64 code reading stream.");
+ } // end else
+ } // end read
+
+ /**
+ * Calls {@link #read()} repeatedly until the end of stream is reached or <var>len</var> bytes are read. Returns number of
+ * bytes read into array or -1 if end of stream is encountered.
+ *
+ * @param dest array to hold values
+ * @param off offset for array
+ * @param len max number of bytes to read into array
+ * @return bytes read into array or -1 if end of stream is encountered.
+ * @throws IOException
+ * @since 1.3
+ */
+ @Override
+ public int read( byte[] dest,
+ int off,
+ int len ) throws IOException {
+ int i;
+ int b;
+ for (i = 0; i < len; i++) {
+ b = read();
+
+ // if( b < 0 && i == 0 )
+ // return -1;
+
+ if (b >= 0) dest[off + i] = (byte)b;
+ else if (i == 0) return -1;
+ else break; // Out of 'for' loop
+ } // end for: each byte read
+ return i;
+ } // end read
+
+ } // end inner class InputStream
+
+ /* ******** I N N E R C L A S S O U T P U T S T R E A M ******** */
+
+ /**
+ * A {@link Base64.OutputStream} will write data to another <tt>java.io.OutputStream</tt>, given in the constructor, and
+ * encode/decode to/from Base64 notation on the fly.
+ *
+ * @see Base64
+ * @since 1.3
+ */
+ public static class OutputStream extends java.io.FilterOutputStream {
+ private boolean encode;
+ private int position;
+ private byte[] buffer;
+ private int bufferLength;
+ private int lineLength;
+ private boolean breakLines;
+ private byte[] b4; // Scratch used in a few places
+ private boolean suspendEncoding;
+ private int options; // Record for later
+ private byte[] alphabet; // Local copies to avoid extra method calls
+ private byte[] decodabet; // Local copies to avoid extra method calls
+
+ /**
+ * Constructs a {@link Base64.OutputStream} in ENCODE mode.
+ *
+ * @param out the <tt>java.io.OutputStream</tt> to which data will be written.
+ * @since 1.3
+ */
+ public OutputStream( java.io.OutputStream out ) {
+ this(out, ENCODE);
+ } // end constructor
+
+ /**
+ * Constructs a {@link Base64.OutputStream} in either ENCODE or DECODE mode.
+ * <p>
+ * Valid options:
+ *
+ * <pre>
+ * ENCODE or DECODE: Encode or Decode as data is read.
+ * DONT_BREAK_LINES: don't break lines at 76 characters
+ * (only meaningful when encoding)
+ * <i>Note: Technically, this makes your encoding non-compliant.</i>
+ * </pre>
+ * <p>
+ * Example: <code>new Base64.OutputStream( out, Base64.ENCODE )</code>
+ *
+ * @param out the <tt>java.io.OutputStream</tt> to which data will be written.
+ * @param options Specified options.
+ * @see Base64#ENCODE
+ * @see Base64#DECODE
+ * @see Base64#DONT_BREAK_LINES
+ * @since 1.3
+ */
+ public OutputStream( java.io.OutputStream out,
+ int options ) {
+ super(out);
+ this.breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES;
+ this.encode = (options & ENCODE) == ENCODE;
+ this.bufferLength = encode ? 3 : 4;
+ this.buffer = new byte[bufferLength];
+ this.position = 0;
+ this.lineLength = 0;
+ this.suspendEncoding = false;
+ this.b4 = new byte[4];
+ this.options = options;
+ this.alphabet = getAlphabet(options);
+ this.decodabet = getDecodabet(options);
+ } // end constructor
+
+ /**
+ * Writes the byte to the output stream after converting to/from Base64 notation. When encoding, bytes are buffered three
+ * at a time before the output stream actually gets a write() call. When decoding, bytes are buffered four at a time.
+ *
+ * @param theByte the byte to write
+ * @throws IOException
+ * @since 1.3
+ */
+ @Override
+ public void write( int theByte ) throws IOException {
+ // Encoding suspended?
+ if (suspendEncoding) {
+ super.out.write(theByte);
+ return;
+ } // end if: supsended
+
+ // Encode?
+ if (encode) {
+ buffer[position++] = (byte)theByte;
+ if (position >= bufferLength) // Enough to encode.
+ {
+ out.write(encode3to4(b4, buffer, bufferLength, options));
+
+ lineLength += 4;
+ if (breakLines && lineLength >= MAX_LINE_LENGTH) {
+ out.write(NEW_LINE);
+ lineLength = 0;
+ } // end if: end of line
+
+ position = 0;
+ } // end if: enough to output
+ } // end if: encoding
+
+ // Else, Decoding
+ else {
+ // Meaningful Base64 character?
+ if (decodabet[theByte & 0x7f] > WHITE_SPACE_ENC) {
+ buffer[position++] = (byte)theByte;
+ if (position >= bufferLength) // Enough to output.
+ {
+ int len = Base64.decode4to3(buffer, 0, b4, 0, options);
+ out.write(b4, 0, len);
+ // out.write( Base64.decode4to3( buffer ) );
+ position = 0;
+ } // end if: enough to output
+ } // end if: meaningful base64 character
+ else if (decodabet[theByte & 0x7f] != WHITE_SPACE_ENC) {
+ throw new IOException("Invalid character in Base64 data.");
+ } // end else: not white space either
+ } // end else: decoding
+ } // end write
+
+ /**
+ * Calls {@link #write(int)} repeatedly until <var>len</var> bytes are written.
+ *
+ * @param theBytes array from which to read bytes
+ * @param off offset for array
+ * @param len max number of bytes to read into array
+ * @throws IOException
+ * @since 1.3
+ */
+ @Override
+ public void write( byte[] theBytes,
+ int off,
+ int len ) throws IOException {
+ // Encoding suspended?
+ if (suspendEncoding) {
+ super.out.write(theBytes, off, len);
+ return;
+ } // end if: supsended
+
+ for (int i = 0; i < len; i++) {
+ write(theBytes[off + i]);
+ } // end for: each byte written
+
+ } // end write
+
+ /**
+ * Method added by PHIL. [Thanks, PHIL. -Rob] This pads the buffer without closing the stream.
+ *
+ * @throws IOException
+ */
+ public void flushBase64() throws IOException {
+ if (position > 0) {
+ if (encode) {
+ out.write(encode3to4(b4, buffer, position, options));
+ position = 0;
+ } // end if: encoding
+ else {
+ throw new IOException("Base64 input not properly padded.");
+ } // end else: decoding
+ } // end if: buffer partially full
+
+ } // end flush
+
+ /**
+ * Flushes and closes (I think, in the superclass) the stream.
+ *
+ * @throws IOException
+ * @since 1.3
+ */
+ @Override
+ public void close() throws IOException {
+ // 1. Ensure that pending characters are written
+ flushBase64();
+
+ // 2. Actually close the stream
+ // Base class both flushes and closes.
+ super.close();
+
+ buffer = null;
+ out = null;
+ } // end close
+
+ /**
+ * Suspends encoding of the stream. May be helpful if you need to embed a piece of base640-encoded data in a stream.
+ *
+ * @throws IOException
+ * @since 1.5.1
+ */
+ public void suspendEncoding() throws IOException {
+ flushBase64();
+ this.suspendEncoding = true;
+ } // end suspendEncoding
+
+ /**
+ * Resumes encoding of the stream. May be helpful if you need to embed a piece of base640-encoded data in a stream.
+ *
+ * @since 1.5.1
+ */
+ public void resumeEncoding() {
+ this.suspendEncoding = false;
+ } // end resumeEncoding
+
+ } // end inner class OutputStream
+
+} // end class Base64
Added: trunk/dna-common/src/test/java/org/jboss/dna/common/text/XmlValueEncoderTest.java
===================================================================
--- trunk/dna-common/src/test/java/org/jboss/dna/common/text/XmlValueEncoderTest.java (rev 0)
+++ trunk/dna-common/src/test/java/org/jboss/dna/common/text/XmlValueEncoderTest.java 2009-03-10 15:17:23 UTC (rev 764)
@@ -0,0 +1,110 @@
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.common.text;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+import org.junit.Before;
+import org.junit.Test;
+
+public class XmlValueEncoderTest {
+
+ private XmlValueEncoder encoder = new XmlValueEncoder();
+
+ @Before
+ public void beforeEach() {
+ }
+
+ protected void checkEncoding( String input,
+ String expected ) {
+ String output = this.encoder.encode(input);
+ assertThat(output, is(notNullValue()));
+ assertEquals(expected, output);
+ assertThat(output.length(), is(expected.length()));
+ assertThat(output, is(expected));
+
+ checkDecoding(output, input);
+ }
+
+ protected void checkForNoEncoding( String input ) {
+ String output = this.encoder.encode(input);
+ assertThat(output, is(notNullValue()));
+ assertEquals(input, output);
+ assertThat(output.length(), is(input.length()));
+ assertThat(output, is(input));
+
+ checkForNoDecoding(input);
+ }
+
+ protected void checkForNoDecoding( String input ) {
+ String output = this.encoder.decode(input);
+ assertThat(output, is(notNullValue()));
+ assertEquals(input, output);
+ assertThat(output.length(), is(input.length()));
+ assertThat(output, is(input));
+ }
+
+ protected void checkDecoding( String input,
+ String output ) {
+ String decoded = this.encoder.decode(input);
+ assertEquals(output, decoded);
+ assertThat(decoded.length(), is(output.length()));
+ assertThat(decoded, is(output));
+ }
+
+ @Test
+ public void shouldEncodeStringWithNoSpecialChars() {
+ checkForNoEncoding("The quick brown fox jumped over the lazy dog.?+=!@#$%^*()_+-[]{}|\\");
+ }
+
+ @Test
+ public void shouldEncodeStringWithSpecialChars() {
+ checkEncoding("<>&'\"", "<>&'"");
+ }
+
+ @Test
+ public void shouldHandleTrivialCase() {
+ assertNull(encoder.encode(null));
+ assertNull(encoder.decode(null));
+ checkEncoding("", "");
+
+ }
+
+ @Test
+ public void shouldDecodeStringWithInvalidMappings() {
+ checkDecoding("&", "&");
+ checkDecoding(""", """);
+ checkDecoding(">", ">");
+ checkDecoding("<", "<");
+ checkDecoding("amp;", "amp;");
+ checkDecoding("quot;", "quot;");
+ checkDecoding("gt;", "gt;");
+ checkDecoding("lt;", "lt;");
+ checkDecoding("&;", "&;");
+ checkDecoding("&&", "&&");
+ }
+}
Property changes on: trunk/dna-common/src/test/java/org/jboss/dna/common/text/XmlValueEncoderTest.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrExporter.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrExporter.java (rev 0)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrExporter.java 2009-03-10 15:17:23 UTC (rev 764)
@@ -0,0 +1,359 @@
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.jcr;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.jcr.ItemVisitor;
+import javax.jcr.NamespaceRegistry;
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.text.XmlNameEncoder;
+import org.jboss.dna.common.text.XmlValueEncoder;
+import org.jboss.dna.graph.property.Name;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * Superclass of DNA JCR exporters, provides basic support for traversing through the nodes recursively (if needed), exception
+ * wrapping (since {@link ItemVisitor} does not allow checked exceptions to be thrown from its visit* methods, and the ability to
+ * wrap an {@link OutputStream} with a {@link ContentHandler}.
+ * <p />
+ * Each exporter is only intended to be used once (by calling <code>exportView</code>) and discarded. This class is <b>NOT</b>
+ * thread-safe.
+ *
+ * @see JcrSystemViewExporter
+ * @see JcrDocumentViewExporter
+ */
+@NotThreadSafe
+abstract class AbstractJcrExporter {
+
+ /**
+ * Encoder to properly escape XML names.
+ *
+ * @see XmlNameEncoder
+ */
+ private static final TextEncoder NAME_ENCODER = new XmlNameEncoder();
+
+ /**
+ * The session in which this exporter was created.
+ */
+ protected final JcrSession session;
+
+ /**
+ * The list of XML namespace prefixes that should never be exported.
+ */
+ private final Collection<String> restrictedPrefixes;
+
+ /**
+ * Creates the exporter
+ *
+ * @param session the session in which the exporter is created
+ * @param restrictedPrefixes the list of XML namespace prefixes that should not be exported
+ */
+ AbstractJcrExporter( JcrSession session,
+ Collection<String> restrictedPrefixes ) {
+ this.session = session;
+ this.restrictedPrefixes = restrictedPrefixes;
+ }
+
+ /**
+ * Exports <code>node</code> (or the subtree rooted at <code>node</code>) into an XML document by invoking SAX events on
+ * <code>contentHandler</code>.
+ *
+ * @param exportRootNode the node which should be exported. If <code>noRecursion</code> was set to <code>false</code> in the
+ * constructor, the entire subtree rooted at <code>node</code> will be exported.
+ * @param contentHandler the SAX content handler for which SAX events will be invoked as the XML document is created.
+ * @param skipBinary if <code>true</code>, indicates that binary properties should not be exported
+ * @param noRecurse if<code>true</code>, indicates that only the given node should be exported, otherwise a recursice export
+ * and not any of its child nodes.
+ * @throws SAXException if an exception occurs during generation of the XML document
+ * @throws RepositoryException if an exception occurs accessing the content repository
+ */
+ public void exportView( Node exportRootNode,
+ ContentHandler contentHandler,
+ boolean skipBinary,
+ boolean noRecurse ) throws RepositoryException, SAXException {
+ assert exportRootNode != null;
+ assert contentHandler != null;
+
+ // Export the namespace mappings used in this session
+ NamespaceRegistry registry = session.getWorkspace().getNamespaceRegistry();
+
+ contentHandler.startDocument();
+ String[] namespacePrefixes = registry.getPrefixes();
+ for (int i = 0; i < namespacePrefixes.length; i++) {
+ String prefix = namespacePrefixes[i];
+
+ if (!restrictedPrefixes.contains(prefix)) {
+ contentHandler.startPrefixMapping(prefix, registry.getURI(prefix));
+ }
+ }
+
+ exportNode(exportRootNode, contentHandler, skipBinary, noRecurse);
+
+ for (int i = 0; i < namespacePrefixes.length; i++) {
+ if (!restrictedPrefixes.contains(namespacePrefixes[i])) {
+ contentHandler.endPrefixMapping(namespacePrefixes[i]);
+ }
+ }
+
+ contentHandler.endDocument();
+ }
+
+ /**
+ * Exports <code>node</code> (or the subtree rooted at <code>node</code>) into an XML document that is written to
+ * <code>os</code>.
+ *
+ * @param node the node which should be exported. If <code>noRecursion</code> was set to <code>false</code> in the
+ * constructor, the entire subtree rooted at <code>node</code> will be exported.
+ * @param os the {@link OutputStream} to which the XML document will be written
+ * @param skipBinary if <code>true</code>, indicates that binary properties should not be exported
+ * @param noRecurse if<code>true</code>, indicates that only the given node should be exported, otherwise a recursive export
+ * and not any of its child nodes.
+ * @throws RepositoryException if an exception occurs accessing the content repository, generating the XML document, or
+ * writing it to the output stream <code>os</code>.
+ */
+ public void exportView( Node node,
+ OutputStream os,
+ boolean skipBinary,
+ boolean noRecurse ) throws RepositoryException {
+ try {
+ exportView(node, new StreamingContentHandler(os), skipBinary, noRecurse);
+ os.flush();
+ } catch (IOException ioe) {
+ throw new RepositoryException(ioe);
+ } catch (SAXException se) {
+ throw new RepositoryException(se);
+ }
+ }
+
+ /**
+ * Exports <code>node</code> (or the subtree rooted at <code>node</code>) into an XML document by invoking SAX events on
+ * <code>contentHandler</code>.
+ *
+ * @param node the node which should be exported. If <code>noRecursion</code> was set to <code>false</code> in the
+ * constructor, the entire subtree rooted at <code>node</code> will be exported.
+ * @param contentHandler the SAX content handler for which SAX events will be invoked as the XML document is created.
+ * @param skipBinary if <code>true</code>, indicates that binary properties should not be exported
+ * @param noRecurse if<code>true</code>, indicates that only the given node should be exported, otherwise a recursive export
+ * and not any of its child nodes.
+ * @throws SAXException if an exception occurs during generation of the XML document
+ * @throws RepositoryException if an exception occurs accessing the content repository
+ */
+ public abstract void exportNode( Node node,
+ ContentHandler contentHandler,
+ boolean skipBinary,
+ boolean noRecurse ) throws RepositoryException, SAXException;
+
+ /**
+ * Convenience method to invoke the {@link ContentHandler#startElement(String, String, String, Attributes)} method on the
+ * given content handler. The name will be encoded to properly escape invalid XML characters.
+ *
+ * @param contentHandler the content handler on which the <code>startElement</code> method should be invoked.
+ * @param name the un-encoded, un-prefixed name of the element to start
+ * @param atts the attributes that should be created for the given element
+ * @throws SAXException if there is an error starting the element
+ */
+ protected void startElement( ContentHandler contentHandler,
+ Name name,
+ Attributes atts ) throws SAXException {
+ contentHandler.startElement(name.getNamespaceUri(),
+ NAME_ENCODER.encode(name.getLocalName()),
+ NAME_ENCODER.encode(name.getString(session.getExecutionContext().getNamespaceRegistry())),
+ atts);
+ }
+
+ /**
+ * Convenience method to invoke the {@link ContentHandler#endElement(String, String, String)} method on the given content
+ * handler. The name will be encoded to properly escape invalid XML characters.
+ *
+ * @param contentHandler the content handler on which the <code>endElement</code> method should be invoked.
+ * @param name the un-encoded, un-prefixed name of the element to end
+ * @throws SAXException if there is an error ending the element
+ */
+ protected void endElement( ContentHandler contentHandler,
+ Name name ) throws SAXException {
+ contentHandler.endElement(name.getNamespaceUri(),
+ NAME_ENCODER.encode(name.getLocalName()),
+ NAME_ENCODER.encode(name.getString(session.getExecutionContext().getNamespaceRegistry())));
+ }
+
+ /**
+ * Helper class that adapts an arbitrary, open {@link OutputStream} to the {@link ContentHandler} interface. SAX events
+ * invoked on this object will be translated into their corresponding XML text and written to the output stream.
+ *
+ * @see AbstractJcrExporter#exportView(Node, OutputStream, boolean, boolean)
+ */
+ private class StreamingContentHandler extends DefaultHandler {
+
+ /** Debug setting that allows all output to be written to {@link System#out}. */
+ private static final boolean LOG_TO_CONSOLE = false;
+
+ /**
+ * Encoder to properly escape XML attribute values
+ *
+ * @see XmlValueEncoder
+ */
+ private final TextEncoder VALUE_ENCODER = new XmlValueEncoder();
+
+ /**
+ * The list of XML namespaces that are predefined and should not be exported by the content handler.
+ */
+ private final List<String> UNEXPORTABLE_NAMESPACES = Arrays.asList(new String[] {"", "xml", "xmlns"});
+
+ /**
+ * The output stream to which the XML will be written
+ */
+ private final OutputStream os;
+
+ /**
+ * The XML namespace prefixes that are currently mapped
+ */
+ private final Map<String, String> mappedPrefixes;
+
+ public StreamingContentHandler( OutputStream os ) {
+ this.os = os;
+ mappedPrefixes = new HashMap<String, String>();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
+ */
+ @Override
+ public void characters( char[] ch,
+ int start,
+ int length ) throws SAXException {
+ emit(VALUE_ENCODER.encode(new String(ch, start, length)));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xml.sax.helpers.DefaultHandler#startDocument()
+ */
+ @Override
+ public void startDocument() throws SAXException {
+ emit("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String, java.lang.String,
+ * org.xml.sax.Attributes)
+ */
+ @Override
+ public void startElement( String uri,
+ String localName,
+ String name,
+ Attributes attributes ) throws SAXException {
+ emit("<");
+ emit(name);
+
+ for (Map.Entry<String, String> mapping : mappedPrefixes.entrySet()) {
+ emit(" xmlns:");
+ emit(mapping.getKey());
+ emit("=\"");
+ emit(mapping.getValue());
+ emit("\"");
+ }
+
+ mappedPrefixes.clear();
+
+ if (attributes != null) {
+ for (int i = 0; i < attributes.getLength(); i++) {
+ emit(" ");
+ emit(attributes.getQName(i));
+ emit("=\"");
+ emit(VALUE_ENCODER.encode(attributes.getValue(i)));
+ emit("\"");
+ }
+ }
+
+ emit(">");
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
+ */
+ @Override
+ public void endElement( String uri,
+ String localName,
+ String name ) throws SAXException {
+ emit("</");
+ emit(name);
+ emit(">");
+ System.out.println();
+
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xml.sax.helpers.DefaultHandler#startPrefixMapping(java.lang.String, java.lang.String)
+ */
+ @Override
+ public void startPrefixMapping( String prefix,
+ String uri ) {
+ if (!UNEXPORTABLE_NAMESPACES.contains(prefix)) {
+ mappedPrefixes.put(prefix, uri);
+ }
+ }
+
+ /**
+ * Writes the given text to the output stream for this {@link StreamingContentHandler}.
+ *
+ * @param text the text to output
+ * @throws SAXException if there is an error writing to the stream
+ * @see StreamingContentHandler#os
+ */
+ private void emit( String text ) throws SAXException {
+
+ try {
+ if (LOG_TO_CONSOLE) {
+ System.out.print(text);
+ }
+
+ os.write(text.getBytes());
+ } catch (IOException ioe) {
+ throw new SAXException(ioe);
+ }
+ }
+ }
+
+}
Property changes on: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrExporter.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaBuiltinNodeTypeSource.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaBuiltinNodeTypeSource.java 2009-03-09 17:57:18 UTC (rev 763)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaBuiltinNodeTypeSource.java 2009-03-10 15:17:23 UTC (rev 764)
@@ -29,8 +29,8 @@
import java.util.List;
import javax.jcr.PropertyType;
import javax.jcr.nodetype.NodeType;
+import net.jcip.annotations.Immutable;
import org.jboss.dna.graph.JcrMixLexicon;
-import net.jcip.annotations.Immutable;
/**
* {@link JcrNodeTypeSource} that provides built-in node types provided by DNA.
@@ -136,8 +136,49 @@
}), NO_PROPERTIES, NOT_MIXIN, UNORDERABLE_CHILD_NODES);
- primaryNodeTypes.addAll(Arrays.asList(new JcrNodeType[] {root, system, namespaces, namespace}));
+ /* Name of node type that holds xmltext from document view import (see JCR 1.0 spec section 7.3.2) */
+ JcrNodeType xmlText = new JcrNodeType(
+ session,
+ DnaLexicon.XML_TEXT_TYPE,
+ Arrays.asList(new NodeType[] {base}),
+ NO_PRIMARY_ITEM_NAME,
+ NO_CHILD_NODES,
+ Arrays.asList(new JcrPropertyDefinition[] {new JcrPropertyDefinition(
+ session,
+ null,
+ JcrLexicon.XMLCHARACTERS,
+ OnParentVersionBehavior.VERSION.getJcrValue(),
+ true,
+ true,
+ true,
+ NO_DEFAULT_VALUES,
+ PropertyType.STRING,
+ NO_CONSTRAINTS,
+ false)}),
+ NOT_MIXIN, UNORDERABLE_CHILD_NODES);
+ /* Mixin type that indicates the node contains an xmltext node which holds xmltext from document view import (see JCR 1.0 spec section 7.3.2) */
+ JcrNodeType xmlContent = new JcrNodeType(
+ session,
+ DnaLexicon.XML_CONTENT,
+ Arrays.asList(new NodeType[] {base}),
+ NO_PRIMARY_ITEM_NAME,
+ Arrays.asList(new JcrNodeDefinition[] {new JcrNodeDefinition(
+ session,
+ null,
+ DnaLexicon.XML_TEXT,
+ OnParentVersionBehavior.VERSION.getJcrValue(),
+ false,
+ true,
+ false,
+ false,
+ DnaLexicon.XML_TEXT_TYPE,
+ new NodeType[] {xmlText})}),
+ NO_PROPERTIES, IS_A_MIXIN, UNORDERABLE_CHILD_NODES);
+
+ primaryNodeTypes.addAll(Arrays.asList(new JcrNodeType[] {root, system, namespaces, namespace, xmlText,}));
+ mixinNodeTypes.addAll(Arrays.asList(new JcrNodeType[] {xmlContent}));
+
}
/**
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java 2009-03-09 17:57:18 UTC (rev 763)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java 2009-03-10 15:17:23 UTC (rev 764)
@@ -33,9 +33,28 @@
public static final Name NAMESPACES = new BasicName(Namespace.URI, "namespaces");
public static final Name NAMESPACE = new BasicName(Namespace.URI, "namespace");
+ public static final Name NODE_DEFINITON = new BasicName(Namespace.URI, "nodeDefinition");
public static final Name ROOT = new BasicName(Namespace.URI, "root");
public static final Name SYSTEM = new BasicName(Namespace.URI, "system");
public static final Name URI = new BasicName(Namespace.URI, "uri");
- public static final Name NODE_DEFINITON = new BasicName(Namespace.URI, "nodeDefinition");
+ /**
+ * Mixin type that indicates the node contains an xmltext node which holds xmltext from document view import (see JCR 1.0
+ * specification section 7.3.2). This node has a child node named {@link DnaLexicon#XML_TEXT} of type
+ * {@link DnaLexicon#XML_TEXT_TYPE}.
+ */
+ public static final Name XML_CONTENT = new BasicName(Namespace.URI, "xmlContent");
+
+ /**
+ * Name of node type that holds xmltext from document view import (see JCR 1.0 specification section 7.3.2). It is defined in
+ * the node type named {@link DnaLexicon#XML_CONTENT}.
+ */
+ public static final Name XML_TEXT_TYPE = new BasicName(Namespace.URI, "xmlText");
+
+ /**
+ * Name of the child node that holds xmltext from document view import (see JCR 1.0 specification section 7.3.2). This is the
+ * name of the child node of the {@link DnaLexicon#XML_CONTENT} mixin type. By definition, this node has a required primary
+ * type of {@link DnaLexicon#XML_TEXT_TYPE}.
+ */
+ public static final Name XML_TEXT = new BasicName(Namespace.URI, "xmltext");
}
Added: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrDocumentViewExporter.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrDocumentViewExporter.java (rev 0)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrDocumentViewExporter.java 2009-03-10 15:17:23 UTC (rev 764)
@@ -0,0 +1,216 @@
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.jcr;
+
+import java.io.OutputStream;
+import java.util.Collections;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.ValueFactories;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * Implementation of {@link AbstractJcrExporter} that implements the document view mapping described in section 6.4.2 of the JCR
+ * 1.0 specification.
+ *
+ * @see JcrSession#exportDocumentView(String, ContentHandler, boolean, boolean)
+ * @see JcrSession#exportDocumentView(String, OutputStream, boolean, boolean)
+ */
+@NotThreadSafe
+class JcrDocumentViewExporter extends AbstractJcrExporter {
+
+ JcrDocumentViewExporter( JcrSession session ) {
+ super(session, Collections.<String>emptyList());
+ }
+
+ /**
+ * Exports <code>node</code> (or the subtree rooted at <code>node</code>) into an XML document by invoking SAX events on
+ * <code>contentHandler</code>.
+ *
+ * @param node the node which should be exported. If <code>noRecursion</code> was set to <code>false</code> in the
+ * constructor, the entire subtree rooted at <code>node</code> will be exported.
+ * @param contentHandler the SAX content handler for which SAX events will be invoked as the XML document is created.
+ * @param skipBinary if <code>true</code>, indicates that binary properties should not be exported
+ * @param noRecurse if<code>true</code>, indicates that only the given node should be exported, otherwise a recursive export
+ * and not any of its child nodes.
+ * @throws SAXException if an exception occurs during generation of the XML document
+ * @throws RepositoryException if an exception occurs accessing the content repository
+ */
+ @Override
+ public void exportNode( Node node,
+ ContentHandler contentHandler,
+ boolean skipBinary,
+ boolean noRecurse ) throws RepositoryException, SAXException {
+ ExecutionContext executionContext = session.getExecutionContext();
+
+ // If this node is a special xmltext node, output it as raw content (see JCR 1.0 spec - section 6.4.2.3
+ if (node.getParent() != null && isXmlTextNode(node)) {
+
+ String xmlCharacters = getXmlCharacters(node);
+ contentHandler.characters(xmlCharacters.toCharArray(), 0, xmlCharacters.length());
+
+ return;
+ }
+
+ ValueFactories valueFactories = executionContext.getValueFactories();
+ AttributesImpl atts = new AttributesImpl();
+
+ // Build the attributes for this node's element
+ PropertyIterator properties = node.getProperties();
+ while (properties.hasNext()) {
+ Property prop = properties.nextProperty();
+
+ if (skipBinary && PropertyType.BINARY == prop.getType()) {
+ continue;
+ }
+
+ Name propName = ((AbstractJcrProperty)prop).getDnaProperty().getName();
+
+ String localPropName = propName.getString(executionContext.getNamespaceRegistry());
+
+ Value value;
+ if (prop instanceof JcrSingleValueProperty) {
+ value = prop.getValue();
+ } else {
+ // Only output the first value of the multi-valued property. This is acceptable as per JCR 1.0 Spec - section
+ // 6.4.2.5
+ value = prop.getValues()[0];
+ }
+ atts.addAttribute(propName.getNamespaceUri(),
+ propName.getLocalName(),
+ localPropName,
+ PropertyType.nameFromValue(prop.getType()),
+ value.getString());
+ }
+
+ Name name;
+
+ // Special case to stub in name for root node as per JCR 1.0 Spec - 6.4.2.2
+ if ("/".equals(node.getPath())) {
+ name = JcrLexicon.ROOT;
+ } else {
+ name = valueFactories.getNameFactory().create(node.getName());
+ }
+
+ startElement(contentHandler, name, atts);
+
+ if (!noRecurse) {
+ NodeIterator nodes = node.getNodes();
+ while (nodes.hasNext()) {
+ exportNode(nodes.nextNode(), contentHandler, skipBinary, noRecurse);
+ }
+ }
+
+ endElement(contentHandler, name);
+
+ }
+
+ /**
+ * Indicates whether the current node is an XML text node as per section 6.4.2.3 of the JCR 1.0 specification.
+ * XML text nodes are nodes that have the name "jcr:xmltext" and only one property (besides the mandatory
+ * "jcr:primaryType"). The property must have a property name of "jcr:xmlcharacters", a type of <code>String</code>,
+ * and does not have multiple values.<p/>
+ * In practice, this is handled in DNA by making XML text nodes have a type of "dna:xmltext", which
+ * enforces these property characteristics.
+ *
+ * @param node the node to test
+ * @return whether this node is a special xml text node
+ * @throws RepositoryException if there is an error accessing the repository
+ */
+ private boolean isXmlTextNode( Node node ) throws RepositoryException {
+ // ./xmltext/xmlcharacters exception (see JSR-170 Spec 6.4.2.3)
+
+ ExecutionContext executionContext = session.getExecutionContext();
+ if (JcrLexicon.XMLTEXT.getString(executionContext.getNamespaceRegistry()).equals(node.getName())) {
+ if (node.getNodes().getSize() == 0) {
+
+ PropertyIterator properties = node.getProperties();
+ boolean xmlCharactersFound = false;
+
+ while (properties.hasNext()) {
+ Property property = properties.nextProperty();
+
+ if (JcrLexicon.PRIMARY_TYPE.getString(executionContext.getNamespaceRegistry()).equals(property.getName())) {
+ continue;
+ }
+
+ if (JcrLexicon.XMLCHARACTERS.getString(executionContext.getNamespaceRegistry()).equals(property.getName())) {
+ xmlCharactersFound = true;
+ continue;
+ }
+
+ // If the xmltext node has any properties other than primaryType or xmlcharacters, return false;
+ return false;
+ }
+
+ return xmlCharactersFound;
+ }
+ }
+
+ return false;
+
+ }
+
+ /**
+ * Returns the XML characters for the given node.
+ * The node must be an XML text node, as defined in {@link #isXmlTextNode(Node)}.
+ *
+ * @param node the node for which XML characters will be retrieved.
+ * @return the xml characters for this node
+ * @throws RepositoryException if there is an error accessing this node
+ */
+ private String getXmlCharacters( Node node ) throws RepositoryException {
+ // ./xmltext/xmlcharacters exception (see JSR-170 Spec 6.4.2.3)
+
+ assert isXmlTextNode(node);
+
+ ExecutionContext executionContext = session.getExecutionContext();
+ Property xmlCharacters = node.getProperty(JcrLexicon.XMLCHARACTERS.getString(executionContext.getNamespaceRegistry()));
+
+ assert xmlCharacters != null;
+
+ if (xmlCharacters.getDefinition().isMultiple()) {
+ StringBuffer buff = new StringBuffer();
+
+ for (Value value : xmlCharacters.getValues()) {
+ buff.append(value.getString());
+ }
+
+ return buff.toString();
+ }
+
+ return xmlCharacters.getValue().getString();
+ }
+
+}
Property changes on: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrDocumentViewExporter.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrI18n.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrI18n.java 2009-03-09 17:57:18 UTC (rev 763)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrI18n.java 2009-03-10 15:17:23 UTC (rev 764)
@@ -63,7 +63,7 @@
public static I18n invalidNamePattern;
public static I18n itemNotFoundWithUuid;
public static I18n errorWhileFindingNodeWithUuid;
- public static I18n nodeDefinitionCouldBeDeterminedForNode;
+ public static I18n nodeDefinitionCouldNotBeDeterminedForNode;
public static I18n typeNotFound;
public static I18n supertypeNotFound;
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNamespaceRegistry.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNamespaceRegistry.java 2009-03-09 17:57:18 UTC (rev 763)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNamespaceRegistry.java 2009-03-10 15:17:23 UTC (rev 764)
@@ -67,6 +67,11 @@
static final String XMLNS_NAMESPACE_PREFIX = XMLConstants.XMLNS_ATTRIBUTE;
static final String XMLNS_NAMESPACE_URI = XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
+ static final String XML_SCHEMA_NAMESPACE_PREFIX = "xsd";
+ static final String XML_SCHEMA_NAMESPACE_URI = "http://www.w3.org/2001/XMLSchema";
+ static final String XML_SCHEMA_INSTANCE_NAMESPACE_PREFIX = "xsi";
+ static final String XML_SCHEMA_INSTANCE_NAMESPACE_URI = "http://www.w3.org/2001/XMLSchema-instance";
+
static final Set<String> STANDARD_BUILT_IN_PREFIXES;
static final Set<String> STANDARD_BUILT_IN_URIS;
static final Map<String, String> STANDARD_BUILT_IN_NAMESPACES_BY_PREFIX;
@@ -82,6 +87,8 @@
namespaces.put(JcrSvLexicon.Namespace.PREFIX, JcrSvLexicon.Namespace.URI);
namespaces.put(XML_NAMESPACE_PREFIX, XML_NAMESPACE_URI);
namespaces.put(XMLNS_NAMESPACE_PREFIX, XMLNS_NAMESPACE_URI);
+ namespaces.put(XML_SCHEMA_NAMESPACE_PREFIX, XML_SCHEMA_NAMESPACE_URI);
+ namespaces.put(XML_SCHEMA_INSTANCE_NAMESPACE_PREFIX, XML_SCHEMA_INSTANCE_NAMESPACE_URI);
namespaces.put(DnaLexicon.Namespace.PREFIX, DnaLexicon.Namespace.URI);
// Set up the reverse map for the standard namespaces ...
Map<String, String> prefixes = new HashMap<String, String>();
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeType.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeType.java 2009-03-09 17:57:18 UTC (rev 763)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeType.java 2009-03-10 15:17:23 UTC (rev 764)
@@ -171,6 +171,7 @@
// Check if the node can be added with the named child node definition
if (childNode != null && primaryNodeTypeName != null) {
NodeType primaryNodeType = getPrimaryNodeType(primaryNodeTypeName);
+ if (primaryNodeType == null) return null;
if (!checkTypeAgainstDefinition(primaryNodeType, childNode)) return null;
}
return childNode;
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java 2009-03-09 17:57:18 UTC (rev 763)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java 2009-03-10 15:17:23 UTC (rev 764)
@@ -73,6 +73,7 @@
import org.jboss.dna.graph.property.basic.LocalNamespaceRegistry;
import org.jboss.dna.jcr.JcrNamespaceRegistry.Behavior;
import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
import com.google.common.base.ReferenceType;
import com.google.common.collect.ReferenceMap;
@@ -290,53 +291,81 @@
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
* @see javax.jcr.Session#exportDocumentView(java.lang.String, org.xml.sax.ContentHandler, boolean, boolean)
*/
public void exportDocumentView( String absPath,
ContentHandler contentHandler,
boolean skipBinary,
- boolean noRecurse ) {
- throw new UnsupportedOperationException();
+ boolean noRecurse ) throws RepositoryException, SAXException {
+ CheckArg.isNotNull(absPath, "absPath");
+ CheckArg.isNotNull(contentHandler, "contentHandler");
+
+ Path exportRootPath = executionContext.getValueFactories().getPathFactory().create(absPath);
+ Node exportRootNode = getNode(exportRootPath);
+
+ AbstractJcrExporter exporter = new JcrDocumentViewExporter(this);
+
+ exporter.exportView(exportRootNode, contentHandler, skipBinary, noRecurse);
}
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
* @see javax.jcr.Session#exportDocumentView(java.lang.String, java.io.OutputStream, boolean, boolean)
*/
public void exportDocumentView( String absPath,
OutputStream out,
boolean skipBinary,
- boolean noRecurse ) {
- throw new UnsupportedOperationException();
+ boolean noRecurse ) throws RepositoryException {
+ CheckArg.isNotNull(absPath, "absPath");
+ CheckArg.isNotNull(out, "out");
+
+ Path exportRootPath = executionContext.getValueFactories().getPathFactory().create(absPath);
+ Node exportRootNode = getNode(exportRootPath);
+
+ AbstractJcrExporter exporter = new JcrDocumentViewExporter(this);
+
+ exporter.exportView(exportRootNode, out, skipBinary, noRecurse);
}
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
* @see javax.jcr.Session#exportSystemView(java.lang.String, org.xml.sax.ContentHandler, boolean, boolean)
*/
public void exportSystemView( String absPath,
ContentHandler contentHandler,
boolean skipBinary,
- boolean noRecurse ) {
- throw new UnsupportedOperationException();
+ boolean noRecurse ) throws RepositoryException, SAXException {
+ CheckArg.isNotNull(absPath, "absPath");
+ CheckArg.isNotNull(contentHandler, "contentHandler");
+
+ Path exportRootPath = executionContext.getValueFactories().getPathFactory().create(absPath);
+ Node exportRootNode = getNode(exportRootPath);
+
+ AbstractJcrExporter exporter = new JcrSystemViewExporter(this);
+
+ exporter.exportView(exportRootNode, contentHandler, skipBinary, noRecurse);
}
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
* @see javax.jcr.Session#exportSystemView(java.lang.String, java.io.OutputStream, boolean, boolean)
*/
public void exportSystemView( String absPath,
OutputStream out,
boolean skipBinary,
- boolean noRecurse ) {
- throw new UnsupportedOperationException();
+ boolean noRecurse ) throws RepositoryException {
+ CheckArg.isNotNull(absPath, "absPath");
+ CheckArg.isNotNull(out, "out");
+
+ Path exportRootPath = executionContext.getValueFactories().getPathFactory().create(absPath);
+ Node exportRootNode = getNode(exportRootPath);
+
+ AbstractJcrExporter exporter = new JcrSystemViewExporter(this);
+
+ exporter.exportView(exportRootNode, out, skipBinary, noRecurse);
}
/**
@@ -518,7 +547,7 @@
String childName = path.getLastSegment().getName().getString(namespaces);
definition = nodeType.findBestNodeDefinitionForChild(childName, primaryTypeNameString);
if (definition == null) {
- String msg = JcrI18n.nodeDefinitionCouldBeDeterminedForNode.text(path, workspace.getName());
+ String msg = JcrI18n.nodeDefinitionCouldNotBeDeterminedForNode.text(path, workspace.getName());
throw new RepositorySourceException(msg);
}
}
Added: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSystemViewExporter.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSystemViewExporter.java (rev 0)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSystemViewExporter.java 2009-03-10 15:17:23 UTC (rev 764)
@@ -0,0 +1,244 @@
+package org.jboss.dna.jcr;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.List;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.common.util.Base64;
+import org.jboss.dna.common.xml.XmlCharacters;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.property.Name;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * Implementation of {@link AbstractJcrExporter} that implements the system view mapping described in section 6.4.1 of the JCR 1.0
+ * specification.
+ *
+ * @see JcrSession#exportSystemView(String, ContentHandler, boolean, boolean)
+ * @see JcrSession#exportSystemView(String, OutputStream, boolean, boolean)
+ */
+@NotThreadSafe
+class JcrSystemViewExporter extends AbstractJcrExporter {
+
+ /**
+ * Buffer size for reading Base64-encoded binary streams for export.
+ */
+ private static final int BASE_64_BUFFER_SIZE = 1024;
+
+ /**
+ * The list of the special JCR properties that must be exported first for each node. These properties must be exported in list
+ * order if they are present on the node as per section 6.4.1 rule 11.
+ */
+ private static final List<Name> SPECIAL_PROPERTY_NAMES = Arrays.asList(new Name[] {JcrLexicon.PRIMARY_TYPE,
+ JcrLexicon.MIXIN_TYPES, JcrLexicon.UUID});
+
+ JcrSystemViewExporter( JcrSession session ) {
+ super(session, Arrays.asList(new String[] {"xml"}));
+ }
+
+ /**
+ * Exports <code>node</code> (or the subtree rooted at <code>node</code>) into an XML document by invoking SAX events on
+ * <code>contentHandler</code>.
+ *
+ * @param node the node which should be exported. If <code>noRecursion</code> was set to <code>false</code> in the
+ * constructor, the entire subtree rooted at <code>node</code> will be exported.
+ * @param contentHandler the SAX content handler for which SAX events will be invoked as the XML document is created.
+ * @param skipBinary if <code>true</code>, indicates that binary properties should not be exported
+ * @param noRecurse if<code>true</code>, indicates that only the given node should be exported, otherwise a recursive export
+ * and not any of its child nodes.
+ * @throws SAXException if an exception occurs during generation of the XML document
+ * @throws RepositoryException if an exception occurs accessing the content repository
+ */
+ @Override
+ public void exportNode( Node node,
+ ContentHandler contentHandler,
+ boolean skipBinary,
+ boolean noRecurse ) throws RepositoryException, SAXException {
+ ExecutionContext executionContext = session.getExecutionContext();
+
+ // start the sv:node element for this JCR node
+ AttributesImpl atts = new AttributesImpl();
+ atts.addAttribute(JcrSvLexicon.NAME.getNamespaceUri(),
+ JcrSvLexicon.NAME.getLocalName(),
+ JcrSvLexicon.NAME.getString(executionContext.getNamespaceRegistry()),
+ PropertyType.nameFromValue(PropertyType.STRING),
+ node.getName());
+
+ startElement(contentHandler, JcrSvLexicon.NODE, atts);
+
+ // Output any special properties first (see Javadoc for SPECIAL_PROPERTY_NAMES for more context)
+ for (Name specialPropertyName : SPECIAL_PROPERTY_NAMES) {
+ Property specialProperty = ((AbstractJcrNode)node).getProperty(specialPropertyName);
+
+ if (specialProperty != null) {
+ emitProperty(specialProperty, contentHandler);
+ }
+ }
+
+ PropertyIterator properties = node.getProperties();
+ while (properties.hasNext()) {
+ exportProperty(properties.nextProperty(), contentHandler, skipBinary);
+ }
+
+ if (!noRecurse) {
+ NodeIterator nodes = node.getNodes();
+ while (nodes.hasNext()) {
+ exportNode(nodes.nextNode(), contentHandler, skipBinary, noRecurse);
+ }
+ }
+
+ endElement(contentHandler, JcrSvLexicon.NODE);
+ }
+
+ /**
+ * @param property
+ * @param contentHandler the SAX content handler for which SAX events will be invoked as the XML document is created.
+ * @param skipBinary if <code>true</code>, indicates that binary properties should not be exported
+ * @throws SAXException if an exception occurs during generation of the XML document
+ * @throws RepositoryException if an exception occurs accessing the content repository
+ */
+ private void exportProperty( Property property,
+ ContentHandler contentHandler,
+ boolean skipBinary ) throws RepositoryException, SAXException {
+ assert property instanceof AbstractJcrProperty : "Illegal attempt to use " + getClass().getName()
+ + " on non-DNA property";
+
+ AbstractJcrProperty prop = (AbstractJcrProperty)property;
+
+ Name propertyName = prop.getDnaProperty().getName();
+ if (SPECIAL_PROPERTY_NAMES.contains(propertyName)) {
+ return;
+ }
+
+ if (skipBinary && PropertyType.BINARY == prop.getType()) {
+ return;
+ }
+
+ emitProperty(property, contentHandler);
+ }
+
+ /**
+ * Fires the appropriate SAX events on the content handler to build the XML elements for the property.
+ *
+ * @param property the property to be exported
+ * @param contentHandler the SAX content handler for which SAX events will be invoked as the XML document is created.
+ * @throws SAXException if an exception occurs during generation of the XML document
+ * @throws RepositoryException if an exception occurs accessing the content repository
+ */
+ private void emitProperty( Property property,
+ ContentHandler contentHandler ) throws RepositoryException, SAXException {
+ assert property instanceof AbstractJcrProperty : "Illegal attempt to use " + getClass().getName()
+ + " on non-DNA property";
+
+ ExecutionContext executionContext = session.getExecutionContext();
+ AbstractJcrProperty prop = (AbstractJcrProperty)property;
+
+ // first set the property sv:name attribute
+ AttributesImpl propAtts = new AttributesImpl();
+ propAtts.addAttribute(JcrSvLexicon.NAME.getNamespaceUri(),
+ JcrSvLexicon.NAME.getLocalName(),
+ JcrSvLexicon.NAME.getString(executionContext.getNamespaceRegistry()),
+ PropertyType.nameFromValue(PropertyType.STRING),
+ prop.getName());
+
+ // and it's sv:type attribute
+ propAtts.addAttribute(JcrSvLexicon.TYPE.getNamespaceUri(),
+ JcrSvLexicon.TYPE.getLocalName(),
+ JcrSvLexicon.TYPE.getString(executionContext.getNamespaceRegistry()),
+ PropertyType.nameFromValue(PropertyType.STRING),
+ PropertyType.nameFromValue(prop.getType()));
+
+ // output the sv:property element
+ startElement(contentHandler, JcrSvLexicon.PROPERTY, propAtts);
+
+ // then output a sv:value element for each of its values
+ if (prop instanceof JcrMultiValueProperty) {
+ Value[] values = prop.getValues();
+ for (int i = 0; i < values.length; i++) {
+
+ emitValue(values[i], contentHandler, property.getType());
+ }
+ } else {
+ emitValue(property.getValue(), contentHandler, property.getType());
+ }
+
+ // end the sv:property element
+ endElement(contentHandler, JcrSvLexicon.PROPERTY);
+ }
+
+ /**
+ * Fires the appropriate SAX events on the content handler to build the XML elements for the value.
+ *
+ * @param value the value to be exported
+ * @param contentHandler the SAX content handler for which SAX events will be invoked as the XML document is created.
+ * @param propertyType the {@link PropertyType} for the given value
+ * @throws SAXException if an exception occurs during generation of the XML document
+ * @throws RepositoryException if an exception occurs accessing the content repository
+ */
+ private void emitValue( Value value,
+ ContentHandler contentHandler,
+ int propertyType ) throws RepositoryException, SAXException {
+
+ if (PropertyType.BINARY == propertyType) {
+ startElement(contentHandler, JcrSvLexicon.VALUE, null);
+
+ byte[] bytes = new byte[BASE_64_BUFFER_SIZE];
+ int len;
+
+ try {
+ InputStream stream = new Base64.InputStream(value.getStream(), Base64.ENCODE | Base64.URL_SAFE
+ | Base64.DONT_BREAK_LINES);
+
+ while (-1 != (len = stream.read(bytes))) {
+ contentHandler.characters(new String(bytes, 0, len).toCharArray(), 0, len);
+ }
+ } catch (IOException ioe) {
+ throw new RepositoryException(ioe);
+ }
+
+ endElement(contentHandler, JcrSvLexicon.VALUE);
+ } else {
+ String s = value.getString();
+
+ // Per 6.4.1.2 Rule #7 of the JCR 1.0 spec, need to check invalid XML characters
+
+ char[] chars = s.toCharArray();
+
+ boolean allCharsAreValidXml = true;
+ for (int i = 0; i < chars.length; i++) {
+ if (!XmlCharacters.isValid(chars[i])) {
+ allCharsAreValidXml = false;
+ break;
+ }
+ }
+
+ if (allCharsAreValidXml) {
+
+ startElement(contentHandler, JcrSvLexicon.VALUE, null);
+ contentHandler.characters(chars, 0, chars.length);
+ endElement(contentHandler, JcrSvLexicon.VALUE);
+ } else {
+ AttributesImpl valueAtts = new AttributesImpl();
+ valueAtts.addAttribute("xsi", "type", "xsi:type", "STRING", "xsd:base64Binary");
+
+ startElement(contentHandler, JcrSvLexicon.VALUE, valueAtts);
+ chars = Base64.encodeBytes(s.getBytes(), Base64.URL_SAFE).toCharArray();
+ contentHandler.characters(chars, 0, chars.length);
+ endElement(contentHandler, JcrSvLexicon.VALUE);
+ }
+ }
+
+ }
+
+}
Property changes on: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSystemViewExporter.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties
===================================================================
--- trunk/dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties 2009-03-09 17:57:18 UTC (rev 763)
+++ trunk/dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties 2009-03-10 15:17:23 UTC (rev 764)
@@ -53,7 +53,7 @@
invalidNamePattern = The "{1}" name pattern contained the '{0}' character, which is not allowed in a name pattern
itemNotFoundWithUuid = An item with UUID "{0}" could not be found in workspace "{1}"
errorWhileFindingNodeWithUuid = Error while finding the item with UUID "{0}" in workspace "{1}"
-nodeDefinitionCouldBeDeterminedForNode = Unable to determine a valid node definition for the node "{0}" in workspace "{1}"
+nodeDefinitionCouldNotBeDeterminedForNode = Unable to determine a valid node definition for the node "{0}" in workspace "{1}"
REP_NAME_DESC = DNA Repository
REP_VENDOR_DESC = JBoss - A division of Red Hat Middleware LLC
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-03-09 17:57:18 UTC (rev 763)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-03-10 15:17:23 UTC (rev 764)
@@ -108,8 +108,8 @@
addTestSuite(org.apache.jackrabbit.test.api.SessionReadMethodsTest.class);
// addTestSuite(org.apache.jackrabbit.test.api.WorkspaceReadMethodsTest.class);
addTestSuite(org.apache.jackrabbit.test.api.ReferenceableRootNodesTest.class);
- // addTestSuite(org.apache.jackrabbit.test.api.ExportSysViewTest.class);
- // addTestSuite(org.apache.jackrabbit.test.api.ExportDocViewTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.ExportSysViewTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.ExportDocViewTest.class);
addTestSuite(org.apache.jackrabbit.test.api.RepositoryLoginTest.class);
// These might not all be level one tests
Modified: trunk/dna-jcr/src/test/resources/repositoryJackrabbitTck.xml
===================================================================
--- trunk/dna-jcr/src/test/resources/repositoryJackrabbitTck.xml 2009-03-09 17:57:18 UTC (rev 763)
+++ trunk/dna-jcr/src/test/resources/repositoryJackrabbitTck.xml 2009-03-10 15:17:23 UTC (rev 764)
@@ -26,9 +26,13 @@
-->
<testroot xmlns:jcr="http://www.jcp.org/jcr/1.0"
xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
+ xmlns:dna="http://www.jboss.org/dna/1.0"
jcr:primaryType="nt:unstructured">
- <nt:unstructured jcr:name="node1" jcr:primaryType="nt:unstructured" prop1="foo" />
- <nt:unstructured jcr:name="node2" jcr:primaryType="nt:unstructured" prop2="bar" />
- <nt:unstructured jcr:name="node3" jcr:primaryType="nt:unstructured" />
- <nt:unstructured jcr:name="node4" jcr:primaryType="nt:unstructured" />
+ <nt:unstructured jcr:name="node1" prop1="<foo&foo>" >
+ <!-- This stanza checks for the jcr:xmltext special case for document export. DO NOT change this element. -->
+ <dna:xmlText jcr:name="jcr:xmltext" jcr:xmlcharacters="This is my "XML" text!" />
+ </nt:unstructured>
+ <nt:unstructured jcr:name="node2 has a multi-word name" prop2="bar" />
+ <nt:unstructured jcr:name="node3" />
+ <nt:unstructured jcr:name="node4" />
</testroot>
\ No newline at end of file
15 years, 1 month
DNA SVN: r763 - in trunk: dna-jcr/src/main/java/org/jboss/dna/jcr and 1 other directories.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-03-09 13:57:18 -0400 (Mon, 09 Mar 2009)
New Revision: 763
Added:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPathAndUuid.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithProperties.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithProperty.java
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/Location.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPath.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPathAndProperties.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPathAndProperty.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithUuid.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrProperty.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrMultiValueProperty.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNode.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRootNode.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSingleValueProperty.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrPropertyTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrMultiValuePropertyTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrNodeTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRootNodeTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSingleValuePropertyTest.java
Log:
DNA-194 Implement update JCR capability
Refactored the fields that are used in the JcrAbstractNode, JcrNode, and JcrRootNode implementations. Because Location objects will play a much more significant role, several new implementations of Location were added, including an optimum implementation of a Location with a path and UUID.
Also made a number of the very-oft-used package-level methods final, hopefully increasing the chance they're inlined. Minimal risk of overriding, although some tests were made a little more complicated (but probably better overall anyway).
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/Location.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/Location.java 2009-03-06 17:03:00 UTC (rev 762)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/Location.java 2009-03-09 17:57:18 UTC (rev 763)
@@ -38,7 +38,6 @@
import org.jboss.dna.graph.property.NamespaceRegistry;
import org.jboss.dna.graph.property.Path;
import org.jboss.dna.graph.property.Property;
-import org.jboss.dna.graph.property.basic.BasicSingleValueProperty;
/**
* The location of a node, as specified by either its path, UUID, and/or identification properties.
@@ -102,8 +101,12 @@
*/
public static Location create( Path path,
UUID uuid ) {
- CheckArg.isNotNull(uuid, "uuid");
- return new LocationWithPathAndProperty(path, new BasicSingleValueProperty(DnaLexicon.UUID, uuid));
+ if (path == null) {
+ CheckArg.isNotNull(uuid, "uuid");
+ return new LocationWithUuid(uuid);
+ }
+ if (uuid == null) return new LocationWithPath(path);
+ return new LocationWithPathAndUuid(path, uuid);
}
/**
@@ -182,7 +185,7 @@
*/
public static Location create( Property idProperty ) {
CheckArg.isNotNull(idProperty, "idProperty");
- return new LocationWithPathAndProperty(null, idProperty);
+ return new LocationWithProperty(idProperty);
}
/**
@@ -197,6 +200,7 @@
Property... remainingIdProperties ) {
CheckArg.isNotNull(firstIdProperty, "firstIdProperty");
CheckArg.isNotNull(remainingIdProperties, "remainingIdProperties");
+ if (remainingIdProperties.length == 0) return new LocationWithProperty(firstIdProperty);
List<Property> idProperties = new ArrayList<Property>(1 + remainingIdProperties.length);
Set<Name> names = new HashSet<Name>();
names.add(firstIdProperty.getName());
@@ -227,9 +231,9 @@
assert false;
return null; // never get here
case 1:
- return new LocationWithPathAndProperty(null, idPropertiesList.get(0));
+ return new LocationWithProperty(idPropertiesList.get(0));
default:
- return new LocationWithPathAndProperties(null, idPropertiesList);
+ return new LocationWithProperties(idPropertiesList);
}
}
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPath.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPath.java 2009-03-06 17:03:00 UTC (rev 762)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPath.java 2009-03-09 17:57:18 UTC (rev 763)
@@ -39,7 +39,7 @@
* @see Location
*/
@Immutable
-class LocationWithPath extends Location {
+final class LocationWithPath extends Location {
private final Path path;
private final int hashCode;
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPathAndProperties.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPathAndProperties.java 2009-03-06 17:03:00 UTC (rev 762)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPathAndProperties.java 2009-03-09 17:57:18 UTC (rev 763)
@@ -40,7 +40,7 @@
* @see Location
*/
@Immutable
-class LocationWithPathAndProperties extends Location {
+final class LocationWithPathAndProperties extends Location {
private final Path path;
private final List<Property> idProperties;
@@ -54,7 +54,7 @@
* @param idProperties the identification properties
*/
LocationWithPathAndProperties( Path path,
- List<Property> idProperties ) {
+ List<Property> idProperties ) {
assert idProperties != null;
assert !idProperties.isEmpty();
this.path = path;
@@ -125,7 +125,7 @@
newIdProperties = Collections.unmodifiableList(newIdProperties);
return new LocationWithPathAndProperties(path, newIdProperties);
}
- return Location.create(path, newIdProperty);
+ return new LocationWithPathAndProperty(path, newIdProperty);
}
/**
@@ -136,7 +136,7 @@
@Override
public Location with( Path newPath ) {
if (newPath == null || this.getPath().equals(newPath)) return this;
- return Location.create(newPath, idProperties);
+ return new LocationWithPathAndProperties(newPath, idProperties);
}
/**
@@ -156,6 +156,6 @@
List<Property> newIdProperties = new ArrayList<Property>(idProperties.size() + 1);
newIdProperties.addAll(idProperties);
newIdProperties.add(newProperty);
- return Location.create(path, newIdProperties);
+ return new LocationWithPathAndProperties(path, newIdProperties);
}
}
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPathAndProperty.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPathAndProperty.java 2009-03-06 17:03:00 UTC (rev 762)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPathAndProperty.java 2009-03-09 17:57:18 UTC (rev 763)
@@ -41,7 +41,7 @@
* @see Location
*/
@Immutable
-class LocationWithPathAndProperty extends Location {
+final class LocationWithPathAndProperty extends Location {
private final Path path;
private final List<Property> idProperties;
@@ -56,16 +56,16 @@
*/
LocationWithPathAndProperty( Path path,
Property idProperty ) {
+ assert path != null;
assert idProperty != null;
assert !idProperty.isEmpty();
- // The path could be null
this.path = path;
this.idProperties = Collections.singletonList(idProperty);
// Paths are immutable, Properties are immutable, the idProperties list
// is wrapped in an unmodifiableList by the Location factory methods...
// ... so we can cache the hash code.
- hashCode = HashCode.compute(path, idProperties);
+ hashCode = HashCode.compute(this.path, idProperties);
}
/**
@@ -81,6 +81,16 @@
/**
* {@inheritDoc}
*
+ * @see org.jboss.dna.graph.Location#hasPath()
+ */
+ @Override
+ public final boolean hasPath() {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
* @see Location#getIdProperties()
*/
@Override
@@ -146,9 +156,9 @@
if (newIdProperty == null || newIdProperty.isEmpty()) return this;
Property idProperty = idProperties.get(0); // fast
if (newIdProperty.getName().equals(idProperty.getName())) {
- return path == null ? Location.create(newIdProperty) : Location.create(path, newIdProperty);
+ return new LocationWithPathAndProperty(path, newIdProperty);
}
- return path == null ? Location.create(idProperty, newIdProperty) : Location.create(path, idProperty, newIdProperty);
+ return Location.create(path, idProperty, newIdProperty);
}
/**
@@ -158,10 +168,10 @@
*/
@Override
public Location with( Path newPath ) {
- if (newPath == null && path == null) return this;
- if (path != null && (path.equals(newPath))) return this;
+ if (newPath == null) return Location.create(idProperties);
+ if (path.equals(newPath)) return this;
Property idProperty = idProperties.get(0); // fast
- return Location.create(newPath, idProperty);
+ return new LocationWithPathAndProperty(newPath, idProperty);
}
/**
@@ -171,12 +181,10 @@
*/
@Override
public Location with( UUID uuid ) {
- if (uuid == null) return this;
Property idProperty = idProperties.get(0); // fast
- if (DnaLexicon.UUID.equals(idProperty.getName())) {
- return path == null ? Location.create(uuid) : Location.create(path, uuid);
- }
+ assert !DnaLexicon.UUID.equals(idProperty.getName());
+ if (uuid == null) return Location.create(path);
Property newUuidProperty = new BasicSingleValueProperty(DnaLexicon.UUID, uuid);
- return path == null ? Location.create(idProperty, newUuidProperty) : Location.create(path, idProperty, newUuidProperty);
+ return Location.create(path, idProperty, newUuidProperty);
}
}
Added: trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPathAndUuid.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPathAndUuid.java (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPathAndUuid.java 2009-03-09 17:57:18 UTC (rev 763)
@@ -0,0 +1,181 @@
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.common.util.HashCode;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.basic.BasicSingleValueProperty;
+
+/**
+ * General purpose location type that supports a path and a UUID property. This class should never be directly instantiated by
+ * users of the DNA framework. Instead, use @{link Location#create} to create the correct location.
+ *
+ * @see Location
+ */
+@Immutable
+final class LocationWithPathAndUuid extends Location {
+
+ private final Path path;
+ private final List<Property> idProperties;
+
+ private final int hashCode;
+
+ /**
+ * Create a new location with a given path and identification property.
+ *
+ * @param path the path
+ * @param uuid the UUID
+ */
+ LocationWithPathAndUuid( Path path,
+ UUID uuid ) {
+ assert path != null;
+ assert uuid != null;
+ this.path = path;
+ this.idProperties = Collections.singletonList((Property)new BasicSingleValueProperty(DnaLexicon.UUID, uuid));
+
+ // Paths are immutable, Properties are immutable, the idProperties list
+ // is wrapped in an unmodifiableList by the Location factory methods...
+ // ... so we can cache the hash code.
+ hashCode = HashCode.compute(this.path, idProperties);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#getPath()
+ */
+ @Override
+ public final Path getPath() {
+ return path;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.Location#hasPath()
+ */
+ @Override
+ public final boolean hasPath() {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#getIdProperties()
+ */
+ @Override
+ public final List<Property> getIdProperties() {
+ return idProperties;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#hasIdProperties()
+ */
+ @Override
+ public final boolean hasIdProperties() {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#getIdProperty(Name)
+ */
+ @Override
+ public final Property getIdProperty( Name name ) {
+ CheckArg.isNotNull(name, "name");
+ Property property = idProperties.get(0); // this is fast
+ return property.getName().equals(name) ? property : null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#getUuid()
+ */
+ @Override
+ public final UUID getUuid() {
+ return (UUID)idProperties.get(0).getFirstValue(); // this is fast, and we know this is a UUID object
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return hashCode;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#with(Property)
+ */
+ @Override
+ public Location with( Property newIdProperty ) {
+ if (newIdProperty == null || newIdProperty.isEmpty()) return this;
+ Property idProperty = idProperties.get(0); // fast
+ if (newIdProperty.getName().equals(idProperty.getName())) {
+ return new LocationWithPathAndProperty(path, newIdProperty);
+ }
+ return Location.create(path, idProperty, newIdProperty);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#with(Path)
+ */
+ @Override
+ public Location with( Path newPath ) {
+ if (newPath == null) return Location.create(idProperties);
+ if (path.equals(newPath)) return this;
+ Property idProperty = idProperties.get(0); // fast
+ return new LocationWithPathAndProperty(newPath, idProperty);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#with(UUID)
+ */
+ @Override
+ public Location with( UUID uuid ) {
+ if (uuid == null) return Location.create(path);
+ if (uuid.equals(getUuid())) return this;
+ return new LocationWithPathAndUuid(path, uuid);
+ }
+}
Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithPathAndUuid.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithProperties.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithProperties.java (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithProperties.java 2009-03-09 17:57:18 UTC (rev 763)
@@ -0,0 +1,164 @@
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.util.HashCode;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.basic.BasicSingleValueProperty;
+
+/**
+ * General purpose location type that supports a path and zero or more properties. This class should never be directly
+ * instantiated by users of the DNA framework. Instead, use @{link Location#create} to create the correct location.
+ *
+ * @see Location
+ */
+@Immutable
+final class LocationWithProperties extends Location {
+
+ private final List<Property> idProperties;
+ private final int hashCode;
+
+ /**
+ * Create a new location with a given path and set of identification properties.
+ *
+ * @param idProperties the identification properties
+ */
+ LocationWithProperties( List<Property> idProperties ) {
+ assert idProperties != null;
+ assert !idProperties.isEmpty();
+ this.idProperties = Collections.unmodifiableList(idProperties);
+ // Paths are immutable, Properties are immutable, the idProperties list
+ // is wrapped in an unmodifiableList by the Location factory methods...
+ // ... so we can cache the hash code.
+ hashCode = HashCode.compute(null, idProperties);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#getPath()
+ */
+ @Override
+ public final Path getPath() {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.Location#hasPath()
+ */
+ @Override
+ public final boolean hasPath() {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#getIdProperties()
+ */
+ @Override
+ public final List<Property> getIdProperties() {
+ return idProperties;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#hasIdProperties()
+ */
+ @Override
+ public final boolean hasIdProperties() {
+ return idProperties.size() > 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return hashCode;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#with(Property)
+ */
+ @Override
+ public Location with( Property newIdProperty ) {
+ if (newIdProperty == null || newIdProperty.isEmpty()) return this;
+
+ List<Property> newIdProperties;
+
+ assert hasIdProperties();
+ newIdProperties = new ArrayList<Property>(idProperties.size() + 1);
+ for (Property property : idProperties) {
+ if (!newIdProperty.getName().equals(property.getName())) newIdProperties.add(property);
+ }
+ newIdProperties.add(newIdProperty);
+ newIdProperties = Collections.unmodifiableList(newIdProperties);
+ return new LocationWithProperties(newIdProperties);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#with(Path)
+ */
+ @Override
+ public Location with( Path newPath ) {
+ if (newPath == null || this.getPath().equals(newPath)) return this;
+ return new LocationWithPathAndProperties(newPath, idProperties);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#with(UUID)
+ */
+ @Override
+ public Location with( UUID uuid ) {
+ if (uuid == null) return this;
+ Property newProperty = new BasicSingleValueProperty(DnaLexicon.UUID, uuid);
+ if (this.hasIdProperties()) {
+ Property existing = this.getIdProperty(DnaLexicon.UUID);
+ if (existing != null && existing.equals(newProperty)) return this;
+ }
+
+ List<Property> newIdProperties = new ArrayList<Property>(idProperties.size() + 1);
+ newIdProperties.addAll(idProperties);
+ newIdProperties.add(newProperty);
+ return new LocationWithProperties(newIdProperties);
+ }
+}
Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithProperties.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithProperty.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithProperty.java (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithProperty.java 2009-03-09 17:57:18 UTC (rev 763)
@@ -0,0 +1,193 @@
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.graph;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.common.util.HashCode;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.basic.BasicSingleValueProperty;
+
+/**
+ * General purpose location type that supports a path and a property. This class should never be directly instantiated by users of
+ * the DNA framework. Instead, use @{link Location#create} to create the correct location.
+ *
+ * @see Location
+ */
+@Immutable
+final class LocationWithProperty extends Location {
+
+ protected final List<Property> idProperties;
+
+ private final int hashCode;
+
+ /**
+ * Create a new location with a given path and identification property.
+ *
+ * @param idProperty the identification property
+ */
+ LocationWithProperty( Property idProperty ) {
+ assert idProperty != null;
+ assert !idProperty.isEmpty();
+ // The path could be null
+ this.idProperties = Collections.singletonList(idProperty);
+
+ // Paths are immutable, Properties are immutable, the idProperties list
+ // is wrapped in an unmodifiableList by the Location factory methods...
+ // ... so we can cache the hash code.
+ hashCode = HashCode.compute(null, idProperties);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#getPath()
+ */
+ @Override
+ public final Path getPath() {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.Location#hasPath()
+ */
+ @Override
+ public boolean hasPath() {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#getIdProperties()
+ */
+ @Override
+ public final List<Property> getIdProperties() {
+ return idProperties;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#hasIdProperties()
+ */
+ @Override
+ public final boolean hasIdProperties() {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#getIdProperty(Name)
+ */
+ @Override
+ public final Property getIdProperty( Name name ) {
+ CheckArg.isNotNull(name, "name");
+ Property property = idProperties.get(0); // this is fast
+ return property.getName().equals(name) ? property : null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#getUuid()
+ */
+ @Override
+ public UUID getUuid() {
+ Property property = idProperties.get(0); // this is fast
+ if (DnaLexicon.UUID.equals(property.getName())) {
+ Object value = property.getFirstValue();
+ if (value instanceof UUID) return (UUID)value;
+ if (value instanceof String) return UUID.fromString((String)value);
+ }
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return hashCode;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#with(Property)
+ */
+ @Override
+ public Location with( Property newIdProperty ) {
+ if (newIdProperty == null || newIdProperty.isEmpty()) return this;
+ Property idProperty = idProperties.get(0); // fast
+ if (newIdProperty.getName().equals(idProperty.getName())) {
+ return Location.create(newIdProperty);
+ }
+ List<Property> newIdProperties = new ArrayList<Property>(idProperties.size() + 1);
+ newIdProperties.add(newIdProperty);
+ newIdProperties.addAll(idProperties);
+ return new LocationWithProperties(newIdProperties);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#with(Path)
+ */
+ @Override
+ public Location with( Path newPath ) {
+ if (newPath == null) return this;
+ Property idProperty = idProperties.get(0); // fast
+ return new LocationWithPathAndProperty(newPath, idProperty);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see Location#with(UUID)
+ */
+ @Override
+ public Location with( UUID uuid ) {
+ if (uuid == null) return this;
+ Property idProperty = idProperties.get(0); // fast
+ if (DnaLexicon.UUID.equals(idProperty.getName())) {
+ return new LocationWithUuid(uuid);
+ }
+ List<Property> newIdProperties = new ArrayList<Property>(idProperties.size() + 1);
+ newIdProperties.add(new BasicSingleValueProperty(DnaLexicon.UUID, uuid));
+ newIdProperties.addAll(idProperties);
+ return new LocationWithProperties(newIdProperties);
+ }
+}
Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithProperty.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithUuid.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithUuid.java 2009-03-06 17:03:00 UTC (rev 762)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/LocationWithUuid.java 2009-03-09 17:57:18 UTC (rev 763)
@@ -39,7 +39,7 @@
* @see Location
*/
@Immutable
-public class LocationWithUuid extends Location {
+final class LocationWithUuid extends Location {
private final UUID uuid;
private final int hashCode;
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java 2009-03-06 17:03:00 UTC (rev 762)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java 2009-03-09 17:57:18 UTC (rev 763)
@@ -53,6 +53,7 @@
import javax.jcr.version.VersionHistory;
import net.jcip.annotations.NotThreadSafe;
import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.Location;
import org.jboss.dna.graph.property.Name;
import org.jboss.dna.graph.property.NamespaceRegistry;
import org.jboss.dna.graph.property.Path;
@@ -68,15 +69,18 @@
private static final NodeType[] EMPTY_NODE_TYPES = new NodeType[] {};
private final JcrSession session;
- Map<Name, Property> properties;
- List<Path.Segment> children;
- private UUID uuid;
private final NodeDefinition definition;
+ protected Location location;
+ private Map<Name, Property> properties;
+ private List<Path.Segment> children;
AbstractJcrNode( JcrSession session,
+ Location location,
NodeDefinition definition ) {
assert session != null;
assert definition != null;
+ assert location != null;
+ this.location = location;
this.session = session;
this.definition = definition;
}
@@ -86,12 +90,16 @@
*
* @see javax.jcr.Item#getSession()
*/
- public final Session getSession() {
+ public Session getSession() {
return session;
}
+ final JcrSession session() {
+ return session;
+ }
+
final UUID internalUuid() {
- return uuid;
+ return location.getUuid();
}
/**
@@ -103,7 +111,7 @@
*/
final void setInternalUuid( UUID uuid ) {
assert uuid != null;
- this.uuid = uuid;
+ location = location.with(uuid);
}
final void setChildren( List<Segment> children ) {
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrProperty.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrProperty.java 2009-03-06 17:03:00 UTC (rev 762)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrProperty.java 2009-03-09 17:57:18 UTC (rev 763)
@@ -43,23 +43,19 @@
@NotThreadSafe
abstract class AbstractJcrProperty extends AbstractJcrItem implements Property {
- private final Node node;
- private final ExecutionContext executionContext;
+ private final AbstractJcrNode node;
private final org.jboss.dna.graph.property.Property dnaProperty;
private final PropertyDefinition jcrPropertyDefinition;
private final int propertyType;
- AbstractJcrProperty( Node node,
- ExecutionContext executionContext,
+ AbstractJcrProperty( AbstractJcrNode node,
PropertyDefinition definition,
int propertyType,
org.jboss.dna.graph.property.Property dnaProperty ) {
assert node != null;
- assert executionContext != null;
assert dnaProperty != null;
assert definition != null;
this.node = node;
- this.executionContext = executionContext;
this.dnaProperty = dnaProperty;
this.jcrPropertyDefinition = definition;
this.propertyType = propertyType;
@@ -77,11 +73,11 @@
}
JcrValue createValue( Object value ) {
- return new JcrValue(executionContext.getValueFactories(), getType(), value);
+ return new JcrValue(getExecutionContext().getValueFactories(), getType(), value);
}
final ExecutionContext getExecutionContext() {
- return executionContext;
+ return node.session().getExecutionContext();
}
final org.jboss.dna.graph.property.Property getDnaProperty() {
@@ -116,7 +112,7 @@
* @see javax.jcr.Item#getName()
*/
public final String getName() {
- return dnaProperty.getName().getString(executionContext.getNamespaceRegistry());
+ return dnaProperty.getName().getString(node.namespaces());
}
/**
@@ -142,7 +138,7 @@
*
* @see javax.jcr.Item#getSession()
*/
- public final Session getSession() throws RepositoryException {
+ public final Session getSession() {
return node.getSession();
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrMultiValueProperty.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrMultiValueProperty.java 2009-03-06 17:03:00 UTC (rev 762)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrMultiValueProperty.java 2009-03-09 17:57:18 UTC (rev 763)
@@ -32,7 +32,6 @@
import javax.jcr.ValueFormatException;
import javax.jcr.nodetype.PropertyDefinition;
import net.jcip.annotations.NotThreadSafe;
-import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.property.Property;
/**
@@ -41,12 +40,11 @@
@NotThreadSafe
final class JcrMultiValueProperty extends AbstractJcrProperty {
- JcrMultiValueProperty( Node node,
- ExecutionContext executionContext,
+ JcrMultiValueProperty( AbstractJcrNode node,
PropertyDefinition definition,
int propertyType,
Property dnaProperty ) {
- super(node, executionContext, definition, propertyType, dnaProperty);
+ super(node, definition, propertyType, dnaProperty);
}
/**
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNode.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNode.java 2009-03-06 17:03:00 UTC (rev 762)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNode.java 2009-03-09 17:57:18 UTC (rev 763)
@@ -29,7 +29,8 @@
import javax.jcr.RepositoryException;
import javax.jcr.nodetype.NodeDefinition;
import net.jcip.annotations.NotThreadSafe;
-import org.jboss.dna.graph.property.Path.Segment;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.property.Path;
/**
* @author jverhaeg
@@ -38,26 +39,27 @@
final class JcrNode extends AbstractJcrNode {
private final UUID parentUuid;
- private final Segment segment;
JcrNode( JcrSession session,
UUID parentUuid,
- Segment segment,
+ Location location,
NodeDefinition nodeDefinition ) {
- super(session, nodeDefinition);
+ super(session, location, nodeDefinition);
assert parentUuid != null;
- assert segment != null;
this.parentUuid = parentUuid;
- this.segment = segment;
}
+ final Path.Segment segment() {
+ return location.getPath().getLastSegment();
+ }
+
/**
* {@inheritDoc}
*
* @see javax.jcr.Node#getIndex()
*/
public int getIndex() {
- return segment.getIndex();
+ return segment().getIndex();
}
/**
@@ -66,7 +68,7 @@
* @see javax.jcr.Item#getName()
*/
public String getName() {
- return segment.getName().getString(((JcrSession)getSession()).getExecutionContext().getNamespaceRegistry());
+ return segment().getName().getString(((JcrSession)getSession()).getExecutionContext().getNamespaceRegistry());
}
/**
@@ -75,7 +77,7 @@
* @see javax.jcr.Item#getParent()
*/
public Node getParent() throws ItemNotFoundException {
- Node node = ((JcrSession)getSession()).getNode(parentUuid);
+ Node node = session().getNode(parentUuid);
if (node == null) {
throw new ItemNotFoundException();
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRootNode.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRootNode.java 2009-03-06 17:03:00 UTC (rev 762)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRootNode.java 2009-03-09 17:57:18 UTC (rev 763)
@@ -27,6 +27,7 @@
import javax.jcr.Node;
import javax.jcr.nodetype.NodeDefinition;
import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.graph.Location;
/**
* @author jverhaeg
@@ -35,8 +36,9 @@
final class JcrRootNode extends AbstractJcrNode {
JcrRootNode( JcrSession session,
+ Location location,
NodeDefinition nodeDefinition ) {
- super(session, nodeDefinition);
+ super(session, location, nodeDefinition);
}
/**
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java 2009-03-06 17:03:00 UTC (rev 762)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java 2009-03-09 17:57:18 UTC (rev 763)
@@ -506,7 +506,7 @@
}
// Create the new node ...
- node = new JcrRootNode(this, definition);
+ node = new JcrRootNode(this, location, definition);
} else {
// Find the parent ...
AbstractJcrNode parent = (AbstractJcrNode)getNode(path.getParent());
@@ -524,7 +524,7 @@
}
// Now create the node object ...
- node = new JcrNode(this, parent.internalUuid(), path.getLastSegment(), definition);
+ node = new JcrNode(this, parent.internalUuid(), location, definition);
}
// Now populate the node and add to the cache ...
@@ -830,8 +830,8 @@
Map<Name, Property> properties = new HashMap<Name, Property>();
if (referenceable) {
PropertyDefinition propertyDefinition = propertyDefinitionsByPropertyName.get(JcrLexicon.UUID);
- properties.put(JcrLexicon.UUID, new JcrSingleValueProperty(node, executionContext, propertyDefinition,
- PropertyType.STRING, uuidProperty));
+ properties.put(JcrLexicon.UUID, new JcrSingleValueProperty(node, propertyDefinition, PropertyType.STRING,
+ uuidProperty));
}
// Now create the JCR property object wrappers around the other properties ...
@@ -892,16 +892,16 @@
}
// Figure out the property type ...
- int type = propertyDefinition.getRequiredType();
- if (type == PropertyType.UNDEFINED) {
- type = jcrPropertyTypeFor(dnaProp);
+ int propertyType = propertyDefinition.getRequiredType();
+ if (propertyType == PropertyType.UNDEFINED) {
+ propertyType = jcrPropertyTypeFor(dnaProp);
}
// Create the appropriate JCR property wrapper ...
if (isMultiple) {
- properties.put(name, new JcrMultiValueProperty(node, executionContext, propertyDefinition, type, dnaProp));
+ properties.put(name, new JcrMultiValueProperty(node, propertyDefinition, propertyType, dnaProp));
} else {
- properties.put(name, new JcrSingleValueProperty(node, executionContext, propertyDefinition, type, dnaProp));
+ properties.put(name, new JcrSingleValueProperty(node, propertyDefinition, propertyType, dnaProp));
}
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSingleValueProperty.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSingleValueProperty.java 2009-03-06 17:03:00 UTC (rev 762)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSingleValueProperty.java 2009-03-09 17:57:18 UTC (rev 763)
@@ -31,7 +31,6 @@
import javax.jcr.Value;
import javax.jcr.ValueFormatException;
import javax.jcr.nodetype.PropertyDefinition;
-import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.property.Binary;
import org.jboss.dna.graph.property.Property;
import org.jboss.dna.graph.property.Reference;
@@ -42,12 +41,11 @@
*/
final class JcrSingleValueProperty extends AbstractJcrProperty {
- JcrSingleValueProperty( Node node,
- ExecutionContext executionContext,
+ JcrSingleValueProperty( AbstractJcrNode node,
PropertyDefinition definition,
int propertyType,
Property dnaProperty ) {
- super(node, executionContext, definition, propertyType, dnaProperty);
+ super(node, definition, propertyType, dnaProperty);
}
/**
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java 2009-03-06 17:03:00 UTC (rev 762)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java 2009-03-09 17:57:18 UTC (rev 763)
@@ -50,6 +50,7 @@
import javax.jcr.nodetype.NodeDefinition;
import javax.jcr.version.Version;
import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.Location;
import org.jboss.dna.graph.property.Name;
import org.jboss.dna.graph.property.Path.Segment;
import org.junit.Before;
@@ -85,7 +86,7 @@
MockAbstractJcrNode( JcrSession session,
String name,
Node parent ) {
- super(session, mock(NodeDefinition.class));
+ super(session, Location.create(UUID.randomUUID()), mock(NodeDefinition.class));
this.name = name;
this.parent = parent;
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrPropertyTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrPropertyTest.java 2009-03-06 17:03:00 UTC (rev 762)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrPropertyTest.java 2009-03-09 17:57:18 UTC (rev 763)
@@ -28,6 +28,7 @@
import static org.mockito.Mockito.stub;
import java.io.InputStream;
import java.util.Calendar;
+import java.util.UUID;
import javax.jcr.Item;
import javax.jcr.ItemNotFoundException;
import javax.jcr.ItemVisitor;
@@ -38,9 +39,12 @@
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.Workspace;
+import javax.jcr.nodetype.NodeDefinition;
import javax.jcr.nodetype.PropertyDefinition;
import org.jboss.dna.common.util.StringUtil;
import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.property.Path;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
@@ -58,13 +62,16 @@
@Mock
private Repository repository;
@Mock
- private Session session;
+ private JcrSession session;
+ private AbstractJcrNode node;
@Mock
- private Node node;
+ private NodeDefinition nodeDefinition;
@Mock
private PropertyDefinition propertyDefinition;
private ExecutionContext executionContext;
private org.jboss.dna.graph.property.Property dnaProperty;
+ private Location rootLocation;
+ private Location nodeLocation;
@Before
public void before() throws Exception {
@@ -74,8 +81,21 @@
stub(propertyDefinition.getRequiredType()).toReturn(PropertyType.STRING);
stub(session.getWorkspace()).toReturn(workspace);
stub(session.getRepository()).toReturn(repository);
- stub(node.getSession()).toReturn(session);
- prop = new MockAbstractJcrProperty(node, executionContext, propertyDefinition, dnaProperty);
+ stub(session.getExecutionContext()).toReturn(executionContext);
+
+ UUID rootUuid = UUID.randomUUID();
+ Path rootPath = executionContext.getValueFactories().getPathFactory().createRootPath();
+ rootLocation = Location.create(rootPath, rootUuid);
+ JcrRootNode rootNode = new JcrRootNode(session, rootLocation, nodeDefinition);
+ stub(session.getNode(rootUuid)).toReturn(rootNode);
+
+ UUID uuid = UUID.randomUUID();
+ Path path = executionContext.getValueFactories().getPathFactory().create("/nodeName");
+ nodeLocation = Location.create(path, uuid);
+ node = new JcrNode(session, rootUuid, nodeLocation, nodeDefinition);
+ stub(session.getNode(uuid)).toReturn(node);
+
+ prop = new MockAbstractJcrProperty(node, propertyDefinition, dnaProperty);
}
@Test
@@ -99,19 +119,17 @@
@Test
public void shouldProvideAncestor() throws Exception {
assertThat(prop.getAncestor(prop.getDepth()), is((Item)prop));
- stub(node.getAncestor(node.getDepth())).toReturn(node);
assertThat(prop.getAncestor(prop.getDepth() - 1), is((Item)node));
}
@Test( expected = ItemNotFoundException.class )
public void shouldNotAllowAncestorDepthGreaterThanNodeDepth() throws Exception {
- stub(node.getAncestor(1)).toThrow(new ItemNotFoundException());
- prop.getAncestor(2);
+ prop.getAncestor(3);
}
@Test
public void shouldProvideDepth() throws Exception {
- assertThat(prop.getDepth(), is(1));
+ assertThat(prop.getDepth(), is(2));
}
@Test
@@ -126,20 +144,17 @@
@Test
public void shouldProvideParent() throws Exception {
- assertThat(prop.getParent(), is(node));
+ assertThat(prop.getParent(), is((Node)node));
}
@Test
public void shouldProvidePath() throws Exception {
- stub(node.getPath()).toReturn("/nodeName");
assertThat(prop.getPath(), is("/nodeName/jcr:mimeType"));
}
@Test
public void shouldProvideSession() throws Exception {
- Session session = Mockito.mock(Session.class);
- stub(node.getSession()).toReturn(session);
- assertThat(prop.getSession(), is(session));
+ assertThat(prop.getSession(), is((Session)session));
}
@Test
@@ -151,30 +166,40 @@
public void shouldIndicateSameAsNodeWithSameParentAndSamePropertyName() throws Exception {
org.jboss.dna.graph.property.Property otherDnaProperty = executionContext.getPropertyFactory()
.create(dnaProperty.getName());
- Node otherNode = Mockito.mock(Node.class);
- stub(otherNode.getSession()).toReturn(session);
- stub(node.isSame(otherNode)).toReturn(true);
- Property otherProp = new MockAbstractJcrProperty(otherNode, executionContext, propertyDefinition, otherDnaProperty);
+ // Make the other node have the same UUID ...
+ JcrNode otherNode = new JcrNode(session, rootLocation.getUuid(), nodeLocation, nodeDefinition);
+
+ assertThat(node.isSame(otherNode), is(true));
+ Property prop = new MockAbstractJcrProperty(node, propertyDefinition, otherDnaProperty);
+ Property otherProp = new MockAbstractJcrProperty(otherNode, propertyDefinition, otherDnaProperty);
assertThat(prop.isSame(otherProp), is(true));
}
@Test
public void shouldIndicateDifferentThanNodeWithDifferentParent() throws Exception {
- org.jboss.dna.graph.property.Property otherDnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.NAME);
- Node otherNode = Mockito.mock(Node.class);
- stub(otherNode.getSession()).toReturn(session);
- stub(node.isSame(otherNode)).toReturn(false);
- Property otherProp = new MockAbstractJcrProperty(otherNode, executionContext, propertyDefinition, otherDnaProperty);
+ org.jboss.dna.graph.property.Property otherDnaProperty = executionContext.getPropertyFactory()
+ .create(dnaProperty.getName());
+ UUID otherUuid = UUID.randomUUID();
+ Path otherPath = executionContext.getValueFactories().getPathFactory().create("/nodeName");
+ Location location = Location.create(otherPath, otherUuid);
+ JcrNode otherNode = new JcrNode(session, rootLocation.getUuid(), location, nodeDefinition);
+ stub(session.getNode(otherUuid)).toReturn(otherNode);
+
+ assertThat(node.isSame(otherNode), is(false));
+ Property prop = new MockAbstractJcrProperty(node, propertyDefinition, otherDnaProperty);
+ Property otherProp = new MockAbstractJcrProperty(otherNode, propertyDefinition, otherDnaProperty);
assertThat(prop.isSame(otherProp), is(false));
}
@Test
public void shouldIndicateDifferentThanPropertyWithSameNodeWithDifferentPropertyName() throws Exception {
org.jboss.dna.graph.property.Property otherDnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.NAME);
- Node otherNode = Mockito.mock(Node.class);
- stub(otherNode.getSession()).toReturn(session);
- stub(node.isSame(otherNode)).toReturn(true);
- Property otherProp = new MockAbstractJcrProperty(otherNode, executionContext, propertyDefinition, otherDnaProperty);
+ // Make the other node have the same UUID ...
+ JcrNode otherNode = new JcrNode(session, rootLocation.getUuid(), nodeLocation, nodeDefinition);
+
+ assertThat(node.isSame(otherNode), is(true));
+ Property prop = new MockAbstractJcrProperty(node, propertyDefinition, dnaProperty);
+ Property otherProp = new MockAbstractJcrProperty(otherNode, propertyDefinition, otherDnaProperty);
assertThat(prop.isSame(otherProp), is(false));
}
@@ -230,11 +255,10 @@
private class MockAbstractJcrProperty extends AbstractJcrProperty {
- MockAbstractJcrProperty( Node node,
- ExecutionContext executionContext,
+ MockAbstractJcrProperty( AbstractJcrNode node,
PropertyDefinition propertyDefinition,
org.jboss.dna.graph.property.Property dnaProperty ) {
- super(node, executionContext, propertyDefinition, propertyDefinition.getRequiredType(), dnaProperty);
+ super(node, propertyDefinition, propertyDefinition.getRequiredType(), dnaProperty);
}
/**
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrMultiValuePropertyTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrMultiValuePropertyTest.java 2009-03-06 17:03:00 UTC (rev 762)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrMultiValuePropertyTest.java 2009-03-09 17:57:18 UTC (rev 763)
@@ -27,13 +27,16 @@
import static org.hamcrest.core.IsNull.notNullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.stub;
-import javax.jcr.Node;
+import java.util.UUID;
import javax.jcr.Property;
import javax.jcr.PropertyType;
import javax.jcr.Value;
import javax.jcr.ValueFormatException;
+import javax.jcr.nodetype.NodeDefinition;
import javax.jcr.nodetype.PropertyDefinition;
import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.property.Path;
import org.junit.Before;
import org.junit.Test;
import org.mockito.MockitoAnnotations;
@@ -45,10 +48,13 @@
public class JcrMultiValuePropertyTest {
private Property prop;
- @Mock
- private Node node;
+ private AbstractJcrNode node;
private ExecutionContext executionContext;
@Mock
+ private JcrSession session;
+ @Mock
+ private NodeDefinition nodeDefinition;
+ @Mock
private PropertyDefinition definition;
private org.jboss.dna.graph.property.Property dnaProperty;
@@ -56,10 +62,17 @@
public void before() {
MockitoAnnotations.initMocks(this);
executionContext = new ExecutionContext();
+
+ UUID rootUuid = UUID.randomUUID();
+ Path rootPath = executionContext.getValueFactories().getPathFactory().createRootPath();
+ Location rootLocation = Location.create(rootPath, rootUuid);
+ node = new JcrRootNode(session, rootLocation, nodeDefinition);
+ stub(session.getExecutionContext()).toReturn(executionContext);
+
dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE, true);
stub(definition.getRequiredType()).toReturn(PropertyType.BOOLEAN);
stub(definition.isMultiple()).toReturn(true);
- prop = new JcrMultiValueProperty(node, executionContext, definition, definition.getRequiredType(), dnaProperty);
+ prop = new JcrMultiValueProperty(node, definition, definition.getRequiredType(), dnaProperty);
}
@Test
@@ -138,7 +151,7 @@
dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE, value);
stub(definition.getRequiredType()).toReturn(PropertyType.STRING);
stub(definition.isMultiple()).toReturn(true);
- prop = new JcrMultiValueProperty(node, executionContext, definition, definition.getRequiredType(), dnaProperty);
+ prop = new JcrMultiValueProperty(node, definition, definition.getRequiredType(), dnaProperty);
lengths = prop.getLengths();
assertThat(lengths, notNullValue());
assertThat(lengths.length, is(1));
@@ -149,7 +162,7 @@
dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE, value);
stub(definition.getRequiredType()).toReturn(PropertyType.STRING);
stub(definition.isMultiple()).toReturn(true);
- prop = new JcrMultiValueProperty(node, executionContext, definition, definition.getRequiredType(), dnaProperty);
+ prop = new JcrMultiValueProperty(node, definition, definition.getRequiredType(), dnaProperty);
lengths = prop.getLengths();
assertThat(lengths, notNullValue());
assertThat(lengths.length, is(1));
@@ -159,7 +172,7 @@
dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE, (Object[])values);
stub(definition.getRequiredType()).toReturn(PropertyType.STRING);
stub(definition.isMultiple()).toReturn(true);
- prop = new JcrMultiValueProperty(node, executionContext, definition, definition.getRequiredType(), dnaProperty);
+ prop = new JcrMultiValueProperty(node, definition, definition.getRequiredType(), dnaProperty);
lengths = prop.getLengths();
assertThat(lengths, notNullValue());
assertThat(lengths.length, is(values.length));
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrNodeTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrNodeTest.java 2009-03-06 17:03:00 UTC (rev 762)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrNodeTest.java 2009-03-09 17:57:18 UTC (rev 763)
@@ -25,7 +25,6 @@
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
-import static org.mockito.Matchers.anyObject;
import static org.mockito.Mockito.stub;
import java.util.ArrayList;
import java.util.HashMap;
@@ -35,12 +34,12 @@
import javax.jcr.Property;
import javax.jcr.nodetype.NodeDefinition;
import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.Location;
import org.jboss.dna.graph.property.Name;
-import org.jboss.dna.graph.property.NamespaceRegistry;
+import org.jboss.dna.graph.property.Path;
import org.jboss.dna.graph.property.Path.Segment;
import org.junit.Before;
import org.junit.Test;
-import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoAnnotations.Mock;
@@ -61,17 +60,18 @@
@Before
public void before() throws Exception {
MockitoAnnotations.initMocks(this);
- root = new JcrRootNode(session, rootNodeDefinition);
- Segment segment = Mockito.mock(Segment.class);
- Name name = Mockito.mock(Name.class);
- stub(name.getString((NamespaceRegistry)anyObject())).toReturn("name");
- stub(segment.getName()).toReturn(name);
- stub(segment.getIndex()).toReturn(2);
+ ExecutionContext context = new ExecutionContext();
+ UUID rootUuid = UUID.randomUUID();
+ Path rootPath = context.getValueFactories().getPathFactory().createRootPath();
+ Location rootLocation = Location.create(rootPath, rootUuid);
+ root = new JcrRootNode(session, rootLocation, rootNodeDefinition);
UUID uuid = UUID.randomUUID();
- node = new JcrNode(session, uuid, segment, nodeDefinition);
- ExecutionContext context = Mockito.mock(ExecutionContext.class);
+ Path path = context.getValueFactories().getPathFactory().create("/name[2]");
+ Location location = Location.create(path, uuid);
+ node = new JcrNode(session, rootUuid, location, nodeDefinition);
stub(session.getExecutionContext()).toReturn(context);
- stub(session.getNode(uuid)).toReturn(root);
+ stub(session.getNode(rootUuid)).toReturn(root);
+ stub(session.getNode(uuid)).toReturn(node);
node.setProperties(new HashMap<Name, Property>());
node.setChildren(new ArrayList<Segment>());
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRootNodeTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRootNodeTest.java 2009-03-06 17:03:00 UTC (rev 762)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRootNodeTest.java 2009-03-09 17:57:18 UTC (rev 763)
@@ -28,10 +28,14 @@
import static org.junit.Assert.assertThat;
import java.util.HashMap;
import java.util.Map;
+import java.util.UUID;
import javax.jcr.ItemNotFoundException;
import javax.jcr.Property;
import javax.jcr.nodetype.NodeDefinition;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.Location;
import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Path;
import org.junit.Before;
import org.junit.Test;
import org.mockito.MockitoAnnotations;
@@ -53,7 +57,11 @@
public void before() throws Exception {
MockitoAnnotations.initMocks(this);
properties = new HashMap<Name, Property>();
- root = new JcrRootNode(session, nodeDefinition);
+ ExecutionContext context = new ExecutionContext();
+ UUID rootUuid = UUID.randomUUID();
+ Path rootPath = context.getValueFactories().getPathFactory().createRootPath();
+ Location rootLocation = Location.create(rootPath, rootUuid);
+ root = new JcrRootNode(session, rootLocation, nodeDefinition);
root.setProperties(properties);
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSingleValuePropertyTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSingleValuePropertyTest.java 2009-03-06 17:03:00 UTC (rev 762)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSingleValuePropertyTest.java 2009-03-09 17:57:18 UTC (rev 763)
@@ -35,8 +35,10 @@
import javax.jcr.PropertyType;
import javax.jcr.Value;
import javax.jcr.ValueFormatException;
+import javax.jcr.nodetype.NodeDefinition;
import javax.jcr.nodetype.PropertyDefinition;
import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.Location;
import org.jboss.dna.graph.property.DateTime;
import org.jboss.dna.graph.property.Name;
import org.jboss.dna.graph.property.Path;
@@ -51,10 +53,13 @@
public class JcrSingleValuePropertyTest {
private Property prop;
- @Mock
- private Node node;
+ private AbstractJcrNode node;
private ExecutionContext executionContext;
@Mock
+ private JcrSession session;
+ @Mock
+ private NodeDefinition nodeDefinition;
+ @Mock
Name name;
@Mock
private PropertyDefinition definition;
@@ -64,15 +69,22 @@
public void before() {
MockitoAnnotations.initMocks(this);
executionContext = new ExecutionContext();
+
+ UUID rootUuid = UUID.randomUUID();
+ Path rootPath = executionContext.getValueFactories().getPathFactory().createRootPath();
+ Location rootLocation = Location.create(rootPath, rootUuid);
+ node = new JcrRootNode(session, rootLocation, nodeDefinition);
+ stub(session.getExecutionContext()).toReturn(executionContext);
+
dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE, "text/plain");
stub(definition.isMultiple()).toReturn(false);
- prop = new JcrSingleValueProperty(node, executionContext, definition, PropertyType.STRING, dnaProperty);
+ prop = new JcrSingleValueProperty(node, definition, PropertyType.STRING, dnaProperty);
}
@Test
public void shouldProvideBoolean() throws Exception {
dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE, "true");
- prop = new JcrSingleValueProperty(node, executionContext, definition, PropertyType.BOOLEAN, dnaProperty);
+ prop = new JcrSingleValueProperty(node, definition, PropertyType.BOOLEAN, dnaProperty);
assertThat(prop.getBoolean(), is(true));
assertThat(prop.getType(), is(PropertyType.BOOLEAN));
}
@@ -88,7 +100,7 @@
public void shouldProvideDate() throws Exception {
DateTime dnaDate = executionContext.getValueFactories().getDateFactory().create();
dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE, dnaDate);
- prop = new JcrSingleValueProperty(node, executionContext, definition, PropertyType.DATE, dnaProperty);
+ prop = new JcrSingleValueProperty(node, definition, PropertyType.DATE, dnaProperty);
assertThat(prop.getDate(), is(dnaDate.toCalendar()));
assertThat(prop.getLong(), is(dnaDate.getMilliseconds()));
assertThat(prop.getType(), is(PropertyType.DATE));
@@ -100,10 +112,8 @@
UUID referencedUuid = UUID.randomUUID();
dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE, referencedUuid);
Node referencedNode = mock(Node.class);
- JcrSession session = mock(JcrSession.class);
- stub(node.getSession()).toReturn(session);
stub(session.getNode(referencedUuid)).toReturn(referencedNode);
- prop = new JcrSingleValueProperty(node, executionContext, definition, PropertyType.REFERENCE, dnaProperty);
+ prop = new JcrSingleValueProperty(node, definition, PropertyType.REFERENCE, dnaProperty);
assertThat(prop.getNode(), is(referencedNode));
assertThat(prop.getType(), is(PropertyType.REFERENCE));
assertThat(prop.getName(), is(dnaProperty.getName().getString(executionContext.getNamespaceRegistry())));
@@ -112,12 +122,12 @@
@Test
public void shouldProvideDouble() throws Exception {
dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE, 1.0);
- prop = new JcrSingleValueProperty(node, executionContext, definition, PropertyType.DOUBLE, dnaProperty);
+ prop = new JcrSingleValueProperty(node, definition, PropertyType.DOUBLE, dnaProperty);
assertThat(prop.getDouble(), is(1.0));
assertThat(prop.getType(), is(PropertyType.DOUBLE));
assertThat(prop.getName(), is(dnaProperty.getName().getString(executionContext.getNamespaceRegistry())));
dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE, 1.0F);
- prop = new JcrSingleValueProperty(node, executionContext, definition, PropertyType.DOUBLE, dnaProperty);
+ prop = new JcrSingleValueProperty(node, definition, PropertyType.DOUBLE, dnaProperty);
assertThat(prop.getDouble(), is(1.0));
assertThat(prop.getType(), is(PropertyType.DOUBLE));
assertThat(prop.getName(), is(dnaProperty.getName().getString(executionContext.getNamespaceRegistry())));
@@ -126,13 +136,13 @@
@Test
public void shouldProvideLong() throws Exception {
dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE, 1);
- prop = new JcrSingleValueProperty(node, executionContext, definition, PropertyType.DOUBLE, dnaProperty);
+ prop = new JcrSingleValueProperty(node, definition, PropertyType.DOUBLE, dnaProperty);
assertThat(prop.getLong(), is(1L));
assertThat(prop.getType(), is(PropertyType.DOUBLE));
assertThat(prop.getName(), is(dnaProperty.getName().getString(executionContext.getNamespaceRegistry())));
dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE, 1L);
- prop = new JcrSingleValueProperty(node, executionContext, definition, PropertyType.DOUBLE, dnaProperty);
+ prop = new JcrSingleValueProperty(node, definition, PropertyType.DOUBLE, dnaProperty);
assertThat(prop.getLong(), is(1L));
assertThat(prop.getString(), is("1"));
assertThat(prop.getType(), is(PropertyType.DOUBLE));
@@ -142,7 +152,7 @@
@Test
public void shouldProvideStream() throws Exception {
dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE, new Object());
- prop = new JcrSingleValueProperty(node, executionContext, definition, PropertyType.BINARY, dnaProperty);
+ prop = new JcrSingleValueProperty(node, definition, PropertyType.BINARY, dnaProperty);
assertThat(prop.getType(), is(PropertyType.BINARY));
assertThat(prop.getName(), is(dnaProperty.getName().getString(executionContext.getNamespaceRegistry())));
InputStream stream = prop.getStream();
@@ -158,7 +168,7 @@
@Test
public void shouldProvideString() throws Exception {
dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE, "value");
- prop = new JcrSingleValueProperty(node, executionContext, definition, PropertyType.STRING, dnaProperty);
+ prop = new JcrSingleValueProperty(node, definition, PropertyType.STRING, dnaProperty);
assertThat(prop.getString(), is("value"));
assertThat(prop.getType(), is(PropertyType.STRING));
assertThat(prop.getName(), is(dnaProperty.getName().getString(executionContext.getNamespaceRegistry())));
@@ -168,7 +178,7 @@
public void shouldAllowReferenceValue() throws Exception {
UUID uuid = UUID.randomUUID();
dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE, uuid);
- prop = new JcrSingleValueProperty(node, executionContext, definition, PropertyType.STRING, dnaProperty);
+ prop = new JcrSingleValueProperty(node, definition, PropertyType.STRING, dnaProperty);
assertThat(prop.getString(), is(uuid.toString()));
assertThat(prop.getType(), is(PropertyType.STRING));
assertThat(prop.getName(), is(dnaProperty.getName().getString(executionContext.getNamespaceRegistry())));
@@ -179,7 +189,7 @@
executionContext.getNamespaceRegistry().register("acme", "http://example.com");
Name path = executionContext.getValueFactories().getNameFactory().create("acme:something");
dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE, path);
- prop = new JcrSingleValueProperty(node, executionContext, definition, PropertyType.NAME, dnaProperty);
+ prop = new JcrSingleValueProperty(node, definition, PropertyType.NAME, dnaProperty);
assertThat(prop.getString(), is("acme:something"));
assertThat(prop.getType(), is(PropertyType.NAME));
assertThat(prop.getName(), is(dnaProperty.getName().getString(executionContext.getNamespaceRegistry())));
@@ -193,7 +203,7 @@
executionContext.getNamespaceRegistry().register("acme", "http://example.com");
Path path = executionContext.getValueFactories().getPathFactory().create("/a/b/acme:c");
dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE, (Object)path);
- prop = new JcrSingleValueProperty(node, executionContext, definition, PropertyType.PATH, dnaProperty);
+ prop = new JcrSingleValueProperty(node, definition, PropertyType.PATH, dnaProperty);
assertThat(prop.getString(), is("/a/b/acme:c"));
assertThat(prop.getType(), is(PropertyType.PATH));
assertThat(prop.getName(), is(dnaProperty.getName().getString(executionContext.getNamespaceRegistry())));
@@ -220,13 +230,13 @@
dnaValue = "some other value";
dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE, dnaValue);
- prop = new JcrSingleValueProperty(node, executionContext, definition, PropertyType.STRING, dnaProperty);
+ prop = new JcrSingleValueProperty(node, definition, PropertyType.STRING, dnaProperty);
assertThat(prop.getLength(), is((long)dnaValue.length()));
Object obj = new Object();
long binaryLength = executionContext.getValueFactories().getBinaryFactory().create(obj).getSize();
dnaProperty = executionContext.getPropertyFactory().create(JcrLexicon.MIMETYPE, obj);
- prop = new JcrSingleValueProperty(node, executionContext, definition, PropertyType.BINARY, dnaProperty);
+ prop = new JcrSingleValueProperty(node, definition, PropertyType.BINARY, dnaProperty);
assertThat(prop.getLength(), is(binaryLength));
}
15 years, 1 month
DNA SVN: r762 - trunk/dna-jcr/src/main/java/org/jboss/dna/jcr.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-03-06 12:03:00 -0500 (Fri, 06 Mar 2009)
New Revision: 762
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaBuiltinNodeTypeSource.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrItemDefinition.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrLexicon.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeManager.java
Log:
DNA-294 Define a custom node type for the root node in a repository
Applied the patch. Also changed the JcrNodeTypeManager.getRootNodeDefinition() method to return "dna:root" node type (rather than "nt:unstructured").
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaBuiltinNodeTypeSource.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaBuiltinNodeTypeSource.java 2009-03-06 16:51:55 UTC (rev 761)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaBuiltinNodeTypeSource.java 2009-03-06 17:03:00 UTC (rev 762)
@@ -29,6 +29,7 @@
import java.util.List;
import javax.jcr.PropertyType;
import javax.jcr.nodetype.NodeType;
+import org.jboss.dna.graph.JcrMixLexicon;
import net.jcip.annotations.Immutable;
/**
@@ -57,17 +58,86 @@
throw new IllegalStateException(JcrI18n.supertypeNotFound.text(baseTypeName, namespaceTypeName));
}
+ JcrNodeType referenceable = findType(JcrMixLexicon.REFERENCEABLE);
+
+ if (referenceable == null) {
+ String baseTypeName = JcrMixLexicon.REFERENCEABLE.getString(session.getExecutionContext().getNamespaceRegistry());
+ String namespaceTypeName = DnaLexicon.SYSTEM.getString(session.getExecutionContext().getNamespaceRegistry());
+ throw new IllegalStateException(JcrI18n.supertypeNotFound.text(baseTypeName, namespaceTypeName));
+ }
+
// Stubbing in child node and property definitions for now
- JcrNodeType namespace = new JcrNodeType(session, DnaLexicon.NAMESPACE, Arrays.asList(new NodeType[] {base}),
- DnaLexicon.URI, NO_CHILD_NODES, Arrays.asList(new JcrPropertyDefinition[] {
- new JcrPropertyDefinition(session, null, DnaLexicon.URI,
- OnParentVersionBehavior.VERSION.getJcrValue(),
- true, true, true, NO_DEFAULT_VALUES,
- PropertyType.STRING, NO_CONSTRAINTS, false)}),
+ JcrNodeType namespace = new JcrNodeType(
+ session,
+ DnaLexicon.NAMESPACE,
+ Arrays.asList(new NodeType[] {base}),
+ DnaLexicon.URI,
+ NO_CHILD_NODES,
+ Arrays.asList(new JcrPropertyDefinition[] {new JcrPropertyDefinition(
+ session,
+ null,
+ DnaLexicon.URI,
+ OnParentVersionBehavior.VERSION.getJcrValue(),
+ true,
+ true,
+ true,
+ NO_DEFAULT_VALUES,
+ PropertyType.STRING,
+ NO_CONSTRAINTS,
+ false)}),
NOT_MIXIN, UNORDERABLE_CHILD_NODES);
- primaryNodeTypes.addAll(Arrays.asList(new JcrNodeType[] {namespace}));
+ JcrNodeType namespaces = new JcrNodeType(
+ session,
+ DnaLexicon.NAMESPACES,
+ Arrays.asList(new NodeType[] {base}),
+ NO_PRIMARY_ITEM_NAME,
+ Arrays.asList(new JcrNodeDefinition[] {new JcrNodeDefinition(
+ session,
+ null,
+ null,
+ OnParentVersionBehavior.VERSION.getJcrValue(),
+ false,
+ false,
+ true,
+ false,
+ DnaLexicon.NAMESPACE,
+ new NodeType[] {namespace})}),
+ NO_PROPERTIES, NOT_MIXIN, UNORDERABLE_CHILD_NODES);
+ JcrNodeType system = new JcrNodeType(
+ session,
+ DnaLexicon.SYSTEM,
+ Arrays.asList(new NodeType[] {base}),
+ NO_PRIMARY_ITEM_NAME,
+ Arrays.asList(new JcrNodeDefinition[] {new JcrNodeDefinition(
+ session,
+ null,
+ DnaLexicon.NAMESPACES,
+ OnParentVersionBehavior.VERSION.getJcrValue(),
+ true,
+ true,
+ true,
+ false,
+ DnaLexicon.NAMESPACES,
+ new NodeType[] {namespaces})}),
+ NO_PROPERTIES, NOT_MIXIN, UNORDERABLE_CHILD_NODES);
+
+ JcrNodeType root = new JcrNodeType(session, DnaLexicon.ROOT, Arrays.asList(new NodeType[] {base, referenceable}),
+ NO_PRIMARY_ITEM_NAME, Arrays.asList(new JcrNodeDefinition[] {
+ new JcrNodeDefinition(session, null, JcrLexicon.SYSTEM,
+ OnParentVersionBehavior.IGNORE.getJcrValue(), true, true,
+ true, false, DnaLexicon.NAMESPACES,
+ new NodeType[] {namespaces}),
+ new JcrNodeDefinition(session, null, null,
+ OnParentVersionBehavior.VERSION.getJcrValue(), false, false,
+ false, true, DnaLexicon.NAMESPACES,
+ new NodeType[] {namespaces}),
+
+ }), NO_PROPERTIES, NOT_MIXIN, UNORDERABLE_CHILD_NODES);
+
+ primaryNodeTypes.addAll(Arrays.asList(new JcrNodeType[] {root, system, namespaces, namespace}));
+
}
/**
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java 2009-03-06 16:51:55 UTC (rev 761)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java 2009-03-06 17:03:00 UTC (rev 762)
@@ -33,6 +33,8 @@
public static final Name NAMESPACES = new BasicName(Namespace.URI, "namespaces");
public static final Name NAMESPACE = new BasicName(Namespace.URI, "namespace");
+ public static final Name ROOT = new BasicName(Namespace.URI, "root");
+ public static final Name SYSTEM = new BasicName(Namespace.URI, "system");
public static final Name URI = new BasicName(Namespace.URI, "uri");
public static final Name NODE_DEFINITON = new BasicName(Namespace.URI, "nodeDefinition");
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrItemDefinition.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrItemDefinition.java 2009-03-06 16:51:55 UTC (rev 761)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrItemDefinition.java 2009-03-06 17:03:00 UTC (rev 762)
@@ -29,8 +29,8 @@
import org.jboss.dna.graph.property.Name;
/**
- * DNA implementation of the {@link ItemDefinition} interface. This implementation is immutable and has all fields initialized
- * through its constructor.
+ * DNA implementation of the {@link ItemDefinition} interface. This implementation is immutable and has all fields initialized
+ * through its constructor.
*/
@Immutable
class JcrItemDefinition implements ItemDefinition {
@@ -77,7 +77,7 @@
*/
public String getName() {
if (name == null) {
- return "*";
+ return JcrNodeType.RESIDUAL_ITEM_NAME;
}
return name.getString(session.getExecutionContext().getNamespaceRegistry());
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrLexicon.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrLexicon.java 2009-03-06 16:51:55 UTC (rev 761)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrLexicon.java 2009-03-06 17:03:00 UTC (rev 762)
@@ -63,6 +63,7 @@
public static final Name PROTECTED = new BasicName(Namespace.URI, "protected");
public static final Name REQUIRED_PRIMARY_TYPES = new BasicName(Namespace.URI, "requiredPrimaryTypes");
public static final Name REQUIRED_TYPE = new BasicName(Namespace.URI, "requiredType");
+ public static final Name ROOT = new BasicName(Namespace.URI, "root");
public static final Name ROOT_VERSION = new BasicName(Namespace.URI, "rootVersion");
public static final Name SAME_NAME_SIBLINGS = new BasicName(Namespace.URI, "sameNameSiblings");
public static final Name STATEMENT = new BasicName(Namespace.URI, "statement");
@@ -73,5 +74,7 @@
public static final Name VERSIONABLE_UUID = new BasicName(Namespace.URI, "versionableUuid");
public static final Name VERSION_HISTORY = new BasicName(Namespace.URI, "versionHistory");
public static final Name VERSION_LABELS = new BasicName(Namespace.URI, "versionLabels");
+ public static final Name XMLTEXT = new BasicName(Namespace.URI, "xmltext");
+ public static final Name XMLCHARACTERS = new BasicName(Namespace.URI, "xmlcharacters");
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeManager.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeManager.java 2009-03-06 16:51:55 UTC (rev 761)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeManager.java 2009-03-06 17:03:00 UTC (rev 762)
@@ -134,8 +134,7 @@
* @throws NoSuchNodeTypeException
*/
JcrNodeDefinition getRootNodeDefinition() throws NoSuchNodeTypeException, RepositoryException {
- // TODO: Fix this
- for (NodeDefinition definition : getNodeType("nt:unstructured").getChildNodeDefinitions()) {
+ for (NodeDefinition definition : getNodeType(DnaLexicon.ROOT).getChildNodeDefinitions()) {
if (definition.getName().equals(JcrNodeType.RESIDUAL_ITEM_NAME)) return (JcrNodeDefinition)definition;
}
assert false; // should not get here
15 years, 1 month
DNA SVN: r761 - in trunk/dna-jcr/src: main/resources/org/jboss/dna/jcr and 1 other directories.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-03-06 11:51:55 -0500 (Fri, 06 Mar 2009)
New Revision: 761
Added:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeManager.java
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrI18n.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNode.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeType.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRootNode.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java
trunk/dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrNodeTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRootNodeTest.java
Log:
DNA-194 Implement update JCR capability
None of the nodes had a Node.getDefinition() implementation. To properly implement this, I refactored how JcrSession was creating and populating nodes, and I added some utility methods to the JcrNodeTypeManager (which is now a separate package-protected class rather than an inner class).
This allows all of the Level 2 TCK unit tests to get further, but none of the other update functionality is implemented, so none of the Level 2 TCK tests run successfully.
I also made a number of utility methods final, in the hopes that they can be inlined since they are called very frequently.
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java 2009-03-05 18:20:33 UTC (rev 760)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java 2009-03-06 16:51:55 UTC (rev 761)
@@ -71,10 +71,14 @@
Map<Name, Property> properties;
List<Path.Segment> children;
private UUID uuid;
+ private final NodeDefinition definition;
- AbstractJcrNode( JcrSession session ) {
+ AbstractJcrNode( JcrSession session,
+ NodeDefinition definition ) {
assert session != null;
+ assert definition != null;
this.session = session;
+ this.definition = definition;
}
/**
@@ -112,26 +116,33 @@
this.properties = properties;
}
+ /**
+ * Utility mehtod to create a {@link Name} from the supplied string.
+ *
+ * @param name the string
+ * @return the name, or null if the supplied string is null
+ */
final Name nameFrom( String name ) {
return session.getExecutionContext().getValueFactories().getNameFactory().create(name);
}
+ final NamespaceRegistry namespaces() {
+ return session.getExecutionContext().getNamespaceRegistry();
+ }
+
/**
* {@inheritDoc}
*
* @see javax.jcr.Node#getUUID()
*/
public final String getUUID() throws RepositoryException {
- // Return JCR UUID only if node is referenceable
- try {
- Property mixinsProp = getProperty("jcr:mixinTypes");
- if (mixinsProp != null) {
- for (Value value : mixinsProp.getValues()) {
- if ("mix:referenceable".equals(value.getString())) return getProperty("jcr:uuid").getString();
- }
+ // Return "jcr:uuid" only if node is referenceable
+ Property mixinsProp = getProperty(JcrLexicon.MIXIN_TYPES);
+ if (mixinsProp != null) {
+ String referenceableMixinName = JcrMixLexicon.REFERENCEABLE.getString(namespaces());
+ for (Value value : mixinsProp.getValues()) {
+ if (referenceableMixinName.equals(value.getString())) return getProperty(JcrLexicon.UUID).getString();
}
- } catch (PathNotFoundException error) {
- throw new UnsupportedRepositoryOperationException(error);
}
throw new UnsupportedRepositoryOperationException();
}
@@ -175,7 +186,7 @@
* @see javax.jcr.Node#getDefinition()
*/
public NodeDefinition getDefinition() {
- return null;
+ return definition;
}
/**
@@ -443,7 +454,7 @@
if (children == null) {
return new JcrEmptyNodeIterator();
}
- return new JcrChildNodeIterator(this, this.session.getExecutionContext().getNamespaceRegistry(), children);
+ return new JcrChildNodeIterator(this, namespaces(), children);
}
/**
@@ -461,7 +472,7 @@
// Implementing exact-matching only for now to prototype types as properties
List<Path.Segment> matchingChildren = new LinkedList<Path.Segment>();
- NamespaceRegistry registry = session.executionContext.getNamespaceRegistry();
+ NamespaceRegistry registry = namespaces();
boolean foundMatch = false;
for (Path.Segment child : children) {
String childName = child.getName().getString(registry);
@@ -480,7 +491,7 @@
}
}
}
- return new JcrChildNodeIterator(this, this.session.executionContext.getNamespaceRegistry(), matchingChildren);
+ return new JcrChildNodeIterator(this, registry, matchingChildren);
}
/**
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java 2009-03-05 18:20:33 UTC (rev 760)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java 2009-03-06 16:51:55 UTC (rev 761)
@@ -34,5 +34,6 @@
public static final Name NAMESPACES = new BasicName(Namespace.URI, "namespaces");
public static final Name NAMESPACE = new BasicName(Namespace.URI, "namespace");
public static final Name URI = new BasicName(Namespace.URI, "uri");
+ public static final Name NODE_DEFINITON = new BasicName(Namespace.URI, "nodeDefinition");
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrI18n.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrI18n.java 2009-03-05 18:20:33 UTC (rev 760)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrI18n.java 2009-03-06 16:51:55 UTC (rev 761)
@@ -63,6 +63,7 @@
public static I18n invalidNamePattern;
public static I18n itemNotFoundWithUuid;
public static I18n errorWhileFindingNodeWithUuid;
+ public static I18n nodeDefinitionCouldBeDeterminedForNode;
public static I18n typeNotFound;
public static I18n supertypeNotFound;
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNode.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNode.java 2009-03-05 18:20:33 UTC (rev 760)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNode.java 2009-03-06 16:51:55 UTC (rev 761)
@@ -27,6 +27,7 @@
import javax.jcr.ItemNotFoundException;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.NodeDefinition;
import net.jcip.annotations.NotThreadSafe;
import org.jboss.dna.graph.property.Path.Segment;
@@ -41,8 +42,9 @@
JcrNode( JcrSession session,
UUID parentUuid,
- Segment segment ) {
- super(session);
+ Segment segment,
+ NodeDefinition nodeDefinition ) {
+ super(session, nodeDefinition);
assert parentUuid != null;
assert segment != null;
this.parentUuid = parentUuid;
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeType.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeType.java 2009-03-05 18:20:33 UTC (rev 760)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeType.java 2009-03-06 16:51:55 UTC (rev 761)
@@ -150,6 +150,33 @@
}
/**
+ * Determine the best (most specific) {@link NodeDefinition} for a child with the supplied name and primary type. If the
+ * primary type is not supplied, then only the name is considered when finding a best match.
+ *
+ * @param childName the name of the child
+ * @param primaryNodeTypeName the name of the primary node type for the child
+ * @return the {@link NodeDefinition} that best matches the child, or null if a child with the supplied name and primary type
+ * are not allowed given this node type
+ */
+ JcrNodeDefinition findBestNodeDefinitionForChild( String childName,
+ String primaryNodeTypeName ) {
+ // First, try to find a child node definition with the given name
+ JcrNodeDefinition childNode = getChildNodeDefinition(childName);
+
+ // If there are no named definitions in the type hierarchy, try to find a residual node definition
+ if (childNode == null) {
+ childNode = getChildNodeDefinition(RESIDUAL_ITEM_NAME);
+ }
+
+ // Check if the node can be added with the named child node definition
+ if (childNode != null && primaryNodeTypeName != null) {
+ NodeType primaryNodeType = getPrimaryNodeType(primaryNodeTypeName);
+ if (!checkTypeAgainstDefinition(primaryNodeType, childNode)) return null;
+ }
+ return childNode;
+ }
+
+ /**
* {@inheritDoc}
*
* @see javax.jcr.nodetype.NodeType#canAddChildNode(java.lang.String)
@@ -179,6 +206,15 @@
return false;
}
+ protected final NodeType getPrimaryNodeType( String primaryNodeTypeName ) {
+ try {
+ return session.getWorkspace().getNodeTypeManager().getNodeType(primaryNodeTypeName);
+ } catch (RepositoryException re) {
+ // If the node type doesn't exist, you can't add a child node with that type
+ return null;
+ }
+ }
+
/**
* {@inheritDoc}
*
@@ -190,11 +226,9 @@
CheckArg.isNotNull(childNodeName, "childNodeName");
CheckArg.isNotNull(primaryNodeTypeName, "primaryNodeTypeName");
- NodeType primaryNodeType;
- try {
- primaryNodeType = session.getWorkspace().getNodeTypeManager().getNodeType(primaryNodeTypeName);
- } catch (RepositoryException re) {
- // If the node type doesn't exist, you can't add a child node with that type
+ NodeType primaryNodeType = getPrimaryNodeType(primaryNodeTypeName);
+ if (primaryNodeType == null) {
+ // The node type doesn't exist, so you can't add a child node with that type
return false;
}
Added: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeManager.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeManager.java (rev 0)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeManager.java 2009-03-06 16:51:55 UTC (rev 761)
@@ -0,0 +1,145 @@
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * Unless otherwise indicated, all code in JBoss DNA is licensed
+ * to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.jcr;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.NoSuchNodeTypeException;
+import javax.jcr.nodetype.NodeDefinition;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.nodetype.NodeTypeIterator;
+import javax.jcr.nodetype.NodeTypeManager;
+import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.graph.property.Name;
+
+/**
+ * Local implementation of @{link NodeTypeManager}. Initialized with {@link NodeType} source data when it is created (in the
+ * {@link JcrWorkspace} constructor.
+ */
+@NotThreadSafe
+class JcrNodeTypeManager implements NodeTypeManager {
+
+ private final Map<Name, JcrNodeType> primaryNodeTypes;
+ private final Map<Name, JcrNodeType> mixinNodeTypes;
+ private final JcrSession session;
+
+ JcrNodeTypeManager( JcrSession session,
+ JcrNodeTypeSource source ) {
+ this.session = session;
+ Collection<JcrNodeType> primary = source.getPrimaryNodeTypes();
+ Collection<JcrNodeType> mixins = source.getMixinNodeTypes();
+
+ primaryNodeTypes = new HashMap<Name, JcrNodeType>(primary.size());
+ for (JcrNodeType nodeType : primary) {
+ primaryNodeTypes.put(nodeType.getInternalName(), nodeType);
+ }
+
+ mixinNodeTypes = new HashMap<Name, JcrNodeType>(mixins.size());
+ for (JcrNodeType nodeType : mixins) {
+ mixinNodeTypes.put(nodeType.getInternalName(), nodeType);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.nodetype.NodeTypeManager#getAllNodeTypes()
+ */
+ public NodeTypeIterator getAllNodeTypes() {
+
+ // TODO: Can revisit this approach later if it becomes a performance issue
+ /*
+ * Note also that this creates a subtle difference in behavior for concurrent modification
+ * between this method and the specific get*NodeTypes methods. That is, if a type is added
+ * while an iterator from the corresponding specific get*NodeType method is being traversed,
+ * a ConcurrentModificationException will be thrown. Because this iterator is based on a copy
+ * of the underlying maps, no exception would be thrown in the same case.
+ */
+
+ List<NodeType> allTypes = new ArrayList<NodeType>(primaryNodeTypes.size() + mixinNodeTypes.size());
+ allTypes.addAll(primaryNodeTypes.values());
+ allTypes.addAll(mixinNodeTypes.values());
+ return new JcrNodeTypeIterator(allTypes);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.nodetype.NodeTypeManager#getMixinNodeTypes()
+ */
+ public NodeTypeIterator getMixinNodeTypes() {
+ return new JcrNodeTypeIterator(mixinNodeTypes.values());
+ }
+
+ final JcrNodeType getNodeType( Name nodeTypeName ) {
+
+ JcrNodeType nodeType = primaryNodeTypes.get(nodeTypeName);
+ if (nodeType == null) {
+ nodeType = mixinNodeTypes.get(nodeTypeName);
+ }
+ return nodeType;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.nodetype.NodeTypeManager#getNodeType(java.lang.String)
+ */
+ public NodeType getNodeType( String nodeTypeName ) throws NoSuchNodeTypeException, RepositoryException {
+ Name ntName = session.getExecutionContext().getValueFactories().getNameFactory().create(nodeTypeName);
+ NodeType type = getNodeType(ntName);
+ if (type != null) return type;
+ throw new NoSuchNodeTypeException(JcrI18n.typeNotFound.text(nodeTypeName));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.nodetype.NodeTypeManager#getPrimaryNodeTypes()
+ */
+ public NodeTypeIterator getPrimaryNodeTypes() {
+ return new JcrNodeTypeIterator(primaryNodeTypes.values());
+ }
+
+ /**
+ * Get the {@link NodeDefinition} for the root node.
+ *
+ * @return the definition; never null
+ * @throws RepositoryException
+ * @throws NoSuchNodeTypeException
+ */
+ JcrNodeDefinition getRootNodeDefinition() throws NoSuchNodeTypeException, RepositoryException {
+ // TODO: Fix this
+ for (NodeDefinition definition : getNodeType("nt:unstructured").getChildNodeDefinitions()) {
+ if (definition.getName().equals(JcrNodeType.RESIDUAL_ITEM_NAME)) return (JcrNodeDefinition)definition;
+ }
+ assert false; // should not get here
+ return null;
+ }
+
+}
Property changes on: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeManager.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRootNode.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRootNode.java 2009-03-05 18:20:33 UTC (rev 760)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRootNode.java 2009-03-06 16:51:55 UTC (rev 761)
@@ -25,6 +25,7 @@
import javax.jcr.ItemNotFoundException;
import javax.jcr.Node;
+import javax.jcr.nodetype.NodeDefinition;
import net.jcip.annotations.NotThreadSafe;
/**
@@ -33,8 +34,9 @@
@NotThreadSafe
final class JcrRootNode extends AbstractJcrNode {
- JcrRootNode( JcrSession session ) {
- super(session);
+ JcrRootNode( JcrSession session,
+ NodeDefinition nodeDefinition ) {
+ super(session, nodeDefinition);
}
/**
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java 2009-03-05 18:20:33 UTC (rev 760)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java 2009-03-06 16:51:55 UTC (rev 761)
@@ -51,6 +51,7 @@
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import javax.jcr.Workspace;
+import javax.jcr.nodetype.NodeDefinition;
import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.NodeTypeManager;
import javax.jcr.nodetype.PropertyDefinition;
@@ -59,9 +60,10 @@
import javax.security.auth.login.LoginException;
import net.jcip.annotations.NotThreadSafe;
import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.DnaLexicon;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.connector.RepositorySourceException;
import org.jboss.dna.graph.property.Name;
import org.jboss.dna.graph.property.NameFactory;
import org.jboss.dna.graph.property.NamespaceRegistry;
@@ -123,8 +125,9 @@
private final ReferenceMap<UUID, Node> nodesByUuid;
private final ReferenceMap<String, Node> nodesByJcrUuid;
private boolean isLive;
- private JcrRootNode rootNode;
+ private AbstractJcrNode rootNode;
private PropertyDefinition anyMultiplePropertyDefinition;
+ private transient org.jboss.dna.graph.property.Property defaultPrimaryType;
JcrSession( JcrRepository repository,
JcrWorkspace workspace,
@@ -165,6 +168,14 @@
return this.executionContext;
}
+ final JcrNodeTypeManager nodeTypeManager() {
+ return this.workspace.nodeTypeManager();
+ }
+
+ final NamespaceRegistry namespaces() {
+ return this.executionContext.getNamespaceRegistry();
+ }
+
/**
* Return an unmodifiable map of nodes given then UUID.
*
@@ -369,7 +380,7 @@
Path parentPath = path.getParent();
Name propertyName = path.getLastSegment().getName();
try {
- return getNode(parentPath).getProperty(propertyName.getString(executionContext.getNamespaceRegistry()));
+ return getNode(parentPath).getProperty(propertyName.getString(namespaces()));
} catch (org.jboss.dna.graph.property.PathNotFoundException e2) {
// If the node isn't found, throw a PathNotFoundException
throw new PathNotFoundException(JcrI18n.pathNotFound.text(path));
@@ -387,25 +398,138 @@
throw new UnsupportedOperationException();
}
+ /**
+ * Find or create a JCR Node for the given path. This method works for the root node, too.
+ *
+ * @param path the path; may not be null
+ * @return the JCR node instance for the given path; never null
+ * @throws RepositoryException if there is a problem
+ */
private Node getNode( Path path ) throws RepositoryException {
- // Get node from source
+ boolean isRoot = path.isRoot();
+ if (isRoot && rootNode != null) return rootNode;
+
+ // Get node from source and get it's UUID ...
org.jboss.dna.graph.Node graphNode = graph.getNodeAt(path);
- // First check if node already exists. We don't need to check for changes since that will be handled by an observer
- org.jboss.dna.graph.property.Property dnaUuidProp = graphNode.getPropertiesByName().get(JcrLexicon.UUID);
- if (dnaUuidProp == null) dnaUuidProp = graphNode.getPropertiesByName().get(DnaLexicon.UUID);
- if (dnaUuidProp != null) {
- UUID uuid = executionContext.getValueFactories().getUuidFactory().create(dnaUuidProp.getValues()).next();
+
+ // Now get the DNA node's UUID ...
+ Location location = graphNode.getLocation();
+ ValueFactories factories = executionContext.getValueFactories();
+ UUID uuid = location.getUuid();
+ org.jboss.dna.graph.property.Property uuidProperty = null;
+ if (uuid != null) {
+ // Considered an identification property ...
+ uuidProperty = location.getIdProperty(JcrLexicon.UUID);
+ if (uuidProperty == null) uuidProperty = location.getIdProperty(DnaLexicon.UUID);
+ }
+ if (uuidProperty == null) {
+ uuidProperty = graphNode.getProperty(JcrLexicon.UUID);
+ if (uuidProperty != null) {
+ // Grab the first 'good' UUID value ...
+ for (Object uuidValue : uuidProperty) {
+ try {
+ uuid = factories.getUuidFactory().create(uuidValue);
+ break;
+ } catch (ValueFormatException e) {
+ // Ignore; just continue with the next property value
+ }
+ }
+ }
+ if (uuid == null) {
+ // Look for the DNA UUID property ...
+ org.jboss.dna.graph.property.Property dnaUuidProperty = graphNode.getProperty(DnaLexicon.UUID);
+ if (dnaUuidProperty != null) {
+ // Grab the first 'good' UUID value ...
+ for (Object uuidValue : dnaUuidProperty) {
+ try {
+ uuid = factories.getUuidFactory().create(uuidValue);
+ break;
+ } catch (ValueFormatException e) {
+ // Ignore; just continue with the next property value
+ }
+ }
+ }
+ }
+ }
+ if (uuid == null) uuid = UUID.randomUUID();
+ if (uuidProperty == null) uuidProperty = executionContext.getPropertyFactory().create(JcrLexicon.UUID, uuid);
+
+ // See if there is already a JCR node object for this UUID ...
+ if (uuid != null && !isRoot) {
Node node = getNode(uuid);
- if (node != null) {
- return node;
+ if (node != null) return node;
+ }
+
+ // Either the UUID is not known, or there was no node. Either way, we have to create the node ...
+ if (uuid == null) uuid = UUID.randomUUID();
+
+ // Look for the primary type of the node ...
+ String primaryTypeNameString = null;
+ NamespaceRegistry namespaces = namespaces();
+ org.jboss.dna.graph.property.Property primaryTypeProperty = graphNode.getProperty(JcrLexicon.PRIMARY_TYPE);
+ if (primaryTypeProperty != null && !primaryTypeProperty.isEmpty()) {
+ Name primaryTypeName = factories.getNameFactory().create(primaryTypeProperty.getFirstValue());
+ primaryTypeNameString = primaryTypeName.getString(namespaces);
+ } else {
+ // We have to have a primary type, so use the default ...
+ if (defaultPrimaryType == null) {
+ defaultPrimaryType = executionContext.getPropertyFactory().create(JcrLexicon.PRIMARY_TYPE,
+ JcrNtLexicon.UNSTRUCTURED);
}
+ primaryTypeProperty = defaultPrimaryType;
+ // We have to add this property to the graph node...
+ graphNode.getPropertiesByName().put(primaryTypeProperty.getName(), primaryTypeProperty);
}
- // If not create a new one & populate it
- JcrNode node;
- Path parentPath = path.getParent();
- if (parentPath.isRoot()) node = new JcrNode(this, ((JcrRootNode)getRootNode()).internalUuid(), path.getLastSegment());
- else node = new JcrNode(this, ((JcrNode)getNode(parentPath)).internalUuid(), path.getLastSegment());
- populateNode(node, graphNode);
+ assert primaryTypeProperty.isEmpty() == false;
+
+ // Look for a node definition stored on the node ...
+ NodeDefinition definition = null;
+ org.jboss.dna.graph.property.Property nodeDefnProperty = graphNode.getProperty(DnaLexicon.NODE_DEFINITON);
+ if (nodeDefnProperty != null && !nodeDefnProperty.isEmpty()) {
+ Path nodeDefnPath = factories.getPathFactory().create(nodeDefnProperty.getFirstValue());
+ // Look up the node definition ...
+ Name nodeTypeName = nodeDefnPath.getSegment(0).getName();
+ JcrNodeType nodeType = nodeTypeManager().getNodeType(nodeTypeName);
+ if (nodeType != null && nodeDefnPath.size() > 1) {
+ // Look up the definition for the child name rule (in the second segment of the relative path) ...
+ String childNameRule = nodeDefnPath.getSegment(1).getString(namespaces);
+ definition = nodeType.findBestNodeDefinitionForChild(childNameRule, primaryTypeNameString);
+ }
+ }
+
+ AbstractJcrNode node = null;
+ if (isRoot) {
+ // The node definition should be set ...
+ if (definition == null) {
+ definition = nodeTypeManager().getRootNodeDefinition();
+ assert definition != null;
+ }
+
+ // Create the new node ...
+ node = new JcrRootNode(this, definition);
+ } else {
+ // Find the parent ...
+ AbstractJcrNode parent = (AbstractJcrNode)getNode(path.getParent());
+
+ // Find the node definition for this node ...
+ if (definition == null) {
+ // Look for the parent's node type, and look for a node definition based upon the name ...
+ JcrNodeType nodeType = (JcrNodeType)parent.getPrimaryNodeType();
+ String childName = path.getLastSegment().getName().getString(namespaces);
+ definition = nodeType.findBestNodeDefinitionForChild(childName, primaryTypeNameString);
+ if (definition == null) {
+ String msg = JcrI18n.nodeDefinitionCouldBeDeterminedForNode.text(path, workspace.getName());
+ throw new RepositorySourceException(msg);
+ }
+ }
+
+ // Now create the node object ...
+ node = new JcrNode(this, parent.internalUuid(), path.getLastSegment(), definition);
+ }
+
+ // Now populate the node and add to the cache ...
+ populateNode(node, graphNode, uuid, uuidProperty, primaryTypeProperty);
+ if (isRoot) rootNode = node;
return node;
}
@@ -443,21 +567,7 @@
if (rootNode != null) {
return rootNode;
}
- // Get root node from source
- assert executionContext.getValueFactories() != null;
- assert executionContext.getValueFactories().getPathFactory() != null;
- rootNode = new JcrRootNode(this);
-
- // Get root node from source
- Path rootPath = executionContext.getValueFactories().getPathFactory().createRootPath();
- org.jboss.dna.graph.Node dnaRootNode = graph.getNodeAt(rootPath);
- if (dnaRootNode.getProperty(JcrLexicon.PRIMARY_TYPE) == null) {
- // Add the primary type and update the source ...
- graph.set(JcrLexicon.PRIMARY_TYPE).to(JcrNtLexicon.BASE).on(rootPath);
- dnaRootNode = graph.getNodeAt(rootPath);
- }
- populateNode(rootNode, dnaRootNode);
- return rootNode;
+ return getNode(executionContext.getValueFactories().getPathFactory().createRootPath());
}
/**
@@ -653,10 +763,16 @@
return PropertyType.UNDEFINED;
}
- private void populateNode( AbstractJcrNode node,
- org.jboss.dna.graph.Node graphNode ) throws RepositoryException {
+ final void populateNode( AbstractJcrNode node,
+ org.jboss.dna.graph.Node graphNode,
+ UUID uuid,
+ org.jboss.dna.graph.property.Property uuidProperty,
+ org.jboss.dna.graph.property.Property primaryTypeProperty ) throws RepositoryException {
assert node != null;
assert graphNode != null;
+ assert uuid != null;
+ assert uuidProperty != null;
+ assert primaryTypeProperty != null;
// --------------------------------------------------
// Create JCR children for corresponding DNA children
@@ -670,35 +786,34 @@
Map<Name, PropertyDefinition> propertyDefinitionsByPropertyName = new HashMap<Name, PropertyDefinition>();
boolean referenceable = false;
- NamespaceRegistry registry = executionContext.getNamespaceRegistry();
+ NamespaceRegistry registry = namespaces();
ValueFactories factories = executionContext.getValueFactories();
NameFactory nameFactory = factories.getNameFactory();
NodeTypeManager nodeTypeManager = getWorkspace().getNodeTypeManager();
List<PropertyDefinition> anyPropertyDefinitions = new LinkedList<PropertyDefinition>();
- org.jboss.dna.graph.property.Property primaryTypeProperty = graphNode.getProperty(JcrLexicon.PRIMARY_TYPE);
- if (primaryTypeProperty != null && !primaryTypeProperty.isEmpty()) {
- Name primaryTypeName = nameFactory.create(primaryTypeProperty.getFirstValue());
- String primaryTypeNameString = primaryTypeName.getString(registry);
- NodeType primaryType = nodeTypeManager.getNodeType(primaryTypeNameString);
- for (PropertyDefinition propertyDefn : primaryType.getPropertyDefinitions()) {
- String nameString = propertyDefn.getName();
- if ("*".equals(nameString)) {
- anyPropertyDefinitions.add(propertyDefn);
- continue;
- }
- Name name = nameFactory.create(nameString);
- PropertyDefinition prev = propertyDefinitionsByPropertyName.put(name, propertyDefn);
- if (prev != null) propertyDefinitionsByPropertyName.put(name, prev); // put the first one back ...
+ // Start with the primary type ...
+ Name primaryTypeName = nameFactory.create(primaryTypeProperty.getFirstValue());
+ String primaryTypeNameString = primaryTypeName.getString(registry);
+ NodeType primaryType = nodeTypeManager.getNodeType(primaryTypeNameString);
+ for (PropertyDefinition propertyDefn : primaryType.getPropertyDefinitions()) {
+ String nameString = propertyDefn.getName();
+ if ("*".equals(nameString)) {
+ anyPropertyDefinitions.add(propertyDefn);
+ continue;
}
+ Name name = nameFactory.create(nameString);
+ PropertyDefinition prev = propertyDefinitionsByPropertyName.put(name, propertyDefn);
+ if (prev != null) propertyDefinitionsByPropertyName.put(name, prev); // put the first one back ...
}
+ // The process the mixin types ...
org.jboss.dna.graph.property.Property mixinTypesProperty = graphNode.getProperty(JcrLexicon.MIXIN_TYPES);
if (mixinTypesProperty != null && !mixinTypesProperty.isEmpty()) {
for (Object mixinTypeValue : mixinTypesProperty) {
Name mixinTypeName = nameFactory.create(mixinTypeValue);
if (!referenceable && JcrMixLexicon.REFERENCEABLE.equals(mixinTypeName)) referenceable = true;
String mixinTypeNameString = mixinTypeName.getString(registry);
- NodeType primaryType = nodeTypeManager.getNodeType(mixinTypeNameString);
- for (PropertyDefinition propertyDefn : primaryType.getPropertyDefinitions()) {
+ NodeType mixinType = nodeTypeManager.getNodeType(mixinTypeNameString);
+ for (PropertyDefinition propertyDefn : mixinType.getPropertyDefinitions()) {
String nameString = propertyDefn.getName();
if ("*".equals(nameString)) {
anyPropertyDefinitions.add(propertyDefn);
@@ -711,45 +826,9 @@
}
}
- // Look for the UUID property ...
- UUID uuid = null;
- org.jboss.dna.graph.property.Property uuidProperty = graphNode.getProperty(JcrLexicon.UUID);
- Name jcrUuidPropertyName = null;
- Name dnaUuidPropertyName = null;
- if (uuidProperty != null) {
- jcrUuidPropertyName = uuidProperty.getName();
- // Grab the first 'good' UUID value ...
- for (Object uuidValue : uuidProperty) {
- try {
- uuid = factories.getUuidFactory().create(uuidValue);
- break;
- } catch (ValueFormatException e) {
- // Ignore; just continue with the next property value
- }
- }
- }
- if (uuid == null) {
- // Look for the DNA UUID property ...
- org.jboss.dna.graph.property.Property dnaUuidProperty = graphNode.getProperty(DnaLexicon.UUID);
- if (dnaUuidProperty != null) {
- dnaUuidPropertyName = dnaUuidProperty.getName();
- // Grab the first 'good' UUID value ...
- for (Object uuidValue : dnaUuidProperty) {
- try {
- uuid = factories.getUuidFactory().create(uuidValue);
- break;
- } catch (ValueFormatException e) {
- // Ignore; just continue with the next property value
- }
- }
- }
- }
-
// Now create the JCR property object wrapper around the "jcr:uuid" property ...
Map<Name, Property> properties = new HashMap<Name, Property>();
- if (uuid == null) uuid = UUID.randomUUID();
if (referenceable) {
- if (uuidProperty == null) uuidProperty = executionContext.getPropertyFactory().create(JcrLexicon.UUID, uuid);
PropertyDefinition propertyDefinition = propertyDefinitionsByPropertyName.get(JcrLexicon.UUID);
properties.put(JcrLexicon.UUID, new JcrSingleValueProperty(node, executionContext, propertyDefinition,
PropertyType.STRING, uuidProperty));
@@ -760,7 +839,7 @@
Name name = dnaProp.getName();
// Skip the JCR and DNA UUID properties (using the EXACT Name instances on the Property) ...
- if (name == jcrUuidPropertyName || name == dnaUuidPropertyName) continue;
+ if (JcrLexicon.UUID.equals(name) || DnaLexicon.UUID.equals(name)) continue;
// Figure out the JCR property type for this property ...
PropertyDefinition propertyDefinition = propertyDefinitionsByPropertyName.get(name);
@@ -826,10 +905,6 @@
}
}
- if (referenceable) {
- assert uuidProperty != null;
- }
-
// Now set the properties on the node ...
node.setProperties(properties);
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java 2009-03-05 18:20:33 UTC (rev 760)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java 2009-03-06 16:51:55 UTC (rev 761)
@@ -25,10 +25,6 @@
import java.io.IOException;
import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.jcr.AccessDeniedException;
@@ -41,9 +37,6 @@
import javax.jcr.Workspace;
import javax.jcr.lock.LockException;
import javax.jcr.nodetype.ConstraintViolationException;
-import javax.jcr.nodetype.NoSuchNodeTypeException;
-import javax.jcr.nodetype.NodeType;
-import javax.jcr.nodetype.NodeTypeIterator;
import javax.jcr.nodetype.NodeTypeManager;
import javax.jcr.observation.ObservationManager;
import javax.jcr.query.QueryManager;
@@ -111,14 +104,13 @@
/**
* Reference to the JCR type manager for this workspace.
*/
- private final NodeTypeManager nodeTypeManager;
+ private final JcrNodeTypeManager nodeTypeManager;
/**
* The {@link Session} instance that this corresponds with this workspace.
*/
private final JcrSession session;
- @SuppressWarnings( "synthetic-access" )
JcrWorkspace( JcrRepository repository,
String workspaceName,
ExecutionContext context,
@@ -156,26 +148,31 @@
this.session = new JcrSession(this.repository, this, this.context, sessionAttributes);
// This must be initialized after the session
- this.nodeTypeManager = new JcrNodeTypeManager(new DnaBuiltinNodeTypeSource(this.session,
+ this.nodeTypeManager = new JcrNodeTypeManager(this.session,
+ new DnaBuiltinNodeTypeSource(this.session,
new JcrBuiltinNodeTypeSource(this.session)));
}
- String getSourceName() {
+ final String getSourceName() {
return this.repository.getRepositorySourceName();
}
+ final JcrNodeTypeManager nodeTypeManager() {
+ return this.nodeTypeManager;
+ }
+
/**
* {@inheritDoc}
*/
- public String getName() {
+ public final String getName() {
return name;
}
/**
* {@inheritDoc}
*/
- public Session getSession() {
+ public final Session getSession() {
return this.session;
}
@@ -184,7 +181,7 @@
*
* @see javax.jcr.Workspace#getNamespaceRegistry()
*/
- public NamespaceRegistry getNamespaceRegistry() {
+ public final NamespaceRegistry getNamespaceRegistry() {
return workspaceRegistry;
}
@@ -203,21 +200,21 @@
/**
* {@inheritDoc}
*/
- public NodeTypeManager getNodeTypeManager() {
+ public final NodeTypeManager getNodeTypeManager() {
return nodeTypeManager;
}
/**
* {@inheritDoc}
*/
- public ObservationManager getObservationManager() {
+ public final ObservationManager getObservationManager() {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
- public QueryManager getQueryManager() {
+ public final QueryManager getQueryManager() {
throw new UnsupportedOperationException();
}
@@ -350,95 +347,4 @@
throw new UnsupportedOperationException();
}
- /**
- * Local implementation of @{link NodeTypeManager}. Initialized with {@link NodeType} source data when it is created (in the
- * {@link JcrWorkspace} constructor.
- */
- @NotThreadSafe
- private class JcrNodeTypeManager implements NodeTypeManager {
-
- private final Map<Name, JcrNodeType> primaryNodeTypes;
- private final Map<Name, JcrNodeType> mixinNodeTypes;
-
- private JcrNodeTypeManager( JcrNodeTypeSource source ) {
- Collection<JcrNodeType> primary = source.getPrimaryNodeTypes();
- Collection<JcrNodeType> mixins = source.getMixinNodeTypes();
-
- primaryNodeTypes = new HashMap<Name, JcrNodeType>(primary.size());
- for (JcrNodeType nodeType : primary) {
- primaryNodeTypes.put(nodeType.getInternalName(), nodeType);
- }
-
- mixinNodeTypes = new HashMap<Name, JcrNodeType>(mixins.size());
- for (JcrNodeType nodeType : mixins) {
- mixinNodeTypes.put(nodeType.getInternalName(), nodeType);
- }
- }
-
- /**
- * {@inheritDoc}
- *
- * @see javax.jcr.nodetype.NodeTypeManager#getAllNodeTypes()
- */
- public NodeTypeIterator getAllNodeTypes() {
-
- // TODO: Can revisit this approach later if it becomes a performance issue
- /*
- * Note also that this creates a subtle difference in behavior for concurrent modification
- * between this method and the specific get*NodeTypes methods. That is, if a type is added
- * while an iterator from the corresponding specific get*NodeType method is being traversed,
- * a ConcurrentModificationException will be thrown. Because this iterator is based on a copy
- * of the underlying maps, no exception would be thrown in the same case.
- */
-
- List<NodeType> allTypes = new ArrayList<NodeType>(primaryNodeTypes.size() + mixinNodeTypes.size());
- allTypes.addAll(primaryNodeTypes.values());
- allTypes.addAll(mixinNodeTypes.values());
- return new JcrNodeTypeIterator(allTypes);
- }
-
- /**
- * {@inheritDoc}
- *
- * @see javax.jcr.nodetype.NodeTypeManager#getMixinNodeTypes()
- */
- public NodeTypeIterator getMixinNodeTypes() {
- return new JcrNodeTypeIterator(mixinNodeTypes.values());
- }
-
- /**
- * {@inheritDoc}
- *
- * @see javax.jcr.nodetype.NodeTypeManager#getNodeType(java.lang.String)
- */
- @SuppressWarnings( "synthetic-access" )
- public NodeType getNodeType( String nodeTypeName ) throws NoSuchNodeTypeException, RepositoryException {
- Name ntName = session.getExecutionContext().getValueFactories().getNameFactory().create(nodeTypeName);
-
- NodeType nodeType = primaryNodeTypes.get(ntName);
-
- if (nodeType != null) {
- return nodeType;
- }
-
- nodeType = mixinNodeTypes.get(ntName);
-
- if (nodeType != null) {
- return nodeType;
- }
-
- throw new NoSuchNodeTypeException(JcrI18n.typeNotFound.text(nodeTypeName));
- }
-
- /**
- * {@inheritDoc}
- *
- * @see javax.jcr.nodetype.NodeTypeManager#getPrimaryNodeTypes()
- */
- public NodeTypeIterator getPrimaryNodeTypes() {
- return new JcrNodeTypeIterator(primaryNodeTypes.values());
- }
-
- }
-
}
Modified: trunk/dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties
===================================================================
--- trunk/dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties 2009-03-05 18:20:33 UTC (rev 760)
+++ trunk/dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties 2009-03-06 16:51:55 UTC (rev 761)
@@ -53,6 +53,7 @@
invalidNamePattern = The "{1}" name pattern contained the '{0}' character, which is not allowed in a name pattern
itemNotFoundWithUuid = An item with UUID "{0}" could not be found in workspace "{1}"
errorWhileFindingNodeWithUuid = Error while finding the item with UUID "{0}" in workspace "{1}"
+nodeDefinitionCouldBeDeterminedForNode = Unable to determine a valid node definition for the node "{0}" in workspace "{1}"
REP_NAME_DESC = DNA Repository
REP_VENDOR_DESC = JBoss - A division of Red Hat Middleware LLC
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java 2009-03-05 18:20:33 UTC (rev 760)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java 2009-03-06 16:51:55 UTC (rev 761)
@@ -26,6 +26,7 @@
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.stub;
import java.io.InputStream;
import java.util.ArrayList;
@@ -46,6 +47,7 @@
import javax.jcr.UnsupportedRepositoryOperationException;
import javax.jcr.Value;
import javax.jcr.Workspace;
+import javax.jcr.nodetype.NodeDefinition;
import javax.jcr.version.Version;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.property.Name;
@@ -83,7 +85,7 @@
MockAbstractJcrNode( JcrSession session,
String name,
Node parent ) {
- super(session);
+ super(session, mock(NodeDefinition.class));
this.name = name;
this.parent = parent;
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrNodeTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrNodeTest.java 2009-03-05 18:20:33 UTC (rev 760)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrNodeTest.java 2009-03-06 16:51:55 UTC (rev 761)
@@ -33,6 +33,7 @@
import javax.jcr.ItemNotFoundException;
import javax.jcr.Node;
import javax.jcr.Property;
+import javax.jcr.nodetype.NodeDefinition;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.property.Name;
import org.jboss.dna.graph.property.NamespaceRegistry;
@@ -52,18 +53,22 @@
private Node root;
@Mock
private JcrSession session;
+ @Mock
+ private NodeDefinition rootNodeDefinition;
+ @Mock
+ private NodeDefinition nodeDefinition;
@Before
public void before() throws Exception {
MockitoAnnotations.initMocks(this);
- root = new JcrRootNode(session);
+ root = new JcrRootNode(session, rootNodeDefinition);
Segment segment = Mockito.mock(Segment.class);
Name name = Mockito.mock(Name.class);
stub(name.getString((NamespaceRegistry)anyObject())).toReturn("name");
stub(segment.getName()).toReturn(name);
stub(segment.getIndex()).toReturn(2);
UUID uuid = UUID.randomUUID();
- node = new JcrNode(session, uuid, segment);
+ node = new JcrNode(session, uuid, segment, nodeDefinition);
ExecutionContext context = Mockito.mock(ExecutionContext.class);
stub(session.getExecutionContext()).toReturn(context);
stub(session.getNode(uuid)).toReturn(root);
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRootNodeTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRootNodeTest.java 2009-03-05 18:20:33 UTC (rev 760)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRootNodeTest.java 2009-03-06 16:51:55 UTC (rev 761)
@@ -30,6 +30,7 @@
import java.util.Map;
import javax.jcr.ItemNotFoundException;
import javax.jcr.Property;
+import javax.jcr.nodetype.NodeDefinition;
import org.jboss.dna.graph.property.Name;
import org.junit.Before;
import org.junit.Test;
@@ -44,13 +45,15 @@
private JcrRootNode root;
@Mock
private JcrSession session;
+ @Mock
+ private NodeDefinition nodeDefinition;
private Map<Name, Property> properties;
@Before
public void before() throws Exception {
MockitoAnnotations.initMocks(this);
properties = new HashMap<Name, Property>();
- root = new JcrRootNode(session);
+ root = new JcrRootNode(session, nodeDefinition);
root.setProperties(properties);
}
15 years, 1 month
DNA SVN: r760 - in trunk/dna-jcr/src: main/resources/org/jboss/dna/jcr and 1 other directories.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-03-05 13:20:33 -0500 (Thu, 05 Mar 2009)
New Revision: 760
Added:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNodeTypeSource.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaBuiltinNodeTypeSource.java
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrBuiltinNodeTypeSource.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrI18n.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeSource.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java
trunk/dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
Log:
DNA-292 System View Creates Nodes With Primary Type That Is Not Defined in Type Load
Applied the patch that builds in the dna:namespace type and adds support for chaining of node type sources.
Added: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNodeTypeSource.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNodeTypeSource.java (rev 0)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNodeTypeSource.java 2009-03-05 18:20:33 UTC (rev 760)
@@ -0,0 +1,161 @@
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.jcr;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import javax.jcr.Value;
+import javax.jcr.nodetype.NodeType;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.property.Name;
+
+/**
+ * Implementation of {@link JcrNodeTypeSource} that supports chaining of node type sources.
+ */
+abstract class AbstractJcrNodeTypeSource implements JcrNodeTypeSource {
+
+ // Convenience constants to help improve readability
+ protected static final Value[] NO_DEFAULT_VALUES = new Value[0];
+ protected static final String[] NO_CONSTRAINTS = new String[0];
+ protected static final List<NodeType> NO_SUPERTYPES = Collections.<NodeType>emptyList();
+ protected static final List<JcrNodeDefinition> NO_CHILD_NODES = Collections.<JcrNodeDefinition>emptyList();
+ protected static final List<JcrPropertyDefinition> NO_PROPERTIES = Collections.<JcrPropertyDefinition>emptyList();
+
+ // Indicates that the node type has no primary item name - added for readability
+ protected static final Name NO_PRIMARY_ITEM_NAME = null;
+ // Indicates that the definition should apply to all property definition or child node definitions - added for readability
+ protected static final Name ALL_NODES = null;
+
+ // Indicates whether or not the node type is a mixin - added for readability
+ protected static final boolean IS_A_MIXIN = true;
+ protected static final boolean NOT_MIXIN = false;
+
+ // Indicates whether or not the node type has orderable children - added for readability
+ protected static final boolean ORDERABLE_CHILD_NODES = true;
+ protected static final boolean UNORDERABLE_CHILD_NODES = false;
+
+ /** The predecessor node type source. */
+ private final JcrNodeTypeSource predecessor;
+
+ AbstractJcrNodeTypeSource() {
+ this(null);
+ }
+
+ AbstractJcrNodeTypeSource( JcrNodeTypeSource parent ) {
+ this.predecessor = parent;
+ }
+
+ /**
+ * Returns the list of mixin node types declared in this type source.
+ *
+ * @return the list of mixin node types declared in this type source.
+ * @see org.jboss.dna.jcr.JcrNodeTypeSource#getMixinNodeTypes()
+ */
+ public abstract Collection<JcrNodeType> getDeclaredMixinNodeTypes();
+
+ /**
+ * Returns the list of primary node types declared in this type source.
+ *
+ * @return the list of primary node types declared in this type source.
+ * @see org.jboss.dna.jcr.JcrNodeTypeSource#getMixinNodeTypes()
+ */
+ public abstract Collection<JcrNodeType> getDeclaredPrimaryNodeTypes();
+
+ /**
+ * Returns the list of mixin node types returned by this and any predecessor source.
+ *
+ * @return the list of mixin node types returned by this and any predecessor source.
+ * @see org.jboss.dna.jcr.JcrNodeTypeSource#getMixinNodeTypes()
+ */
+ public Collection<JcrNodeType> getMixinNodeTypes() {
+ if (predecessor == null) {
+ return getDeclaredMixinNodeTypes();
+ }
+
+ Collection<JcrNodeType> declaredMixins = getDeclaredMixinNodeTypes();
+ Collection<JcrNodeType> predecessorMixins = predecessor.getMixinNodeTypes();
+
+ List<JcrNodeType> mixins = new ArrayList<JcrNodeType>(declaredMixins.size() + predecessorMixins.size());
+ mixins.addAll(predecessorMixins);
+ mixins.addAll(declaredMixins);
+
+ return mixins;
+ }
+
+ /**
+ * Returns the list of primary node types returned by this and any predecessor source.
+ *
+ * @return the list of primary node types returned by this and any predecessor source.
+ * @see org.jboss.dna.jcr.JcrNodeTypeSource#getPrimaryNodeTypes()
+ */
+ public Collection<JcrNodeType> getPrimaryNodeTypes() {
+ if (predecessor == null) {
+ return getDeclaredPrimaryNodeTypes();
+ }
+
+ Collection<JcrNodeType> declaredPrimaries = getDeclaredPrimaryNodeTypes();
+ Collection<JcrNodeType> predecessorPrimaries = predecessor.getPrimaryNodeTypes();
+
+ List<JcrNodeType> primaries = new ArrayList<JcrNodeType>(declaredPrimaries.size() + predecessorPrimaries.size());
+ primaries.addAll(predecessorPrimaries);
+ primaries.addAll(declaredPrimaries);
+
+ return primaries;
+ }
+
+ /**
+ * Finds the type with the given name and returns its definition.
+ * <p>
+ * This implementation delegates to the <code>predecessor</code> (if it exists) if the type is not found within the declareded
+ * primary and mixin types.
+ * </p>
+ *
+ * @param typeName the name of the type to return
+ * @return the type named <code>typeName</code> if it exists, otherwise <code>null</code>.
+ * @throw IllegalArgumentException if <code>typeName</code> is <code>null</code>.
+ * @see org.jboss.dna.jcr.JcrNodeTypeSource#findType(org.jboss.dna.graph.property.Name)
+ */
+ public JcrNodeType findType( Name typeName ) {
+ CheckArg.isNotNull(typeName, "typeName");
+ for (JcrNodeType type : getDeclaredPrimaryNodeTypes()) {
+ if (typeName.equals(type.getInternalName())) {
+ return type;
+ }
+ }
+
+ for (JcrNodeType type : getDeclaredMixinNodeTypes()) {
+ if (typeName.equals(type.getInternalName())) {
+ return type;
+ }
+ }
+
+ if (predecessor != null) {
+ return predecessor.findType(typeName);
+ }
+
+ return null;
+ }
+}
Property changes on: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNodeTypeSource.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaBuiltinNodeTypeSource.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaBuiltinNodeTypeSource.java (rev 0)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaBuiltinNodeTypeSource.java 2009-03-05 18:20:33 UTC (rev 760)
@@ -0,0 +1,93 @@
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.jcr;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import javax.jcr.PropertyType;
+import javax.jcr.nodetype.NodeType;
+import net.jcip.annotations.Immutable;
+
+/**
+ * {@link JcrNodeTypeSource} that provides built-in node types provided by DNA.
+ */
+@Immutable
+class DnaBuiltinNodeTypeSource extends AbstractJcrNodeTypeSource {
+
+ /** The list of primary node types. */
+ private final List<JcrNodeType> primaryNodeTypes;
+ /** The list of mixin node types. */
+ private final List<JcrNodeType> mixinNodeTypes;
+
+ DnaBuiltinNodeTypeSource( JcrSession session,
+ JcrNodeTypeSource predecessor ) {
+ super(predecessor);
+
+ primaryNodeTypes = new ArrayList<JcrNodeType>();
+ mixinNodeTypes = new ArrayList<JcrNodeType>();
+
+ JcrNodeType base = findType(JcrNtLexicon.BASE);
+
+ if (base == null) {
+ String baseTypeName = JcrNtLexicon.BASE.getString(session.getExecutionContext().getNamespaceRegistry());
+ String namespaceTypeName = DnaLexicon.NAMESPACE.getString(session.getExecutionContext().getNamespaceRegistry());
+ throw new IllegalStateException(JcrI18n.supertypeNotFound.text(baseTypeName, namespaceTypeName));
+ }
+
+ // Stubbing in child node and property definitions for now
+ JcrNodeType namespace = new JcrNodeType(session, DnaLexicon.NAMESPACE, Arrays.asList(new NodeType[] {base}),
+ DnaLexicon.URI, NO_CHILD_NODES, Arrays.asList(new JcrPropertyDefinition[] {
+ new JcrPropertyDefinition(session, null, DnaLexicon.URI,
+ OnParentVersionBehavior.VERSION.getJcrValue(),
+ true, true, true, NO_DEFAULT_VALUES,
+ PropertyType.STRING, NO_CONSTRAINTS, false)}),
+ NOT_MIXIN, UNORDERABLE_CHILD_NODES);
+
+ primaryNodeTypes.addAll(Arrays.asList(new JcrNodeType[] {namespace}));
+
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.jcr.JcrNodeTypeSource#getMixinNodeTypes()
+ */
+ @Override
+ public Collection<JcrNodeType> getDeclaredMixinNodeTypes() {
+ return mixinNodeTypes;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.jcr.JcrNodeTypeSource#getPrimaryNodeTypes()
+ */
+ @Override
+ public Collection<JcrNodeType> getDeclaredPrimaryNodeTypes() {
+ return primaryNodeTypes;
+ }
+
+}
Property changes on: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaBuiltinNodeTypeSource.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java 2009-03-05 18:14:56 UTC (rev 759)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java 2009-03-05 18:20:33 UTC (rev 760)
@@ -33,5 +33,6 @@
public static final Name NAMESPACES = new BasicName(Namespace.URI, "namespaces");
public static final Name NAMESPACE = new BasicName(Namespace.URI, "namespace");
+ public static final Name URI = new BasicName(Namespace.URI, "uri");
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrBuiltinNodeTypeSource.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrBuiltinNodeTypeSource.java 2009-03-05 18:14:56 UTC (rev 759)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrBuiltinNodeTypeSource.java 2009-03-05 18:20:33 UTC (rev 760)
@@ -26,7 +26,6 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
import java.util.List;
import javax.jcr.PropertyType;
import javax.jcr.Value;
@@ -39,34 +38,21 @@
* {@link JcrNodeTypeSource} that provides built-in node types per the 1.0 specification.
*/
@Immutable
-class JcrBuiltinNodeTypeSource implements JcrNodeTypeSource {
+class JcrBuiltinNodeTypeSource extends AbstractJcrNodeTypeSource {
- // Convenience constants to help improve readability
- private static final Value[] NO_DEFAULT_VALUES = new Value[0];
- private static final String[] NO_CONSTRAINTS = new String[0];
- private static final List<NodeType> NO_SUPERTYPES = Collections.<NodeType>emptyList();
- private static final List<JcrNodeDefinition> NO_CHILD_NODES = Collections.<JcrNodeDefinition>emptyList();
- private static final List<JcrPropertyDefinition> NO_PROPERTIES = Collections.<JcrPropertyDefinition>emptyList();
-
- // Indicates that the node type has no primary item name - added for readability
- private static final Name NO_PRIMARY_ITEM_NAME = null;
- // Indicates that the definition should apply to all property definition or child node definitions - added for readability
- private static final Name ALL_NODES = null;
-
- // Indicates whether or not the node type is a mixin - added for readability
- private static final boolean IS_A_MIXIN = true;
- private static final boolean NOT_MIXIN = false;
-
- // Indicates whether or not the node type has orderable children - added for readability
- private static final boolean ORDERABLE_CHILD_NODES = true;
- private static final boolean UNORDERABLE_CHILD_NODES = false;
-
/** The list of primary node types. */
private final List<JcrNodeType> primaryNodeTypes;
/** The list of mixin node types. */
private final List<JcrNodeType> mixinNodeTypes;
JcrBuiltinNodeTypeSource( JcrSession session ) {
+ this(session, null);
+ }
+
+ JcrBuiltinNodeTypeSource( JcrSession session,
+ JcrNodeTypeSource predecessor ) {
+ super(predecessor);
+
primaryNodeTypes = new ArrayList<JcrNodeType>();
Value trueValue = new JcrValue(session.getExecutionContext().getValueFactories(), PropertyType.BOOLEAN, Boolean.TRUE);
@@ -620,7 +606,8 @@
*
* @see org.jboss.dna.jcr.JcrNodeTypeSource#getMixinNodeTypes()
*/
- public Collection<JcrNodeType> getMixinNodeTypes() {
+ @Override
+ public Collection<JcrNodeType> getDeclaredMixinNodeTypes() {
return mixinNodeTypes;
}
@@ -629,7 +616,8 @@
*
* @see org.jboss.dna.jcr.JcrNodeTypeSource#getPrimaryNodeTypes()
*/
- public Collection<JcrNodeType> getPrimaryNodeTypes() {
+ @Override
+ public Collection<JcrNodeType> getDeclaredPrimaryNodeTypes() {
return primaryNodeTypes;
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrI18n.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrI18n.java 2009-03-05 18:14:56 UTC (rev 759)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrI18n.java 2009-03-05 18:20:33 UTC (rev 760)
@@ -65,6 +65,7 @@
public static I18n errorWhileFindingNodeWithUuid;
public static I18n typeNotFound;
+ public static I18n supertypeNotFound;
// Used in AbstractJcrNode#getAncestor
public static I18n noNegativeDepth;
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeSource.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeSource.java 2009-03-05 18:14:56 UTC (rev 759)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeTypeSource.java 2009-03-05 18:20:33 UTC (rev 760)
@@ -2,6 +2,7 @@
import java.util.Collection;
import javax.jcr.nodetype.NodeType;
+import org.jboss.dna.graph.property.Name;
/**
* Interface for any potential provider of {@link JcrNodeType} definitions, the DNA implementation of {@link NodeType}. Possible
@@ -25,4 +26,10 @@
*/
public Collection<JcrNodeType> getMixinNodeTypes();
+ /**
+ * Finds the type with the given name and returns its definition.
+ * @param typeName the name of the type to return
+ * @return the type named <code>typeName</code> if it exists, otherwise <code>null</code>.
+ */
+ public JcrNodeType findType(Name typeName);
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java 2009-03-05 18:14:56 UTC (rev 759)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java 2009-03-05 18:20:33 UTC (rev 760)
@@ -156,7 +156,8 @@
this.session = new JcrSession(this.repository, this, this.context, sessionAttributes);
// This must be initialized after the session
- this.nodeTypeManager = new JcrNodeTypeManager(new JcrBuiltinNodeTypeSource(this.session));
+ this.nodeTypeManager = new JcrNodeTypeManager(new DnaBuiltinNodeTypeSource(this.session,
+ new JcrBuiltinNodeTypeSource(this.session)));
}
Modified: trunk/dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties
===================================================================
--- trunk/dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties 2009-03-05 18:14:56 UTC (rev 759)
+++ trunk/dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties 2009-03-05 18:20:33 UTC (rev 760)
@@ -63,6 +63,7 @@
workspaceNameIsInvalid = "{1}" is not a valid workspace name for the "{0}" repository
errorVerifyingWorkspaceName =Error validating the workspace name "{1}" for the "{0}" repository\: {2}
typeNotFound=No type exists with name "{0}"
+supertypeNotFound=Could not find type "{0}" which is a required supertype of type "{1}"
noNegativeDepth=Depth parameter ({0}) cannot be negative
tooDeep=Depth parameter ({0}) cannot be greater than the result of getDepth() for this node
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-03-05 18:14:56 UTC (rev 759)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-03-05 18:20:33 UTC (rev 760)
@@ -127,7 +127,7 @@
// addTestSuite(org.apache.jackrabbit.test.api.query.SimpleSelectionTest.class);
// The tests in this suite are level one
- // addTest(org.apache.jackrabbit.test.api.nodetype.TestAll.suite());
+ addTest(org.apache.jackrabbit.test.api.nodetype.TestAll.suite());
}
}
15 years, 1 month
DNA SVN: r759 - trunk/dna-jcr/src/main/java/org/jboss/dna/jcr.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-03-05 13:14:56 -0500 (Thu, 05 Mar 2009)
New Revision: 759
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeType.java
Log:
DNA-91 Implement node type management
Applied the latest patch to correct the behavior JcrNodeType.can* methods re considering the definitions from supertypes. The patch also cleans up the can* methods in general.
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeType.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeType.java 2009-03-05 18:02:40 UTC (rev 758)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrNodeType.java 2009-03-05 18:14:56 UTC (rev 759)
@@ -39,6 +39,7 @@
import org.jboss.dna.common.util.CheckArg;
import org.jboss.dna.graph.property.Name;
import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.graph.property.ValueFactories;
import org.jboss.dna.graph.property.ValueFormatException;
import org.jboss.dna.graph.property.Path.Segment;
@@ -48,6 +49,8 @@
@Immutable
class JcrNodeType implements NodeType {
+ public static final String RESIDUAL_ITEM_NAME = "*";
+
/** The name of the node type (e.g., <code>{http://www.jcp.org/jcr/nt/1.0}base</code>) */
private final Name name;
/** The name of the node's primary item */
@@ -97,6 +100,56 @@
}
/**
+ * Returns the property definition with the given name. This method first checks the property definitions declared within this
+ * type to see if any property definitions have the given name. If no matches are found, this method initiates a recursive
+ * depth first search up the type hierarchy to attempt to find a definition in one of the supertypes (or one the supertypes of
+ * the supertypes).
+ *
+ * @param propertyName the name of the property for which the definition should be retrieved. Use
+ * {@link JcrNodeType#RESIDUAL_ITEM_NAME} to retrieve the residual property definition (if any).
+ * @return the property definition for the given name or <code>null</code> if no such definition exists.
+ * @see JcrNodeType#RESIDUAL_ITEM_NAME
+ */
+ JcrPropertyDefinition getPropertyDefinition( String propertyName ) {
+ for (JcrPropertyDefinition property : propertyDefinitions) {
+ if (propertyName.equals(property.getName())) {
+ return property;
+ }
+ }
+
+ for (NodeType nodeType : declaredSupertypes) {
+ JcrPropertyDefinition definition = ((JcrNodeType)nodeType).getPropertyDefinition(propertyName);
+ if (definition != null) return definition;
+ }
+ return null;
+ }
+
+ /**
+ * Returns the node definition for the child node with the given name. This method first checks the child node definitions
+ * declared within this type to see if any child node definitions have the given name. If no matches are found, this method
+ * initiates a recursive depth first search up the type hierarchy to attempt to find a definition in one of the supertypes (or
+ * one the supertypes of the supertypes).
+ *
+ * @param childNodeName the name of the child node for which the definition should be retrieved. Use
+ * {@link JcrNodeType#RESIDUAL_ITEM_NAME} to retrieve the residual child node definition (if any).
+ * @return the child node definition with the given name or <code>null</code> if no such definition exists.
+ * @see JcrNodeType#RESIDUAL_ITEM_NAME
+ */
+ JcrNodeDefinition getChildNodeDefinition( String childNodeName ) {
+ for (JcrNodeDefinition childNode : childNodeDefinitions) {
+ if (childNodeName.equals(childNode.getName())) {
+ return childNode;
+ }
+ }
+
+ for (NodeType nodeType : declaredSupertypes) {
+ JcrNodeDefinition definition = ((JcrNodeType)nodeType).getChildNodeDefinition(childNodeName);
+ if (definition != null) return definition;
+ }
+ return null;
+ }
+
+ /**
* {@inheritDoc}
*
* @see javax.jcr.nodetype.NodeType#canAddChildNode(java.lang.String)
@@ -105,39 +158,25 @@
CheckArg.isNotNull(childNodeName, "childNodeName");
- JcrNodeDefinition residual = null;
-
// First, try to find a child node definition with the given name
- for (JcrNodeDefinition childNode : childNodeDefinitions) {
- if (childNodeName.equals(childNode.getName())) {
- NodeType defaultType = childNode.getDefaultPrimaryType();
- // If there's no default type, the child node can't be created
- if (defaultType == null) {
- return false;
- }
+ JcrNodeDefinition childNode = getChildNodeDefinition(childNodeName);
- // Check if the node can be added with the named child node definition
- return checkTypeAgainstDefinition(defaultType, childNode);
- // If we run into a residual (*) definition, save it just in case
- } else if (childNode.name == null) {
- residual = childNode;
- }
+ // If there are no named definitions in the type hierarchy, try to find a residual node definition
+ if (childNode == null) {
+ childNode = getChildNodeDefinition(RESIDUAL_ITEM_NAME);
}
- // If there's no matching child node definition for the name and no residual definition, the node cannot be added
- if (residual == null) {
- return false;
- }
+ if (childNode != null) {
+ NodeType defaultType = childNode.getDefaultPrimaryType();
+ // If there's no default type, the child node can't be created
+ if (defaultType == null) {
+ return false;
+ }
- NodeType defaultType = residual.getDefaultPrimaryType();
-
- // If there's no default type, the child node can't be created
- if (defaultType == null) {
- return false;
+ // Check if the node can be added with the named child node definition
+ return checkTypeAgainstDefinition(defaultType, childNode);
}
-
- // Check if the node can be added with the default type of the residual child node definition
- return checkTypeAgainstDefinition(defaultType, residual);
+ return false;
}
/**
@@ -159,24 +198,20 @@
return false;
}
- JcrNodeDefinition residual = null;
+ // First, try to find a child node definition with the given name
+ JcrNodeDefinition childNode = getChildNodeDefinition(childNodeName);
- // First, try to find a child node definition with the given name
- for (JcrNodeDefinition childNode : childNodeDefinitions) {
- if (childNodeName.equals(childNode.getName())) {
- return checkTypeAgainstDefinition(primaryNodeType, childNode);
- // If we run into a residual (*) definition, save it just in case
- } else if (childNode.name == null) {
- residual = childNode;
- }
+ // If there are no named definitions in the type hierarchy, try to find a residual node definition
+ if (childNode == null) {
+ childNode = getChildNodeDefinition(RESIDUAL_ITEM_NAME);
}
- // If there's no matching child node definition for the name and no residual definition, the node cannot be added
- if (residual == null) {
- return false;
+ // Check if the node can be added with the named child node definition
+ if (childNode != null) {
+ return checkTypeAgainstDefinition(primaryNodeType, childNode);
}
- return checkTypeAgainstDefinition(primaryNodeType, residual);
+ return false;
}
/**
@@ -209,6 +244,7 @@
public boolean canRemoveItem( String itemName ) {
CheckArg.isNotNull(itemName, "itemName");
+ // Don't know if item is a property or a node, so check both locally before moving up the type hierarchy
for (PropertyDefinition item : propertyDefinitions) {
if (itemName.equals(item.getName())) {
return !item.isMandatory() && !item.isProtected();
@@ -221,6 +257,13 @@
}
}
+ // Check if any supertypes prevent the removal of this item
+ for (NodeType type : declaredSupertypes) {
+ if (!type.canRemoveItem(itemName)) {
+ return false;
+ }
+ }
+
return true;
}
@@ -233,127 +276,117 @@
Value value ) {
CheckArg.isNotNull(propertyName, "propertyName");
- JcrPropertyDefinition residual = null;
+ JcrPropertyDefinition property = getPropertyDefinition(propertyName);
+ if (property == null) {
+ property = getPropertyDefinition(RESIDUAL_ITEM_NAME);
+ }
- for (JcrPropertyDefinition property : propertyDefinitions) {
- if (propertyName.equals(property.getName())) {
- if (property.isMultiple()) {
- return false;
- }
+ if (property == null) {
+ return false;
+ }
- return canSetProperty(property, value);
- } else if (property.name == null && !property.isMultiple()) {
- residual = property;
- }
+ // Can't modify a multi-property with a single value. Can't modify a protected property at all.
+ if (property.isMultiple() || property.isProtected()) {
+ return false;
}
- return canSetProperty(residual, value);
+ // Null values indicates an attempt to unset property
+ if (value == null) {
+ return !property.isMandatory();
+ }
+
+ return canCastValueToType(value, property.getRequiredType());
}
/**
- * Internal method to validate that a value can be set on a given property. The values are set according to the following
- * rules:
+ * Internal method to validate that a value can be cast to a given JCR property type. The values are set according to the
+ * following rules:
* <ol>
- * <li>If <code>value</code> is <code>null</code>, return the value of {@link JcrNodeType#canRemoveItem(String)}</li>
- * <li>If <code>property.isProtected()</code> is <code>true</code>, return <code>false</code></li>
* <li>If <code>property.getRequiredType()</code> is {@link PropertyType#UNDEFINED}, return <code>true</code></li>
* <li>Compare the type of the given value to the required type and see if they are compatible based on the rules in the JCR
* 1.0 spec.</li>
* </ol>
*
- * @param property the property to be set
- * @param value the value to set (may be <code>null</code>)
- * @return whether the property can be set to the value based on the described rules
+ * @param jcrPropertyType a value from the {@link PropertyType} constants to which this value MAY be able to be casted.
+ * @param value the value to set (may not be <code>null</code>)
+ * @return whether the value can be cast to the given property type
*/
- private boolean canSetProperty( JcrPropertyDefinition property,
- Value value ) {
- assert property != null;
+ private boolean canCastValueToType( Value value,
+ int jcrPropertyType ) {
+ assert value != null;
- if (value == null) {
- return !property.isProtected() && !property.isMandatory();
- }
+ int valueType = value.getType();
- if (property.isProtected()) {
- return false;
+ // Trivial case - no cast required
+ if (valueType == jcrPropertyType) {
+ return true;
}
- int valueType = value.getType();
+ try {
+ switch (jcrPropertyType) {
+ case PropertyType.BOOLEAN:
+ if (valueType == PropertyType.STRING) {
+ return true;
+ }
- switch (property.getRequiredType()) {
- case PropertyType.BINARY:
- return true;
- case PropertyType.BOOLEAN:
- if (valueType == PropertyType.BOOLEAN || valueType == PropertyType.STRING) {
- return true;
- }
-
- // If the binary can be converted to a UTF-8 string, it can be set onto a boolean property
- if (valueType == PropertyType.BINARY) {
- try {
+ if (valueType == PropertyType.BINARY) {
+ // If the binary can be converted to a UTF-8 string, it can be set onto a boolean property
value.getString();
return true;
- } catch (RepositoryException re) {
- return false;
}
- }
- return false;
+ return false;
- case PropertyType.DATE:
- if (valueType == PropertyType.DATE || valueType == PropertyType.DOUBLE || valueType == PropertyType.LONG) {
- return true;
- }
+ case PropertyType.DATE:
+ if (valueType == PropertyType.DOUBLE || valueType == PropertyType.LONG) {
+ return true;
+ }
- if (valueType == PropertyType.STRING || valueType == PropertyType.BINARY) {
- try {
+ if (valueType == PropertyType.STRING || valueType == PropertyType.BINARY) {
+ // If the binary can be converted to a date, it can be set onto a date property
value.getDate();
return true;
- } catch (RepositoryException re) {
- return false;
}
- }
- return false;
+ return false;
- case PropertyType.DOUBLE:
- return value.getType() == PropertyType.DOUBLE;
- case PropertyType.LONG:
- return value.getType() == PropertyType.LONG;
- case PropertyType.NAME:
- if (value.getType() == PropertyType.NAME) {
- return true;
- }
-
- try {
+ case PropertyType.NAME:
+ ValueFactories valueFactories = session.getExecutionContext().getValueFactories();
if (valueType == PropertyType.STRING || valueType == PropertyType.BINARY) {
- session.getExecutionContext().getValueFactories().getNameFactory().create(value.getString());
+ valueFactories.getNameFactory().create(value.getString());
return true;
}
if (valueType == PropertyType.PATH) {
- Path path = session.getExecutionContext().getValueFactories().getPathFactory().create(value.getString());
+ Path path = valueFactories.getPathFactory().create(value.getString());
Segment[] segments = path.getSegmentsArray();
return !path.isAbsolute() && segments.length == 1 && !segments[0].hasIndex();
}
- } catch (ValueFormatException re) {
+
return false;
- } catch (RepositoryException re) {
- return false;
- }
- return false;
+ case PropertyType.PATH:
+ return value.getType() == PropertyType.STRING;
- case PropertyType.PATH:
- return value.getType() == PropertyType.PATH || value.getType() == PropertyType.STRING;
- case PropertyType.REFERENCE:
- return value.getType() == PropertyType.REFERENCE;
+ // Nothing can be converted to these types (except themselves)
+ case PropertyType.REFERENCE:
+ case PropertyType.DOUBLE:
+ case PropertyType.LONG:
+ return false;
- // Anything can be converted to these types
- case PropertyType.STRING:
- case PropertyType.UNDEFINED:
- return true;
- default:
- throw new IllegalStateException("Invalid required property type " + property.getRequiredType() + " for property "
- + property.getName());
+ // Anything can be converted to these types
+ case PropertyType.BINARY:
+ case PropertyType.STRING:
+ case PropertyType.UNDEFINED:
+ return true;
+ default:
+ assert false : "Unexpected JCR property type " + jcrPropertyType;
+ // This should still throw an exception even if assertions are turned off
+ throw new IllegalStateException("Invalid property type " + jcrPropertyType);
+ }
+ } catch (RepositoryException re) {
+ return false;
+ } catch (ValueFormatException vfe) {
+ return false;
}
}
@@ -366,49 +399,33 @@
Value[] values ) {
CheckArg.isNotNull(propertyName, "propertyName");
- JcrPropertyDefinition residual = null;
+ JcrPropertyDefinition property = getPropertyDefinition(propertyName);
+ if (property == null) {
+ property = getPropertyDefinition(RESIDUAL_ITEM_NAME);
+ }
- for (JcrPropertyDefinition property : propertyDefinitions) {
- if (propertyName.equals(property.getName())) {
- if (!property.isMultiple()) {
- return false;
- }
+ if (property == null) {
+ return false;
+ }
- return canSetProperty(property, values);
- } else if (property.name == null && property.isMultiple()) {
- residual = property;
- }
+ // Can't modify a single valued property with a multiple values. Can't modify a protected property at all.
+ if (!property.isMultiple() || property.isProtected()) {
+ return false;
}
- return canSetProperty(residual, values);
- }
+ // Null values indicates an attempt to unset property
+ if (values == null) {
+ return !property.isMandatory();
+ }
- /**
- * Internal method to validate that an array of values can be set on a given property. This method returns <code>true</code>
- * if the following algorithm would return <code>true</code> when applied to each non-null value in <code>values</code>:
- * <ol>
- * <li>If the value is null, return the value of {@link JcrNodeType#canRemoveItem(String)}</li>
- * <li>If the property definition has a no required type ({@link PropertyType#UNDEFINED}), return <code>true</code></li>
- * <li>Compare the type of the given value to the required type and see if they are compatible</li>
- * </ol>
- *
- * @param property the property to be set
- * @param values the array of values to set (may be <code>null</code>)
- * @return whether the property can be set to the value based on the described rules
- */
- private boolean canSetProperty( JcrPropertyDefinition property,
- Value[] values ) {
- if (values != null) {
- for (int i = 0; i < values.length; i++) {
- if (values[i] != null) {
- if (!canSetProperty(property, values[i])) {
- return false;
- }
+ for (int i = 0; i < values.length; i++) {
+ if (values[i] != null) {
+ if (!canCastValueToType(values[i], property.getRequiredType())) {
+ return false;
}
}
}
-
- return !property.isProtected();
+ return true;
}
/**
15 years, 1 month
DNA SVN: r758 - in trunk/dna-jcr/src: test/java/org/jboss/dna/jcr and 1 other directory.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-03-05 13:02:40 -0500 (Thu, 05 Mar 2009)
New Revision: 758
Removed:
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckLevelOneTestSuite.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckLevelTwoTestSuite.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckOptionalTestSuite.java
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrPropertyIterator.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrNodeTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrPropertyIteratorTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRootNodeTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
Log:
DNA-194 Implement update JCR capability
Refactored the TCK unit tests again to make them easier to run/understand. Also improved the implementation of some JCR API methods, and reorganized the methods in JcrAbstractNode.
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java 2009-03-05 14:55:09 UTC (rev 757)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/AbstractJcrNode.java 2009-03-05 18:02:40 UTC (rev 758)
@@ -24,11 +24,11 @@
package org.jboss.dna.jcr;
import java.io.InputStream;
-import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Pattern;
@@ -48,11 +48,11 @@
import javax.jcr.lock.Lock;
import javax.jcr.nodetype.NodeDefinition;
import javax.jcr.nodetype.NodeType;
+import javax.jcr.nodetype.NodeTypeManager;
import javax.jcr.version.Version;
import javax.jcr.version.VersionHistory;
import net.jcip.annotations.NotThreadSafe;
import org.jboss.dna.common.util.CheckArg;
-import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.property.Name;
import org.jboss.dna.graph.property.NamespaceRegistry;
import org.jboss.dna.graph.property.Path;
@@ -65,8 +65,10 @@
@NotThreadSafe
abstract class AbstractJcrNode extends AbstractJcrItem implements Node {
+ private static final NodeType[] EMPTY_NODE_TYPES = new NodeType[] {};
+
private final JcrSession session;
- Set<Property> properties;
+ Map<Name, Property> properties;
List<Path.Segment> children;
private UUID uuid;
@@ -78,137 +80,113 @@
/**
* {@inheritDoc}
*
- * @throws IllegalArgumentException if <code>visitor</code> is <code>null</code>.
- * @see javax.jcr.Item#accept(javax.jcr.ItemVisitor)
+ * @see javax.jcr.Item#getSession()
*/
- public final void accept( ItemVisitor visitor ) throws RepositoryException {
- CheckArg.isNotNull(visitor, "visitor");
- visitor.visit(this);
+ public final Session getSession() {
+ return session;
}
- /**
- * {@inheritDoc}
- *
- * @throws UnsupportedOperationException always
- * @see javax.jcr.Node#addMixin(java.lang.String)
- */
- public final void addMixin( String mixinName ) {
- throw new UnsupportedOperationException();
+ final UUID internalUuid() {
+ return uuid;
}
/**
- * {@inheritDoc}
+ * Change the internal UUID. Technically, it is possible for this to change, but only because a new node may be assigned a
+ * UUID when it is created within the session and (according to the spec) this UUID can change when the new node is persisted
+ * upon {@link #save()}.
*
- * @throws UnsupportedOperationException always
- * @see javax.jcr.Node#addNode(java.lang.String)
+ * @param uuid the new UUID; may not be null
*/
- public final Node addNode( String relPath ) {
- throw new UnsupportedOperationException();
+ final void setInternalUuid( UUID uuid ) {
+ assert uuid != null;
+ this.uuid = uuid;
}
- /**
- * {@inheritDoc}
- *
- * @throws UnsupportedOperationException always
- * @see javax.jcr.Node#addNode(java.lang.String, java.lang.String)
- */
- public final Node addNode( String relPath,
- String primaryNodeTypeName ) {
- throw new UnsupportedOperationException();
+ final void setChildren( List<Segment> children ) {
+ assert children != null;
+ this.children = children;
}
- /**
- * {@inheritDoc}
- *
- * @return <code>false</code>
- * @see javax.jcr.Node#canAddMixin(java.lang.String)
- */
- public final boolean canAddMixin( String mixinName ) {
- return false;
+ final void setProperties( Map<Name, Property> properties ) {
+ assert properties != null;
+ this.properties = properties;
}
- /**
- * {@inheritDoc}
- *
- * @throws UnsupportedOperationException always
- * @see javax.jcr.Node#cancelMerge(javax.jcr.version.Version)
- */
- public final void cancelMerge( Version version ) {
- throw new UnsupportedOperationException();
+ final Name nameFrom( String name ) {
+ return session.getExecutionContext().getValueFactories().getNameFactory().create(name);
}
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
- * @see javax.jcr.Node#checkin()
+ * @see javax.jcr.Node#getUUID()
*/
- public final Version checkin() {
- throw new UnsupportedOperationException();
+ public final String getUUID() throws RepositoryException {
+ // Return JCR UUID only if node is referenceable
+ try {
+ Property mixinsProp = getProperty("jcr:mixinTypes");
+ if (mixinsProp != null) {
+ for (Value value : mixinsProp.getValues()) {
+ if ("mix:referenceable".equals(value.getString())) return getProperty("jcr:uuid").getString();
+ }
+ }
+ } catch (PathNotFoundException error) {
+ throw new UnsupportedRepositoryOperationException(error);
+ }
+ throw new UnsupportedRepositoryOperationException();
}
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
- * @see javax.jcr.Node#checkout()
+ * @return <code>true</code>
+ * @see javax.jcr.Item#isNode()
*/
- public final void checkout() {
- throw new UnsupportedOperationException();
+ public final boolean isNode() {
+ return true;
}
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
- * @see javax.jcr.Node#doneMerge(javax.jcr.version.Version)
+ * @return <code>false</code>
+ * @see javax.jcr.Node#isNodeType(java.lang.String)
*/
- public final void doneMerge( Version version ) {
- throw new UnsupportedOperationException();
- }
+ public boolean isNodeType( String nodeTypeName ) throws RepositoryException {
+ NodeType nodeType = getPrimaryNodeType();
- /**
- * {@inheritDoc}
- *
- * @throws UnsupportedRepositoryOperationException always
- * @see javax.jcr.Node#getBaseVersion()
- */
- public final Version getBaseVersion() throws UnsupportedRepositoryOperationException {
- throw new UnsupportedRepositoryOperationException();
- }
+ if (nodeType.isNodeType(nodeTypeName)) {
+ return true;
+ }
- /**
- * {@inheritDoc}
- *
- * @throws UnsupportedOperationException always
- * @see javax.jcr.Node#getCorrespondingNodePath(java.lang.String)
- */
- public final String getCorrespondingNodePath( String workspaceName ) {
- throw new UnsupportedOperationException();
+ NodeType[] mixinNodeTypes = getMixinNodeTypes();
+ for (int i = 0; i < mixinNodeTypes.length; i++) {
+ if (mixinNodeTypes[i].isNodeType(nodeTypeName)) {
+ return true;
+ }
+ }
+
+ return false;
}
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
* @see javax.jcr.Node#getDefinition()
*/
public NodeDefinition getDefinition() {
- throw new UnsupportedOperationException();
+ return null;
}
- final UUID getInternalUuid() {
- return uuid;
- }
-
/**
* {@inheritDoc}
*
- * @throws UnsupportedRepositoryOperationException always
- * @see javax.jcr.Node#getLock()
+ * @throws UnsupportedOperationException always
+ * @see javax.jcr.Node#getPrimaryNodeType()
*/
- public final Lock getLock() throws UnsupportedRepositoryOperationException {
- throw new UnsupportedRepositoryOperationException();
+ public NodeType getPrimaryNodeType() throws RepositoryException {
+ String nodeTypeName = getProperty(JcrLexicon.PRIMARY_TYPE).getString();
+ return session.getWorkspace().getNodeTypeManager().getNodeType(nodeTypeName);
}
/**
@@ -218,85 +196,36 @@
* @see javax.jcr.Node#getMixinNodeTypes()
*/
public NodeType[] getMixinNodeTypes() throws RepositoryException {
- PropertyIterator mixinProperties = getProperties(JcrLexicon.MIXIN_TYPES.getString(session.getExecutionContext()
- .getNamespaceRegistry()));
- List<NodeType> mixinNodeTypes = new ArrayList<NodeType>((int)mixinProperties.getSize());
-
- while (mixinProperties.hasNext()) {
- Property property = mixinProperties.nextProperty();
-
- String nodeTypeName = property.getValue().getString();
- NodeType nodeType = session.getWorkspace().getNodeTypeManager().getNodeType(nodeTypeName);
-
- mixinNodeTypes.add(nodeType);
+ NodeTypeManager nodeTypeManager = session.getWorkspace().getNodeTypeManager();
+ Property mixinTypesProperty = getProperty(JcrLexicon.MIXIN_TYPES);
+ if (mixinTypesProperty == null) return EMPTY_NODE_TYPES;
+ List<NodeType> mixinNodeTypes = new LinkedList<NodeType>();
+ for (Value value : mixinTypesProperty.getValues()) {
+ String nodeTypeName = value.getString();
+ NodeType nodeType = nodeTypeManager.getNodeType(nodeTypeName);
+ if (nodeType != null) mixinNodeTypes.add(nodeType);
}
-
return mixinNodeTypes.toArray(new NodeType[mixinNodeTypes.size()]);
}
/**
* {@inheritDoc}
*
- * @throws IllegalArgumentException if <code>relativePath</code> is empty or <code>null</code>.
- * @see javax.jcr.Node#getNode(java.lang.String)
+ * @return <code>false</code>
+ * @see javax.jcr.Node#canAddMixin(java.lang.String)
*/
- public final Node getNode( String relativePath ) throws RepositoryException {
- CheckArg.isNotEmpty(relativePath, "relativePath");
- String path = getPath(getPath(), relativePath);
- Item item = getSession().getItem(path);
- if (item instanceof Node) {
- return (Node)item;
- }
- throw new PathNotFoundException();
+ public final boolean canAddMixin( String mixinName ) {
+ return false;
}
/**
* {@inheritDoc}
*
- * @see javax.jcr.Node#getNodes()
- */
- public final NodeIterator getNodes() {
- if (children == null) {
- return new JcrEmptyNodeIterator();
- }
- return new JcrChildNodeIterator(this, this.session.getExecutionContext().getNamespaceRegistry(), children);
- }
-
- /**
- * {@inheritDoc}
- *
* @throws UnsupportedOperationException always
- * @see javax.jcr.Node#getNodes(java.lang.String)
+ * @see javax.jcr.Node#removeMixin(java.lang.String)
*/
- public NodeIterator getNodes( String namePattern ) throws RepositoryException {
- CheckArg.isNotNull(namePattern, "namePattern");
- namePattern = namePattern.trim();
- if (namePattern.length() == 0) return new JcrEmptyNodeIterator();
- if ("*".equals(namePattern)) return getNodes();
- List<Object> patterns = createPatternsFor(namePattern);
-
- // Implementing exact-matching only for now to prototype types as properties
- List<Path.Segment> matchingChildren = new LinkedList<Path.Segment>();
- NamespaceRegistry registry = session.executionContext.getNamespaceRegistry();
- boolean foundMatch = false;
- for (Path.Segment child : children) {
- String childName = child.getName().getString(registry);
- for (Object patternOrMatch : patterns) {
- if (patternOrMatch instanceof Pattern) {
- Pattern pattern = (Pattern)patternOrMatch;
- if (pattern.matcher(childName).matches()) foundMatch = true;
- } else {
- String match = (String)patternOrMatch;
- if (childName.equals(match)) foundMatch = true;
- }
- if (foundMatch) {
- foundMatch = false;
- matchingChildren.add(child);
- break;
- }
- }
- }
- return new JcrChildNodeIterator(this, this.session.executionContext.getNamespaceRegistry(), matchingChildren);
+ public final void removeMixin( String mixinName ) {
+ throw new UnsupportedOperationException();
}
/**
@@ -317,19 +246,45 @@
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
- * @see javax.jcr.Node#getPrimaryNodeType()
+ * @throws IllegalArgumentException if <code>otherItem</code> is <code>null</code>.
+ * @see javax.jcr.Item#isSame(javax.jcr.Item)
*/
- public NodeType getPrimaryNodeType() throws RepositoryException {
- String primaryTypeName = JcrLexicon.PRIMARY_TYPE.getString(session.getExecutionContext().getNamespaceRegistry());
- Property primaryNodeTypeProperty = getProperty(primaryTypeName);
- Value nodeValue = primaryNodeTypeProperty.getValue();
+ @Override
+ public final boolean isSame( Item otherItem ) throws RepositoryException {
+ CheckArg.isNotNull(otherItem, "otherItem");
+ if (super.isSame(otherItem) && otherItem instanceof Node) {
+ if (otherItem instanceof AbstractJcrNode) {
+ return internalUuid().equals(((AbstractJcrNode)otherItem).internalUuid());
+ }
+ // If not our implementation, let the other item figure out whether we are the same.
+ return otherItem.isSame(this);
+ }
+ return false;
+ }
- ExecutionContext context = session.getExecutionContext();
- Name nodeValueAsName = context.getValueFactories().getNameFactory().create(nodeValue.getString());
+ /**
+ * {@inheritDoc}
+ *
+ * @see javax.jcr.Node#hasProperties()
+ */
+ public final boolean hasProperties() {
+ assert properties != null;
+ return !properties.isEmpty();
+ }
- String nodeTypeName = nodeValueAsName.getString(context.getNamespaceRegistry());
- return session.getWorkspace().getNodeTypeManager().getNodeType(nodeTypeName);
+ /**
+ * {@inheritDoc}
+ *
+ * @throws IllegalArgumentException if <code>relativePath</code> is empty or <code>null</code>.
+ * @see javax.jcr.Node#hasProperty(java.lang.String)
+ */
+ public final boolean hasProperty( String relativePath ) throws RepositoryException {
+ CheckArg.isNotEmpty(relativePath, "relativePath");
+ if (relativePath.indexOf('/') >= 0) {
+ return (getProperty(relativePath) != null);
+ }
+ assert properties != null;
+ return properties.containsKey(nameFrom(relativePath));
}
/**
@@ -338,7 +293,7 @@
* @see javax.jcr.Node#getProperties()
*/
public final PropertyIterator getProperties() {
- return new JcrPropertyIterator(properties);
+ return new JcrPropertyIterator(properties.values());
}
/**
@@ -350,84 +305,40 @@
CheckArg.isNotNull(namePattern, "namePattern");
namePattern = namePattern.trim();
if (namePattern.length() == 0) return new JcrEmptyPropertyIterator();
- if ("*".equals(namePattern)) return new JcrPropertyIterator(properties);
+ if ("*".equals(namePattern)) return new JcrPropertyIterator(properties.values());
List<Object> patterns = createPatternsFor(namePattern);
// Implementing exact-matching only for now to prototype types as properties
Set<Property> matchingProps = new HashSet<Property>();
- for (Object patternOrMatch : patterns) {
- if (patternOrMatch instanceof Pattern) {
- Pattern pattern = (Pattern)patternOrMatch;
- for (Property prop : properties) {
- String propName = prop.getName();
- if (pattern.matcher(propName).matches()) matchingProps.add(prop);
+ boolean foundMatch = false;
+ for (Property property : properties.values()) {
+ String propName = property.getName();
+ for (Object patternOrMatch : patterns) {
+ if (patternOrMatch instanceof Pattern) {
+ Pattern pattern = (Pattern)patternOrMatch;
+ if (pattern.matcher(propName).matches()) foundMatch = true;
+ } else {
+ String match = (String)patternOrMatch;
+ if (propName.equals(match)) foundMatch = true;
}
- } else {
- String match = (String)patternOrMatch;
- for (Property prop : properties) {
- String propName = prop.getName();
- if (propName.equals(match)) matchingProps.add(prop);
+ if (foundMatch) {
+ foundMatch = false;
+ matchingProps.add(property);
+ break;
}
}
}
return new JcrPropertyIterator(matchingProps);
}
- protected static List<Object> createPatternsFor( String namePattern ) throws RepositoryException {
- List<Object> patterns = new LinkedList<Object>();
- for (String stringPattern : namePattern.split("[|]")) {
- stringPattern = stringPattern.trim();
- int length = stringPattern.length();
- if (length == 0) continue;
- if (stringPattern.indexOf("*") == -1) {
- // Doesn't use wildcard, so use String not Pattern
- patterns.add(stringPattern);
- } else {
- // We need to escape the regular expression characters ...
- StringBuilder sb = new StringBuilder(length);
- for (int i = 0; i != length; i++) {
- char c = stringPattern.charAt(i);
- switch (c) {
- // Per the spec, the the following characters are not allowed in patterns:
- case '/':
- case '[':
- case ']':
- case '\'':
- case '"':
- case '|':
- case '\t':
- case '\n':
- case '\r':
- String msg = JcrI18n.invalidNamePattern.text(c, namePattern);
- throw new RepositoryException(msg);
- // The following characters must be escaped when used in regular expressions ...
- case '?':
- case '(':
- case ')':
- case '$':
- case '^':
- case '.':
- case '{':
- case '}':
- case '\\':
- sb.append("\\");
- sb.append(c);
- break;
- case '*':
- // replace with the regular expression wildcard
- sb.append(".*");
- break;
- default:
- sb.append(c);
- break;
- }
- }
- String escapedString = sb.toString();
- Pattern pattern = Pattern.compile(escapedString);
- patterns.add(pattern);
- }
- }
- return patterns;
+ /**
+ * A non-standard method to obtain a property given the {@link Name DNA Name} object. This method is faster
+ *
+ * @param propertyName the property name
+ * @return the JCR property with the supplied name, or null if the property doesn't exist
+ */
+ public final Property getProperty( Name propertyName ) {
+ return properties.get(propertyName);
}
/**
@@ -450,9 +361,8 @@
return ((Node)item).getParent().getProperty(item.getName());
}
assert properties != null;
- for (Property property : properties) {
- if (relativePath.equals(property.getName())) return property;
- }
+ Property property = properties.get(nameFrom(relativePath));
+ if (property != null) return property;
throw new PathNotFoundException();
}
@@ -465,7 +375,7 @@
public final PropertyIterator getReferences() throws RepositoryException {
// Iterate through the properties to see which ones have a REFERENCE type ...
Set<Property> references = new HashSet<Property>();
- for (Property property : properties) {
+ for (Property property : properties.values()) {
if (property.getType() == PropertyType.REFERENCE) references.add(property);
}
if (references.isEmpty()) return new JcrEmptyPropertyIterator();
@@ -475,45 +385,6 @@
/**
* {@inheritDoc}
*
- * @see javax.jcr.Item#getSession()
- */
- public final Session getSession() {
- return session;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see javax.jcr.Node#getUUID()
- */
- public final String getUUID() throws RepositoryException {
- // Return JCR UUID only if node is referenceable
- try {
- Property mixinsProp = getProperty("jcr:mixinTypes");
- if (mixinsProp != null) {
- for (Value value : mixinsProp.getValues()) {
- if ("mix:referenceable".equals(value.getString())) return getProperty("jcr:uuid").getString();
- }
- }
- } catch (PathNotFoundException error) {
- throw new UnsupportedRepositoryOperationException(error);
- }
- throw new UnsupportedRepositoryOperationException();
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws UnsupportedRepositoryOperationException always
- * @see javax.jcr.Node#getVersionHistory()
- */
- public final VersionHistory getVersionHistory() throws UnsupportedRepositoryOperationException {
- throw new UnsupportedRepositoryOperationException();
- }
-
- /**
- * {@inheritDoc}
- *
* @throws IllegalArgumentException if <code>relativePath</code> is empty or <code>null</code>.
* @see javax.jcr.Node#hasNode(java.lang.String)
*/
@@ -550,221 +421,123 @@
/**
* {@inheritDoc}
*
- * @see javax.jcr.Node#hasProperties()
- */
- public final boolean hasProperties() {
- assert properties != null;
- return !properties.isEmpty();
- }
-
- /**
- * {@inheritDoc}
- *
* @throws IllegalArgumentException if <code>relativePath</code> is empty or <code>null</code>.
- * @see javax.jcr.Node#hasProperty(java.lang.String)
+ * @see javax.jcr.Node#getNode(java.lang.String)
*/
- public final boolean hasProperty( String relativePath ) throws RepositoryException {
+ public final Node getNode( String relativePath ) throws RepositoryException {
CheckArg.isNotEmpty(relativePath, "relativePath");
- if (relativePath.indexOf('/') >= 0) {
- return (getProperty(relativePath) != null);
+ String path = getPath(getPath(), relativePath);
+ Item item = getSession().getItem(path);
+ if (item instanceof Node) {
+ return (Node)item;
}
- assert properties != null;
- for (Property property : properties) {
- if (relativePath.equals(property.getName())) {
- return true;
- }
- }
- return false;
+ throw new PathNotFoundException();
}
/**
* {@inheritDoc}
*
- * @return <code>false</code>
- * @see javax.jcr.Node#holdsLock()
+ * @see javax.jcr.Node#getNodes()
*/
- public final boolean holdsLock() {
- return false;
+ public final NodeIterator getNodes() {
+ if (children == null) {
+ return new JcrEmptyNodeIterator();
+ }
+ return new JcrChildNodeIterator(this, this.session.getExecutionContext().getNamespaceRegistry(), children);
}
/**
* {@inheritDoc}
*
- * @return <code>false</code>
- * @see javax.jcr.Node#isCheckedOut()
+ * @throws UnsupportedOperationException always
+ * @see javax.jcr.Node#getNodes(java.lang.String)
*/
- public final boolean isCheckedOut() {
- return false;
- }
+ public NodeIterator getNodes( String namePattern ) throws RepositoryException {
+ CheckArg.isNotNull(namePattern, "namePattern");
+ namePattern = namePattern.trim();
+ if (namePattern.length() == 0) return new JcrEmptyNodeIterator();
+ if ("*".equals(namePattern)) return getNodes();
+ List<Object> patterns = createPatternsFor(namePattern);
- /**
- * {@inheritDoc}
- *
- * @return <code>false</code>
- * @see javax.jcr.Node#isLocked()
- */
- public final boolean isLocked() {
- return false;
- }
-
- /**
- * {@inheritDoc}
- *
- * @return <code>true</code>
- * @see javax.jcr.Item#isNode()
- */
- public final boolean isNode() {
- return true;
- }
-
- /**
- * {@inheritDoc}
- *
- * @return <code>false</code>
- * @see javax.jcr.Node#isNodeType(java.lang.String)
- */
- public boolean isNodeType( String nodeTypeName ) throws RepositoryException {
- NodeType nodeType = getPrimaryNodeType();
-
- if (nodeType.isNodeType(nodeTypeName)) {
- return true;
- }
-
- NodeType[] mixinNodeTypes = getMixinNodeTypes();
- for (int i = 0; i < mixinNodeTypes.length; i++) {
- if (mixinNodeTypes[i].isNodeType(nodeTypeName)) {
- return true;
+ // Implementing exact-matching only for now to prototype types as properties
+ List<Path.Segment> matchingChildren = new LinkedList<Path.Segment>();
+ NamespaceRegistry registry = session.executionContext.getNamespaceRegistry();
+ boolean foundMatch = false;
+ for (Path.Segment child : children) {
+ String childName = child.getName().getString(registry);
+ for (Object patternOrMatch : patterns) {
+ if (patternOrMatch instanceof Pattern) {
+ Pattern pattern = (Pattern)patternOrMatch;
+ if (pattern.matcher(childName).matches()) foundMatch = true;
+ } else {
+ String match = (String)patternOrMatch;
+ if (childName.equals(match)) foundMatch = true;
+ }
+ if (foundMatch) {
+ foundMatch = false;
+ matchingChildren.add(child);
+ break;
+ }
}
}
-
- return false;
+ return new JcrChildNodeIterator(this, this.session.executionContext.getNamespaceRegistry(), matchingChildren);
}
/**
* {@inheritDoc}
*
- * @throws IllegalArgumentException if <code>otherItem</code> is <code>null</code>.
- * @see javax.jcr.Item#isSame(javax.jcr.Item)
+ * @throws IllegalArgumentException if <code>visitor</code> is <code>null</code>.
+ * @see javax.jcr.Item#accept(javax.jcr.ItemVisitor)
*/
- @Override
- public final boolean isSame( Item otherItem ) throws RepositoryException {
- CheckArg.isNotNull(otherItem, "otherItem");
- if (super.isSame(otherItem) && otherItem instanceof Node) {
- if (otherItem instanceof AbstractJcrNode) {
- return getInternalUuid().equals(((AbstractJcrNode)otherItem).getInternalUuid());
- }
- // If not our implementation, let the other item figure out whether we are the same.
- return otherItem.isSame(this);
- }
- return false;
+ public final void accept( ItemVisitor visitor ) throws RepositoryException {
+ CheckArg.isNotNull(visitor, "visitor");
+ visitor.visit(this);
}
/**
* {@inheritDoc}
*
- * @throws UnsupportedRepositoryOperationException always
- * @see javax.jcr.Node#lock(boolean, boolean)
+ * @throws UnsupportedOperationException always
+ * @see javax.jcr.Node#addMixin(java.lang.String)
*/
- public final Lock lock( boolean isDeep,
- boolean isSessionScoped ) throws UnsupportedRepositoryOperationException {
- throw new UnsupportedRepositoryOperationException();
+ public final void addMixin( String mixinName ) {
+ throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always
- * @see javax.jcr.Node#merge(java.lang.String, boolean)
+ * @see javax.jcr.Node#addNode(java.lang.String)
*/
- public final NodeIterator merge( String srcWorkspace,
- boolean bestEffort ) {
+ public final Node addNode( String relPath ) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*
- * @throws UnsupportedRepositoryOperationException always
- * @see javax.jcr.Node#orderBefore(java.lang.String, java.lang.String)
+ * @throws UnsupportedOperationException always
+ * @see javax.jcr.Node#addNode(java.lang.String, java.lang.String)
*/
- public final void orderBefore( String srcChildRelPath,
- String destChildRelPath ) throws UnsupportedRepositoryOperationException {
- throw new UnsupportedRepositoryOperationException();
+ public final Node addNode( String relPath,
+ String primaryNodeTypeName ) {
+ throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException always
- * @see javax.jcr.Node#removeMixin(java.lang.String)
+ * @see javax.jcr.Node#update(java.lang.String)
*/
- public final void removeMixin( String mixinName ) {
+ public final void update( String srcWorkspaceName ) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*
- * @throws UnsupportedRepositoryOperationException always
- * @see javax.jcr.Node#restore(java.lang.String, boolean)
- */
- public final void restore( String versionName,
- boolean removeExisting ) throws UnsupportedRepositoryOperationException {
- throw new UnsupportedRepositoryOperationException();
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws UnsupportedRepositoryOperationException always
- * @see javax.jcr.Node#restore(javax.jcr.version.Version, boolean)
- */
- public final void restore( Version version,
- boolean removeExisting ) throws UnsupportedRepositoryOperationException {
- throw new UnsupportedRepositoryOperationException();
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws UnsupportedRepositoryOperationException always
- * @see javax.jcr.Node#restore(javax.jcr.version.Version, java.lang.String, boolean)
- */
- public final void restore( Version version,
- String relPath,
- boolean removeExisting ) throws UnsupportedRepositoryOperationException {
- throw new UnsupportedRepositoryOperationException();
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws UnsupportedRepositoryOperationException always
- * @see javax.jcr.Node#restoreByLabel(java.lang.String, boolean)
- */
- public final void restoreByLabel( String versionLabel,
- boolean removeExisting ) throws UnsupportedRepositoryOperationException {
- throw new UnsupportedRepositoryOperationException();
- }
-
- final void setChildren( List<Segment> children ) {
- assert children != null;
- this.children = children;
- }
-
- final void setInternalUuid( UUID uuid ) {
- assert uuid != null;
- this.uuid = uuid;
- }
-
- final void setProperties( Set<Property> properties ) {
- assert properties != null;
- this.properties = properties;
- }
-
- /**
- * {@inheritDoc}
- *
* @throws UnsupportedOperationException always
* @see javax.jcr.Node#setProperty(java.lang.String, boolean)
*/
@@ -923,7 +696,68 @@
/**
* {@inheritDoc}
*
+ * @return <code>false</code>
+ * @see javax.jcr.Node#isCheckedOut()
+ */
+ public final boolean isCheckedOut() {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws UnsupportedOperationException always
+ * @see javax.jcr.Node#checkin()
+ */
+ public final Version checkin() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws UnsupportedOperationException always
+ * @see javax.jcr.Node#checkout()
+ */
+ public final void checkout() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return <code>false</code>
+ * @see javax.jcr.Node#holdsLock()
+ */
+ public final boolean holdsLock() {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return <code>false</code>
+ * @see javax.jcr.Node#isLocked()
+ */
+ public final boolean isLocked() {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
* @throws UnsupportedRepositoryOperationException always
+ * @see javax.jcr.Node#lock(boolean, boolean)
+ */
+ public final Lock lock( boolean isDeep,
+ boolean isSessionScoped ) throws UnsupportedRepositoryOperationException {
+ throw new UnsupportedRepositoryOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws UnsupportedRepositoryOperationException always
* @see javax.jcr.Node#unlock()
*/
public final void unlock() throws UnsupportedRepositoryOperationException {
@@ -933,10 +767,184 @@
/**
* {@inheritDoc}
*
+ * @throws UnsupportedRepositoryOperationException always
+ * @see javax.jcr.Node#getLock()
+ */
+ public final Lock getLock() throws UnsupportedRepositoryOperationException {
+ throw new UnsupportedRepositoryOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
* @throws UnsupportedOperationException always
- * @see javax.jcr.Node#update(java.lang.String)
+ * @see javax.jcr.Node#merge(java.lang.String, boolean)
*/
- public final void update( String srcWorkspaceName ) {
+ public final NodeIterator merge( String srcWorkspace,
+ boolean bestEffort ) {
throw new UnsupportedOperationException();
}
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws UnsupportedOperationException always
+ * @see javax.jcr.Node#cancelMerge(javax.jcr.version.Version)
+ */
+ public final void cancelMerge( Version version ) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws UnsupportedOperationException always
+ * @see javax.jcr.Node#doneMerge(javax.jcr.version.Version)
+ */
+ public final void doneMerge( Version version ) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws UnsupportedOperationException always
+ * @see javax.jcr.Node#getCorrespondingNodePath(java.lang.String)
+ */
+ public final String getCorrespondingNodePath( String workspaceName ) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws UnsupportedRepositoryOperationException always
+ * @see javax.jcr.Node#getVersionHistory()
+ */
+ public final VersionHistory getVersionHistory() throws UnsupportedRepositoryOperationException {
+ throw new UnsupportedRepositoryOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws UnsupportedRepositoryOperationException always
+ * @see javax.jcr.Node#getBaseVersion()
+ */
+ public final Version getBaseVersion() throws UnsupportedRepositoryOperationException {
+ throw new UnsupportedRepositoryOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws UnsupportedRepositoryOperationException always
+ * @see javax.jcr.Node#restore(java.lang.String, boolean)
+ */
+ public final void restore( String versionName,
+ boolean removeExisting ) throws UnsupportedRepositoryOperationException {
+ throw new UnsupportedRepositoryOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws UnsupportedRepositoryOperationException always
+ * @see javax.jcr.Node#restore(javax.jcr.version.Version, boolean)
+ */
+ public final void restore( Version version,
+ boolean removeExisting ) throws UnsupportedRepositoryOperationException {
+ throw new UnsupportedRepositoryOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws UnsupportedRepositoryOperationException always
+ * @see javax.jcr.Node#restore(javax.jcr.version.Version, java.lang.String, boolean)
+ */
+ public final void restore( Version version,
+ String relPath,
+ boolean removeExisting ) throws UnsupportedRepositoryOperationException {
+ throw new UnsupportedRepositoryOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws UnsupportedRepositoryOperationException always
+ * @see javax.jcr.Node#restoreByLabel(java.lang.String, boolean)
+ */
+ public final void restoreByLabel( String versionLabel,
+ boolean removeExisting ) throws UnsupportedRepositoryOperationException {
+ throw new UnsupportedRepositoryOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws UnsupportedRepositoryOperationException always
+ * @see javax.jcr.Node#orderBefore(java.lang.String, java.lang.String)
+ */
+ public final void orderBefore( String srcChildRelPath,
+ String destChildRelPath ) throws UnsupportedRepositoryOperationException {
+ throw new UnsupportedRepositoryOperationException();
+ }
+
+ protected static List<Object> createPatternsFor( String namePattern ) throws RepositoryException {
+ List<Object> patterns = new LinkedList<Object>();
+ for (String stringPattern : namePattern.split("[|]")) {
+ stringPattern = stringPattern.trim();
+ int length = stringPattern.length();
+ if (length == 0) continue;
+ if (stringPattern.indexOf("*") == -1) {
+ // Doesn't use wildcard, so use String not Pattern
+ patterns.add(stringPattern);
+ } else {
+ // We need to escape the regular expression characters ...
+ StringBuilder sb = new StringBuilder(length);
+ for (int i = 0; i != length; i++) {
+ char c = stringPattern.charAt(i);
+ switch (c) {
+ // Per the spec, the the following characters are not allowed in patterns:
+ case '/':
+ case '[':
+ case ']':
+ case '\'':
+ case '"':
+ case '|':
+ case '\t':
+ case '\n':
+ case '\r':
+ String msg = JcrI18n.invalidNamePattern.text(c, namePattern);
+ throw new RepositoryException(msg);
+ // The following characters must be escaped when used in regular expressions ...
+ case '?':
+ case '(':
+ case ')':
+ case '$':
+ case '^':
+ case '.':
+ case '{':
+ case '}':
+ case '\\':
+ sb.append("\\");
+ sb.append(c);
+ break;
+ case '*':
+ // replace with the regular expression wildcard
+ sb.append(".*");
+ break;
+ default:
+ sb.append(c);
+ break;
+ }
+ }
+ String escapedString = sb.toString();
+ Pattern pattern = Pattern.compile(escapedString);
+ patterns.add(pattern);
+ }
+ }
+ return patterns;
+ }
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrPropertyIterator.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrPropertyIterator.java 2009-03-05 14:55:09 UTC (rev 757)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrPropertyIterator.java 2009-03-05 18:02:40 UTC (rev 758)
@@ -23,8 +23,8 @@
*/
package org.jboss.dna.jcr;
+import java.util.Collection;
import java.util.Iterator;
-import java.util.Set;
import javax.jcr.Property;
import javax.jcr.PropertyIterator;
import net.jcip.annotations.Immutable;
@@ -40,7 +40,7 @@
private int ndx;
private int size;
- JcrPropertyIterator( Set<Property> properties ) {
+ JcrPropertyIterator( Collection<Property> properties ) {
assert properties != null;
iterator = properties.iterator();
size = properties.size();
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java 2009-03-05 14:55:09 UTC (rev 757)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java 2009-03-05 18:02:40 UTC (rev 758)
@@ -121,7 +121,7 @@
}
// Initialize required JCR descriptors.
modifiableDescriptors.put(Repository.LEVEL_1_SUPPORTED, "true");
- modifiableDescriptors.put(Repository.LEVEL_2_SUPPORTED, "false");
+ modifiableDescriptors.put(Repository.LEVEL_2_SUPPORTED, "true");
modifiableDescriptors.put(Repository.OPTION_LOCKING_SUPPORTED, "false");
modifiableDescriptors.put(Repository.OPTION_OBSERVATION_SUPPORTED, "false");
modifiableDescriptors.put(Repository.OPTION_QUERY_SQL_SUPPORTED, "false");
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java 2009-03-05 14:55:09 UTC (rev 757)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java 2009-03-05 18:02:40 UTC (rev 758)
@@ -30,7 +30,6 @@
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@@ -404,8 +403,8 @@
// If not create a new one & populate it
JcrNode node;
Path parentPath = path.getParent();
- if (parentPath.isRoot()) node = new JcrNode(this, ((JcrRootNode)getRootNode()).getInternalUuid(), path.getLastSegment());
- else node = new JcrNode(this, ((JcrNode)getNode(parentPath)).getInternalUuid(), path.getLastSegment());
+ if (parentPath.isRoot()) node = new JcrNode(this, ((JcrRootNode)getRootNode()).internalUuid(), path.getLastSegment());
+ else node = new JcrNode(this, ((JcrNode)getNode(parentPath)).internalUuid(), path.getLastSegment());
populateNode(node, graphNode);
return node;
}
@@ -747,13 +746,13 @@
}
// Now create the JCR property object wrapper around the "jcr:uuid" property ...
- Set<Property> properties = new HashSet<Property>();
+ Map<Name, Property> properties = new HashMap<Name, Property>();
if (uuid == null) uuid = UUID.randomUUID();
if (referenceable) {
if (uuidProperty == null) uuidProperty = executionContext.getPropertyFactory().create(JcrLexicon.UUID, uuid);
PropertyDefinition propertyDefinition = propertyDefinitionsByPropertyName.get(JcrLexicon.UUID);
- properties.add(new JcrSingleValueProperty(node, executionContext, propertyDefinition, PropertyType.STRING,
- uuidProperty));
+ properties.put(JcrLexicon.UUID, new JcrSingleValueProperty(node, executionContext, propertyDefinition,
+ PropertyType.STRING, uuidProperty));
}
// Now create the JCR property object wrappers around the other properties ...
@@ -814,16 +813,16 @@
}
// Figure out the property type ...
- int propertyType = propertyDefinition.getRequiredType();
- if (propertyType == PropertyType.UNDEFINED) {
- propertyType = jcrPropertyTypeFor(dnaProp);
+ int type = propertyDefinition.getRequiredType();
+ if (type == PropertyType.UNDEFINED) {
+ type = jcrPropertyTypeFor(dnaProp);
}
// Create the appropriate JCR property wrapper ...
if (isMultiple) {
- properties.add(new JcrMultiValueProperty(node, executionContext, propertyDefinition, propertyType, dnaProp));
+ properties.put(name, new JcrMultiValueProperty(node, executionContext, propertyDefinition, type, dnaProp));
} else {
- properties.add(new JcrSingleValueProperty(node, executionContext, propertyDefinition, propertyType, dnaProp));
+ properties.put(name, new JcrSingleValueProperty(node, executionContext, propertyDefinition, type, dnaProp));
}
}
@@ -844,11 +843,9 @@
/**
* {@inheritDoc}
*
- * @throws UnsupportedOperationException always
* @see javax.jcr.Session#refresh(boolean)
*/
public void refresh( boolean keepChanges ) {
- throw new UnsupportedOperationException();
}
/**
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java 2009-03-05 14:55:09 UTC (rev 757)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrNodeTest.java 2009-03-05 18:02:40 UTC (rev 758)
@@ -30,9 +30,9 @@
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Calendar;
-import java.util.HashSet;
+import java.util.HashMap;
import java.util.List;
-import java.util.Set;
+import java.util.Map;
import java.util.UUID;
import javax.jcr.Item;
import javax.jcr.ItemNotFoundException;
@@ -48,6 +48,7 @@
import javax.jcr.Workspace;
import javax.jcr.version.Version;
import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.property.Name;
import org.jboss.dna.graph.property.Path.Segment;
import org.junit.Before;
import org.junit.Test;
@@ -117,19 +118,24 @@
@Mock
private Repository repository;
private List<Segment> children;
- private Set<Property> properties;
+ private Map<Name, Property> properties;
+ private ExecutionContext context;
@Before
public void before() throws Exception {
MockitoAnnotations.initMocks(this);
- ExecutionContext context = new ExecutionContext();
+ context = new ExecutionContext();
stub(session.getExecutionContext()).toReturn(context);
children = new ArrayList<Segment>();
- properties = new HashSet<Property>();
+ properties = new HashMap<Name, Property>();
node = new MockAbstractJcrNode(session, "node", null);
node.setProperties(properties);
}
+ protected Name name( String name ) {
+ return context.getValueFactories().getNameFactory().create(name);
+ }
+
@Test
public void shouldAllowVisitation() throws Exception {
ItemVisitor visitor = Mockito.mock(ItemVisitor.class);
@@ -161,14 +167,14 @@
public void shouldProvideInternalUuid() throws Exception {
UUID uuid = UUID.randomUUID();
node.setInternalUuid(uuid);
- assertThat(node.getInternalUuid(), is(uuid));
+ assertThat(node.internalUuid(), is(uuid));
}
@Test
public void shouldProvideNamedProperty() throws Exception {
Property property = Mockito.mock(Property.class);
stub(property.getName()).toReturn("test");
- properties.add(property);
+ properties.put(name(property.getName()), property);
assertThat(node.getProperty("test"), is(property));
}
@@ -262,7 +268,7 @@
Property property = Mockito.mock(Property.class);
stub(property.getName()).toReturn("jcr:primaryItemName");
stub(property.getString()).toReturn("primaryItem");
- properties.add(property);
+ properties.put(name(property.getName()), property);
Item primaryItem = Mockito.mock(Item.class);
stub(session.getItem("/node/primaryItem")).toReturn(primaryItem);
assertThat(node.getPrimaryItem(), is(primaryItem));
@@ -277,29 +283,29 @@
public void shouldProvideProperty() throws Exception {
Property prop1 = Mockito.mock(Property.class);
stub(prop1.getName()).toReturn("prop1");
- properties.add(prop1);
+ properties.put(name(prop1.getName()), prop1);
assertThat(node.getProperty("prop1"), is(prop1));
MockAbstractJcrNode child = createChild(session, "child", 1, children, node);
- Set<Property> properties = new HashSet<Property>();
+ Map<Name, Property> properties = new HashMap<Name, Property>();
child.setProperties(properties);
Property prop2 = Mockito.mock(Property.class);
stub(prop2.getName()).toReturn("prop2");
stub(session.getItem("/node/child/prop2")).toReturn(prop2);
- properties.add(prop2);
+ properties.put(name(prop2.getName()), prop2);
MockAbstractJcrNode prop3Node = createChild(session, "prop3", 1, children, child);
node.setChildren(children);
assertThat(node.getProperty("child/prop2"), is(prop2));
// Ensure we return a property even when a child exists with the same name
Property prop3 = Mockito.mock(Property.class);
stub(prop3.getName()).toReturn("prop3");
- properties.add(prop3);
+ properties.put(name(prop3.getName()), prop3);
stub(session.getItem("/node/child/prop3")).toReturn(prop3Node);
assertThat(node.getProperty("child/prop3"), is(prop3));
}
@Test( expected = IllegalArgumentException.class )
public void shouldNotAllowGetPropertyWithNullPath() throws Exception {
- node.getProperty(null);
+ node.getProperty((String)null);
}
@Test( expected = IllegalArgumentException.class )
@@ -315,7 +321,7 @@
@Test( expected = PathNotFoundException.class )
public void shouldNotProvideDescendentPropertyIfNotAvailable() throws Exception {
MockAbstractJcrNode child = createChild(session, "child", 1, children, node);
- Set<Property> properties = new HashSet<Property>();
+ Map<Name, Property> properties = new HashMap<Name, Property>();
child.setProperties(properties);
MockAbstractJcrNode propNode = createChild(session, "prop", 1, children, child);
node.setChildren(children);
@@ -343,11 +349,11 @@
Value value = Mockito.mock(Value.class);
stub(value.getString()).toReturn("mix:referenceable");
stub(mixinProp.getValues()).toReturn(new Value[] {value});
- properties.add(mixinProp);
+ properties.put(name(mixinProp.getName()), mixinProp);
Property uuidProp = Mockito.mock(Property.class);
stub(uuidProp.getName()).toReturn("jcr:uuid");
stub(uuidProp.getString()).toReturn(uuid);
- properties.add(uuidProp);
+ properties.put(name(uuidProp.getName()), uuidProp);
assertThat(node.getUUID(), is(uuid));
}
@@ -358,11 +364,11 @@
stub(mixinProp.getName()).toReturn("jcr:mixinTypes");
Value value = Mockito.mock(Value.class);
stub(mixinProp.getValues()).toReturn(new Value[] {value});
- properties.add(mixinProp);
+ properties.put(name(mixinProp.getName()), mixinProp);
Property uuidProp = Mockito.mock(Property.class);
stub(uuidProp.getName()).toReturn("jcr:uuid");
stub(uuidProp.getString()).toReturn(uuid);
- properties.add(uuidProp);
+ properties.put(name(uuidProp.getName()), uuidProp);
node.getUUID();
}
@@ -372,7 +378,7 @@
Property uuidProp = Mockito.mock(Property.class);
stub(uuidProp.getName()).toReturn("jcr:uuid");
stub(uuidProp.getString()).toReturn(uuid);
- properties.add(uuidProp);
+ properties.put(name(uuidProp.getName()), uuidProp);
node.getUUID();
}
@@ -386,7 +392,7 @@
assertThat(node.hasNode("{}child"), is(false));
Property prop = Mockito.mock(Property.class);
stub(prop.getName()).toReturn("prop");
- properties.add(prop);
+ properties.put(name(prop.getName()), prop);
assertThat(node.hasNode("prop"), is(false));
Node child = createChild(session, "child", 1, children, node);
Node child2 = createChild(session, "child2", 1, children, child);
@@ -417,7 +423,7 @@
@Test
public void shouldProvideHasProperties() throws Exception {
assertThat(node.hasProperties(), is(false));
- properties.add(Mockito.mock(Property.class));
+ properties.put(name("something"), Mockito.mock(Property.class));
assertThat(node.hasProperties(), is(true));
}
@@ -429,13 +435,13 @@
assertThat(node.hasProperty("child"), is(false));
Property prop = Mockito.mock(Property.class);
stub(prop.getName()).toReturn("prop");
- properties.add(prop);
+ properties.put(name(prop.getName()), prop);
assertThat(node.hasProperty("prop"), is(true));
- Set<Property> properties = new HashSet<Property>();
+ Map<Name, Property> properties = new HashMap<Name, Property>();
child.setProperties(properties);
Property prop2 = Mockito.mock(Property.class);
stub(prop2.getName()).toReturn("prop2");
- properties.add(prop2);
+ properties.put(name(prop2.getName()), prop2);
stub(session.getItem("/node/child/prop2")).toReturn(prop2);
assertThat(node.hasProperty("child/prop2"), is(true));
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrNodeTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrNodeTest.java 2009-03-05 14:55:09 UTC (rev 757)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrNodeTest.java 2009-03-05 18:02:40 UTC (rev 758)
@@ -28,7 +28,7 @@
import static org.mockito.Matchers.anyObject;
import static org.mockito.Mockito.stub;
import java.util.ArrayList;
-import java.util.HashSet;
+import java.util.HashMap;
import java.util.UUID;
import javax.jcr.ItemNotFoundException;
import javax.jcr.Node;
@@ -67,7 +67,7 @@
ExecutionContext context = Mockito.mock(ExecutionContext.class);
stub(session.getExecutionContext()).toReturn(context);
stub(session.getNode(uuid)).toReturn(root);
- node.setProperties(new HashSet<Property>());
+ node.setProperties(new HashMap<Name, Property>());
node.setChildren(new ArrayList<Segment>());
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrPropertyIteratorTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrPropertyIteratorTest.java 2009-03-05 14:55:09 UTC (rev 757)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrPropertyIteratorTest.java 2009-03-05 18:02:40 UTC (rev 758)
@@ -26,10 +26,12 @@
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.junit.Assert.assertThat;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.HashMap;
+import java.util.Map;
import javax.jcr.Property;
import javax.jcr.PropertyIterator;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.property.Name;
import org.jboss.dna.jcr.AbstractJcrNodeTest.MockAbstractJcrNode;
import org.junit.Before;
import org.junit.Test;
@@ -45,22 +47,28 @@
private AbstractJcrNode node;
@Mock
private JcrSession session;
- private Set<Property> properties;
+ private Map<Name, Property> properties;
+ private ExecutionContext context;
@Before
public void before() throws Exception {
MockitoAnnotations.initMocks(this);
- properties = new HashSet<Property>();
+ context = new ExecutionContext();
+ properties = new HashMap<Name, Property>();
node = new MockAbstractJcrNode(session, "node", null);
node.setProperties(properties);
}
+ protected Name name( String name ) {
+ return context.getValueFactories().getNameFactory().create(name);
+ }
+
@Test
public void shouldProvidePropertyIterator() throws Exception {
- properties.add(Mockito.mock(Property.class));
- properties.add(Mockito.mock(Property.class));
- properties.add(Mockito.mock(Property.class));
- properties.add(Mockito.mock(Property.class));
+ properties.put(name("prop1"), Mockito.mock(Property.class));
+ properties.put(name("prop2"), Mockito.mock(Property.class));
+ properties.put(name("prop3"), Mockito.mock(Property.class));
+ properties.put(name("prop4"), Mockito.mock(Property.class));
PropertyIterator iter = node.getProperties();
assertThat(iter, notNullValue());
assertThat(iter.getSize(), is(4L));
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java 2009-03-05 14:55:09 UTC (rev 757)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java 2009-03-05 18:02:40 UTC (rev 758)
@@ -253,7 +253,7 @@
private void testDescriptorValues( Repository repository ) {
assertThat(repository.getDescriptor(Repository.LEVEL_1_SUPPORTED), is("true"));
- assertThat(repository.getDescriptor(Repository.LEVEL_2_SUPPORTED), is("false"));
+ assertThat(repository.getDescriptor(Repository.LEVEL_2_SUPPORTED), is("true"));
assertThat(repository.getDescriptor(Repository.OPTION_LOCKING_SUPPORTED), is("false"));
assertThat(repository.getDescriptor(Repository.OPTION_OBSERVATION_SUPPORTED), is("false"));
assertThat(repository.getDescriptor(Repository.OPTION_QUERY_SQL_SUPPORTED), is("false"));
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRootNodeTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRootNodeTest.java 2009-03-05 14:55:09 UTC (rev 757)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRootNodeTest.java 2009-03-05 18:02:40 UTC (rev 758)
@@ -26,10 +26,11 @@
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.junit.Assert.assertThat;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.HashMap;
+import java.util.Map;
import javax.jcr.ItemNotFoundException;
import javax.jcr.Property;
+import org.jboss.dna.graph.property.Name;
import org.junit.Before;
import org.junit.Test;
import org.mockito.MockitoAnnotations;
@@ -43,12 +44,12 @@
private JcrRootNode root;
@Mock
private JcrSession session;
- private Set<Property> properties;
+ private Map<Name, Property> properties;
@Before
public void before() throws Exception {
MockitoAnnotations.initMocks(this);
- properties = new HashSet<Property>();
+ properties = new HashMap<Name, Property>();
root = new JcrRootNode(session);
root.setProperties(properties);
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java 2009-03-05 14:55:09 UTC (rev 757)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java 2009-03-05 18:02:40 UTC (rev 758)
@@ -285,7 +285,7 @@
assertThat(nodesByUuid.isEmpty(), is(true));
Node root = session.getRootNode();
assertThat(root, notNullValue());
- UUID uuid = ((JcrRootNode)root).getInternalUuid();
+ UUID uuid = ((JcrRootNode)root).internalUuid();
assertThat(uuid, notNullValue());
assertThat(nodesByUuid.get(uuid), is(root));
}
Deleted: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckLevelOneTestSuite.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckLevelOneTestSuite.java 2009-03-05 14:55:09 UTC (rev 757)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckLevelOneTestSuite.java 2009-03-05 18:02:40 UTC (rev 758)
@@ -1,95 +0,0 @@
-/*
- * JBoss DNA (http://www.jboss.org/dna)
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * Unless otherwise indicated, all code in JBoss DNA is licensed
- * to you under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * JBoss DNA is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.jcr;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-/**
- * Test suite that includes the Level 1 JCR TCK API tests from the Jackrabbit project.
- *
- * @see JcrTckLevelTwoTestSuite
- * @see JcrTckOptionalTestSuite
- * @see JcrTckTest
- */
-public class JcrTckLevelOneTestSuite extends TestCase {
-
- /**
- * 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("JCR 1.0 Level 1 API tests");
-
- // We currently don't pass the tests in those suites that are commented out
- // See https://jira.jboss.org/jira/browse/DNA-285
-
- suite.addTestSuite(org.apache.jackrabbit.test.api.RootNodeTest.class);
- suite.addTestSuite(org.apache.jackrabbit.test.api.NodeReadMethodsTest.class);
- suite.addTestSuite(org.apache.jackrabbit.test.api.PropertyTypeTest.class);
- suite.addTestSuite(org.apache.jackrabbit.test.api.NodeDiscoveringNodeTypesTest.class);
- suite.addTestSuite(org.apache.jackrabbit.test.api.BinaryPropertyTest.class);
- suite.addTestSuite(org.apache.jackrabbit.test.api.BooleanPropertyTest.class);
- suite.addTestSuite(org.apache.jackrabbit.test.api.DatePropertyTest.class);
- suite.addTestSuite(org.apache.jackrabbit.test.api.DoublePropertyTest.class);
- suite.addTestSuite(org.apache.jackrabbit.test.api.LongPropertyTest.class);
- suite.addTestSuite(org.apache.jackrabbit.test.api.NamePropertyTest.class);
- suite.addTestSuite(org.apache.jackrabbit.test.api.PathPropertyTest.class);
- suite.addTestSuite(org.apache.jackrabbit.test.api.ReferencePropertyTest.class);
- suite.addTestSuite(org.apache.jackrabbit.test.api.StringPropertyTest.class);
- suite.addTestSuite(org.apache.jackrabbit.test.api.UndefinedPropertyTest.class);
- suite.addTestSuite(org.apache.jackrabbit.test.api.NamespaceRegistryReadMethodsTest.class);
- suite.addTestSuite(org.apache.jackrabbit.test.api.NamespaceRemappingTest.class);
- suite.addTestSuite(org.apache.jackrabbit.test.api.NodeIteratorTest.class);
- suite.addTestSuite(org.apache.jackrabbit.test.api.PropertyReadMethodsTest.class);
- suite.addTestSuite(org.apache.jackrabbit.test.api.RepositoryDescriptorTest.class);
- suite.addTestSuite(org.apache.jackrabbit.test.api.SessionReadMethodsTest.class);
- // suite.addTestSuite(org.apache.jackrabbit.test.api.WorkspaceReadMethodsTest.class);
- suite.addTestSuite(org.apache.jackrabbit.test.api.ReferenceableRootNodesTest.class);
- // suite.addTestSuite(org.apache.jackrabbit.test.api.ExportSysViewTest.class);
- // suite.addTestSuite(org.apache.jackrabbit.test.api.ExportDocViewTest.class);
- suite.addTestSuite(org.apache.jackrabbit.test.api.RepositoryLoginTest.class);
-
- // These might not all be level one tests
- // suite.addTestSuite(org.apache.jackrabbit.test.api.query.XPathPosIndexTest.class);
- // suite.addTestSuite(org.apache.jackrabbit.test.api.query.XPathDocOrderTest.class);
- // suite.addTestSuite(org.apache.jackrabbit.test.api.query.XPathOrderByTest.class);
- // suite.addTestSuite(org.apache.jackrabbit.test.api.query.XPathJcrPathTest.class);
- // suite.addTestSuite(org.apache.jackrabbit.test.api.query.DerefQueryLevel1Test.class);
- // suite.addTestSuite(org.apache.jackrabbit.test.api.query.GetLanguageTest.class);
- // suite.addTestSuite(org.apache.jackrabbit.test.api.query.GetPersistentQueryPathLevel1Test.class);
- // suite.addTestSuite(org.apache.jackrabbit.test.api.query.GetStatementTest.class);
- // suite.addTestSuite(org.apache.jackrabbit.test.api.query.GetSupportedQueryLanguagesTest.class);
- // suite.addTestSuite(org.apache.jackrabbit.test.api.query.GetPropertyNamesTest.class);
- // suite.addTestSuite(org.apache.jackrabbit.test.api.query.PredicatesTest.class);
- // suite.addTestSuite(org.apache.jackrabbit.test.api.query.SimpleSelectionTest.class);
-
- // The tests in this suite are level one
- // suite.addTest(org.apache.jackrabbit.test.api.nodetype.TestAll.suite());
-
- return suite;
- }
-}
Deleted: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckLevelTwoTestSuite.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckLevelTwoTestSuite.java 2009-03-05 14:55:09 UTC (rev 757)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckLevelTwoTestSuite.java 2009-03-05 18:02:40 UTC (rev 758)
@@ -1,178 +0,0 @@
-/*
- * JBoss DNA (http://www.jboss.org/dna)
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * Unless otherwise indicated, all code in JBoss DNA is licensed
- * to you under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * JBoss DNA is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.jcr;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-import org.apache.jackrabbit.test.api.AddNodeTest;
-import org.apache.jackrabbit.test.api.CheckPermissionTest;
-import org.apache.jackrabbit.test.api.DocumentViewImportTest;
-import org.apache.jackrabbit.test.api.ImpersonateTest;
-import org.apache.jackrabbit.test.api.NamespaceRegistryTest;
-import org.apache.jackrabbit.test.api.NodeAddMixinTest;
-import org.apache.jackrabbit.test.api.NodeCanAddMixinTest;
-import org.apache.jackrabbit.test.api.NodeItemIsModifiedTest;
-import org.apache.jackrabbit.test.api.NodeItemIsNewTest;
-import org.apache.jackrabbit.test.api.NodeOrderableChildNodesTest;
-import org.apache.jackrabbit.test.api.NodeRemoveMixinTest;
-import org.apache.jackrabbit.test.api.NodeTest;
-import org.apache.jackrabbit.test.api.NodeUUIDTest;
-import org.apache.jackrabbit.test.api.PropertyItemIsModifiedTest;
-import org.apache.jackrabbit.test.api.PropertyItemIsNewTest;
-import org.apache.jackrabbit.test.api.PropertyTest;
-import org.apache.jackrabbit.test.api.ReferencesTest;
-import org.apache.jackrabbit.test.api.RepositoryLoginTest;
-import org.apache.jackrabbit.test.api.SerializationTest;
-import org.apache.jackrabbit.test.api.SessionTest;
-import org.apache.jackrabbit.test.api.SessionUUIDTest;
-import org.apache.jackrabbit.test.api.SetPropertyAssumeTypeTest;
-import org.apache.jackrabbit.test.api.SetPropertyBooleanTest;
-import org.apache.jackrabbit.test.api.SetPropertyCalendarTest;
-import org.apache.jackrabbit.test.api.SetPropertyConstraintViolationExceptionTest;
-import org.apache.jackrabbit.test.api.SetPropertyDoubleTest;
-import org.apache.jackrabbit.test.api.SetPropertyInputStreamTest;
-import org.apache.jackrabbit.test.api.SetPropertyLongTest;
-import org.apache.jackrabbit.test.api.SetPropertyNodeTest;
-import org.apache.jackrabbit.test.api.SetPropertyStringTest;
-import org.apache.jackrabbit.test.api.SetPropertyValueTest;
-import org.apache.jackrabbit.test.api.SetValueBinaryTest;
-import org.apache.jackrabbit.test.api.SetValueBooleanTest;
-import org.apache.jackrabbit.test.api.SetValueConstraintViolationExceptionTest;
-import org.apache.jackrabbit.test.api.SetValueDateTest;
-import org.apache.jackrabbit.test.api.SetValueDoubleTest;
-import org.apache.jackrabbit.test.api.SetValueLongTest;
-import org.apache.jackrabbit.test.api.SetValueReferenceTest;
-import org.apache.jackrabbit.test.api.SetValueStringTest;
-import org.apache.jackrabbit.test.api.SetValueValueFormatExceptionTest;
-import org.apache.jackrabbit.test.api.SetValueVersionExceptionTest;
-import org.apache.jackrabbit.test.api.ValueFactoryTest;
-import org.apache.jackrabbit.test.api.WorkspaceCloneReferenceableTest;
-import org.apache.jackrabbit.test.api.WorkspaceCloneSameNameSibsTest;
-import org.apache.jackrabbit.test.api.WorkspaceCloneTest;
-import org.apache.jackrabbit.test.api.WorkspaceCloneVersionableTest;
-import org.apache.jackrabbit.test.api.WorkspaceCopyBetweenWorkspacesReferenceableTest;
-import org.apache.jackrabbit.test.api.WorkspaceCopyBetweenWorkspacesSameNameSibsTest;
-import org.apache.jackrabbit.test.api.WorkspaceCopyBetweenWorkspacesTest;
-import org.apache.jackrabbit.test.api.WorkspaceCopyBetweenWorkspacesVersionableTest;
-import org.apache.jackrabbit.test.api.WorkspaceCopyReferenceableTest;
-import org.apache.jackrabbit.test.api.WorkspaceCopySameNameSibsTest;
-import org.apache.jackrabbit.test.api.WorkspaceCopyTest;
-import org.apache.jackrabbit.test.api.WorkspaceCopyVersionableTest;
-import org.apache.jackrabbit.test.api.WorkspaceMoveReferenceableTest;
-import org.apache.jackrabbit.test.api.WorkspaceMoveSameNameSibsTest;
-import org.apache.jackrabbit.test.api.WorkspaceMoveTest;
-import org.apache.jackrabbit.test.api.WorkspaceMoveVersionableTest;
-
-/**
- * Test suite that includes the Level 2 JCR TCK API tests from the Jackrabbit project.
- *
- * @see JcrTckLevelOneTestSuite
- * @see JcrTckOptionalTestSuite
- * @see JcrTckTest
- */
-public class JcrTckLevelTwoTestSuite extends TestCase {
-
- /**
- * 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("JCR 1.0 Level 2 API tests");
-
- // We currently don't pass the tests in those suites that are commented out
- // See https://jira.jboss.org/jira/browse/DNA-285
-
- // level 2 tests
- suite.addTestSuite(AddNodeTest.class);
- suite.addTestSuite(NamespaceRegistryTest.class);
- suite.addTestSuite(ReferencesTest.class);
- suite.addTestSuite(SessionTest.class);
- suite.addTestSuite(SessionUUIDTest.class);
- suite.addTestSuite(NodeTest.class);
- suite.addTestSuite(NodeUUIDTest.class);
- suite.addTestSuite(NodeOrderableChildNodesTest.class);
- suite.addTestSuite(PropertyTest.class);
-
- suite.addTestSuite(SetValueBinaryTest.class);
- suite.addTestSuite(SetValueBooleanTest.class);
- suite.addTestSuite(SetValueDateTest.class);
- suite.addTestSuite(SetValueDoubleTest.class);
- suite.addTestSuite(SetValueLongTest.class);
- suite.addTestSuite(SetValueReferenceTest.class);
- suite.addTestSuite(SetValueStringTest.class);
- suite.addTestSuite(SetValueConstraintViolationExceptionTest.class);
- suite.addTestSuite(SetValueValueFormatExceptionTest.class);
- suite.addTestSuite(SetValueVersionExceptionTest.class);
-
- suite.addTestSuite(SetPropertyBooleanTest.class);
- suite.addTestSuite(SetPropertyCalendarTest.class);
- suite.addTestSuite(SetPropertyDoubleTest.class);
- suite.addTestSuite(SetPropertyInputStreamTest.class);
- suite.addTestSuite(SetPropertyLongTest.class);
- suite.addTestSuite(SetPropertyNodeTest.class);
- suite.addTestSuite(SetPropertyStringTest.class);
- suite.addTestSuite(SetPropertyValueTest.class);
- suite.addTestSuite(SetPropertyConstraintViolationExceptionTest.class);
- suite.addTestSuite(SetPropertyAssumeTypeTest.class);
-
- suite.addTestSuite(NodeItemIsModifiedTest.class);
- suite.addTestSuite(NodeItemIsNewTest.class);
- suite.addTestSuite(PropertyItemIsModifiedTest.class);
- suite.addTestSuite(PropertyItemIsNewTest.class);
-
- suite.addTestSuite(NodeAddMixinTest.class);
- suite.addTestSuite(NodeCanAddMixinTest.class);
- suite.addTestSuite(NodeRemoveMixinTest.class);
-
- suite.addTestSuite(WorkspaceCloneReferenceableTest.class);
- suite.addTestSuite(WorkspaceCloneSameNameSibsTest.class);
- suite.addTestSuite(WorkspaceCloneTest.class);
- suite.addTestSuite(WorkspaceCloneVersionableTest.class);
- suite.addTestSuite(WorkspaceCopyBetweenWorkspacesReferenceableTest.class);
- suite.addTestSuite(WorkspaceCopyBetweenWorkspacesSameNameSibsTest.class);
- suite.addTestSuite(WorkspaceCopyBetweenWorkspacesTest.class);
- suite.addTestSuite(WorkspaceCopyBetweenWorkspacesVersionableTest.class);
- suite.addTestSuite(WorkspaceCopyReferenceableTest.class);
- suite.addTestSuite(WorkspaceCopySameNameSibsTest.class);
- suite.addTestSuite(WorkspaceCopyTest.class);
- suite.addTestSuite(WorkspaceCopyVersionableTest.class);
- suite.addTestSuite(WorkspaceMoveReferenceableTest.class);
- suite.addTestSuite(WorkspaceMoveSameNameSibsTest.class);
- suite.addTestSuite(WorkspaceMoveTest.class);
- suite.addTestSuite(WorkspaceMoveVersionableTest.class);
-
- suite.addTestSuite(RepositoryLoginTest.class);
- suite.addTestSuite(ImpersonateTest.class);
- suite.addTestSuite(CheckPermissionTest.class);
-
- suite.addTestSuite(DocumentViewImportTest.class);
- suite.addTestSuite(SerializationTest.class);
-
- suite.addTestSuite(ValueFactoryTest.class);
-
- return suite;
- }
-}
Deleted: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckOptionalTestSuite.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckOptionalTestSuite.java 2009-03-05 14:55:09 UTC (rev 757)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckOptionalTestSuite.java 2009-03-05 18:02:40 UTC (rev 758)
@@ -1,57 +0,0 @@
-/*
- * JBoss DNA (http://www.jboss.org/dna)
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * Unless otherwise indicated, all code in JBoss DNA is licensed
- * to you under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * JBoss DNA is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.jcr;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-/**
- * Test suite that includes the Optional JCR TCK API tests from the Jackrabbit project.
- *
- * @see JcrTckLevelOneTestSuite
- * @see JcrTckLevelTwoTestSuite
- * @see JcrTckTest
- */
-public class JcrTckOptionalTestSuite extends TestCase {
-
- /**
- * 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("JCR 1.0 Optional API tests");
-
- // We currently don't pass the tests in those suites that are commented out
- // See https://jira.jboss.org/jira/browse/DNA-285
-
- suite.addTest(org.apache.jackrabbit.test.api.observation.TestAll.suite());
- suite.addTest(org.apache.jackrabbit.test.api.version.TestAll.suite());
- suite.addTest(org.apache.jackrabbit.test.api.lock.TestAll.suite());
- suite.addTest(org.apache.jackrabbit.test.api.util.TestAll.suite());
-
- return suite;
- }
-}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-03-05 14:55:09 UTC (rev 757)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-03-05 18:02:40 UTC (rev 758)
@@ -35,6 +35,7 @@
import junit.framework.TestSuite;
import org.apache.jackrabbit.test.JCRTestSuite;
import org.apache.jackrabbit.test.RepositoryStub;
+import org.apache.jackrabbit.test.api.RepositoryLoginTest;
import org.jboss.dna.graph.DnaLexicon;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.Graph;
@@ -48,14 +49,16 @@
/**
* Test suite to wrap Apache Jackrabbit JCR technology compatibility kit (TCK) unit tests.
- *
- * @see JcrTckLevelOneTestSuite
- * @see JcrTckLevelTwoTestSuite
- * @see JcrTckOptionalTestSuite
*/
public class JcrTckTest {
/**
+ *
+ */
+ public JcrTckTest() {
+ }
+
+ /**
* Wrapper so that the Jackrabbit TCK test suite gets picked up by the DNA Maven test target.
*
* @return a new instance of {@link JCRTestSuite}.
@@ -66,14 +69,164 @@
// Or uncomment the following lines to execute the different sets/suites of tests ...
TestSuite suite = new TestSuite("JCR 1.0 API tests");
- suite.addTest(JcrTckLevelOneTestSuite.suite());
- // suite.addTest(JcrTckLevelTwoTestSuite.suite());
- // suite.addTest(JcrTckOptionalTestSuite.suite());
+ suite.addTest(new LevelOneFeatureTests());
+ suite.addTest(new LevelTwoFeatureTests());
+ suite.addTest(new OptionalFeatureTests());
+
return suite;
}
/**
+ * Test suite that includes the Level 1 JCR TCK API tests from the Jackrabbit project.
+ */
+ private static class LevelOneFeatureTests extends TestSuite {
+ protected LevelOneFeatureTests() {
+ super("JCR Level 1 API Tests");
+ // We currently don't pass the tests in those suites that are commented out
+ // See https://jira.jboss.org/jira/browse/DNA-285
+
+ addTestSuite(org.apache.jackrabbit.test.api.RootNodeTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.NodeReadMethodsTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.PropertyTypeTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.NodeDiscoveringNodeTypesTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.BinaryPropertyTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.BooleanPropertyTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.DatePropertyTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.DoublePropertyTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.LongPropertyTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.NamePropertyTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.PathPropertyTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.ReferencePropertyTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.StringPropertyTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.UndefinedPropertyTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.NamespaceRegistryReadMethodsTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.NamespaceRemappingTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.NodeIteratorTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.PropertyReadMethodsTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.RepositoryDescriptorTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.SessionReadMethodsTest.class);
+ // addTestSuite(org.apache.jackrabbit.test.api.WorkspaceReadMethodsTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.ReferenceableRootNodesTest.class);
+ // addTestSuite(org.apache.jackrabbit.test.api.ExportSysViewTest.class);
+ // addTestSuite(org.apache.jackrabbit.test.api.ExportDocViewTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.RepositoryLoginTest.class);
+
+ // These might not all be level one tests
+ // addTestSuite(org.apache.jackrabbit.test.api.query.XPathPosIndexTest.class);
+ // addTestSuite(org.apache.jackrabbit.test.api.query.XPathDocOrderTest.class);
+ // addTestSuite(org.apache.jackrabbit.test.api.query.XPathOrderByTest.class);
+ // addTestSuite(org.apache.jackrabbit.test.api.query.XPathJcrPathTest.class);
+ // addTestSuite(org.apache.jackrabbit.test.api.query.DerefQueryLevel1Test.class);
+ // addTestSuite(org.apache.jackrabbit.test.api.query.GetLanguageTest.class);
+ // addTestSuite(org.apache.jackrabbit.test.api.query.GetPersistentQueryPathLevel1Test.class);
+ // addTestSuite(org.apache.jackrabbit.test.api.query.GetStatementTest.class);
+ // addTestSuite(org.apache.jackrabbit.test.api.query.GetSupportedQueryLanguagesTest.class);
+ // addTestSuite(org.apache.jackrabbit.test.api.query.GetPropertyNamesTest.class);
+ // addTestSuite(org.apache.jackrabbit.test.api.query.PredicatesTest.class);
+ // addTestSuite(org.apache.jackrabbit.test.api.query.SimpleSelectionTest.class);
+
+ // The tests in this suite are level one
+ // addTest(org.apache.jackrabbit.test.api.nodetype.TestAll.suite());
+ }
+ }
+
+ /**
+ * Test suite that includes the Level 2 JCR TCK API tests from the Jackrabbit project.
+ */
+ private static class LevelTwoFeatureTests extends TestSuite {
+ protected LevelTwoFeatureTests() {
+ super("JCR Level 2 API Tests");
+ // We currently don't pass the tests in those suites that are commented out
+ // See https://jira.jboss.org/jira/browse/DNA-285
+
+ // level 2 tests
+ // addTestSuite(AddNodeTest.class);
+ // addTestSuite(NamespaceRegistryTest.class);
+ // addTestSuite(ReferencesTest.class);
+ // addTestSuite(SessionTest.class);
+ // addTestSuite(SessionUUIDTest.class);
+ // addTestSuite(NodeTest.class);
+ // addTestSuite(NodeUUIDTest.class);
+ // addTestSuite(NodeOrderableChildNodesTest.class);
+ // addTestSuite(PropertyTest.class);
+ //
+ // addTestSuite(SetValueBinaryTest.class);
+ // addTestSuite(SetValueBooleanTest.class);
+ // addTestSuite(SetValueDateTest.class);
+ // addTestSuite(SetValueDoubleTest.class);
+ // addTestSuite(SetValueLongTest.class);
+ // addTestSuite(SetValueReferenceTest.class);
+ // addTestSuite(SetValueStringTest.class);
+ // addTestSuite(SetValueConstraintViolationExceptionTest.class);
+ // addTestSuite(SetValueValueFormatExceptionTest.class);
+ // addTestSuite(SetValueVersionExceptionTest.class);
+ //
+ // addTestSuite(SetPropertyBooleanTest.class);
+ // addTestSuite(SetPropertyCalendarTest.class);
+ // addTestSuite(SetPropertyDoubleTest.class);
+ // addTestSuite(SetPropertyInputStreamTest.class);
+ // addTestSuite(SetPropertyLongTest.class);
+ // addTestSuite(SetPropertyNodeTest.class);
+ // addTestSuite(SetPropertyStringTest.class);
+ // addTestSuite(SetPropertyValueTest.class);
+ // addTestSuite(SetPropertyConstraintViolationExceptionTest.class);
+ // addTestSuite(SetPropertyAssumeTypeTest.class);
+ //
+ // addTestSuite(NodeItemIsModifiedTest.class);
+ // addTestSuite(NodeItemIsNewTest.class);
+ // addTestSuite(PropertyItemIsModifiedTest.class);
+ // addTestSuite(PropertyItemIsNewTest.class);
+ //
+ // addTestSuite(NodeAddMixinTest.class);
+ // addTestSuite(NodeCanAddMixinTest.class);
+ // addTestSuite(NodeRemoveMixinTest.class);
+ //
+ // addTestSuite(WorkspaceCloneReferenceableTest.class);
+ // addTestSuite(WorkspaceCloneSameNameSibsTest.class);
+ // addTestSuite(WorkspaceCloneTest.class);
+ // addTestSuite(WorkspaceCloneVersionableTest.class);
+ // addTestSuite(WorkspaceCopyBetweenWorkspacesReferenceableTest.class);
+ // addTestSuite(WorkspaceCopyBetweenWorkspacesSameNameSibsTest.class);
+ // addTestSuite(WorkspaceCopyBetweenWorkspacesTest.class);
+ // addTestSuite(WorkspaceCopyBetweenWorkspacesVersionableTest.class);
+ // addTestSuite(WorkspaceCopyReferenceableTest.class);
+ // addTestSuite(WorkspaceCopySameNameSibsTest.class);
+ // addTestSuite(WorkspaceCopyTest.class);
+ // addTestSuite(WorkspaceCopyVersionableTest.class);
+ // addTestSuite(WorkspaceMoveReferenceableTest.class);
+ // addTestSuite(WorkspaceMoveSameNameSibsTest.class);
+ // addTestSuite(WorkspaceMoveTest.class);
+ // addTestSuite(WorkspaceMoveVersionableTest.class);
+ //
+ addTestSuite(RepositoryLoginTest.class);
+ // addTestSuite(ImpersonateTest.class);
+ // addTestSuite(CheckPermissionTest.class);
+ //
+ // addTestSuite(DocumentViewImportTest.class);
+ // addTestSuite(SerializationTest.class);
+ //
+ // addTestSuite(ValueFactoryTest.class);
+ }
+ }
+
+ /**
+ * Test suite that includes the Optional JCR TCK API tests from the Jackrabbit project.
+ */
+ private static class OptionalFeatureTests extends TestSuite {
+ protected OptionalFeatureTests() {
+ super("JCR Optional API Tests");
+ // We currently don't pass the tests in those suites that are commented out
+ // See https://jira.jboss.org/jira/browse/DNA-285
+
+ // addTest(org.apache.jackrabbit.test.api.observation.TestAll.suite());
+ // addTest(org.apache.jackrabbit.test.api.version.TestAll.suite());
+ // addTest(org.apache.jackrabbit.test.api.lock.TestAll.suite());
+ // addTest(org.apache.jackrabbit.test.api.util.TestAll.suite());
+ }
+ }
+
+ /**
* Concrete implementation of {@link RepositoryStub} based on DNA-specific configuration.
*/
public static class InMemoryRepositoryStub extends RepositoryStub {
15 years, 1 month
DNA SVN: r757 - in trunk/dna-jcr/src/test: resources and 1 other directory.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-03-05 09:55:09 -0500 (Thu, 05 Mar 2009)
New Revision: 757
Added:
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckLevelOneTestSuite.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckLevelTwoTestSuite.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckOptionalTestSuite.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
Removed:
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JackrabbitJcrTckTest.java
Modified:
trunk/dna-jcr/src/test/resources/repositoryStubImpl.properties
Log:
DNA-194 Implement update JCR capability
Refactored the TCK unit tests to make it easy to add Level 2 and Optional unit tests from the Jackrabbit TCK unit tests.
Deleted: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JackrabbitJcrTckTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JackrabbitJcrTckTest.java 2009-03-04 22:18:45 UTC (rev 756)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JackrabbitJcrTckTest.java 2009-03-05 14:55:09 UTC (rev 757)
@@ -1,229 +0,0 @@
-/*
- * JBoss DNA (http://www.jboss.org/dna)
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- * See the AUTHORS.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
- * is licensed to you under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * JBoss DNA is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.dna.jcr;
-
-import java.io.File;
-import java.net.URI;
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.util.Collections;
-import java.util.Properties;
-import javax.jcr.Credentials;
-import javax.jcr.Repository;
-import junit.framework.Test;
-import junit.framework.TestSuite;
-import org.apache.jackrabbit.test.JCRTestSuite;
-import org.apache.jackrabbit.test.RepositoryStub;
-import org.jboss.dna.graph.DnaLexicon;
-import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.Graph;
-import org.jboss.dna.graph.GraphImporter;
-import org.jboss.dna.graph.JcrNtLexicon;
-import org.jboss.dna.graph.Location;
-import org.jboss.dna.graph.connector.RepositoryConnection;
-import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
-import org.jboss.dna.graph.connector.inmemory.InMemoryRepositorySource;
-import org.jboss.dna.graph.property.Path;
-
-/**
- * Test suite to wrap Apache Jackrabbit JCR technology compatibility kit (TCK) tests.
- */
-public class JackrabbitJcrTckTest {
-
- /**
- * Wrapper so that the Jackrabbit TCK test suite gets picked up by the DNA Maven test target.
- *
- * @return a new instance of {@link JCRTestSuite}.
- */
- public static Test suite() {
- // Uncomment this to execute all tests
- // return new JCRTestSuite();
-
- // Uncomment this to execute level one tests only
- return new JcrLevelOneTestSuite();
- }
-
- /** Test suite that includes all of the Jackrabbit TCK API tests <b>except</b> the level two tests. */
- private static class JcrLevelOneTestSuite extends TestSuite {
- public JcrLevelOneTestSuite() {
- super("JCR 1.0 Level 1 API tests");
-
- // We currently don't pass the tests in those suites that are commented out
- // See https://jira.jboss.org/jira/browse/DNA-285
-
- addTestSuite(org.apache.jackrabbit.test.api.RootNodeTest.class);
- addTestSuite(org.apache.jackrabbit.test.api.NodeReadMethodsTest.class);
- addTestSuite(org.apache.jackrabbit.test.api.PropertyTypeTest.class);
- addTestSuite(org.apache.jackrabbit.test.api.NodeDiscoveringNodeTypesTest.class);
- addTestSuite(org.apache.jackrabbit.test.api.BinaryPropertyTest.class);
- addTestSuite(org.apache.jackrabbit.test.api.BooleanPropertyTest.class);
- addTestSuite(org.apache.jackrabbit.test.api.DatePropertyTest.class);
- addTestSuite(org.apache.jackrabbit.test.api.DoublePropertyTest.class);
- addTestSuite(org.apache.jackrabbit.test.api.LongPropertyTest.class);
- addTestSuite(org.apache.jackrabbit.test.api.NamePropertyTest.class);
- addTestSuite(org.apache.jackrabbit.test.api.PathPropertyTest.class);
- addTestSuite(org.apache.jackrabbit.test.api.ReferencePropertyTest.class);
- addTestSuite(org.apache.jackrabbit.test.api.StringPropertyTest.class);
- addTestSuite(org.apache.jackrabbit.test.api.UndefinedPropertyTest.class);
- addTestSuite(org.apache.jackrabbit.test.api.NamespaceRegistryReadMethodsTest.class);
- addTestSuite(org.apache.jackrabbit.test.api.NamespaceRemappingTest.class);
- addTestSuite(org.apache.jackrabbit.test.api.NodeIteratorTest.class);
- addTestSuite(org.apache.jackrabbit.test.api.PropertyReadMethodsTest.class);
- addTestSuite(org.apache.jackrabbit.test.api.RepositoryDescriptorTest.class);
- addTestSuite(org.apache.jackrabbit.test.api.SessionReadMethodsTest.class);
- // addTestSuite(org.apache.jackrabbit.test.api.WorkspaceReadMethodsTest.class);
- addTestSuite(org.apache.jackrabbit.test.api.ReferenceableRootNodesTest.class);
- // addTestSuite(org.apache.jackrabbit.test.api.ExportSysViewTest.class);
- // addTestSuite(org.apache.jackrabbit.test.api.ExportDocViewTest.class);
- addTestSuite(org.apache.jackrabbit.test.api.RepositoryLoginTest.class);
-
- // These might not all be level one tests
- // addTestSuite(org.apache.jackrabbit.test.api.query.XPathPosIndexTest.class);
- // addTestSuite(org.apache.jackrabbit.test.api.query.XPathDocOrderTest.class);
- // addTestSuite(org.apache.jackrabbit.test.api.query.XPathOrderByTest.class);
- // addTestSuite(org.apache.jackrabbit.test.api.query.XPathJcrPathTest.class);
- // addTestSuite(org.apache.jackrabbit.test.api.query.DerefQueryLevel1Test.class);
- // addTestSuite(org.apache.jackrabbit.test.api.query.GetLanguageTest.class);
- // addTestSuite(org.apache.jackrabbit.test.api.query.GetPersistentQueryPathLevel1Test.class);
- // addTestSuite(org.apache.jackrabbit.test.api.query.GetStatementTest.class);
- // addTestSuite(org.apache.jackrabbit.test.api.query.GetSupportedQueryLanguagesTest.class);
- // addTestSuite(org.apache.jackrabbit.test.api.query.GetPropertyNamesTest.class);
- // addTestSuite(org.apache.jackrabbit.test.api.query.PredicatesTest.class);
- // addTestSuite(org.apache.jackrabbit.test.api.query.SimpleSelectionTest.class);
-
- // The tests in this suite are level one
- // addTest(org.apache.jackrabbit.test.api.nodetype.TestAll.suite());
- }
-
- }
-
- /**
- * Concrete implementation of {@link RepositoryStub} based on DNA-specific configuration.
- */
- public static class InMemoryRepositoryStub extends RepositoryStub {
- private Repository repository;
- protected RepositoryConnection connection;
- protected AccessControlContext accessControlContext = AccessController.getContext();
-
- private Credentials credentials = new Credentials() {
- private static final long serialVersionUID = 1L;
-
- @SuppressWarnings( "unused" )
- public AccessControlContext getAccessControlContext() {
- return accessControlContext;
- }
- };
-
- protected ExecutionContext executionContext = new ExecutionContext() {
-
- @Override
- public ExecutionContext create( AccessControlContext accessControlContext ) {
- return executionContext;
- }
- };
-
- protected RepositoryConnectionFactory connectionFactory = new RepositoryConnectionFactory() {
- public RepositoryConnection createConnection( String sourceName ) {
- return connection;
- }
- };
-
- public InMemoryRepositoryStub( Properties env ) {
- super(env);
-
- // Create the in-memory (DNA) repository
- InMemoryRepositorySource source = new InMemoryRepositorySource();
-
- // Various calls will fail if you do not set a non-null name for the source
- source.setName("TestRepositorySource");
-
- // Wrap a connection to the in-memory (DNA) repository in a (JCR) repository
- connection = source.getConnection();
- repository = new JcrRepository(Collections.<String, String>emptyMap(), executionContext.create(accessControlContext),
- connectionFactory, source.getName());
-
- // Make sure the path to the namespaces exists ...
- Graph graph = Graph.create(source.getName(), connectionFactory, executionContext);
- graph.create("/jcr:system").and().create("/jcr:system/dna:namespaces");
-
- // Set up some sample nodes in the graph to match the expected test configuration
- try {
-
- // TODO: Should there be an easier way to define these since they will be needed for all JCR repositories?
- executionContext.getNamespaceRegistry().register(DnaLexicon.Namespace.PREFIX, DnaLexicon.Namespace.URI);
- executionContext.getNamespaceRegistry().register(JcrLexicon.Namespace.PREFIX, JcrLexicon.Namespace.URI);
- executionContext.getNamespaceRegistry().register(JcrNtLexicon.Namespace.PREFIX, JcrNtLexicon.Namespace.URI);
- executionContext.getNamespaceRegistry().register("sv", "http://www.jcp.org/jcr/sv/1.0");
-
- Path destinationPath = executionContext.getValueFactories().getPathFactory().create("/");
- GraphImporter importer = new GraphImporter(graph);
-
- URI xmlContent = new File("src/test/resources/repositoryJackrabbitTck.xml").toURI();
- Graph.Batch batch = importer.importXml(xmlContent, Location.create(destinationPath));
- batch.execute();
-
- } catch (Exception ex) {
- // The TCK tries to quash this exception. Print it out to be more obvious.
- ex.printStackTrace();
- throw new IllegalStateException("Repository initialization failed.", ex);
- }
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.apache.jackrabbit.test.RepositoryStub#getSuperuserCredentials()
- */
- @Override
- public Credentials getSuperuserCredentials() {
- // TODO: Why must we override this method? The default TCK implementation just returns a particular instance of
- // SimpleCredentials.
- return credentials;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.apache.jackrabbit.test.RepositoryStub#getReadOnlyCredentials()
- */
- @Override
- public Credentials getReadOnlyCredentials() {
- // TODO: Why must we override this method? The default TCK implementation just returns a particular instance of
- // SimpleCredentials.
- return credentials;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.apache.jackrabbit.test.RepositoryStub#getRepository()
- */
- @Override
- public Repository getRepository() {
- return repository;
- }
-
- }
-
-}
Added: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckLevelOneTestSuite.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckLevelOneTestSuite.java (rev 0)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckLevelOneTestSuite.java 2009-03-05 14:55:09 UTC (rev 757)
@@ -0,0 +1,95 @@
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * Unless otherwise indicated, all code in JBoss DNA is licensed
+ * to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.jcr;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Test suite that includes the Level 1 JCR TCK API tests from the Jackrabbit project.
+ *
+ * @see JcrTckLevelTwoTestSuite
+ * @see JcrTckOptionalTestSuite
+ * @see JcrTckTest
+ */
+public class JcrTckLevelOneTestSuite extends TestCase {
+
+ /**
+ * 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("JCR 1.0 Level 1 API tests");
+
+ // We currently don't pass the tests in those suites that are commented out
+ // See https://jira.jboss.org/jira/browse/DNA-285
+
+ suite.addTestSuite(org.apache.jackrabbit.test.api.RootNodeTest.class);
+ suite.addTestSuite(org.apache.jackrabbit.test.api.NodeReadMethodsTest.class);
+ suite.addTestSuite(org.apache.jackrabbit.test.api.PropertyTypeTest.class);
+ suite.addTestSuite(org.apache.jackrabbit.test.api.NodeDiscoveringNodeTypesTest.class);
+ suite.addTestSuite(org.apache.jackrabbit.test.api.BinaryPropertyTest.class);
+ suite.addTestSuite(org.apache.jackrabbit.test.api.BooleanPropertyTest.class);
+ suite.addTestSuite(org.apache.jackrabbit.test.api.DatePropertyTest.class);
+ suite.addTestSuite(org.apache.jackrabbit.test.api.DoublePropertyTest.class);
+ suite.addTestSuite(org.apache.jackrabbit.test.api.LongPropertyTest.class);
+ suite.addTestSuite(org.apache.jackrabbit.test.api.NamePropertyTest.class);
+ suite.addTestSuite(org.apache.jackrabbit.test.api.PathPropertyTest.class);
+ suite.addTestSuite(org.apache.jackrabbit.test.api.ReferencePropertyTest.class);
+ suite.addTestSuite(org.apache.jackrabbit.test.api.StringPropertyTest.class);
+ suite.addTestSuite(org.apache.jackrabbit.test.api.UndefinedPropertyTest.class);
+ suite.addTestSuite(org.apache.jackrabbit.test.api.NamespaceRegistryReadMethodsTest.class);
+ suite.addTestSuite(org.apache.jackrabbit.test.api.NamespaceRemappingTest.class);
+ suite.addTestSuite(org.apache.jackrabbit.test.api.NodeIteratorTest.class);
+ suite.addTestSuite(org.apache.jackrabbit.test.api.PropertyReadMethodsTest.class);
+ suite.addTestSuite(org.apache.jackrabbit.test.api.RepositoryDescriptorTest.class);
+ suite.addTestSuite(org.apache.jackrabbit.test.api.SessionReadMethodsTest.class);
+ // suite.addTestSuite(org.apache.jackrabbit.test.api.WorkspaceReadMethodsTest.class);
+ suite.addTestSuite(org.apache.jackrabbit.test.api.ReferenceableRootNodesTest.class);
+ // suite.addTestSuite(org.apache.jackrabbit.test.api.ExportSysViewTest.class);
+ // suite.addTestSuite(org.apache.jackrabbit.test.api.ExportDocViewTest.class);
+ suite.addTestSuite(org.apache.jackrabbit.test.api.RepositoryLoginTest.class);
+
+ // These might not all be level one tests
+ // suite.addTestSuite(org.apache.jackrabbit.test.api.query.XPathPosIndexTest.class);
+ // suite.addTestSuite(org.apache.jackrabbit.test.api.query.XPathDocOrderTest.class);
+ // suite.addTestSuite(org.apache.jackrabbit.test.api.query.XPathOrderByTest.class);
+ // suite.addTestSuite(org.apache.jackrabbit.test.api.query.XPathJcrPathTest.class);
+ // suite.addTestSuite(org.apache.jackrabbit.test.api.query.DerefQueryLevel1Test.class);
+ // suite.addTestSuite(org.apache.jackrabbit.test.api.query.GetLanguageTest.class);
+ // suite.addTestSuite(org.apache.jackrabbit.test.api.query.GetPersistentQueryPathLevel1Test.class);
+ // suite.addTestSuite(org.apache.jackrabbit.test.api.query.GetStatementTest.class);
+ // suite.addTestSuite(org.apache.jackrabbit.test.api.query.GetSupportedQueryLanguagesTest.class);
+ // suite.addTestSuite(org.apache.jackrabbit.test.api.query.GetPropertyNamesTest.class);
+ // suite.addTestSuite(org.apache.jackrabbit.test.api.query.PredicatesTest.class);
+ // suite.addTestSuite(org.apache.jackrabbit.test.api.query.SimpleSelectionTest.class);
+
+ // The tests in this suite are level one
+ // suite.addTest(org.apache.jackrabbit.test.api.nodetype.TestAll.suite());
+
+ return suite;
+ }
+}
Property changes on: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckLevelOneTestSuite.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckLevelTwoTestSuite.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckLevelTwoTestSuite.java (rev 0)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckLevelTwoTestSuite.java 2009-03-05 14:55:09 UTC (rev 757)
@@ -0,0 +1,178 @@
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * Unless otherwise indicated, all code in JBoss DNA is licensed
+ * to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.jcr;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.jackrabbit.test.api.AddNodeTest;
+import org.apache.jackrabbit.test.api.CheckPermissionTest;
+import org.apache.jackrabbit.test.api.DocumentViewImportTest;
+import org.apache.jackrabbit.test.api.ImpersonateTest;
+import org.apache.jackrabbit.test.api.NamespaceRegistryTest;
+import org.apache.jackrabbit.test.api.NodeAddMixinTest;
+import org.apache.jackrabbit.test.api.NodeCanAddMixinTest;
+import org.apache.jackrabbit.test.api.NodeItemIsModifiedTest;
+import org.apache.jackrabbit.test.api.NodeItemIsNewTest;
+import org.apache.jackrabbit.test.api.NodeOrderableChildNodesTest;
+import org.apache.jackrabbit.test.api.NodeRemoveMixinTest;
+import org.apache.jackrabbit.test.api.NodeTest;
+import org.apache.jackrabbit.test.api.NodeUUIDTest;
+import org.apache.jackrabbit.test.api.PropertyItemIsModifiedTest;
+import org.apache.jackrabbit.test.api.PropertyItemIsNewTest;
+import org.apache.jackrabbit.test.api.PropertyTest;
+import org.apache.jackrabbit.test.api.ReferencesTest;
+import org.apache.jackrabbit.test.api.RepositoryLoginTest;
+import org.apache.jackrabbit.test.api.SerializationTest;
+import org.apache.jackrabbit.test.api.SessionTest;
+import org.apache.jackrabbit.test.api.SessionUUIDTest;
+import org.apache.jackrabbit.test.api.SetPropertyAssumeTypeTest;
+import org.apache.jackrabbit.test.api.SetPropertyBooleanTest;
+import org.apache.jackrabbit.test.api.SetPropertyCalendarTest;
+import org.apache.jackrabbit.test.api.SetPropertyConstraintViolationExceptionTest;
+import org.apache.jackrabbit.test.api.SetPropertyDoubleTest;
+import org.apache.jackrabbit.test.api.SetPropertyInputStreamTest;
+import org.apache.jackrabbit.test.api.SetPropertyLongTest;
+import org.apache.jackrabbit.test.api.SetPropertyNodeTest;
+import org.apache.jackrabbit.test.api.SetPropertyStringTest;
+import org.apache.jackrabbit.test.api.SetPropertyValueTest;
+import org.apache.jackrabbit.test.api.SetValueBinaryTest;
+import org.apache.jackrabbit.test.api.SetValueBooleanTest;
+import org.apache.jackrabbit.test.api.SetValueConstraintViolationExceptionTest;
+import org.apache.jackrabbit.test.api.SetValueDateTest;
+import org.apache.jackrabbit.test.api.SetValueDoubleTest;
+import org.apache.jackrabbit.test.api.SetValueLongTest;
+import org.apache.jackrabbit.test.api.SetValueReferenceTest;
+import org.apache.jackrabbit.test.api.SetValueStringTest;
+import org.apache.jackrabbit.test.api.SetValueValueFormatExceptionTest;
+import org.apache.jackrabbit.test.api.SetValueVersionExceptionTest;
+import org.apache.jackrabbit.test.api.ValueFactoryTest;
+import org.apache.jackrabbit.test.api.WorkspaceCloneReferenceableTest;
+import org.apache.jackrabbit.test.api.WorkspaceCloneSameNameSibsTest;
+import org.apache.jackrabbit.test.api.WorkspaceCloneTest;
+import org.apache.jackrabbit.test.api.WorkspaceCloneVersionableTest;
+import org.apache.jackrabbit.test.api.WorkspaceCopyBetweenWorkspacesReferenceableTest;
+import org.apache.jackrabbit.test.api.WorkspaceCopyBetweenWorkspacesSameNameSibsTest;
+import org.apache.jackrabbit.test.api.WorkspaceCopyBetweenWorkspacesTest;
+import org.apache.jackrabbit.test.api.WorkspaceCopyBetweenWorkspacesVersionableTest;
+import org.apache.jackrabbit.test.api.WorkspaceCopyReferenceableTest;
+import org.apache.jackrabbit.test.api.WorkspaceCopySameNameSibsTest;
+import org.apache.jackrabbit.test.api.WorkspaceCopyTest;
+import org.apache.jackrabbit.test.api.WorkspaceCopyVersionableTest;
+import org.apache.jackrabbit.test.api.WorkspaceMoveReferenceableTest;
+import org.apache.jackrabbit.test.api.WorkspaceMoveSameNameSibsTest;
+import org.apache.jackrabbit.test.api.WorkspaceMoveTest;
+import org.apache.jackrabbit.test.api.WorkspaceMoveVersionableTest;
+
+/**
+ * Test suite that includes the Level 2 JCR TCK API tests from the Jackrabbit project.
+ *
+ * @see JcrTckLevelOneTestSuite
+ * @see JcrTckOptionalTestSuite
+ * @see JcrTckTest
+ */
+public class JcrTckLevelTwoTestSuite extends TestCase {
+
+ /**
+ * 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("JCR 1.0 Level 2 API tests");
+
+ // We currently don't pass the tests in those suites that are commented out
+ // See https://jira.jboss.org/jira/browse/DNA-285
+
+ // level 2 tests
+ suite.addTestSuite(AddNodeTest.class);
+ suite.addTestSuite(NamespaceRegistryTest.class);
+ suite.addTestSuite(ReferencesTest.class);
+ suite.addTestSuite(SessionTest.class);
+ suite.addTestSuite(SessionUUIDTest.class);
+ suite.addTestSuite(NodeTest.class);
+ suite.addTestSuite(NodeUUIDTest.class);
+ suite.addTestSuite(NodeOrderableChildNodesTest.class);
+ suite.addTestSuite(PropertyTest.class);
+
+ suite.addTestSuite(SetValueBinaryTest.class);
+ suite.addTestSuite(SetValueBooleanTest.class);
+ suite.addTestSuite(SetValueDateTest.class);
+ suite.addTestSuite(SetValueDoubleTest.class);
+ suite.addTestSuite(SetValueLongTest.class);
+ suite.addTestSuite(SetValueReferenceTest.class);
+ suite.addTestSuite(SetValueStringTest.class);
+ suite.addTestSuite(SetValueConstraintViolationExceptionTest.class);
+ suite.addTestSuite(SetValueValueFormatExceptionTest.class);
+ suite.addTestSuite(SetValueVersionExceptionTest.class);
+
+ suite.addTestSuite(SetPropertyBooleanTest.class);
+ suite.addTestSuite(SetPropertyCalendarTest.class);
+ suite.addTestSuite(SetPropertyDoubleTest.class);
+ suite.addTestSuite(SetPropertyInputStreamTest.class);
+ suite.addTestSuite(SetPropertyLongTest.class);
+ suite.addTestSuite(SetPropertyNodeTest.class);
+ suite.addTestSuite(SetPropertyStringTest.class);
+ suite.addTestSuite(SetPropertyValueTest.class);
+ suite.addTestSuite(SetPropertyConstraintViolationExceptionTest.class);
+ suite.addTestSuite(SetPropertyAssumeTypeTest.class);
+
+ suite.addTestSuite(NodeItemIsModifiedTest.class);
+ suite.addTestSuite(NodeItemIsNewTest.class);
+ suite.addTestSuite(PropertyItemIsModifiedTest.class);
+ suite.addTestSuite(PropertyItemIsNewTest.class);
+
+ suite.addTestSuite(NodeAddMixinTest.class);
+ suite.addTestSuite(NodeCanAddMixinTest.class);
+ suite.addTestSuite(NodeRemoveMixinTest.class);
+
+ suite.addTestSuite(WorkspaceCloneReferenceableTest.class);
+ suite.addTestSuite(WorkspaceCloneSameNameSibsTest.class);
+ suite.addTestSuite(WorkspaceCloneTest.class);
+ suite.addTestSuite(WorkspaceCloneVersionableTest.class);
+ suite.addTestSuite(WorkspaceCopyBetweenWorkspacesReferenceableTest.class);
+ suite.addTestSuite(WorkspaceCopyBetweenWorkspacesSameNameSibsTest.class);
+ suite.addTestSuite(WorkspaceCopyBetweenWorkspacesTest.class);
+ suite.addTestSuite(WorkspaceCopyBetweenWorkspacesVersionableTest.class);
+ suite.addTestSuite(WorkspaceCopyReferenceableTest.class);
+ suite.addTestSuite(WorkspaceCopySameNameSibsTest.class);
+ suite.addTestSuite(WorkspaceCopyTest.class);
+ suite.addTestSuite(WorkspaceCopyVersionableTest.class);
+ suite.addTestSuite(WorkspaceMoveReferenceableTest.class);
+ suite.addTestSuite(WorkspaceMoveSameNameSibsTest.class);
+ suite.addTestSuite(WorkspaceMoveTest.class);
+ suite.addTestSuite(WorkspaceMoveVersionableTest.class);
+
+ suite.addTestSuite(RepositoryLoginTest.class);
+ suite.addTestSuite(ImpersonateTest.class);
+ suite.addTestSuite(CheckPermissionTest.class);
+
+ suite.addTestSuite(DocumentViewImportTest.class);
+ suite.addTestSuite(SerializationTest.class);
+
+ suite.addTestSuite(ValueFactoryTest.class);
+
+ return suite;
+ }
+}
Property changes on: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckLevelTwoTestSuite.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckOptionalTestSuite.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckOptionalTestSuite.java (rev 0)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckOptionalTestSuite.java 2009-03-05 14:55:09 UTC (rev 757)
@@ -0,0 +1,57 @@
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * Unless otherwise indicated, all code in JBoss DNA is licensed
+ * to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.jcr;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Test suite that includes the Optional JCR TCK API tests from the Jackrabbit project.
+ *
+ * @see JcrTckLevelOneTestSuite
+ * @see JcrTckLevelTwoTestSuite
+ * @see JcrTckTest
+ */
+public class JcrTckOptionalTestSuite extends TestCase {
+
+ /**
+ * 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("JCR 1.0 Optional API tests");
+
+ // We currently don't pass the tests in those suites that are commented out
+ // See https://jira.jboss.org/jira/browse/DNA-285
+
+ suite.addTest(org.apache.jackrabbit.test.api.observation.TestAll.suite());
+ suite.addTest(org.apache.jackrabbit.test.api.version.TestAll.suite());
+ suite.addTest(org.apache.jackrabbit.test.api.lock.TestAll.suite());
+ suite.addTest(org.apache.jackrabbit.test.api.util.TestAll.suite());
+
+ return suite;
+ }
+}
Property changes on: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckOptionalTestSuite.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Copied: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java (from rev 756, trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JackrabbitJcrTckTest.java)
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java (rev 0)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-03-05 14:55:09 UTC (rev 757)
@@ -0,0 +1,184 @@
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.jcr;
+
+import java.io.File;
+import java.net.URI;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.util.Collections;
+import java.util.Properties;
+import javax.jcr.Credentials;
+import javax.jcr.Repository;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.apache.jackrabbit.test.JCRTestSuite;
+import org.apache.jackrabbit.test.RepositoryStub;
+import org.jboss.dna.graph.DnaLexicon;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.GraphImporter;
+import org.jboss.dna.graph.JcrNtLexicon;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.connector.RepositoryConnection;
+import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
+import org.jboss.dna.graph.connector.inmemory.InMemoryRepositorySource;
+import org.jboss.dna.graph.property.Path;
+
+/**
+ * Test suite to wrap Apache Jackrabbit JCR technology compatibility kit (TCK) unit tests.
+ *
+ * @see JcrTckLevelOneTestSuite
+ * @see JcrTckLevelTwoTestSuite
+ * @see JcrTckOptionalTestSuite
+ */
+public class JcrTckTest {
+
+ /**
+ * Wrapper so that the Jackrabbit TCK test suite gets picked up by the DNA Maven test target.
+ *
+ * @return a new instance of {@link JCRTestSuite}.
+ */
+ public static Test suite() {
+ // Uncomment this to execute all tests
+ // return new JCRTestSuite();
+
+ // Or uncomment the following lines to execute the different sets/suites of tests ...
+ TestSuite suite = new TestSuite("JCR 1.0 API tests");
+ suite.addTest(JcrTckLevelOneTestSuite.suite());
+ // suite.addTest(JcrTckLevelTwoTestSuite.suite());
+ // suite.addTest(JcrTckOptionalTestSuite.suite());
+
+ return suite;
+ }
+
+ /**
+ * Concrete implementation of {@link RepositoryStub} based on DNA-specific configuration.
+ */
+ public static class InMemoryRepositoryStub extends RepositoryStub {
+ private Repository repository;
+ protected RepositoryConnection connection;
+ protected AccessControlContext accessControlContext = AccessController.getContext();
+
+ private Credentials credentials = new Credentials() {
+ private static final long serialVersionUID = 1L;
+
+ @SuppressWarnings( "unused" )
+ public AccessControlContext getAccessControlContext() {
+ return accessControlContext;
+ }
+ };
+
+ protected ExecutionContext executionContext = new ExecutionContext() {
+
+ @Override
+ public ExecutionContext create( AccessControlContext accessControlContext ) {
+ return executionContext;
+ }
+ };
+
+ protected RepositoryConnectionFactory connectionFactory = new RepositoryConnectionFactory() {
+ public RepositoryConnection createConnection( String sourceName ) {
+ return connection;
+ }
+ };
+
+ public InMemoryRepositoryStub( Properties env ) {
+ super(env);
+
+ // Create the in-memory (DNA) repository
+ InMemoryRepositorySource source = new InMemoryRepositorySource();
+
+ // Various calls will fail if you do not set a non-null name for the source
+ source.setName("TestRepositorySource");
+
+ // Wrap a connection to the in-memory (DNA) repository in a (JCR) repository
+ connection = source.getConnection();
+ repository = new JcrRepository(Collections.<String, String>emptyMap(), executionContext.create(accessControlContext),
+ connectionFactory, source.getName());
+
+ // Make sure the path to the namespaces exists ...
+ Graph graph = Graph.create(source.getName(), connectionFactory, executionContext);
+ graph.create("/jcr:system").and().create("/jcr:system/dna:namespaces");
+
+ // Set up some sample nodes in the graph to match the expected test configuration
+ try {
+
+ // TODO: Should there be an easier way to define these since they will be needed for all JCR repositories?
+ executionContext.getNamespaceRegistry().register(DnaLexicon.Namespace.PREFIX, DnaLexicon.Namespace.URI);
+ executionContext.getNamespaceRegistry().register(JcrLexicon.Namespace.PREFIX, JcrLexicon.Namespace.URI);
+ executionContext.getNamespaceRegistry().register(JcrNtLexicon.Namespace.PREFIX, JcrNtLexicon.Namespace.URI);
+ executionContext.getNamespaceRegistry().register("sv", "http://www.jcp.org/jcr/sv/1.0");
+
+ Path destinationPath = executionContext.getValueFactories().getPathFactory().create("/");
+ GraphImporter importer = new GraphImporter(graph);
+
+ URI xmlContent = new File("src/test/resources/repositoryJackrabbitTck.xml").toURI();
+ Graph.Batch batch = importer.importXml(xmlContent, Location.create(destinationPath));
+ batch.execute();
+
+ } catch (Exception ex) {
+ // The TCK tries to quash this exception. Print it out to be more obvious.
+ ex.printStackTrace();
+ throw new IllegalStateException("Repository initialization failed.", ex);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.apache.jackrabbit.test.RepositoryStub#getSuperuserCredentials()
+ */
+ @Override
+ public Credentials getSuperuserCredentials() {
+ // TODO: Why must we override this method? The default TCK implementation just returns a particular instance of
+ // SimpleCredentials.
+ return credentials;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.apache.jackrabbit.test.RepositoryStub#getReadOnlyCredentials()
+ */
+ @Override
+ public Credentials getReadOnlyCredentials() {
+ // TODO: Why must we override this method? The default TCK implementation just returns a particular instance of
+ // SimpleCredentials.
+ return credentials;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.apache.jackrabbit.test.RepositoryStub#getRepository()
+ */
+ @Override
+ public Repository getRepository() {
+ return repository;
+ }
+
+ }
+
+}
Property changes on: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/dna-jcr/src/test/resources/repositoryStubImpl.properties
===================================================================
--- trunk/dna-jcr/src/test/resources/repositoryStubImpl.properties 2009-03-04 22:18:45 UTC (rev 756)
+++ trunk/dna-jcr/src/test/resources/repositoryStubImpl.properties 2009-03-05 14:55:09 UTC (rev 757)
@@ -1,4 +1,4 @@
-javax.jcr.tck.repository_stub_impl=org.jboss.dna.jcr.JackrabbitJcrTckTest$InMemoryRepositoryStub
+javax.jcr.tck.repository_stub_impl=org.jboss.dna.jcr.JcrTckTest$InMemoryRepositoryStub
javax.jcr.tck.testroot=/testroot
javax.jcr.tck.nodename1=node1
javax.jcr.tck.nodename2=node2
15 years, 1 month
DNA SVN: r756 - trunk/dna-jcr/src/main/java/org/jboss/dna/jcr.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2009-03-04 17:18:45 -0500 (Wed, 04 Mar 2009)
New Revision: 756
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
Log:
DNA-293 JcrSession creates Property instances that use the PropertyType.UNDEFINED, which is not allowed
Changed how JcrSession.populateNode(...) determines the PropertyType for an existing DNA Property instance. It is now based upon the first value, since the Java type for that value should be based upon the PropertyType specified when creating or updating the JCR property.
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java 2009-03-04 21:58:43 UTC (rev 755)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java 2009-03-04 22:18:45 UTC (rev 756)
@@ -609,13 +609,20 @@
/**
* Compute the JCR {@link PropertyType} for the given DNA {@link org.jboss.dna.graph.property.PropertyType}.
+ * <p>
+ * See DNA-293 for complete discussion on why this method works the way it does. The best option appears to be basing the
+ * PropertyType on the first value, since that should be compatible with the PropertyType that was used when the values were
+ * set on the property in the first place.
+ * </p>
*
- * @param dnaPropertyType the DNA property type; never null
- * @return the JCR property type
+ * @param property the DNA property for which the {@link PropertyType} is to be determined; never null
+ * @return the JCR property type; always a valid value and never {@link PropertyType#UNDEFINED}.
*/
- static final int jcrPropertyTypeFor( org.jboss.dna.graph.property.PropertyType dnaPropertyType ) {
+ static final int jcrPropertyTypeFor( org.jboss.dna.graph.property.Property property ) {
+ Object value = property.getFirstValue();
+
// Get the DNA property type for this ...
- switch (dnaPropertyType) {
+ switch (org.jboss.dna.graph.property.PropertyType.discoverType(value)) {
case STRING:
return PropertyType.STRING;
case NAME:
@@ -809,16 +816,7 @@
// Figure out the property type ...
int propertyType = propertyDefinition.getRequiredType();
if (propertyType == PropertyType.UNDEFINED) {
- // See DNA-293 for discussion. Best option is to use PropertyType.STRING, since values can always
- // be converted to Strings (and because clients might use Property.getType() to decide how to
- // manipulate or set values).
- propertyType = PropertyType.STRING;
-
- // // Or, we can choose the property type for the first value (or the default value, if there is one) ...
- // Object value = dnaProp.getFirstValue();
- // org.jboss.dna.graph.property.PropertyType dnaType =
- // org.jboss.dna.graph.property.PropertyType.discoverType(value);
- // propertyType = jcrPropertyTypeFor(dnaType);
+ propertyType = jcrPropertyTypeFor(dnaProp);
}
// Create the appropriate JCR property wrapper ...
15 years, 2 months