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 2005/04/04 19:55:21 UTC
svn commit: r160072 - in
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core:
util/ValueHelper.java xml/DocViewImportHandler.java xml/ImportHandler.java
xml/Importer.java xml/SessionImporter.java xml/SysViewImportHandler.java
xml/TargetImportHandler.java xml/WorkspaceImporter.java
Author: stefan
Date: Mon Apr 4 10:55:20 2005
New Revision: 160072
URL: http://svn.apache.org/viewcvs?view=rev&rev=160072
Log:
re-implemented handling of values on import to allow import of large binary properties
Added:
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/TargetImportHandler.java (with props)
Modified:
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/util/ValueHelper.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/DocViewImportHandler.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/ImportHandler.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/Importer.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SessionImporter.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SysViewImportHandler.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/WorkspaceImporter.java
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/util/ValueHelper.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/util/ValueHelper.java?view=diff&r1=160071&r2=160072
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/util/ValueHelper.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/util/ValueHelper.java Mon Apr 4 10:55:20 2005
@@ -471,7 +471,8 @@
* @param reader reader for the string data to be deserialized
* @param type type of value
* @param decodeBlanks if <code>true</code> <code>"_x0020_"</code>
- * character sequences will be decoded to single space characters each.
+ * character sequences will be decoded to single space
+ * characters each.
* @return the deserialized <code>Value</code>
* @throws IOException if an i/o error occured during the
* serialization
@@ -487,6 +488,15 @@
// base64 encoded binary value;
// the encodeBlanks flag can be ignored since base64-encoded
// data cannot contain encoded space characters
+/*
+ // @todo decode to temp file and pass FileInputStream to BinaryValue constructor
+ File tmpFile = File.createTempFile("bin", null);
+ FileOutputStream out = new FileOutputStream(tmpFile);
+ tmpFile.deleteOnExit();
+ Base64.decode(reader, out);
+ out.close();
+ return new BinaryValue(new FileInputStream(tmpFile));
+*/
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Base64.decode(reader, baos);
// no need to close ByteArrayOutputStream
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/DocViewImportHandler.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/DocViewImportHandler.java?view=diff&r1=160071&r2=160072
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/DocViewImportHandler.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/DocViewImportHandler.java Mon Apr 4 10:55:20 2005
@@ -17,9 +17,7 @@
package org.apache.jackrabbit.core.xml;
import org.apache.jackrabbit.core.BaseException;
-import org.apache.jackrabbit.core.Constants;
import org.apache.jackrabbit.core.IllegalNameException;
-import org.apache.jackrabbit.core.InternalValue;
import org.apache.jackrabbit.core.NamespaceResolver;
import org.apache.jackrabbit.core.QName;
import org.apache.jackrabbit.core.UnknownPrefixException;
@@ -27,7 +25,6 @@
import org.apache.log4j.Logger;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
@@ -38,13 +35,10 @@
* <code>DocViewImportHandler</code> processes Document View XML SAX events
* and 'translates' them into <code>{@link Importer}</code> method calls.
*/
-class DocViewImportHandler extends DefaultHandler implements Constants {
+class DocViewImportHandler extends TargetImportHandler {
private static Logger log = Logger.getLogger(DocViewImportHandler.class);
- private final Importer importer;
- private final NamespaceResolver nsContext;
-
/**
* stack of NodeInfo instances; an instance is pushed onto the stack
* in the startElement method and is popped from the stack in the
@@ -52,11 +46,16 @@
*/
private final Stack stack = new Stack();
// buffer used to merge adjacent character data
- private final StringBuffer text = new StringBuffer();
+ private StringBufferValue textHandler = new StringBufferValue();
+ /**
+ * Constructs a new <code>DocViewImportHandler</code>.
+ *
+ * @param importer
+ * @param nsContext
+ */
DocViewImportHandler(Importer importer, NamespaceResolver nsContext) {
- this.importer = importer;
- this.nsContext = nsContext;
+ super(importer, nsContext);
}
/**
@@ -68,30 +67,28 @@
* @param text
* @throws SAXException
*/
- private void onTextNode(String text)
+ private void onTextNode(StringBufferValue text)
throws SAXException {
- if (text.trim().length() == 0) {
+ String s = textHandler.retrieve();
+ if (s.trim().length() == 0) {
// ignore whitespace-only character data
- log.debug("ignoring withespace character data: " + text);
+ log.debug("ignoring withespace character data: " + s);
return;
}
- if (text.length() > 0) {
- try {
- Importer.NodeInfo node =
- new Importer.NodeInfo(JCR_XMLTEXT, null, null, null);
- InternalValue[] values = new InternalValue[1];
- values[0] = InternalValue.create(text.toString());
- ArrayList props = new ArrayList();
- Importer.PropInfo prop =
- new Importer.PropInfo(JCR_XMLCHARACTERS,
- PropertyType.STRING, values);
- props.add(prop);
- // call Importer
- importer.startNode(node, props, nsContext);
- importer.endNode(node);
- } catch (RepositoryException re) {
- throw new SAXException(re);
- }
+ try {
+ Importer.NodeInfo node =
+ new Importer.NodeInfo(JCR_XMLTEXT, null, null, null);
+ Importer.TextValue[] values = new Importer.TextValue[]{text};
+ ArrayList props = new ArrayList();
+ Importer.PropInfo prop =
+ new Importer.PropInfo(JCR_XMLCHARACTERS,
+ PropertyType.STRING, values);
+ props.add(prop);
+ // call Importer
+ importer.startNode(node, props, nsContext);
+ importer.endNode(node);
+ } catch (RepositoryException re) {
+ throw new SAXException(re);
}
}
@@ -113,11 +110,12 @@
public void startElement(String namespaceURI, String localName,
String qName, Attributes atts)
throws SAXException {
- if (text.length() > 0) {
+ if (textHandler != null && textHandler.length() > 0) {
// there is character data that needs to be added to the current node
- onTextNode(text.toString());
- // reset buffer
- text.setLength(0);
+ onTextNode(textHandler);
+ // reset handler
+ textHandler.dispose();
+ textHandler = null;
}
try {
@@ -162,7 +160,7 @@
// value(s)
String attrValue = atts.getValue(i);
- InternalValue[] propValues;
+ Importer.TextValue[] propValues;
/*
// @todo should attribute value be interpreted as LIST type (i.e. multi-valued property)?
String[] strings = Text.explode(attrValue, ' ', true);
@@ -200,19 +198,19 @@
uuid = attrValue;
}
} else {
- propValues = new InternalValue[1];
- propValues[0] = InternalValue.create(atts.getValue(i));
+ propValues = new Importer.TextValue[1];
+ propValues[0] = new StringValue(atts.getValue(i));
props.add(new Importer.PropInfo(propName,
PropertyType.UNDEFINED, propValues));
}
}
- Importer.NodeInfo nodeInfo =
+ Importer.NodeInfo node =
new Importer.NodeInfo(nodeName, nodeTypeName, mixinTypes, uuid);
// all information has been collected, now delegate to importer
- importer.startNode(nodeInfo, props, nsContext);
+ importer.startNode(node, props, nsContext);
// push current node data onto stack
- stack.push(nodeInfo);
+ stack.push(node);
} catch (RepositoryException re) {
throw new SAXException(re);
}
@@ -221,23 +219,29 @@
/**
* {@inheritDoc}
*/
- public void characters(char[] ch, int start, int length) throws SAXException {
+ public void characters(char[] ch, int start, int length)
+ throws SAXException {
/**
* buffer character data; will be processed
* in endElement and startElement method
*/
- text.append(ch, start, length);
+ if (textHandler == null) {
+ textHandler = new StringBufferValue();
+ }
+ textHandler.append(ch, start, length);
}
/**
* {@inheritDoc}
*/
- public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
- if (text.length() > 0) {
+ public void endElement(String namespaceURI, String localName, String qName)
+ throws SAXException {
+ if (textHandler != null && textHandler.length() > 0) {
// there is character data that needs to be added to the current node
- onTextNode(text.toString());
- // reset buffer
- text.setLength(0);
+ onTextNode(textHandler);
+ // reset handler
+ textHandler.dispose();
+ textHandler = null;
}
Importer.NodeInfo node = (Importer.NodeInfo) stack.peek();
try {
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/ImportHandler.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/ImportHandler.java?view=diff&r1=160071&r2=160072
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/ImportHandler.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/ImportHandler.java Mon Apr 4 10:55:20 2005
@@ -270,6 +270,9 @@
}
//--------------------------------------------------------< inner classes >
+ /**
+ * <code>NamespaceContext</code> supports scoped namespace declarations.
+ */
class NamespaceContext implements NamespaceResolver {
private final NamespaceSupport nsContext;
@@ -347,6 +350,5 @@
}
return prefix;
}
-
}
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/Importer.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/Importer.java?view=diff&r1=160071&r2=160072
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/Importer.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/Importer.java Mon Apr 4 10:55:20 2005
@@ -16,12 +16,13 @@
*/
package org.apache.jackrabbit.core.xml;
-import org.apache.jackrabbit.core.InternalValue;
import org.apache.jackrabbit.core.NamespaceResolver;
import org.apache.jackrabbit.core.QName;
import javax.jcr.RepositoryException;
import javax.jcr.Workspace;
+import java.io.IOException;
+import java.io.Reader;
import java.util.List;
/**
@@ -29,10 +30,14 @@
*/
public interface Importer {
- public static final int IMPORT_UUID_CREATE_NEW = Workspace.IMPORT_UUID_CREATE_NEW;
- public static final int IMPORT_UUID_COLLISION_REMOVE_EXISTING = Workspace.IMPORT_UUID_COLLISION_REMOVE_EXISTING;
- public static final int IMPORT_UUID_COLLISION_REPLACE_EXISTING = Workspace.IMPORT_UUID_COLLISION_REPLACE_EXISTING;
- public static final int IMPORT_UUID_COLLISION_THROW = Workspace.IMPORT_UUID_COLLISION_THROW;
+ public static final int IMPORT_UUID_CREATE_NEW =
+ Workspace.IMPORT_UUID_CREATE_NEW;
+ public static final int IMPORT_UUID_COLLISION_REMOVE_EXISTING =
+ Workspace.IMPORT_UUID_COLLISION_REMOVE_EXISTING;
+ public static final int IMPORT_UUID_COLLISION_REPLACE_EXISTING =
+ Workspace.IMPORT_UUID_COLLISION_REPLACE_EXISTING;
+ public static final int IMPORT_UUID_COLLISION_THROW =
+ Workspace.IMPORT_UUID_COLLISION_THROW;
/**
* @throws RepositoryException
@@ -113,12 +118,12 @@
public static class PropInfo {
private QName name;
private int type;
- private InternalValue[] values;
+ private TextValue[] values;
public PropInfo() {
}
- public PropInfo(QName name, int type, InternalValue[] values) {
+ public PropInfo(QName name, int type, TextValue[] values) {
this.name = name;
this.type = type;
this.values = values;
@@ -140,12 +145,48 @@
return type;
}
- public void setValues(InternalValue[] values) {
+ public void setValues(TextValue[] values) {
this.values = values;
}
- public InternalValue[] getValues() {
+ public TextValue[] getValues() {
return values;
}
+ }
+
+ /**
+ * <code>TextValue</code> represents a serialized property value read
+ * from a System or Document View XML document.
+ */
+ public interface TextValue {
+ /**
+ * Returns the length of the serialized value.
+ * @return the length of the serialized value
+ * @throws IllegalStateException if the serialized value is not
+ * available anymore (e.g. because it
+ * been discarded)
+ * @throws IOException if an I/O error occurs
+ */
+ public long length() throws IllegalStateException, IOException;
+
+ /**
+ * Retrieves the serialized value.
+ * @return the serialized value
+ * @throws IllegalStateException if the serialized value is not
+ * available anymore (e.g. because it
+ * been discarded)
+ * @throws IOException if an I/O error occurs
+ */
+ public String retrieve() throws IllegalStateException, IOException;
+
+ /**
+ * Returns a <code>Reader</code> for reading the serialized value.
+ * @return a <code>Reader</code> for reading the serialized value.
+ * @throws IllegalStateException if the serialized value is not
+ * available anymore (e.g. because it
+ * been discarded)
+ * @throws IOException if an I/O error occurs
+ */
+ public Reader reader() throws IllegalStateException, IOException;
}
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SessionImporter.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SessionImporter.java?view=diff&r1=160071&r2=160072
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SessionImporter.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SessionImporter.java Mon Apr 4 10:55:20 2005
@@ -38,6 +38,8 @@
import javax.jcr.ValueFormatException;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.NodeDef;
+import java.io.IOException;
+import java.io.Reader;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;
@@ -225,14 +227,14 @@
while (iter.hasNext()) {
PropInfo pi = (PropInfo) iter.next();
QName propName = pi.getName();
- InternalValue[] iva = pi.getValues();
+ TextValue[] tva = pi.getValues();
int type = pi.getType();
// find applicable definition
EffectiveNodeType ent = node.getEffectiveNodeType();
PropDef def;
// multi- or single-valued property?
- if (iva.length == 1) {
+ if (tva.length == 1) {
// could be single- or multi-valued (n == 1)
try {
// try single-valued
@@ -252,33 +254,66 @@
continue;
}
- // convert InternalValue objects to Value objects using this
- // session's namespace mappings
- Value[] va = new Value[iva.length];
- // check whether type conversion is required
- if (def.getRequiredType() != PropertyType.UNDEFINED
- && def.getRequiredType() != type) {
- // type doesn't match required type,
- // type conversion required
- // FIXME: awkward code
- for (int i = 0; i < iva.length; i++) {
- // convert InternalValue to Value of required type
- Value v =
- ValueHelper.convert(iva[i].toJCRValue(nsContext),
- def.getRequiredType());
- // convert Value to InternalValue using
+ // convert serialized values to Value objects
+ Value[] va = new Value[tva.length];
+ int targetType = def.getRequiredType();
+ if (targetType == PropertyType.UNDEFINED) {
+ if (type == PropertyType.UNDEFINED) {
+ targetType = PropertyType.STRING;
+ } else {
+ targetType = type;
+ }
+ }
+ for (int i = 0; i < tva.length; i++) {
+ TextValue tv = tva[i];
+
+ if (targetType == PropertyType.NAME ||
+ targetType == PropertyType.PATH) {
+ // NAME and PATH require special treatment because
+ // they depend on the current namespace context
+ // of the xml document
+
+ // retrieve serialized value
+ String serValue;
+ try {
+ serValue = tv.retrieve();
+ } catch (IOException ioe) {
+ String msg = "failed to retrieve serialized value";
+ log.debug(msg, ioe);
+ throw new RepositoryException(msg, ioe);
+ }
+
+ // convert serialized value to InternalValue using
// current namespace context of xml document
- InternalValue ival = InternalValue.create(v, nsContext);
- // convert InternalValue back to Value using this
+ InternalValue ival =
+ InternalValue.create(serValue, targetType, nsContext);
+ // convert InternalValue to Value using this
// session's namespace mappings
va[i] = ival.toJCRValue(session.getNamespaceResolver());
- }
- } else {
- // no type conversion required:
- // convert InternalValue to Value using this
- // session's namespace mappings
- for (int i = 0; i < iva.length; i++) {
- va[i] = iva[i].toJCRValue(session.getNamespaceResolver());
+ } else if (targetType == PropertyType.BINARY) {
+ // deserialize BINARY type using Reader
+ try {
+ Reader reader = tv.reader();
+ va[i] = ValueHelper.deserialize(reader, targetType, false);
+ } catch (IOException ioe) {
+ String msg = "failed to deserialize binary value";
+ log.debug(msg, ioe);
+ throw new RepositoryException(msg, ioe);
+ }
+ } else {
+ // all other types
+
+ // retrieve serialized value
+ String serValue;
+ try {
+ serValue = tv.retrieve();
+ } catch (IOException ioe) {
+ String msg = "failed to retrieve serialized value";
+ log.debug(msg, ioe);
+ throw new RepositoryException(msg, ioe);
+ }
+
+ va[i] = ValueHelper.deserialize(serValue, targetType, true);
}
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SysViewImportHandler.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SysViewImportHandler.java?view=diff&r1=160071&r2=160072
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SysViewImportHandler.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/SysViewImportHandler.java Mon Apr 4 10:55:20 2005
@@ -17,34 +17,29 @@
package org.apache.jackrabbit.core.xml;
import org.apache.jackrabbit.core.BaseException;
-import org.apache.jackrabbit.core.Constants;
import org.apache.jackrabbit.core.IllegalNameException;
-import org.apache.jackrabbit.core.InternalValue;
import org.apache.jackrabbit.core.NamespaceResolver;
import org.apache.jackrabbit.core.QName;
import org.apache.jackrabbit.core.UnknownPrefixException;
-import org.apache.jackrabbit.core.util.ValueHelper;
import org.apache.log4j.Logger;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
import javax.jcr.InvalidSerializedDataException;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
+import java.io.IOException;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.Stack;
/**
* <code>SysViewImportHandler</code> ...
*/
-class SysViewImportHandler extends DefaultHandler implements Constants {
+class SysViewImportHandler extends TargetImportHandler {
private static Logger log = Logger.getLogger(SysViewImportHandler.class);
- private final Importer importer;
- private final NamespaceResolver nsContext;
-
/**
* stack of ImportState instances; an instance is pushed onto the stack
* in the startElement method every time a sv:node element is encountered;
@@ -58,12 +53,18 @@
*/
private QName currentPropName;
private int currentPropType = PropertyType.UNDEFINED;
+ // list of AppendableValue objects
private ArrayList currentPropValues = new ArrayList();
- private StringBuffer currentPropValue;
+ private AppendableValue currentPropValue;
+ /**
+ * Constructs a new <code>SysViewImportHandler</code>.
+ *
+ * @param importer
+ * @param nsContext
+ */
SysViewImportHandler(Importer importer, NamespaceResolver nsContext) {
- this.importer = importer;
- this.nsContext = nsContext;
+ super(importer, nsContext);
}
private void processNode(ImportState state, boolean start, boolean end)
@@ -83,6 +84,12 @@
try {
if (start) {
importer.startNode(node, state.props, nsContext);
+ // dispose temporary property values
+ for (Iterator iter = state.props.iterator(); iter.hasNext();) {
+ Importer.PropInfo pi = (Importer.PropInfo) iter.next();
+ disposePropertyValues(pi);
+ }
+
}
if (end) {
importer.endNode(node);
@@ -135,11 +142,7 @@
// sv:node element
// node name (value of sv:name attribute)
- String name = atts.getValue(SysViewSAXEventGenerator.NS_SV_URI, SysViewSAXEventGenerator.NAME_ATTRIBUTE);
- if (name == null) {
- // try qualified name
- name = atts.getValue(SysViewSAXEventGenerator.NS_SV_PREFIX + ":" + SysViewSAXEventGenerator.NAME_ATTRIBUTE);
- }
+ String name = atts.getValue(SysViewSAXEventGenerator.PREFIXED_NAME_ATTRIBUTE);
if (name == null) {
throw new SAXException(new InvalidSerializedDataException("missing mandatory sv:name attributeof element sv:node"));
}
@@ -171,11 +174,7 @@
currentPropValues.clear();
// property name (value of sv:name attribute)
- String name = atts.getValue(SysViewSAXEventGenerator.NS_SV_URI, SysViewSAXEventGenerator.NAME_ATTRIBUTE);
- if (name == null) {
- // try qualified name
- name = atts.getValue(SysViewSAXEventGenerator.NS_SV_PREFIX + ":" + SysViewSAXEventGenerator.NAME_ATTRIBUTE);
- }
+ String name = atts.getValue(SysViewSAXEventGenerator.PREFIXED_NAME_ATTRIBUTE);
if (name == null) {
throw new SAXException(new InvalidSerializedDataException("missing mandatory sv:name attributeof element sv:property"));
}
@@ -187,11 +186,7 @@
throw new SAXException(new InvalidSerializedDataException("illegal property name: " + name, upe));
}
// property type (sv:type attribute)
- String type = atts.getValue(SysViewSAXEventGenerator.NS_SV_URI, SysViewSAXEventGenerator.TYPE_ATTRIBUTE);
- if (type == null) {
- // try qualified name
- type = atts.getValue(SysViewSAXEventGenerator.NS_SV_PREFIX + ":" + SysViewSAXEventGenerator.TYPE_ATTRIBUTE);
- }
+ String type = atts.getValue(SysViewSAXEventGenerator.PREFIXED_TYPE_ATTRIBUTE);
if (type == null) {
throw new SAXException(new InvalidSerializedDataException("missing mandatory sv:type attributeof element sv:property"));
}
@@ -200,7 +195,18 @@
// sv:value element
// reset temp fields
- currentPropValue = new StringBuffer();
+ if (currentPropType == PropertyType.BINARY) {
+ // binary value; use temp-file backed value appender
+ try {
+ currentPropValue = new CLOBValue();
+ } catch (IOException ioe) {
+ throw new SAXException("error while processing property value",
+ ioe);
+ }
+ } else {
+ // 'normal' value; use StringBuffer-backed value appender
+ currentPropValue = new StringBufferValue();
+ }
} else {
throw new SAXException(new InvalidSerializedDataException("unexpected element found in system view xml document: " + elemName));
}
@@ -209,103 +215,112 @@
/**
* {@inheritDoc}
*/
- public void characters(char[] ch, int start, int length) throws SAXException {
+ public void characters(char[] ch, int start, int length)
+ throws SAXException {
if (currentPropValue != null) {
// property value (character data of sv:value element)
- currentPropValue.append(ch, start, length);
+ try {
+ currentPropValue.append(ch, start, length);
+ } catch (IOException ioe) {
+ throw new SAXException("error while processing property value",
+ ioe);
+ }
}
}
/**
* {@inheritDoc}
*/
- public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
- try {
- String elemName;
- if (localName != null && !"".equals(localName)) {
- elemName = localName;
+ public void endElement(String namespaceURI, String localName, String qName)
+ throws SAXException {
+ String elemName;
+ if (localName != null && !"".equals(localName)) {
+ elemName = localName;
+ } else {
+ try {
+ elemName = QName.fromJCRName(qName, nsContext).getLocalName();
+ } catch (BaseException e) {
+ // should never happen...
+ String msg = "internal error: failed to parse/resolve element name " + qName;
+ log.debug(msg);
+ throw new SAXException(msg, e);
+ }
+ }
+ // check element name
+ ImportState state = (ImportState) stack.peek();
+ if (SysViewSAXEventGenerator.NODE_ELEMENT.equals(elemName)) {
+ // sv:node element
+ if (!state.started) {
+ // need to start & end current node
+ processNode(state, true, true);
+ state.started = true;
} else {
+ // need to end current node
+ processNode(state, false, true);
+ }
+ // pop current state from stack
+ stack.pop();
+ } else if (SysViewSAXEventGenerator.PROPERTY_ELEMENT.equals(elemName)) {
+ // sv:property element
+
+ // check if all system properties (jcr:primaryType, jcr:uuid etc.)
+ // have been collected and create node as necessary
+ if (currentPropName.equals(JCR_PRIMARYTYPE)) {
+ AppendableValue val = (AppendableValue) currentPropValues.get(0);
+ String s = null;
try {
- elemName = QName.fromJCRName(qName, nsContext).getLocalName();
- } catch (BaseException e) {
- // should never happen...
- String msg = "internal error: failed to parse/resolve element name " + qName;
- log.debug(msg);
- throw new SAXException(msg, e);
+ s = val.retrieve();
+ state.nodeTypeName = QName.fromJCRName(s, nsContext);
+ } catch (IOException ioe) {
+ throw new SAXException("error while retrieving value", ioe);
+ } catch (IllegalNameException ine) {
+ throw new SAXException(new InvalidSerializedDataException("illegal node type name: " + s, ine));
+ } catch (UnknownPrefixException upe) {
+ throw new SAXException(new InvalidSerializedDataException("illegal node type name: " + s, upe));
}
- }
- // check element name
- ImportState state = (ImportState) stack.peek();
- if (SysViewSAXEventGenerator.NODE_ELEMENT.equals(elemName)) {
- // sv:node element
- if (!state.started) {
- // need to start & end current node
- processNode(state, true, true);
- state.started = true;
- } else {
- // need to end current node
- processNode(state, false, true);
+ } else if (currentPropName.equals(JCR_MIXINTYPES)) {
+ if (state.mixinNames == null) {
+ state.mixinNames = new ArrayList(currentPropValues.size());
}
- // pop current state from stack
- stack.pop();
- } else if (SysViewSAXEventGenerator.PROPERTY_ELEMENT.equals(elemName)) {
- // sv:property element
-
- // check if all system properties (jcr:primaryType, jcr:uuid etc.)
- // have been collected and create node as necessary
- if (currentPropName.equals(JCR_PRIMARYTYPE)) {
+ for (int i = 0; i < currentPropValues.size(); i++) {
+ AppendableValue val = (AppendableValue) currentPropValues.get(0);
+ String s = null;
try {
- state.nodeTypeName = QName.fromJCRName((String) currentPropValues.get(0), nsContext);
+ s = val.retrieve();
+ QName mixin = QName.fromJCRName(s, nsContext);
+ state.mixinNames.add(mixin);
+ } catch (IOException ioe) {
+ throw new SAXException("error while retrieving value", ioe);
} catch (IllegalNameException ine) {
- throw new SAXException(new InvalidSerializedDataException("illegal node type name: " + currentPropValues.get(0), ine));
+ throw new SAXException(new InvalidSerializedDataException("illegal mixin type name: " + s, ine));
} catch (UnknownPrefixException upe) {
- throw new SAXException(new InvalidSerializedDataException("illegal node type name: " + currentPropValues.get(0), upe));
- }
- } else if (currentPropName.equals(JCR_MIXINTYPES)) {
- if (state.mixinNames == null) {
- state.mixinNames = new ArrayList(currentPropValues.size());
- }
- for (int i = 0; i < currentPropValues.size(); i++) {
- try {
- QName mixin = QName.fromJCRName((String) currentPropValues.get(i), nsContext);
- state.mixinNames.add(mixin);
- } catch (IllegalNameException ine) {
- throw new SAXException(new InvalidSerializedDataException("illegal mixin type name: " + currentPropValues.get(i), ine));
- } catch (UnknownPrefixException upe) {
- throw new SAXException(new InvalidSerializedDataException("illegal mixin type name: " + currentPropValues.get(i), upe));
- }
+ throw new SAXException(new InvalidSerializedDataException("illegal mixin type name: " + s, upe));
}
- } else if (currentPropName.equals(JCR_UUID)) {
- state.uuid = (String) currentPropValues.get(0);
- } else {
- // convert values to native type
- InternalValue[] vals = new InternalValue[currentPropValues.size()];
- for (int i = 0; i < currentPropValues.size(); i++) {
- String value = (String) currentPropValues.get(i);
- vals[i] = InternalValue.create(
- ValueHelper.deserialize(value, currentPropType,
- false), nsContext);
- }
- Importer.PropInfo prop = new Importer.PropInfo();
- prop.setName(currentPropName);
- prop.setType(currentPropType);
- prop.setValues(vals);
-
- state.props.add(prop);
}
-
- // reset temp fields
- currentPropValues.clear();
- } else if (SysViewSAXEventGenerator.VALUE_ELEMENT.equals(elemName)) {
- // sv:value element
- currentPropValues.add(currentPropValue.toString());
- // reset temp fields
- currentPropValue = null;
+ } else if (currentPropName.equals(JCR_UUID)) {
+ AppendableValue val = (AppendableValue) currentPropValues.get(0);
+ try {
+ state.uuid = val.retrieve();
+ } catch (IOException ioe) {
+ throw new SAXException("error while retrieving value", ioe);
+ }
} else {
- throw new SAXException(new InvalidSerializedDataException("invalid element in system view xml document: " + elemName));
+ Importer.PropInfo prop = new Importer.PropInfo();
+ prop.setName(currentPropName);
+ prop.setType(currentPropType);
+ prop.setValues((Importer.TextValue[])
+ currentPropValues.toArray(new Importer.TextValue[currentPropValues.size()]));
+ state.props.add(prop);
}
- } catch (RepositoryException re) {
- throw new SAXException(re);
+ // reset temp fields
+ currentPropValues.clear();
+ } else if (SysViewSAXEventGenerator.VALUE_ELEMENT.equals(elemName)) {
+ // sv:value element
+ currentPropValues.add(currentPropValue);
+ // reset temp fields
+ currentPropValue = null;
+ } else {
+ throw new SAXException(new InvalidSerializedDataException("invalid element in system view xml document: " + elemName));
}
}
Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/TargetImportHandler.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/TargetImportHandler.java?view=auto&rev=160072
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/TargetImportHandler.java (added)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/TargetImportHandler.java Mon Apr 4 10:55:20 2005
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.xml;
+
+import org.apache.jackrabbit.core.Constants;
+import org.apache.jackrabbit.core.NamespaceResolver;
+import org.apache.log4j.Logger;
+import org.xml.sax.helpers.DefaultHandler;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.Writer;
+
+/**
+ * <code>TargetImportHandler</code> serves as the base class for the concrete
+ * classes <code>{@link DocViewImportHandler}</code> and
+ * <code>{@link SysViewImportHandler}</code>.
+ */
+abstract class TargetImportHandler extends DefaultHandler implements Constants {
+
+ private static Logger log = Logger.getLogger(TargetImportHandler.class);
+
+ protected final Importer importer;
+ protected final NamespaceResolver nsContext;
+
+ protected TargetImportHandler(Importer importer,
+ NamespaceResolver nsContext) {
+ this.importer = importer;
+ this.nsContext = nsContext;
+ }
+
+ protected void disposePropertyValues(Importer.PropInfo prop) {
+ Importer.TextValue[] vals = prop.getValues();
+ for (int i = 0; i < vals.length; i++) {
+ if (vals[i] instanceof AppendableValue) {
+ try {
+ ((AppendableValue) vals[i]).dispose();
+ } catch (IOException ioe) {
+ log.warn("error while disposing temporary value appender",
+ ioe);
+ }
+ }
+ }
+ }
+
+ //--------------------------------------------------------< inner classes >
+ /**
+ * <code>AppendableValue</code> represents a serialized value that is
+ * appendable.
+ */
+ public interface AppendableValue extends Importer.TextValue {
+ public void append(char[] chars, int start, int length)
+ throws IllegalStateException, IOException;
+
+ /**
+ * @throws IOException
+ */
+ public void close() throws IOException;
+
+ /**
+ * @throws IOException
+ */
+ public void dispose() throws IOException;
+ }
+
+ /**
+ * <code>StringValue</code> represents an immutable serialized value.
+ */
+ protected class StringValue implements Importer.TextValue {
+
+ private final String value;
+
+ /**
+ * Constructs a new <code>StringValue</code> representing the given
+ * value.
+ *
+ * @param value
+ */
+ protected StringValue(String value) {
+ this.value = value;
+ }
+
+ //--------------------------------------------------------< TextValue >
+ /**
+ * {@inheritDoc}
+ */
+ public long length() {
+ return value.length();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String retrieve() {
+ return value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Reader reader() {
+ return new StringReader(value);
+ }
+ }
+
+ /**
+ * <code>StringBufferValue</code> represents an appendable serialized value
+ * that is internally backed by a <code>StringBuffer</code>.
+ */
+ protected class StringBufferValue implements AppendableValue {
+
+ private final StringBuffer buffer;
+
+ /**
+ * Constructs a new empty <code>StringBufferValue</code>.
+ */
+ protected StringBufferValue() {
+ buffer = new StringBuffer();
+ }
+
+ //--------------------------------------------------------< TextValue >
+ /**
+ * {@inheritDoc}
+ */
+ public long length() {
+ return buffer.length();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String retrieve() {
+ return buffer.toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Reader reader() {
+ return new StringReader(buffer.toString());
+ }
+
+ //--------------------------------------------------< AppendableValue >
+ /**
+ * {@inheritDoc}
+ */
+ public void append(char[] chars, int start, int length) {
+ buffer.append(chars, start, length);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void close() {
+ // nop
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void dispose() {
+ buffer.setLength(0);
+ }
+ }
+
+ /**
+ * <code>CLOBValue</code> represents an appendable serialized value
+ * that is internally backed by a temporary file.
+ */
+ protected class CLOBValue implements AppendableValue {
+
+ private File tmpFile;
+ private Writer writer;
+
+ protected CLOBValue() throws IOException {
+ tmpFile = File.createTempFile("bin", null);
+ writer = new FileWriter(tmpFile);
+ }
+
+ //--------------------------------------------------------< TextValue >
+ /**
+ * {@inheritDoc}
+ */
+ public long length() throws IllegalStateException, IOException {
+ if (tmpFile == null) {
+ throw new IllegalStateException();
+ }
+ return tmpFile.length();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String retrieve() throws IllegalStateException, IOException {
+ Reader reader = reader();
+ char[] chunk = new char[8192];
+ int read;
+ StringBuffer buf = new StringBuffer();
+ while ((read = reader.read(chunk)) > -1) {
+ buf.append(chunk, 0, read);
+ }
+ return buf.toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Reader reader() throws IllegalStateException, IOException {
+ if (tmpFile == null) {
+ throw new IllegalStateException();
+ }
+ return new FileReader(tmpFile);
+ }
+
+ //--------------------------------------------------< AppendableValue >
+ /**
+ * {@inheritDoc}
+ */
+ public void append(char[] chars, int start, int length)
+ throws IllegalStateException, IOException {
+ if (writer == null) {
+ throw new IllegalStateException();
+ }
+ writer.write(chars, start, length);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void close() throws IOException {
+ if (writer != null) {
+ writer.close();
+ writer = null;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void dispose() throws IOException {
+ close();
+ if (tmpFile != null) {
+ tmpFile.delete();
+ tmpFile = null;
+ }
+ }
+ }
+}
Propchange: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/TargetImportHandler.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/WorkspaceImporter.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/WorkspaceImporter.java?view=diff&r1=160071&r2=160072
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/WorkspaceImporter.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/xml/WorkspaceImporter.java Mon Apr 4 10:55:20 2005
@@ -40,16 +40,18 @@
import org.apache.jackrabbit.core.state.NodeState;
import org.apache.jackrabbit.core.state.PropertyState;
import org.apache.jackrabbit.core.state.UpdatableItemStateManager;
+import org.apache.jackrabbit.core.util.Base64;
import org.apache.jackrabbit.core.util.ReferenceChangeTracker;
-import org.apache.jackrabbit.core.util.ValueHelper;
import org.apache.jackrabbit.core.util.uuid.UUID;
import org.apache.log4j.Logger;
import javax.jcr.ItemExistsException;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
-import javax.jcr.Value;
import javax.jcr.nodetype.ConstraintViolationException;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
@@ -178,7 +180,7 @@
String msg = "an applicable node type could not be determined for "
+ nodeName;
log.debug(msg);
- throw new ConstraintViolationException (msg);
+ throw new ConstraintViolationException(msg);
}
}
NodeState node = stateMgr.createNew(uuid, nodeTypeName, parent.getUUID());
@@ -709,7 +711,7 @@
while (iter.hasNext()) {
PropInfo pi = (PropInfo) iter.next();
QName propName = pi.getName();
- InternalValue[] vals = pi.getValues();
+ TextValue[] tva = pi.getValues();
int type = pi.getType();
PropertyState prop = null;
@@ -742,7 +744,7 @@
// find applicable definition
// multi- or single-valued property?
- if (vals.length == 1) {
+ if (tva.length == 1) {
// could be single- or multi-valued (n == 1)
try {
// try single-valued
@@ -770,29 +772,80 @@
}
// check multi-valued characteristic
- if ((vals.length == 0 || vals.length > 1) && !def.isMultiple()) {
+ if ((tva.length == 0 || tva.length > 1) && !def.isMultiple()) {
throw new ConstraintViolationException(resolveJCRPath(prop.getId())
+ " is not multi-valued");
}
- // check whether type conversion is required
- if (def.getRequiredType() != PropertyType.UNDEFINED
- && def.getRequiredType() != type) {
- // type doesn't match required type,
- // type conversion required
- for (int i = 0; i < vals.length; i++) {
- // convert InternalValue to Value of required type
- Value v =
- ValueHelper.convert(vals[i].toJCRValue(nsContext),
- def.getRequiredType());
- // convert Value to InternalValue using
+ // convert serialized values to InternalValue objects
+ InternalValue[] iva = new InternalValue[tva.length];
+ int targetType = def.getRequiredType();
+ if (targetType == PropertyType.UNDEFINED) {
+ if (type == PropertyType.UNDEFINED) {
+ targetType = PropertyType.STRING;
+ } else {
+ targetType = type;
+ }
+ }
+ for (int i = 0; i < tva.length; i++) {
+ TextValue tv = tva[i];
+ if (targetType == PropertyType.BINARY) {
+ // base64 encoded BINARY type;
+ // decode using Reader
+/*
+ // @todo decode to temp file and pass FileInputStream to InternalValue factory method
+ File tmpFile = null;
+ try {
+ tmpFile = File.createTempFile("bin", null);
+ FileOutputStream out = new FileOutputStream(tmpFile);
+ Base64.decode(tv.reader(), out);
+ out.close();
+ iva[i] = InternalValue.create(new FileInputStream(tmpFile));
+ } catch (IOException ioe) {
+ String msg = "failed to decode binary value";
+ log.debug(msg, ioe);
+ throw new RepositoryException(msg, ioe);
+ } finally {
+ // the temp file can be deleted because
+ // the InternalValue instance has spooled
+ // its contents
+ if (tmpFile != null) {
+ tmpFile.delete();
+ }
+ }
+*/
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try {
+ Base64.decode(tv.reader(), baos);
+ // no need to close ByteArrayOutputStream
+ //baos.close();
+ iva[i] = InternalValue.create(new ByteArrayInputStream(baos.toByteArray()));
+ } catch (IOException ioe) {
+ String msg = "failed to decode binary value";
+ log.debug(msg, ioe);
+ throw new RepositoryException(msg, ioe);
+ }
+ } else {
+ // retrieve serialized value
+ String serValue;
+ try {
+ serValue = tv.retrieve();
+ } catch (IOException ioe) {
+ String msg = "failed to retrieve serialized value";
+ log.debug(msg, ioe);
+ throw new RepositoryException(msg, ioe);
+ }
+
+ // convert serialized value to InternalValue using
// current namespace context of xml document
- vals[i] = InternalValue.create(v, nsContext);
+ iva[i] = InternalValue.create(serValue, targetType,
+ nsContext);
}
+
}
// set values
- prop.setValues(vals);
+ prop.setValues(iva);
// make sure node is valid according to its definition
wsp.validate(prop);