KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > jcr > importer > JCRSystemXMLHandler


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.jcr.importer;
18
19 import java.io.File JavaDoc;
20 import java.io.FileInputStream JavaDoc;
21 import java.io.FileNotFoundException JavaDoc;
22 import java.io.InputStream JavaDoc;
23 import java.io.Serializable JavaDoc;
24 import java.util.List JavaDoc;
25 import java.util.Stack JavaDoc;
26
27 import javax.jcr.InvalidSerializedDataException;
28 import javax.jcr.PropertyType;
29 import javax.jcr.RepositoryException;
30
31 import org.alfresco.jcr.dictionary.DataTypeMap;
32 import org.alfresco.jcr.dictionary.JCRNamespace;
33 import org.alfresco.jcr.exporter.JCRSystemXMLExporter;
34 import org.alfresco.jcr.item.property.JCRMixinTypesProperty;
35 import org.alfresco.jcr.item.property.JCRPrimaryTypeProperty;
36 import org.alfresco.jcr.item.property.JCRUUIDProperty;
37 import org.alfresco.jcr.session.SessionImpl;
38 import org.alfresco.repo.importer.ImportContentHandler;
39 import org.alfresco.repo.importer.Importer;
40 import org.alfresco.repo.importer.view.ElementContext;
41 import org.alfresco.repo.importer.view.NodeContext;
42 import org.alfresco.repo.importer.view.ParentContext;
43 import org.alfresco.service.cmr.dictionary.AspectDefinition;
44 import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
45 import org.alfresco.service.cmr.dictionary.InvalidTypeException;
46 import org.alfresco.service.cmr.dictionary.TypeDefinition;
47 import org.alfresco.service.cmr.repository.NodeRef;
48 import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
49 import org.alfresco.service.cmr.view.ImporterException;
50 import org.alfresco.service.namespace.NamespacePrefixResolver;
51 import org.alfresco.service.namespace.QName;
52 import org.alfresco.util.Base64;
53 import org.xml.sax.Attributes JavaDoc;
54 import org.xml.sax.Locator JavaDoc;
55 import org.xml.sax.SAXException JavaDoc;
56 import org.xml.sax.SAXParseException JavaDoc;
57
58
59 /**
60  * Alfresco implementation of a System View Import Content Handler
61  *
62  * @author David Caruana
63  */

64 public class JCRSystemXMLHandler implements ImportContentHandler
65 {
66     private Importer importer;
67     private SessionImpl session;
68     private NamespacePrefixResolver importResolver;
69     private Stack JavaDoc<ElementContext> contextStack = new Stack JavaDoc<ElementContext>();
70     
71
72     /**
73      * Construct
74      *
75      * @param session JCR Session
76      * @param importResolver Namespace Resolver for the Import
77      */

78     public JCRSystemXMLHandler(SessionImpl session, NamespacePrefixResolver importResolver)
79     {
80         this.session = session;
81         this.importResolver = importResolver;
82     }
83
84     /*
85      * (non-Javadoc)
86      * @see org.alfresco.repo.importer.ImportContentHandler#setImporter(org.alfresco.repo.importer.Importer)
87      */

88     public void setImporter(Importer importer)
89     {
90         this.importer = importer;
91     }
92
93     /*
94      * (non-Javadoc)
95      * @see org.alfresco.repo.importer.ImportContentHandler#importStream(java.lang.String)
96      */

97     public InputStream JavaDoc importStream(String JavaDoc content)
98     {
99         File JavaDoc contentFile = new File JavaDoc(content);
100         try
101         {
102             FileInputStream JavaDoc contentStream = new FileInputStream JavaDoc(contentFile);
103             return new Base64.InputStream(contentStream, Base64.DECODE | Base64.DONT_BREAK_LINES);
104         }
105         catch (FileNotFoundException JavaDoc e)
106         {
107             throw new ImporterException("Failed to retrieve import input stream on temporary content file " + content);
108         }
109     }
110
111     /*
112      * (non-Javadoc)
113      * @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator)
114      */

115     public void setDocumentLocator(Locator JavaDoc locator)
116     {
117         // NOOP
118
}
119
120     /*
121      * (non-Javadoc)
122      * @see org.xml.sax.ContentHandler#startDocument()
123      */

124     public void startDocument() throws SAXException JavaDoc
125     {
126         // NOOP
127
}
128
129     /*
130      * (non-Javadoc)
131      * @see org.xml.sax.ContentHandler#endDocument()
132      */

133     public void endDocument() throws SAXException JavaDoc
134     {
135         // NOOP
136
}
137
138     /*
139      * (non-Javadoc)
140      * @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, java.lang.String)
141      */

142     public void startPrefixMapping(String JavaDoc prefix, String JavaDoc uri) throws SAXException JavaDoc
143     {
144         // NOOP
145
}
146
147     /*
148      * (non-Javadoc)
149      * @see org.xml.sax.ContentHandler#endPrefixMapping(java.lang.String)
150      */

151     public void endPrefixMapping(String JavaDoc prefix) throws SAXException JavaDoc
152     {
153         // NOOP
154
}
155
156     /*
157      * (non-Javadoc)
158      * @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
159      */

160     public void startElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc qName, Attributes JavaDoc atts) throws SAXException JavaDoc
161     {
162         try
163         {
164             // construct qname for element
165
QName elementName = QName.createQName(qName, importResolver);
166     
167             if (JCRSystemXMLExporter.NODE_QNAME.equals(elementName))
168             {
169                 processStartNode(elementName, atts);
170             }
171             else if (JCRSystemXMLExporter.PROPERTY_QNAME.equals(elementName))
172             {
173                 processStartProperty(elementName, atts);
174             }
175             else if (JCRSystemXMLExporter.VALUE_QNAME.equals(elementName))
176             {
177                 processStartValue(elementName, atts);
178             }
179         }
180         catch(Exception JavaDoc e)
181         {
182             throw new SAXException JavaDoc("Failed to process element " + qName, e);
183         }
184     }
185     
186     /**
187      * Process start of Node Element
188      *
189      * @param elementName
190      * @param atts
191      * @throws InvalidSerializedDataException
192      */

