mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
- Incorporate JCR project into Repository project
- Single configuration entry point for JCR and non-JCR clients (i.e. application-context.xml) - Addition of build-war, incremental-war build targets (no deploy) - Remove build of JCR TCK war file by default git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2777 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
78
source/java/org/alfresco/jcr/importer/ImportTest.java
Normal file
78
source/java/org/alfresco/jcr/importer/ImportTest.java
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* 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.alfresco.jcr.importer;
|
||||
|
||||
import javax.jcr.ImportUUIDBehavior;
|
||||
import javax.jcr.RepositoryException;
|
||||
import javax.jcr.Session;
|
||||
import javax.jcr.SimpleCredentials;
|
||||
|
||||
import org.alfresco.jcr.test.BaseJCRTest;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
|
||||
public class ImportTest extends BaseJCRTest
|
||||
{
|
||||
protected Session superuserSession;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception
|
||||
{
|
||||
super.setUp();
|
||||
|
||||
SimpleCredentials superuser = new SimpleCredentials("superuser", "".toCharArray());
|
||||
superuserSession = repository.login(superuser, getWorkspace());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception
|
||||
{
|
||||
super.tearDown();
|
||||
superuserSession.logout();
|
||||
}
|
||||
|
||||
public void testSysImport()
|
||||
throws Exception
|
||||
{
|
||||
ClassPathResource sysview = new ClassPathResource("org/alfresco/jcr/test/sysview.xml");
|
||||
superuserSession.importXML("/testroot", sysview.getInputStream(), ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
|
||||
}
|
||||
|
||||
public void testDocImport()
|
||||
throws Exception
|
||||
{
|
||||
ClassPathResource sysview = new ClassPathResource("org/alfresco/jcr/test/docview.xml");
|
||||
superuserSession.importXML("/testroot", sysview.getInputStream(), ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
|
||||
}
|
||||
|
||||
public void testThrowCollision()
|
||||
throws Exception
|
||||
{
|
||||
ClassPathResource sysview = new ClassPathResource("org/alfresco/jcr/test/docview.xml");
|
||||
superuserSession.importXML("/testroot", sysview.getInputStream(), ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING);
|
||||
|
||||
try
|
||||
{
|
||||
superuserSession.importXML("/testroot", sysview.getInputStream(), ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW);
|
||||
fail("Failed to catch UUID collision");
|
||||
}
|
||||
catch(RepositoryException e)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
}
|
396
source/java/org/alfresco/jcr/importer/JCRDocXMLHandler.java
Normal file
396
source/java/org/alfresco/jcr/importer/JCRDocXMLHandler.java
Normal file
@@ -0,0 +1,396 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* 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.alfresco.jcr.importer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
import javax.jcr.InvalidSerializedDataException;
|
||||
|
||||
import org.alfresco.jcr.dictionary.JCRNamespace;
|
||||
import org.alfresco.jcr.item.property.JCRMixinTypesProperty;
|
||||
import org.alfresco.jcr.item.property.JCRPrimaryTypeProperty;
|
||||
import org.alfresco.jcr.item.property.JCRUUIDProperty;
|
||||
import org.alfresco.jcr.session.SessionImpl;
|
||||
import org.alfresco.repo.importer.ImportContentHandler;
|
||||
import org.alfresco.repo.importer.Importer;
|
||||
import org.alfresco.repo.importer.view.ElementContext;
|
||||
import org.alfresco.repo.importer.view.NodeContext;
|
||||
import org.alfresco.repo.importer.view.ParentContext;
|
||||
import org.alfresco.service.cmr.dictionary.AspectDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.dictionary.InvalidTypeException;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||
import org.alfresco.service.cmr.view.ImporterException;
|
||||
import org.alfresco.service.namespace.NamespacePrefixResolver;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.Base64;
|
||||
import org.alfresco.util.ISO9075;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXParseException;
|
||||
|
||||
|
||||
/**
|
||||
* Alfresco implementation of a Doc View Import Content Handler
|
||||
*
|
||||
* @author David Caruana
|
||||
*/
|
||||
public class JCRDocXMLHandler implements ImportContentHandler
|
||||
{
|
||||
private Importer importer;
|
||||
private SessionImpl session;
|
||||
private DictionaryService dictionaryService;
|
||||
private NamespacePrefixResolver importResolver;
|
||||
private Stack<ElementContext> contextStack = new Stack<ElementContext>();
|
||||
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param session JCR Session
|
||||
* @param importResolver Namespace Resolver for the Import
|
||||
*/
|
||||
public JCRDocXMLHandler(SessionImpl session, NamespacePrefixResolver importResolver)
|
||||
{
|
||||
this.session = session;
|
||||
this.importResolver = importResolver;
|
||||
this.dictionaryService = session.getRepositoryImpl().getServiceRegistry().getDictionaryService();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.alfresco.repo.importer.ImportContentHandler#setImporter(org.alfresco.repo.importer.Importer)
|
||||
*/
|
||||
public void setImporter(Importer importer)
|
||||
{
|
||||
this.importer = importer;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.alfresco.repo.importer.ImportContentHandler#importStream(java.lang.String)
|
||||
*/
|
||||
public InputStream importStream(String content)
|
||||
{
|
||||
File contentFile = new File(content);
|
||||
try
|
||||
{
|
||||
FileInputStream contentStream = new FileInputStream(contentFile);
|
||||
return new Base64.InputStream(contentStream, Base64.DECODE | Base64.DONT_BREAK_LINES);
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
throw new ImporterException("Failed to retrieve import input stream on temporary content file " + content);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator)
|
||||
*/
|
||||
public void setDocumentLocator(Locator locator)
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#startDocument()
|
||||
*/
|
||||
public void startDocument() throws SAXException
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#endDocument()
|
||||
*/
|
||||
public void endDocument() throws SAXException
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, java.lang.String)
|
||||
*/
|
||||
public void startPrefixMapping(String prefix, String uri) throws SAXException
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#endPrefixMapping(java.lang.String)
|
||||
*/
|
||||
public void endPrefixMapping(String prefix) throws SAXException
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
|
||||
*/
|
||||
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException
|
||||
{
|
||||
try
|
||||
{
|
||||
// construct qname for element
|
||||
QName elementName = decodeQName(QName.createQName(qName, importResolver));
|
||||
|
||||
// setup parent context
|
||||
ParentContext parentContext = null;
|
||||
if (contextStack.empty())
|
||||
{
|
||||
// create root parent context
|
||||
parentContext = new ParentContext(elementName, dictionaryService, importer);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create parent context
|
||||
NodeContext parentNode = (NodeContext)contextStack.peek();
|
||||
parentContext = new ParentContext(elementName, parentNode);
|
||||
}
|
||||
|
||||
// create node context
|
||||
NodeContext node = new NodeContext(elementName, parentContext, null);
|
||||
node.setChildName(elementName.toPrefixString(importResolver));
|
||||
contextStack.push(node);
|
||||
|
||||
// process node properties
|
||||
for (int i = 0; i < atts.getLength(); i++)
|
||||
{
|
||||
QName propName = decodeQName(QName.createQName(atts.getURI(i), atts.getLocalName(i)));
|
||||
String value = atts.getValue(i);
|
||||
|
||||
//
|
||||
// process "well-known" properties
|
||||
//
|
||||
|
||||
if (propName.equals(JCRPrimaryTypeProperty.PROPERTY_NAME))
|
||||
{
|
||||
// primary type
|
||||
QName primaryTypeQName = QName.createQName(value, importResolver);
|
||||
TypeDefinition typeDef = dictionaryService.getType(primaryTypeQName);
|
||||
if (typeDef == null)
|
||||
{
|
||||
throw new InvalidTypeException(primaryTypeQName);
|
||||
}
|
||||
node.setTypeDefinition(typeDef);
|
||||
}
|
||||
else if (propName.equals(JCRMixinTypesProperty.PROPERTY_NAME))
|
||||
{
|
||||
// aspects
|
||||
String[] aspects = value.split(" ");
|
||||
for (String aspect : aspects)
|
||||
{
|
||||
// ignore JCR specific aspects
|
||||
QName aspectQName = QName.createQName(aspect, importResolver);
|
||||
if (!(JCRNamespace.JCR_URI.equals(aspectQName.getNamespaceURI()) ||
|
||||
JCRNamespace.MIX_URI.equals(aspectQName.getNamespaceURI())))
|
||||
{
|
||||
AspectDefinition aspectDef = dictionaryService.getAspect(aspectQName);
|
||||
if (aspectDef == null)
|
||||
{
|
||||
throw new InvalidTypeException(aspectQName);
|
||||
}
|
||||
node.addAspect(aspectDef);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (JCRUUIDProperty.PROPERTY_NAME.equals(propName))
|
||||
{
|
||||
node.setUUID(value);
|
||||
}
|
||||
|
||||
//
|
||||
// Note: ignore JCR specific properties
|
||||
//
|
||||
|
||||
else if (JCRNamespace.JCR_URI.equals(propName.getNamespaceURI()))
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// process all other properties
|
||||
//
|
||||
|
||||
else
|
||||
{
|
||||
// determine type of property
|
||||
PropertyDefinition propDef = dictionaryService.getProperty(propName);
|
||||
if (propDef == null)
|
||||
{
|
||||
throw new ImporterException("Property " + propName + " is not known to the repository data dictionary");
|
||||
}
|
||||
DataTypeDefinition dataTypeDef = propDef.getDataType();
|
||||
|
||||
// extract values from node xml attribute
|
||||
String[] propValues = null;
|
||||
PropertyContext propertyContext = new PropertyContext(elementName, node, propName, dataTypeDef.getName());
|
||||
if (dataTypeDef.getName().equals(DataTypeDefinition.CONTENT))
|
||||
{
|
||||
// Note: we only support single valued content properties
|
||||
propValues = new String[] { value };
|
||||
}
|
||||
else
|
||||
{
|
||||
// attempt to split multi-value properties
|
||||
propValues = value.split(" ");
|
||||
}
|
||||
|
||||
// extract values appropriately
|
||||
for (String propValue : propValues)
|
||||
{
|
||||
propertyContext.startValue();
|
||||
propertyContext.appendCharacters(propValue.toCharArray(), 0, propValue.length());
|
||||
propertyContext.endValue();
|
||||
}
|
||||
|
||||
// add each value to the node
|
||||
if (propertyContext.isMultiValue())
|
||||
{
|
||||
node.addPropertyCollection(propName);
|
||||
}
|
||||
List<StringBuffer> nodeValues = propertyContext.getValues();
|
||||
for (StringBuffer nodeValue : nodeValues)
|
||||
{
|
||||
// first, cast value to appropriate type (using JCR converters)
|
||||
Serializable objVal = (Serializable)session.getTypeConverter().convert(dataTypeDef, nodeValue.toString());
|
||||
String strValue = DefaultTypeConverter.INSTANCE.convert(String.class, objVal);
|
||||
node.addProperty(propName, strValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// import node
|
||||
NodeRef nodeRef = node.getImporter().importNode(node);
|
||||
node.setNodeRef(nodeRef);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new SAXException("Failed to process element " + qName, e);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
|
||||
*/
|
||||
public void endElement(String uri, String localName, String qName) throws SAXException
|
||||
{
|
||||
try
|
||||
{
|
||||
// ensure context matches parse
|
||||
ElementContext context = (ElementContext)contextStack.pop();
|
||||
QName elementName = QName.createQName(qName, importResolver);
|
||||
if (!context.getElementName().equals(elementName))
|
||||
{
|
||||
throw new InvalidSerializedDataException("Expected element " + context.getElementName() + " but was " + elementName);
|
||||
}
|
||||
|
||||
// signal end of node
|
||||
NodeContext nodeContext = (NodeContext)context;
|
||||
nodeContext.getImporter().childrenImported(nodeContext.getNodeRef());
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new SAXException("Failed to process element " + qName, e);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#characters(char[], int, int)
|
||||
*/
|
||||
public void characters(char[] ch, int start, int length) throws SAXException
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int)
|
||||
*/
|
||||
public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#processingInstruction(java.lang.String, java.lang.String)
|
||||
*/
|
||||
public void processingInstruction(String target, String data) throws SAXException
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#skippedEntity(java.lang.String)
|
||||
*/
|
||||
public void skippedEntity(String name) throws SAXException
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ErrorHandler#warning(org.xml.sax.SAXParseException)
|
||||
*/
|
||||
public void warning(SAXParseException exception) throws SAXException
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ErrorHandler#error(org.xml.sax.SAXParseException)
|
||||
*/
|
||||
public void error(SAXParseException exception) throws SAXException
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ErrorHandler#fatalError(org.xml.sax.SAXParseException)
|
||||
*/
|
||||
public void fatalError(SAXParseException exception) throws SAXException
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode QName
|
||||
*
|
||||
* @param name name to decode
|
||||
* @return the decoded name
|
||||
*/
|
||||
private QName decodeQName(QName name)
|
||||
{
|
||||
return QName.createQName(name.getNamespaceURI(), ISO9075.decode(name.getLocalName()));
|
||||
}
|
||||
|
||||
}
|
359
source/java/org/alfresco/jcr/importer/JCRImportHandler.java
Normal file
359
source/java/org/alfresco/jcr/importer/JCRImportHandler.java
Normal file
@@ -0,0 +1,359 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* 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.alfresco.jcr.importer;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.jcr.dictionary.JCRNamespace;
|
||||
import org.alfresco.jcr.session.SessionImpl;
|
||||
import org.alfresco.repo.importer.ImportContentHandler;
|
||||
import org.alfresco.repo.importer.Importer;
|
||||
import org.alfresco.service.cmr.view.ImporterException;
|
||||
import org.alfresco.service.namespace.NamespacePrefixResolver;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXParseException;
|
||||
import org.xml.sax.helpers.NamespaceSupport;
|
||||
|
||||
|
||||
/**
|
||||
* Import Handler that is sensitive to Document and System View XML schemas.
|
||||
*
|
||||
* @author David Caruana
|
||||
*/
|
||||
public class JCRImportHandler implements ImportContentHandler
|
||||
{
|
||||
private Importer importer;
|
||||
private SessionImpl session;
|
||||
private NamespaceContext namespaceContext;
|
||||
private ImportContentHandler targetHandler = null;
|
||||
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param session
|
||||
*/
|
||||
public JCRImportHandler(SessionImpl session)
|
||||
{
|
||||
this.session = session;
|
||||
this.namespaceContext = new NamespaceContext();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.alfresco.repo.importer.ImportContentHandler#setImporter(org.alfresco.repo.importer.Importer)
|
||||
*/
|
||||
public void setImporter(Importer importer)
|
||||
{
|
||||
this.importer = importer;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.alfresco.repo.importer.ImportContentHandler#importStream(java.lang.String)
|
||||
*/
|
||||
public InputStream importStream(String content)
|
||||
{
|
||||
return targetHandler.importStream(content);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator)
|
||||
*/
|
||||
public void setDocumentLocator(Locator locator)
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#startDocument()
|
||||
*/
|
||||
public void startDocument() throws SAXException
|
||||
{
|
||||
namespaceContext.reset();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#endDocument()
|
||||
*/
|
||||
public void endDocument() throws SAXException
|
||||
{
|
||||
targetHandler.endDocument();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, java.lang.String)
|
||||
*/
|
||||
public void startPrefixMapping(String prefix, String uri) throws SAXException
|
||||
{
|
||||
// ensure uri has been registered
|
||||
NamespacePrefixResolver resolver = session.getNamespaceResolver();
|
||||
Collection<String> uris = resolver.getURIs();
|
||||
if (!uris.contains(uri))
|
||||
{
|
||||
throw new ImporterException("Namespace URI " + uri + " has not been registered with the repository");
|
||||
}
|
||||
|
||||
// register prefix within this namespace context
|
||||
namespaceContext.registerPrefix(prefix, uri);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#endPrefixMapping(java.lang.String)
|
||||
*/
|
||||
public void endPrefixMapping(String prefix) throws SAXException
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
|
||||
*/
|
||||
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException
|
||||
{
|
||||
namespaceContext.pushContext();
|
||||
|
||||
// determine content handler based on first element of document
|
||||
if (targetHandler == null)
|
||||
{
|
||||
if (JCRNamespace.SV_URI.equals(uri))
|
||||
{
|
||||
targetHandler = new JCRSystemXMLHandler(session, namespaceContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
targetHandler = new JCRDocXMLHandler(session, namespaceContext);
|
||||
}
|
||||
targetHandler.setImporter(importer);
|
||||
targetHandler.startDocument();
|
||||
}
|
||||
|
||||
targetHandler.startElement(uri, localName, qName, atts);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
|
||||
*/
|
||||
public void endElement(String uri, String localName, String qName) throws SAXException
|
||||
{
|
||||
targetHandler.endElement(uri, localName, qName);
|
||||
namespaceContext.popContext();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#characters(char[], int, int)
|
||||
*/
|
||||
public void characters(char[] ch, int start, int length) throws SAXException
|
||||
{
|
||||
targetHandler.characters(ch, start, length);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int)
|
||||
*/
|
||||
public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException
|
||||
{
|
||||
targetHandler.characters(ch, start, length);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#processingInstruction(java.lang.String, java.lang.String)
|
||||
*/
|
||||
public void processingInstruction(String target, String data) throws SAXException
|
||||
{
|
||||
targetHandler.processingInstruction(target, data);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#skippedEntity(java.lang.String)
|
||||
*/
|
||||
public void skippedEntity(String name) throws SAXException
|
||||
{
|
||||
targetHandler.skippedEntity(name);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ErrorHandler#warning(org.xml.sax.SAXParseException)
|
||||
*/
|
||||
public void warning(SAXParseException exception) throws SAXException
|
||||
{
|
||||
targetHandler.warning(exception);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ErrorHandler#error(org.xml.sax.SAXParseException)
|
||||
*/
|
||||
public void error(SAXParseException exception) throws SAXException
|
||||
{
|
||||
targetHandler.error(exception);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ErrorHandler#fatalError(org.xml.sax.SAXParseException)
|
||||
*/
|
||||
public void fatalError(SAXParseException exception) throws SAXException
|
||||
{
|
||||
targetHandler.fatalError(exception);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Namespace Context
|
||||
*
|
||||
* Implementation supported by NamespaceSupport which itself does not
|
||||
* handle empty uri registration.
|
||||
*/
|
||||
private static class NamespaceContext implements NamespacePrefixResolver
|
||||
{
|
||||
private final NamespaceSupport context;
|
||||
private static final String REMAPPED_DEFAULT_URI = " ";
|
||||
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*/
|
||||
private NamespaceContext()
|
||||
{
|
||||
context = new NamespaceSupport();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear namespace declarations
|
||||
*/
|
||||
private void reset()
|
||||
{
|
||||
context.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Push a new Namespace Context
|
||||
*/
|
||||
private void pushContext()
|
||||
{
|
||||
context.pushContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop a Namespace Context
|
||||
*/
|
||||
private void popContext()
|
||||
{
|
||||
context.popContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a namespace prefix
|
||||
*
|
||||
* @param prefix
|
||||
* @param uri
|
||||
* @return true => legal prefix; false => illegal prefix
|
||||
*/
|
||||
private boolean registerPrefix(String prefix, String uri)
|
||||
{
|
||||
if (NamespaceService.DEFAULT_URI.equals(uri))
|
||||
{
|
||||
uri = REMAPPED_DEFAULT_URI;
|
||||
}
|
||||
return context.declarePrefix(prefix, uri);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.alfresco.service.namespace.NamespacePrefixResolver#getNamespaceURI(java.lang.String)
|
||||
*/
|
||||
public String getNamespaceURI(String prefix) throws org.alfresco.service.namespace.NamespaceException
|
||||
{
|
||||
String uri = context.getURI(prefix);
|
||||
if (uri == null)
|
||||
{
|
||||
throw new org.alfresco.service.namespace.NamespaceException("Namespace prefix " + prefix + " not registered.");
|
||||
}
|
||||
if (REMAPPED_DEFAULT_URI.equals(uri))
|
||||
{
|
||||
return NamespaceService.DEFAULT_URI;
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.alfresco.service.namespace.NamespacePrefixResolver#getPrefixes(java.lang.String)
|
||||
*/
|
||||
public Collection<String> getPrefixes(String namespaceURI) throws org.alfresco.service.namespace.NamespaceException
|
||||
{
|
||||
if (NamespaceService.DEFAULT_URI.equals(namespaceURI))
|
||||
{
|
||||
namespaceURI = REMAPPED_DEFAULT_URI;
|
||||
}
|
||||
String prefix = context.getPrefix(namespaceURI);
|
||||
if (prefix == null)
|
||||
{
|
||||
if (namespaceURI.equals(context.getURI(NamespaceService.DEFAULT_PREFIX)))
|
||||
{
|
||||
prefix = NamespaceService.DEFAULT_PREFIX;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new org.alfresco.service.namespace.NamespaceException("Namespace URI " + namespaceURI + " not registered.");
|
||||
}
|
||||
}
|
||||
List<String> prefixes = new ArrayList<String>(1);
|
||||
prefixes.add(prefix);
|
||||
return prefixes;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.alfresco.service.namespace.NamespacePrefixResolver#getPrefixes()
|
||||
*/
|
||||
public Collection<String> getPrefixes()
|
||||
{
|
||||
// NOTE: not required in this context
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.alfresco.service.namespace.NamespacePrefixResolver#getURIs()
|
||||
*/
|
||||
public Collection<String> getURIs()
|
||||
{
|
||||
// NOTE: not required in this context
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
552
source/java/org/alfresco/jcr/importer/JCRSystemXMLHandler.java
Normal file
552
source/java/org/alfresco/jcr/importer/JCRSystemXMLHandler.java
Normal file
@@ -0,0 +1,552 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* 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.alfresco.jcr.importer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
import javax.jcr.InvalidSerializedDataException;
|
||||
import javax.jcr.PropertyType;
|
||||
import javax.jcr.RepositoryException;
|
||||
|
||||
import org.alfresco.jcr.dictionary.DataTypeMap;
|
||||
import org.alfresco.jcr.dictionary.JCRNamespace;
|
||||
import org.alfresco.jcr.exporter.JCRSystemXMLExporter;
|
||||
import org.alfresco.jcr.item.property.JCRMixinTypesProperty;
|
||||
import org.alfresco.jcr.item.property.JCRPrimaryTypeProperty;
|
||||
import org.alfresco.jcr.item.property.JCRUUIDProperty;
|
||||
import org.alfresco.jcr.session.SessionImpl;
|
||||
import org.alfresco.repo.importer.ImportContentHandler;
|
||||
import org.alfresco.repo.importer.Importer;
|
||||
import org.alfresco.repo.importer.view.ElementContext;
|
||||
import org.alfresco.repo.importer.view.NodeContext;
|
||||
import org.alfresco.repo.importer.view.ParentContext;
|
||||
import org.alfresco.service.cmr.dictionary.AspectDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.InvalidTypeException;
|
||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||
import org.alfresco.service.cmr.view.ImporterException;
|
||||
import org.alfresco.service.namespace.NamespacePrefixResolver;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.Base64;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXParseException;
|
||||
|
||||
|
||||
/**
|
||||
* Alfresco implementation of a System View Import Content Handler
|
||||
*
|
||||
* @author David Caruana
|
||||
*/
|
||||
public class JCRSystemXMLHandler implements ImportContentHandler
|
||||
{
|
||||
private Importer importer;
|
||||
private SessionImpl session;
|
||||
private NamespacePrefixResolver importResolver;
|
||||
private Stack<ElementContext> contextStack = new Stack<ElementContext>();
|
||||
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param session JCR Session
|
||||
* @param importResolver Namespace Resolver for the Import
|
||||
*/
|
||||
public JCRSystemXMLHandler(SessionImpl session, NamespacePrefixResolver importResolver)
|
||||
{
|
||||
this.session = session;
|
||||
this.importResolver = importResolver;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.alfresco.repo.importer.ImportContentHandler#setImporter(org.alfresco.repo.importer.Importer)
|
||||
*/
|
||||
public void setImporter(Importer importer)
|
||||
{
|
||||
this.importer = importer;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.alfresco.repo.importer.ImportContentHandler#importStream(java.lang.String)
|
||||
*/
|
||||
public InputStream importStream(String content)
|
||||
{
|
||||
File contentFile = new File(content);
|
||||
try
|
||||
{
|
||||
FileInputStream contentStream = new FileInputStream(contentFile);
|
||||
return new Base64.InputStream(contentStream, Base64.DECODE | Base64.DONT_BREAK_LINES);
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
throw new ImporterException("Failed to retrieve import input stream on temporary content file " + content);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator)
|
||||
*/
|
||||
public void setDocumentLocator(Locator locator)
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#startDocument()
|
||||
*/
|
||||
public void startDocument() throws SAXException
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#endDocument()
|
||||
*/
|
||||
public void endDocument() throws SAXException
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, java.lang.String)
|
||||
*/
|
||||
public void startPrefixMapping(String prefix, String uri) throws SAXException
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#endPrefixMapping(java.lang.String)
|
||||
*/
|
||||
public void endPrefixMapping(String prefix) throws SAXException
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
|
||||
*/
|
||||
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException
|
||||
{
|
||||
try
|
||||
{
|
||||
// construct qname for element
|
||||
QName elementName = QName.createQName(qName, importResolver);
|
||||
|
||||
if (JCRSystemXMLExporter.NODE_QNAME.equals(elementName))
|
||||
{
|
||||
processStartNode(elementName, atts);
|
||||
}
|
||||
else if (JCRSystemXMLExporter.PROPERTY_QNAME.equals(elementName))
|
||||
{
|
||||
processStartProperty(elementName, atts);
|
||||
}
|
||||
else if (JCRSystemXMLExporter.VALUE_QNAME.equals(elementName))
|
||||
{
|
||||
processStartValue(elementName, atts);
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new SAXException("Failed to process element " + qName, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process start of Node Element
|
||||
*
|
||||
* @param elementName
|
||||
* @param atts
|
||||
* @throws InvalidSerializedDataException
|
||||
*/
|
||||
private void processStartNode(QName elementName, Attributes atts)
|
||||
throws InvalidSerializedDataException
|
||||
{
|
||||
ParentContext parentContext = null;
|
||||
if (contextStack.empty())
|
||||
{
|
||||
// create root parent context
|
||||
parentContext = new ParentContext(elementName, session.getRepositoryImpl().getServiceRegistry().getDictionaryService(), importer);
|
||||
}
|
||||
else
|
||||
{
|
||||
NodeContext parentNode = (NodeContext)contextStack.peek();
|
||||
|
||||
// if we haven't yet imported the node before its children, do so now
|
||||
if (parentNode.getNodeRef() == null)
|
||||
{
|
||||
NodeRef nodeRef = importer.importNode(parentNode);
|
||||
parentNode.setNodeRef(nodeRef);
|
||||
}
|
||||
|
||||
// create parent context
|
||||
parentContext = new ParentContext(elementName, parentNode);
|
||||
}
|
||||
|
||||
// create node context
|
||||
// NOTE: we don't yet know its type (we have to wait for a property)
|
||||
NodeContext nodeContext = new NodeContext(elementName, parentContext, null);
|
||||
|
||||
// establish node child name
|
||||
String name = atts.getValue(JCRSystemXMLExporter.NAME_QNAME.toPrefixString(importResolver));
|
||||
if (name == null)
|
||||
{
|
||||
throw new InvalidSerializedDataException("Mandatory sv:name attribute of element sv:node not present.");
|
||||
}
|
||||
nodeContext.setChildName(name);
|
||||
|
||||
// record new node
|
||||
contextStack.push(nodeContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process start of Property element
|
||||
*
|
||||
* @param elementName
|
||||
* @param atts
|
||||
* @throws InvalidSerializedDataException
|
||||
*/
|
||||
private void processStartProperty(QName elementName, Attributes atts)
|
||||
throws InvalidSerializedDataException
|
||||
{
|
||||
// establish correct context
|
||||
ElementContext context = contextStack.peek();
|
||||
if (!(context instanceof NodeContext))
|
||||
{
|
||||
throw new InvalidSerializedDataException("Element " + elementName + " not expected.");
|
||||
}
|
||||
NodeContext parentNode = (NodeContext)context;
|
||||
|
||||
// establish property name
|
||||
String name = atts.getValue(JCRSystemXMLExporter.NAME_QNAME.toPrefixString(importResolver));
|
||||
if (name == null)
|
||||
{
|
||||
throw new InvalidSerializedDataException("Mandatory sv:name attribute of element sv:node not present.");
|
||||
}
|
||||
QName propertyName = QName.createQName(name, importResolver);
|
||||
|
||||
// establish property type and validate property type
|
||||
QName dataType = null;
|
||||
String type = atts.getValue(JCRSystemXMLExporter.TYPE_QNAME.toPrefixString(importResolver));
|
||||
if (type == null)
|
||||
{
|
||||
throw new InvalidSerializedDataException("Mandatory sv:type attribute of element sv:node not present.");
|
||||
}
|
||||
try
|
||||
{
|
||||
dataType = DataTypeMap.convertPropertyTypeToDataType(PropertyType.valueFromName(type));
|
||||
}
|
||||
catch(IllegalArgumentException e)
|
||||
{
|
||||
throw new ImporterException("Type " + type + " is not known for property " + name);
|
||||
}
|
||||
|
||||
// construct property context
|
||||
PropertyContext propertyContext = new PropertyContext(elementName, parentNode, propertyName, dataType);
|
||||
contextStack.push(propertyContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process start of Value element
|
||||
*
|
||||
* @param elementName
|
||||
* @param atts
|
||||
* @throws InvalidSerializedDataException
|
||||
*/
|
||||
private void processStartValue(QName elementName, Attributes atts)
|
||||
throws InvalidSerializedDataException
|
||||
{
|
||||
// establish correct context
|
||||
ElementContext context = contextStack.peek();
|
||||
if (!(context instanceof PropertyContext))
|
||||
{
|
||||
throw new InvalidSerializedDataException("Element " + elementName + " not expected.");
|
||||
}
|
||||
PropertyContext property = (PropertyContext)context;
|
||||
property.startValue();
|
||||
|
||||
ValueContext value = new ValueContext(elementName, property);
|
||||
contextStack.push(value);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
|
||||
*/
|
||||
public void endElement(String uri, String localName, String qName) throws SAXException
|
||||
{
|
||||
try
|
||||
{
|
||||
// ensure context matches parse
|
||||
ElementContext context = (ElementContext)contextStack.peek();
|
||||
QName elementName = QName.createQName(qName, importResolver);
|
||||
if (!context.getElementName().equals(elementName))
|
||||
{
|
||||
throw new InvalidSerializedDataException("Expected element " + context.getElementName() + " but was " + elementName);
|
||||
}
|
||||
|
||||
if (JCRSystemXMLExporter.NODE_QNAME.equals(elementName))
|
||||
{
|
||||
processEndNode((NodeContext)context);
|
||||
}
|
||||
else if (JCRSystemXMLExporter.PROPERTY_QNAME.equals(elementName))
|
||||
{
|
||||
processEndProperty((PropertyContext)context);
|
||||
}
|
||||
else if (JCRSystemXMLExporter.VALUE_QNAME.equals(elementName))
|
||||
{
|
||||
processEndValue((ValueContext)context);
|
||||
}
|
||||
|
||||
// cleanup
|
||||
contextStack.pop();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new SAXException("Failed to process element " + qName, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process end of Node element
|
||||
*
|
||||
* @param node
|
||||
*/
|
||||
private void processEndNode(NodeContext node)
|
||||
{
|
||||
// import node, if not already imported (this will be the case when no child nodes exist)
|
||||
NodeRef nodeRef = node.getNodeRef();
|
||||
if (nodeRef == null)
|
||||
{
|
||||
nodeRef = node.getImporter().importNode(node);
|
||||
node.setNodeRef(nodeRef);
|
||||
}
|
||||
|
||||
// signal end of node
|
||||
node.getImporter().childrenImported(nodeRef);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process end of Property element
|
||||
*
|
||||
* @param context
|
||||
* @throws InvalidSerializedDataException
|
||||
* @throws RepositoryException
|
||||
*/
|
||||
private void processEndProperty(PropertyContext context)
|
||||
throws InvalidSerializedDataException, RepositoryException
|
||||
{
|
||||
QName propertyName = context.getName();
|
||||
|
||||
// ensure a value has been provided
|
||||
if (context.isNull())
|
||||
{
|
||||
throw new InvalidSerializedDataException("Property " + propertyName + " must have a value");
|
||||
}
|
||||
|
||||
//
|
||||
// process known properties
|
||||
//
|
||||
|
||||
if (JCRPrimaryTypeProperty.PROPERTY_NAME.equals(propertyName))
|
||||
{
|
||||
// apply type definition
|
||||
if (!context.isNull())
|
||||
{
|
||||
QName typeQName = QName.createQName(context.getValues().get(0).toString(), importResolver);
|
||||
TypeDefinition typeDef = context.getDictionaryService().getType(typeQName);
|
||||
if (typeDef == null)
|
||||
{
|
||||
throw new InvalidTypeException(typeQName);
|
||||
}
|
||||
|
||||
// update node context
|
||||
context.getNode().setTypeDefinition(typeDef);
|
||||
}
|
||||
}
|
||||
else if (JCRMixinTypesProperty.PROPERTY_NAME.equals(propertyName))
|
||||
{
|
||||
// apply aspect definitions
|
||||
List<StringBuffer> values = context.getValues();
|
||||
for (StringBuffer value : values)
|
||||
{
|
||||
QName aspectQName = QName.createQName(value.toString(), importResolver);
|
||||
|
||||
// ignore JCR specific aspects
|
||||
if (!(JCRNamespace.JCR_URI.equals(aspectQName.getNamespaceURI()) ||
|
||||
JCRNamespace.MIX_URI.equals(aspectQName.getNamespaceURI())))
|
||||
{
|
||||
AspectDefinition aspectDef = context.getDictionaryService().getAspect(aspectQName);
|
||||
if (aspectDef == null)
|
||||
{
|
||||
throw new InvalidTypeException(aspectQName);
|
||||
}
|
||||
context.getNode().addAspect(aspectDef);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (JCRUUIDProperty.PROPERTY_NAME.equals(propertyName))
|
||||
{
|
||||
StringBuffer value = context.getValues().get(0);
|
||||
context.getNode().setUUID(value.toString());
|
||||
}
|
||||
|
||||
//
|
||||
// Note: ignore all other JCR specific properties
|
||||
//
|
||||
|
||||
else if (JCRNamespace.JCR_URI.equals(propertyName.getNamespaceURI()))
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// process all other properties
|
||||
//
|
||||
|
||||
else
|
||||
{
|
||||
// apply the property values to the node
|
||||
NodeContext node = context.getNode();
|
||||
if (node.getTypeDefinition() == null)
|
||||
{
|
||||
throw new InvalidSerializedDataException("Node jcr:primaryType property has not been specified.");
|
||||
}
|
||||
|
||||
// determine data type of value
|
||||
QName dataType = context.getType();
|
||||
DataTypeDefinition dataTypeDef = context.getDictionaryService().getDataType(dataType);
|
||||
if (dataTypeDef == null)
|
||||
{
|
||||
throw new InvalidTypeException(dataType);
|
||||
}
|
||||
node.addDatatype(propertyName, dataTypeDef);
|
||||
|
||||
// determine if multi-value property
|
||||
if (context.isMultiValue())
|
||||
{
|
||||
node.addPropertyCollection(propertyName);
|
||||
}
|
||||
|
||||
// add each value to the node
|
||||
List<StringBuffer> values = context.getValues();
|
||||
for (StringBuffer value : values)
|
||||
{
|
||||
// first, cast value to appropriate type (using JCR converters)
|
||||
Serializable objVal = (Serializable)session.getTypeConverter().convert(dataTypeDef, value.toString());
|
||||
String strValue = DefaultTypeConverter.INSTANCE.convert(String.class, objVal);
|
||||
node.addProperty(propertyName, strValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process end of value element
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
private void processEndValue(ValueContext context)
|
||||
{
|
||||
PropertyContext property = context.getProperty();
|
||||
property.endValue();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#characters(char[], int, int)
|
||||
*/
|
||||
public void characters(char[] ch, int start, int length) throws SAXException
|
||||
{
|
||||
ElementContext context = (ElementContext)contextStack.peek();
|
||||
if (context instanceof ValueContext)
|
||||
{
|
||||
PropertyContext property = ((ValueContext)context).getProperty();
|
||||
property.appendCharacters(ch, start, length);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int)
|
||||
*/
|
||||
public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException
|
||||
{
|
||||
ElementContext context = (ElementContext)contextStack.peek();
|
||||
if (context instanceof ValueContext)
|
||||
{
|
||||
PropertyContext property = ((ValueContext)context).getProperty();
|
||||
property.appendCharacters(ch, start, length);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#processingInstruction(java.lang.String, java.lang.String)
|
||||
*/
|
||||
public void processingInstruction(String target, String data) throws SAXException
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ContentHandler#skippedEntity(java.lang.String)
|
||||
*/
|
||||
public void skippedEntity(String name) throws SAXException
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ErrorHandler#warning(org.xml.sax.SAXParseException)
|
||||
*/
|
||||
public void warning(SAXParseException exception) throws SAXException
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ErrorHandler#error(org.xml.sax.SAXParseException)
|
||||
*/
|
||||
public void error(SAXParseException exception) throws SAXException
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.xml.sax.ErrorHandler#fatalError(org.xml.sax.SAXParseException)
|
||||
*/
|
||||
public void fatalError(SAXParseException exception) throws SAXException
|
||||
{
|
||||
}
|
||||
|
||||
}
|
210
source/java/org/alfresco/jcr/importer/PropertyContext.java
Normal file
210
source/java/org/alfresco/jcr/importer/PropertyContext.java
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* 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.alfresco.jcr.importer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.importer.view.ElementContext;
|
||||
import org.alfresco.repo.importer.view.NodeContext;
|
||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
import org.alfresco.service.cmr.view.ImporterException;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.ISO9075;
|
||||
import org.alfresco.util.TempFileProvider;
|
||||
|
||||
|
||||
/**
|
||||
* Maintains state about currently imported Property
|
||||
*
|
||||
* @author David Caruana
|
||||
*
|
||||
*/
|
||||
public class PropertyContext extends ElementContext
|
||||
{
|
||||
private NodeContext parentContext;
|
||||
private QName propertyName;
|
||||
private QName propertyType;
|
||||
|
||||
private List<StringBuffer> values = new ArrayList<StringBuffer>();
|
||||
private Map<QName, FileWriter> contentWriters = new HashMap<QName, FileWriter>();
|
||||
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param elementName
|
||||
* @param parentContext
|
||||
* @param propertyName
|
||||
* @param propertyType
|
||||
*/
|
||||
public PropertyContext(QName elementName, NodeContext parentContext, QName propertyName, QName propertyType)
|
||||
{
|
||||
super(elementName, parentContext.getDictionaryService(), parentContext.getImporter());
|
||||
this.parentContext = parentContext;
|
||||
this.propertyName = propertyName;
|
||||
this.propertyType = propertyType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get node containing property
|
||||
*
|
||||
* @return node
|
||||
*/
|
||||
public NodeContext getNode()
|
||||
{
|
||||
return parentContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get property name
|
||||
*
|
||||
* @return property name
|
||||
*/
|
||||
public QName getName()
|
||||
{
|
||||
return propertyName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get property type
|
||||
*
|
||||
* @return property type
|
||||
*/
|
||||
public QName getType()
|
||||
{
|
||||
return propertyType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is property multi-valued?
|
||||
*
|
||||
* @return true => multi-valued; false => single value
|
||||
*/
|
||||
public boolean isMultiValue()
|
||||
{
|
||||
return values.size() > 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is null property value
|
||||
*
|
||||
* @return true => value has not been provided
|
||||
*/
|
||||
public boolean isNull()
|
||||
{
|
||||
return values.size() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get property values
|
||||
*
|
||||
* @return values
|
||||
*/
|
||||
public List<StringBuffer> getValues()
|
||||
{
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a new property value
|
||||
*/
|
||||
public void startValue()
|
||||
{
|
||||
StringBuffer buffer = new StringBuffer(128);
|
||||
if (propertyType.equals(DataTypeDefinition.CONTENT))
|
||||
{
|
||||
// create temporary file to hold content
|
||||
File tempFile = TempFileProvider.createTempFile("import", ".tmp");
|
||||
try
|
||||
{
|
||||
FileWriter tempWriter = new FileWriter(tempFile);
|
||||
contentWriters.put(propertyName, tempWriter);
|
||||
ContentData contentData = new ContentData(tempFile.getAbsolutePath(), MimetypeMap.MIMETYPE_BINARY, 0, tempWriter.getEncoding());
|
||||
buffer.append(contentData.toString());
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
throw new ImporterException("Failed to create temporary content holder for property " + propertyName, e);
|
||||
}
|
||||
}
|
||||
values.add(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* End a property value
|
||||
*/
|
||||
public void endValue()
|
||||
{
|
||||
if (propertyType.equals(DataTypeDefinition.CONTENT))
|
||||
{
|
||||
// close content writer
|
||||
FileWriter tempWriter = contentWriters.get(propertyName);
|
||||
try
|
||||
{
|
||||
tempWriter.close();
|
||||
contentWriters.remove(propertyName);
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
throw new ImporterException("Failed to create temporary content holder for property " + propertyName, e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// decode value
|
||||
StringBuffer buffer = values.get(values.size() -1);
|
||||
values.set(values.size() -1, new StringBuffer(ISO9075.decode(buffer.toString())));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append property value characters
|
||||
*
|
||||
* @param ch
|
||||
* @param start
|
||||
* @param length
|
||||
*/
|
||||
public void appendCharacters(char[] ch, int start, int length)
|
||||
{
|
||||
if (propertyType.equals(DataTypeDefinition.CONTENT))
|
||||
{
|
||||
FileWriter tempWriter = contentWriters.get(propertyName);
|
||||
try
|
||||
{
|
||||
tempWriter.write(ch, start, length);
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
throw new ImporterException("Failed to write temporary content for property " + propertyName, e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
StringBuffer buffer = values.get(values.size() -1);
|
||||
buffer.append(ch, start, length);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
54
source/java/org/alfresco/jcr/importer/ValueContext.java
Normal file
54
source/java/org/alfresco/jcr/importer/ValueContext.java
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* 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.alfresco.jcr.importer;
|
||||
|
||||
import org.alfresco.repo.importer.view.ElementContext;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* Maintains state about currently imported value
|
||||
*
|
||||
* @author David Caruana
|
||||
*/
|
||||
public class ValueContext extends ElementContext
|
||||
{
|
||||
private PropertyContext property;
|
||||
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param elementName
|
||||
* @param property
|
||||
*/
|
||||
public ValueContext(QName elementName, PropertyContext property)
|
||||
{
|
||||
super(elementName, property.getDictionaryService(), property.getImporter());
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get property
|
||||
*
|
||||
* @return property holding value
|
||||
*/
|
||||
public PropertyContext getProperty()
|
||||
{
|
||||
return property;
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user