You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by st...@apache.org on 2004/11/09 15:03:36 UTC

svn commit: rev 57040 - in incubator/jackrabbit/trunk/src: conf java/org/apache/jackrabbit/core java/org/apache/jackrabbit/core/state/xml

Author: stefan
Date: Tue Nov  9 06:03:35 2004
New Revision: 57040

Modified:
   incubator/jackrabbit/trunk/src/conf/repository.xml
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/Test.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/xml/XMLPersistenceManager.java
Log:
changed XMLPersistenceManager back to store everything in (less efficient but human readable) xml format (as its name would suggest); 
ObjectPersistenceManager can be used for a more efficient 
filesystem-based serialization format


Modified: incubator/jackrabbit/trunk/src/conf/repository.xml
==============================================================================
--- incubator/jackrabbit/trunk/src/conf/repository.xml	(original)
+++ incubator/jackrabbit/trunk/src/conf/repository.xml	Tue Nov  9 06:03:35 2004
@@ -114,7 +114,7 @@
             class: FQN of class implementing PersistenceManager interface
         -->
         <!--
-        <PersistenceManager class="org.apache.jackrabbit.core.state.xml.XMLPersistenceManager">
+        <PersistenceManager class="org.apache.jackrabbit.core.state.xml.XMLPersistenceManager"/>
         -->
         <!--
         <PersistenceManager class="org.apache.jackrabbit.core.state.mem.InMemPersistenceManager">

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/Test.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/Test.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/Test.java	Tue Nov  9 06:03:35 2004
@@ -243,7 +243,7 @@
             imported = root.getNode("imported");
         }
 
-        importNode(new File("d:/dev/jsr170/jackrabbit/src/java"), imported);
+        importNode(new File("d:/dev/jackrabbit/src/test"), imported);
 
         if (root.hasNode("foo")) {
             root.getNode("foo").remove();

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/xml/XMLPersistenceManager.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/xml/XMLPersistenceManager.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/xml/XMLPersistenceManager.java	Tue Nov  9 06:03:35 2004
@@ -26,6 +26,8 @@
 import org.apache.log4j.Logger;
 import org.jdom.Element;
 import org.jdom.JDOMException;
+import org.jdom.filter.ContentFilter;
+import org.jdom.filter.Filter;
 import org.jdom.input.SAXBuilder;
 
 import javax.jcr.PropertyType;
@@ -72,13 +74,20 @@
     private static final String PROPERTY_ELEMENT = "property";
     private static final String NAME_ATTRIBUTE = "name";
     private static final String TYPE_ATTRIBUTE = "type";
-    private static final String COUNT_ATTRIBUTE = "count";
+
+    private static final String VALUES_ELEMENT = "values";
+    private static final String VALUE_ELEMENT = "value";
 
     private static final String NODES_ELEMENT = "nodes";
 
+    private static final String NODEREFERENCES_ELEMENT = "references";
+    private static final String TARGETID_ATTRIBUTE = "targetId";
+    private static final String NODEREFERENCE_ELEMENT = "reference";
+    private static final String PROPERTYID_ATTRIBUTE = "propertyId";
+
     private static final String NODEFILENAME = ".node.xml";
 
-    private static final String NODEREFSFILENAME = ".references";
+    private static final String NODEREFSFILENAME = ".references.xml";
 
     private boolean initialized;
 
@@ -124,11 +133,10 @@
                 chars[j++] = HEXDIGITS[(bytes[i] >> 4) & 0x0f];
                 chars[j++] = HEXDIGITS[bytes[i] & 0x0f];
             }
-            //fileName = new String(chars) + ".xml";
-            fileName = new String(chars);
+            fileName = new String(chars) + ".xml";
         } catch (NoSuchAlgorithmException nsae) {
             // should never get here as MD5 should always be available in the JRE
-            String msg = "MD5 not available: ";
+            String msg = "MD5 not available";
             log.fatal(msg, nsae);
             throw new InternalError(msg + nsae);
         }
@@ -226,10 +234,32 @@
         }
     }
 