193     private void processStartNode(QName elementName, Attributes JavaDoc atts)
194         throws InvalidSerializedDataException
195     {
196         ParentContext parentContext = null;
197         if (contextStack.empty())
198         {
199             // create root parent context
200
parentContext = new ParentContext(elementName, session.getRepositoryImpl().getServiceRegistry().getDictionaryService(), importer);
201         }
202         else
203         {
204             NodeContext parentNode = (NodeContext)contextStack.peek();
205             
206             // if we haven't yet imported the node before its children, do so now
207
if (parentNode.getNodeRef() == null)
208             {
209                 NodeRef nodeRef = importer.importNode(parentNode);
210                 parentNode.setNodeRef(nodeRef);
211             }
212
213             // create parent context
214
parentContext = new ParentContext(elementName, parentNode);
215         }
216         
217         // create node context
218
// NOTE: we don't yet know its type (we have to wait for a property)
219
NodeContext nodeContext = new NodeContext(elementName, parentContext, null);
220
221         // establish node child name
222
String JavaDoc name = atts.getValue(JCRSystemXMLExporter.NAME_QNAME.toPrefixString(importResolver));
223         if (name == null)
224         {
225             throw new InvalidSerializedDataException("Mandatory sv:name attribute of element sv:node not present.");
226         }
227         nodeContext.setChildName(name);
228
229         // record new node
230
contextStack.push(nodeContext);
231     }
232
233     /**
234      * Process start of Property element
235      *
236      * @param elementName
237      * @param atts
238      * @throws InvalidSerializedDataException
239      */

240     private void processStartProperty(QName elementName, Attributes JavaDoc atts)
241         throws InvalidSerializedDataException
242     {
243         // establish correct context
244
ElementContext context = contextStack.peek();
245         if (!(context instanceof NodeContext))
246         {
247             throw new InvalidSerializedDataException("Element " + elementName + " not expected.");
248         }
249         NodeContext parentNode = (NodeContext)context;
250     
251         // establish property name
252
String JavaDoc name = atts.getValue(JCRSystemXMLExporter.NAME_QNAME.toPrefixString(importResolver));
253         if (name == null)
254         {
255             throw new InvalidSerializedDataException("Mandatory sv:name attribute of element sv:node not present.");
256         }
257         QName propertyName = QName.createQName(name, importResolver);
258         
259         // establish property type and validate property type
260
QName dataType = null;
261         String JavaDoc type = atts.getValue(JCRSystemXMLExporter.TYPE_QNAME.toPrefixString(importResolver));
262         if (type == null)
263         {
264             throw new InvalidSerializedDataException("Mandatory sv:type attribute of element sv:node not present.");
265         }
266         try
267         {
268             dataType = DataTypeMap.convertPropertyTypeToDataType(PropertyType.valueFromName(type));
269         }
270         catch(IllegalArgumentException JavaDoc e)
271         {
272             throw new ImporterException("Type " + type + " is not known for property " + name);
273         }
274         
275         // construct property context
276
PropertyContext propertyContext = new PropertyContext(elementName, parentNode, propertyName, dataType);
277         contextStack.push(propertyContext);
278     }
279
280     /**
281      * Process start of Value element
282      *
283      * @param elementName
284      * @param atts
285      * @throws InvalidSerializedDataException
286      */

