mirror of
				https://github.com/Alfresco/alfresco-community-repo.git
				synced 2025-10-29 15:21:53 +00:00 
			
		
		
		
	6580: AVM bulk import performance tweaks. 6582: WCM-767, WCM-768 6583: Fix for AWC-1528 (potential NPE in ErrorsRenderer) 6584: Fix for AWC-1256 (Links produced by inline HTML editor are incorrect) 6585: AR-1635: event listeners added in a beforeCommit event are now executed successfully 6586: AR-1561 Update Web Scripts readme.html to be consistent with "Category Search Sample" (or vice-versa) 6587: Fix for AWC-1390 (Paste all doesn't work for forum items) 6588: AR-1701 Script getDocument call doesn't check for non-existent content 6589: Fix for AWC-1530 - Saved search does not work for custom properties of type d:text with list constraint 6591: Improvement for submit speed. 6592: Removed obsolete tests. 6594: Index tracking sample to include AVM index tracking 6595: Added the AVM helpers methods from the FreeMarker AVM API that were missing from the JavaScript API 6597: Rationalize post commit execution hooks for deployment receiver 6598: Properly escape path names for ProgramRunnable. 6599: AVM store name lookup cache is (theoretically) clusterable. 6600: Some or other gramatically incorrect stuff about Chiba. 6601: Fix for AR-1121 and AR-1673 6602: AR-1655: Versioning is not MLText aware 6603: Updated messages from lang packs 6604: Fixed AR-1476: JCR import end element escaping 6605: Updated Japanese lang messages git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@6746 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
		
			
				
	
	
		
			405 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			405 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| /*
 | |
|  * Copyright (C) 2005-2007 Alfresco Software Limited.
 | |
|  *
 | |
|  * This program is free software; you can redistribute it and/or
 | |
|  * modify it under the terms of the GNU General Public License
 | |
|  * as published by the Free Software Foundation; either version 2
 | |
|  * of the License, or (at your option) any later version.
 | |
| 
 | |
|  * This program is distributed in the hope that it will be useful,
 | |
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|  * GNU General Public License for more details.
 | |
| 
 | |
|  * You should have received a copy of the GNU General Public License
 | |
|  * along with this program; if not, write to the Free Software
 | |
|  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 | |
| 
 | |
|  * As a special exception to the terms and conditions of version 2.0 of 
 | |
|  * the GPL, you may redistribute this Program in connection with Free/Libre 
 | |
|  * and Open Source Software ("FLOSS") applications as described in Alfresco's 
 | |
|  * FLOSS exception.  You should have recieved a copy of the text describing 
 | |
|  * the FLOSS exception, and it is also available here: 
 | |
|  * http://www.alfresco.com/legal/licensing"
 | |
|  */
 | |
| 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 = decodeQName(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()));
 | |
|     }
 | |
| 
 | |
| }
 |