-    private void readState(Properties props, PersistentPropertyState state)
+    private void readState(Element propElement, PersistentPropertyState state)
             throws ItemStateException {
+        // first do some paranoid sanity checks
+        if (!propElement.getName().equals(PROPERTY_ELEMENT)) {
+            String msg = "invalid serialization format (unexpected element: " + propElement.getName() + ")";
+            log.error(msg);
+            throw new ItemStateException(msg);
+        }
+        // check name
+        if (!state.getName().equals(QName.valueOf(propElement.getAttributeValue(NAME_ATTRIBUTE)))) {
+            String msg = "invalid serialized state: name mismatch";
+            log.error(msg);
+            throw new ItemStateException(msg);
+        }
+        // check parentUUID
+        String parentUUID = propElement.getAttributeValue(PARENTUUID_ATTRIBUTE);
+        if (!parentUUID.equals(state.getParentUUID())) {
+            String msg = "invalid serialized state: parentUUID mismatch";
+            log.error(msg);
+            throw new ItemStateException(msg);
+        }
+
+        // now we're ready to read state
+
         // type
-        String typeName = props.getProperty(TYPE_ATTRIBUTE);
+        String typeName = propElement.getAttributeValue(TYPE_ATTRIBUTE);
         int type;
         try {
             type = PropertyType.valueFromName(typeName);
@@ -240,46 +270,66 @@
         state.setType(type);
 
         // definition id
-        if (props.containsKey(DEFINITIONID_ATTRIBUTE)) {
-            state.setDefinitionId(PropDefId.valueOf(props.getProperty(DEFINITIONID_ATTRIBUTE)));
-        }
-
-        // # of values
-        int cnt = Integer.parseInt(props.getProperty(COUNT_ATTRIBUTE));
+        String definitionId = propElement.getAttributeValue(DEFINITIONID_ATTRIBUTE);
+        state.setDefinitionId(PropDefId.valueOf(definitionId));
 
         // values
-        InternalValue[] values = new InternalValue[cnt];
-        Enumeration names = props.propertyNames();
-        while (names.hasMoreElements()) {
-            String name = (String) names.nextElement();
-            if (TYPE_ATTRIBUTE.equals(name) || COUNT_ATTRIBUTE.equals(name)
-                    || DEFINITIONID_ATTRIBUTE.equals(name)) {
-                continue;
-            }
-            int i = Integer.parseInt(name);
+        Iterator iter = propElement.getChild(VALUES_ELEMENT).getChildren(VALUE_ELEMENT).iterator();
+        ArrayList values = new ArrayList();
+        while (iter.hasNext()) {
+            Element valueElement = (Element) iter.next();
+            Filter filter = new ContentFilter(ContentFilter.TEXT | ContentFilter.CDATA);
+            List content = valueElement.getContent(filter);
+
             InternalValue val;
-            String text = props.getProperty(name);
-            if (text != null) {
+            if (!content.isEmpty()) {
+                // read serialized value
+                String text = valueElement.getTextTrim();
                 if (type == PropertyType.BINARY) {
                     // special handling required for binary value:
                     // the value stores the path to the actual binary file in the blob store
                     try {
                         val = InternalValue.create(new FileSystemResource(blobStore, text));
                     } catch (IOException ioe) {
-                        String msg = "error while reading serialized binary value";
+                        String msg = "error while reading serialized binary valuey";
                         log.error(msg, ioe);
                         throw new ItemStateException(msg, ioe);
                     }
                 } else {
                     val = InternalValue.valueOf(text, type);
                 }
+                values.add(val);
             } else {
-                // null value
-                val = null;
+                continue;
             }
-            values[i] = val;
         }
-        state.setValues(values);
+        state.setValues((InternalValue[]) values.toArray(new InternalValue[values.size()]));
+    }
+
+    private void readState(Element refsElement, NodeReferences refs)
+            throws ItemStateException {
+        // first do some paranoid sanity checks
+        if (!refsElement.getName().equals(NODEREFERENCES_ELEMENT)) {
+            String msg = "invalid serialization format (unexpected element: " + refsElement.getName() + ")";
+            log.error(msg);
+            throw new ItemStateException(msg);
+        }
+        // check targetId
+        if (!refs.getTargetId().equals(NodeId.valueOf(refsElement.getAttributeValue(TARGETID_ATTRIBUTE)))) {
+            String msg = "invalid serialized state: targetId  mismatch";
+            log.error(msg);
+            throw new ItemStateException(msg);
+        }
+
+        // now we're ready to read the references data
+
+        // property id's
+        refs.clearAllReferences();
+        Iterator iter = refsElement.getChildren(NODEREFERENCE_ELEMENT).iterator();
+        while (iter.hasNext()) {
+            Element elem = (Element) iter.next();
+            refs.addReference(PropertyId.valueOf(elem.getAttributeValue(PROPERTYID_ATTRIBUTE)));
+        }
     }
 
     //---------------------------------------------------< PersistenceManager >
@@ -397,13 +447,17 @@
             }
             InputStream in = itemStateStore.getInputStream(propFilePath);
             try {
-                Properties props = new Properties();
-                props.load(in);
-                readState(props, state);
+                SAXBuilder builder = new SAXBuilder();
+                Element rootElement = builder.build(in).getRootElement();
+
+                readState(rootElement, state);
                 return;
             } finally {
                 in.close();
             }
+        } catch (JDOMException jde) {
+            e = jde;
+            // fall through
         } catch (IOException ioe) {
             e = ioe;
             // fall through
@@ -411,7 +465,6 @@
             e = fse;
             // fall through
         }
-
         String msg = "failed to read property state: " + parentUUID + "/" + propName;
         log.error(msg, e);
         throw new ItemStateException(msg, e);
@@ -515,172 +568,98 @@
         try {
             propFile.makeParentDirs();
             OutputStream os = propFile.getOutputStream();
-/*
             // write property state to xml file
-	    Writer writer = null;
-	    try {
-		String encoding = DEFAULT_ENCODING;
-		try {
-		    writer = new BufferedWriter(new OutputStreamWriter(os, encoding));
-		} catch (UnsupportedEncodingException e) {
-		    // should never get here!
-		    OutputStreamWriter osw = new OutputStreamWriter(os);
-		    encoding = osw.getEncoding();
-		    writer = new BufferedWriter(osw);
-		}
-
-		String typeName;
-		int type = state.getType();
-		try {
-		    typeName = PropertyType.nameFromValue(type);
-		} catch (IllegalArgumentException iae) {
-		    // should never be getting here
-		    throw new ItemStateException("unexpected property-type ordinal: " + type, iae);
-		}
-
-		writer.write("<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>\n");
-		writer.write("<" + PROPERTY_ELEMENT + " " +
-			NAME_ATTRIBUTE + "=\"" + state.getName() + "\" " +
-			PARENTUUID_ATTRIBUTE + "=\"" + state.getParentUUID() + "\" " +
-	    		DEFINITIONID_ATTRIBUTE + "=\"" + state.getDefinitionId().toString() + "\" " +
-			TYPE_ATTRIBUTE + "=\"" + typeName + "\">\n");
-		// values
-		writer.write("\t<" + VALUES_ELEMENT + ">\n");
-		InternalValue[] values = state.getValues();
-		if (values != null) {
-		    for (int i = 0; i < values.length; i++) {
-			writer.write("\t\t<" + VALUE_ELEMENT + ">");
-			InternalValue val = values[i];
-			if (val != null) {
-			    if (type == PropertyType.BINARY) {
-				// special handling required for binary value:
-				// spool binary value to file in blob store
-				BLOBFileValue blobVal = (BLOBFileValue) val.internalValue();
-				String binPath = buildBlobFilePath(state.getParentUUID(), state.getName(), i);
-				OutputStream binOut = null;
-			        FileSystemResource internalBlobFile = new FileSystemResource(blobStore, binPath);
-				internalBlobFile.makeParentDirs();
-				try {
-				    binOut = internalBlobFile.getOutputStream();
-				    blobVal.spool(binOut);
-				} finally {
-				    try {
-					if (binOut != null) {
-					    binOut.close();
-					}
-				    } catch (IOException ioe) {
-				    }
-				}
-				// store path to binary file as property value
-				writer.write(binPath);
-				// FIXME: hack!
-				// replace value instance with value
-				// backed by internal file and delete temp file
-				values[i] = InternalValue.create(internalBlobFile);
-				if (blobVal.isTempFile()) {
-				    blobVal.delete();
-				    blobVal = null;
-				}
-			    } else {
-				// escape '<' and '&'
-				char chars[] = val.toString().toCharArray();
-				int j = 0, last = 0;
-				while (j < chars.length) {
-				    char c = chars[j];
-				    if (c == '<') {
-					writer.write(chars, last, j - last);
-					writer.write("&lt;");
-					last = j + 1;
-				    } else if (c == '&') {
-					writer.write(chars, last, j - last);
-					writer.write("&amp;");
-					last = j + 1;
-				    }
-				    j++;
-				}
-				writer.write(chars, last, j - last);
-			    }
-			}
-			writer.write("</" + VALUE_ELEMENT + ">\n");
-		    }
-		}
-		writer.write("\t</" + VALUES_ELEMENT + ">\n");
-		writer.write("</" + PROPERTY_ELEMENT + ">\n");
-	    } finally {
-		writer.close();
-	    }
-*/
-            // write property state to java.util.Properties file
-            Properties props = new Properties();
-
-            // type
-            String typeName;
-            int type = state.getType();
+            Writer writer = null;
             try {
-                typeName = PropertyType.nameFromValue(type);
-            } catch (IllegalArgumentException iae) {
-                // should never be getting here
-                throw new ItemStateException("unexpected property-type ordinal: " + type, iae);
-            }
-            props.setProperty(TYPE_ATTRIBUTE, typeName);
-
-            // definition id
-            props.setProperty(DEFINITIONID_ATTRIBUTE, state.getDefinitionId().toString());
-
-            InternalValue[] values = state.getValues();
-
-            // # of values
-            props.setProperty(COUNT_ATTRIBUTE, Integer.toString(values == null ? 0 : values.length));
-
-            // values
-            if (values != null) {
-                for (int i = 0; i < values.length; i++) {
-                    InternalValue val = values[i];
-                    if (val != null) {
-                        if (type == PropertyType.BINARY) {
-                            // special handling required for binary value:
-                            // spool binary value to file in blob store
-                            BLOBFileValue blobVal = (BLOBFileValue) val.internalValue();
-
-                            String binPath = buildBlobFilePath(state.getParentUUID(), state.getName(), i);
-                            OutputStream binOut = null;
-                            FileSystemResource internalBlobFile = new FileSystemResource(blobStore, binPath);
-                            internalBlobFile.makeParentDirs();
-                            try {
-                                binOut = internalBlobFile.getOutputStream();
-                                blobVal.spool(binOut);
-                            } finally {
+                String encoding = DEFAULT_ENCODING;
+                try {
+                    writer = new BufferedWriter(new OutputStreamWriter(os, encoding));
+                } catch (UnsupportedEncodingException e) {
+                    // should never get here!
+                    OutputStreamWriter osw = new OutputStreamWriter(os);
+                    encoding = osw.getEncoding();
+                    writer = new BufferedWriter(osw);
+                }
+
+                String typeName;
+                int type = state.getType();
+                try {
+                    typeName = PropertyType.nameFromValue(type);
+                } catch (IllegalArgumentException iae) {
+                    // should never be getting here
+                    throw new ItemStateException("unexpected property-type ordinal: " + type, iae);
+                }
+
+                writer.write("<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>\n");
+                writer.write("<" + PROPERTY_ELEMENT + " " +
+                        NAME_ATTRIBUTE + "=\"" + state.getName() + "\" " +
+                        PARENTUUID_ATTRIBUTE + "=\"" + state.getParentUUID() + "\" " +
+                        DEFINITIONID_ATTRIBUTE + "=\"" + state.getDefinitionId().toString() + "\" " +
+                        TYPE_ATTRIBUTE + "=\"" + typeName + "\">\n");
+                // values
+                writer.write("\t<" + VALUES_ELEMENT + ">\n");
+                InternalValue[] values = state.getValues();
+                if (values != null) {
+                    for (int i = 0; i < values.length; i++) {
+                        writer.write("\t\t<" + VALUE_ELEMENT + ">");
+                        InternalValue val = values[i];
+                        if (val != null) {
+                            if (type == PropertyType.BINARY) {
+                                // special handling required for binary value:
+                                // spool binary value to file in blob store
+                                BLOBFileValue blobVal = (BLOBFileValue) val.internalValue();
+                                String binPath = buildBlobFilePath(state.getParentUUID(), state.getName(), i);
+                                OutputStream binOut = null;
+                                FileSystemResource internalBlobFile = new FileSystemResource(blobStore, binPath);
+                                internalBlobFile.makeParentDirs();
                                 try {
-                                    if (binOut != null) {
-                                        binOut.close();
+                                    binOut = internalBlobFile.getOutputStream();
+                                    blobVal.spool(binOut);
+                                } finally {
+                                    try {
+                                        if (binOut != null) {
+                                            binOut.close();
+                                        }
+                                    } catch (IOException ioe) {
                                     }
-                                } catch (IOException ioe) {
                                 }
+                                // store path to binary file as property value
+                                writer.write(binPath);
+                                // FIXME: hack!
+                                // replace value instance with value
+                                // backed by internal file and delete temp file
+                                values[i] = InternalValue.create(internalBlobFile);
+                                if (blobVal.isTempFile()) {
+                                    blobVal.delete();
+                                    blobVal = null;
+                                }
+                            } else {
+                                // escape '<' and '&'
+                                char chars[] = val.toString().toCharArray();
+                                int j = 0, last = 0;
+                                while (j < chars.length) {
+                                    char c = chars[j];
+                                    if (c == '<') {
+                                        writer.write(chars, last, j - last);
+                                        writer.write("&lt;");
+                                        last = j + 1;
+                                    } else if (c == '&') {
+                                        writer.write(chars, last, j - last);
+                                        writer.write("&amp;");
+                                        last = j + 1;
+                                    }
+                                    j++;
+                                }
+                                writer.write(chars, last, j - last);
                             }
-                            // store path to binary file as property value
-                            props.setProperty(Integer.toString(i), binPath);
-                            // replace value instance with value
-                            // backed by internal file and delete temp file
-                            values[i] = InternalValue.create(internalBlobFile);
-                            if (blobVal.isTempFile()) {
-                                blobVal.delete();
-                                blobVal = null;
-                            }
-                        } else {
-                            props.setProperty(Integer.toString(i), val.toString());
                         }
-                    } else {
-                        // null value
-                        props.setProperty(Integer.toString(i), null);
+                        writer.write("</" + VALUE_ELEMENT + ">\n");
                     }
                 }
-            }
-
-            try {
-                props.store(os, null);
+                writer.write("\t</" + VALUES_ELEMENT + ">\n");
+                writer.write("</" + PROPERTY_ELEMENT + ">\n");
             } finally {
-                // make sure stream is closed
-                os.close();
+                writer.close();
             }
         } catch (Exception e) {
             String msg = "failed to store property state: " + state.getParentUUID() + "/" + state.getName();
@@ -770,30 +749,19 @@
             refs.clearAllReferences();
 
             InputStream in = itemStateStore.getInputStream(refsFilePath);
-            BufferedReader reader = null;
+
             try {
-                String encoding = DEFAULT_ENCODING;
-                try {
-                    reader = new BufferedReader(new InputStreamReader(in, encoding));
-                } catch (UnsupportedEncodingException uee) {
-                    // should never get here!
-                    InputStreamReader isw = new InputStreamReader(in);
-                    encoding = isw.getEncoding();
-                    reader = new BufferedReader(isw);
-                }
-                // read references (i.e. the id's of the REFERENCE properties)
-                String s;
-                while ((s = reader.readLine()) != null) {
-                    if (s.length() > 0) {
-                        PropertyId propId = PropertyId.valueOf(s);
-                        refs.addReference(propId);
-                    }
-                }
-                return;
+                SAXBuilder builder = new SAXBuilder();
+                Element rootElement = builder.build(in).getRootElement();
 
+                readState(rootElement, refs);
+                return;
             } finally {
-                reader.close();
+                in.close();
             }
+        } catch (JDOMException jde) {
+            e = jde;
+            // fall through
         } catch (IOException ioe) {
             e = ioe;
             // fall through
@@ -831,13 +799,17 @@
                     encoding = osw.getEncoding();
                     writer = new BufferedWriter(osw);
                 }
+                writer.write("<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>\n");
+                writer.write("<" + NODEREFERENCES_ELEMENT + " "
+                        + TARGETID_ATTRIBUTE + "=\"" + refs.getTargetId() + "\">\n");
                 // write references (i.e. the id's of the REFERENCE properties)
                 Iterator iter = refs.getReferences().iterator();
                 while (iter.hasNext()) {
                     PropertyId propId = (PropertyId) iter.next();
-                    writer.write(propId.toString());
-                    writer.newLine();
+                    writer.write("\t<" + NODEREFERENCE_ELEMENT + " "
+                    + PROPERTYID_ATTRIBUTE+ "=\"" + propId +  "\"/>\n");
                 }
+                writer.write("</" + NODEREFERENCES_ELEMENT + ">\n");
             } finally {
                 writer.close();
             }