287     private void processStartValue(QName elementName, Attributes JavaDoc atts)
288         throws InvalidSerializedDataException
289     {
290         // establish correct context
291
ElementContext context = contextStack.peek();
292         if (!(context instanceof PropertyContext))
293         {
294             throw new InvalidSerializedDataException("Element " + elementName + " not expected.");
295         }
296         PropertyContext property = (PropertyContext)context;
297         property.startValue();
298         
299         ValueContext value = new ValueContext(elementName, property);
300         contextStack.push(value);
301     }
302
303     /*
304      * (non-Javadoc)
305      * @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
306      */

307     public void endElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc qName) throws SAXException JavaDoc
308     {
309         try
310         {
311             // ensure context matches parse
312
ElementContext context = (ElementContext)contextStack.peek();
313             QName elementName = QName.createQName(qName, importResolver);
314             if (!context.getElementName().equals(elementName))
315             {
316                 throw new InvalidSerializedDataException("Expected element " + context.getElementName() + " but was " + elementName);
317             }
318     
319             if (JCRSystemXMLExporter.NODE_QNAME.equals(elementName))
320             {
321                 processEndNode((NodeContext)context);
322             }
323             else if (JCRSystemXMLExporter.PROPERTY_QNAME.equals(elementName))
324             {
325                 processEndProperty((PropertyContext)context);
326             }
327             else if (JCRSystemXMLExporter.VALUE_QNAME.equals(elementName))
328             {
329                 processEndValue((ValueContext)context);
330             }
331     
332             // cleanup
333
contextStack.pop();
334         }
335         catch(Exception JavaDoc e)
336         {
337             throw new SAXException JavaDoc("Failed to process element " + qName, e);
338         }
339     }
340
341     /**
342      * Process end of Node element
343      *
344      * @param node
345      */

346     private void processEndNode(NodeContext node)
347     {
348         // import node, if not already imported (this will be the case when no child nodes exist)
349
NodeRef nodeRef = node.getNodeRef();
350         if (nodeRef == null)
351         {
352             nodeRef = node.getImporter().importNode(node);
353             node.setNodeRef(nodeRef);
354         }
355         
356         // signal end of node
357
node.getImporter().childrenImported(nodeRef);
358     }
359     
360     /**
361      * Process end of Property element
362      *
363      * @param context
364      * @throws InvalidSerializedDataException
365      * @throws RepositoryException
366      */

367     private void processEndProperty(PropertyContext context)
368         throws InvalidSerializedDataException, RepositoryException
369     {
370         QName propertyName = context.getName();
371
372         // ensure a value has been provided
373
if (context.isNull())
374         {
375             throw new InvalidSerializedDataException("Property " + propertyName + " must have a value");
376         }
377         
378         //
379
// process known properties
380
//
381

382         if (JCRPrimaryTypeProperty.PROPERTY_NAME.equals(propertyName))
383         {
384             // apply type definition
385
if (!context.isNull())
386             {
387                 QName typeQName = QName.createQName(context.getValues().get(0).toString(), importResolver);
388                 TypeDefinition typeDef = context.getDictionaryService().getType(typeQName);
389                 if (typeDef == null)
390                 {
391                     throw new InvalidTypeException(typeQName);
392                 }
393                 
394                 // update node context
395
context.getNode().setTypeDefinition(typeDef);
396             }
397         }
398         else if (JCRMixinTypesProperty.PROPERTY_NAME.equals(propertyName))
399         {
400             // apply aspect definitions
401
List JavaDoc<StringBuffer JavaDoc> values = context.getValues();
402             for (StringBuffer JavaDoc value : values)
403             {
404                 QName aspectQName = QName.createQName(value.toString(), importResolver);
405                 
406                 // ignore JCR specific aspects
407
if (!(JCRNamespace.JCR_URI.equals(aspectQName.getNamespaceURI()) ||
408                       JCRNamespace.MIX_URI.equals(aspectQName.getNamespaceURI())))
409                 {
410                     AspectDefinition aspectDef = context.getDictionaryService().getAspect(aspectQName);
411                     if (aspectDef == null)
412                     {
413                         throw new InvalidTypeException(aspectQName);
414                     }
415                     context.getNode().addAspect(aspectDef);
416                 }
417             }
418         }
419         else if (JCRUUIDProperty.PROPERTY_NAME.equals(propertyName))
420         {
421             StringBuffer JavaDoc value = context.getValues().get(0);
422             context.getNode().setUUID(value.toString());
423         }
424
425         //
426
// Note: ignore all other JCR specific properties
427
//
428

429         else if (JCRNamespace.JCR_URI.equals(propertyName.getNamespaceURI()))
430         {
431         }
432         
433         //
434
// process all other properties
435
//
436

437         else
438         {
439             // apply the property values to the node
440
NodeContext node = context.getNode();
441             if (node.getTypeDefinition() == null)
442             {
443                 throw new InvalidSerializedDataException("Node jcr:primaryType property has not been specified.");
444             }
445             
446             // determine data type of value
447
QName dataType = context.getType();
448             DataTypeDefinition dataTypeDef = context.getDictionaryService().getDataType(dataType);
449             if (dataTypeDef == null)
450             {
451                 throw new InvalidTypeException(dataType);
452             }
453             node.addDatatype(propertyName, dataTypeDef);
454
455             // determine if multi-value property
456
if (context.isMultiValue())
457             {
458                 node.addPropertyCollection(propertyName);
459             }
460             
461             // add each value to the node
462
List JavaDoc<StringBuffer JavaDoc> values = context.getValues();
463             for (StringBuffer JavaDoc value : values)
464             {
465                 // first, cast value to appropriate type (using JCR converters)
466
Serializable JavaDoc objVal = (Serializable JavaDoc)session.getTypeConverter().convert(dataTypeDef, value.toString());
467                 String JavaDoc strValue = DefaultTypeConverter.INSTANCE.convert(String JavaDoc.class, objVal);
468                 node.addProperty(propertyName, strValue);
469             }
470         }
471     }
472
473     /**
474      * Process end of value element
475      *
476      * @param context
477      */

478     private void processEndValue(ValueContext context)
479     {
480         PropertyContext property = context.getProperty();
481         property.endValue();
482     }
483
484     /*
485      * (non-Javadoc)
486      * @see org.xml.sax.ContentHandler#characters(char[], int, int)
487      */

488     public void characters(char[] ch, int start, int length) throws SAXException JavaDoc
489     {
490         ElementContext context = (ElementContext)contextStack.peek();
491         if (context instanceof ValueContext)
492         {
493             PropertyContext property = ((ValueContext)context).getProperty();
494             property.appendCharacters(ch, start, length);
495         }
496     }
497
498     /*
499      * (non-Javadoc)
500      * @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int)
501      */

502     public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException JavaDoc
503     {
504         ElementContext context = (ElementContext)contextStack.peek();
505         if (context instanceof ValueContext)
506         {
507             PropertyContext property = ((ValueContext)context).getProperty();
508             property.appendCharacters(ch, start, length);
509         }
510     }
511
512     /*
513      * (non-Javadoc)
514      * @see org.xml.sax.ContentHandler#processingInstruction(java.lang.String, java.lang.String)
515      */

516     public void processingInstruction(String JavaDoc target, String JavaDoc data) throws SAXException JavaDoc
517     {
518     }
519
520     /*
521      * (non-Javadoc)
522      * @see org.xml.sax.ContentHandler#skippedEntity(java.lang.String)
523      */

524     public void skippedEntity(String JavaDoc name) throws SAXException JavaDoc
525     {
526     }
527
528     /*
529      * (non-Javadoc)
530      * @see org.xml.sax.ErrorHandler#warning(org.xml.sax.SAXParseException)
531      */

532     public void warning(SAXParseException JavaDoc exception) throws SAXException JavaDoc
533     {
534     }
535
536     /*
537      * (non-Javadoc)
538      * @see org.xml.sax.ErrorHandler#error(org.xml.sax.SAXParseException)
539      */

540     public void error(SAXParseException JavaDoc exception) throws SAXException JavaDoc
541     {
542     }
543
544     /*
545      * (non-Javadoc)
546      * @see org.xml.sax.ErrorHandler#fatalError(org.xml.sax.SAXParseException)
547      */

548     public void fatalError(SAXParseException JavaDoc exception) throws SAXException JavaDoc
549     {
550     }
551
552 }
553
Popular Tags