KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > repo > importer > ImporterComponent


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.repo.importer;
18
19 import java.io.IOException JavaDoc;
20 import java.io.InputStream JavaDoc;
21 import java.io.Reader JavaDoc;
22 import java.io.Serializable JavaDoc;
23 import java.util.ArrayList JavaDoc;
24 import java.util.Collection JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import java.util.HashSet JavaDoc;
27 import java.util.List JavaDoc;
28 import java.util.Map JavaDoc;
29 import java.util.Set JavaDoc;
30
31 import org.alfresco.error.AlfrescoRuntimeException;
32 import org.alfresco.model.ContentModel;
33 import org.alfresco.repo.policy.BehaviourFilter;
34 import org.alfresco.service.cmr.dictionary.AssociationDefinition;
35 import org.alfresco.service.cmr.dictionary.ChildAssociationDefinition;
36 import org.alfresco.service.cmr.dictionary.ClassDefinition;
37 import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
38 import org.alfresco.service.cmr.dictionary.DictionaryService;
39 import org.alfresco.service.cmr.dictionary.PropertyDefinition;
40 import org.alfresco.service.cmr.dictionary.TypeDefinition;
41 import org.alfresco.service.cmr.repository.ChildAssociationRef;
42 import org.alfresco.service.cmr.repository.ContentData;
43 import org.alfresco.service.cmr.repository.ContentService;
44 import org.alfresco.service.cmr.repository.ContentWriter;
45 import org.alfresco.service.cmr.repository.InvalidNodeRefException;
46 import org.alfresco.service.cmr.repository.NodeRef;
47 import org.alfresco.service.cmr.repository.NodeService;
48 import org.alfresco.service.cmr.repository.XPathException;
49 import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
50 import org.alfresco.service.cmr.rule.RuleService;
51 import org.alfresco.service.cmr.search.ResultSet;
52 import org.alfresco.service.cmr.search.SearchParameters;
53 import org.alfresco.service.cmr.search.SearchService;
54 import org.alfresco.service.cmr.security.AccessPermission;
55 import org.alfresco.service.cmr.security.AccessStatus;
56 import org.alfresco.service.cmr.security.AuthenticationService;
57 import org.alfresco.service.cmr.security.AuthorityService;
58 import org.alfresco.service.cmr.security.OwnableService;
59 import org.alfresco.service.cmr.security.PermissionService;
60 import org.alfresco.service.cmr.view.ImportPackageHandler;
61 import org.alfresco.service.cmr.view.ImporterBinding;
62 import org.alfresco.service.cmr.view.ImporterException;
63 import org.alfresco.service.cmr.view.ImporterProgress;
64 import org.alfresco.service.cmr.view.ImporterService;
65 import org.alfresco.service.cmr.view.Location;
66 import org.alfresco.service.cmr.view.ImporterBinding.UUID_BINDING;
67 import org.alfresco.service.namespace.NamespaceService;
68 import org.alfresco.service.namespace.QName;
69 import org.alfresco.util.ParameterCheck;
70 import org.springframework.core.io.DefaultResourceLoader;
71 import org.springframework.core.io.Resource;
72 import org.springframework.core.io.ResourceLoader;
73 import org.springframework.util.StringUtils;
74 import org.xml.sax.ContentHandler JavaDoc;
75
76
77 /**
78  * Default implementation of the Importer Service
79  *
80  * @author David Caruana
81  */

82 public class ImporterComponent
83     implements ImporterService
84 {
85     // default importer
86
// TODO: Allow registration of plug-in parsers (by namespace)
87
private Parser viewParser;
88
89     // supporting services
90
private NamespaceService namespaceService;
91     private DictionaryService dictionaryService;
92     private BehaviourFilter behaviourFilter;
93     private NodeService nodeService;
94     private SearchService searchService;
95     private ContentService contentService;
96     private RuleService ruleService;
97     private PermissionService permissionService;
98     private AuthorityService authorityService;
99     private AuthenticationService authenticationService;
100     private OwnableService ownableService;
101
102     // binding markers
103
private static final String JavaDoc START_BINDING_MARKER = "${";
104     private static final String JavaDoc END_BINDING_MARKER = "}";
105     
106     
107     /**
108      * @param viewParser the default parser
109      */

110     public void setViewParser(Parser viewParser)
111     {
112         this.viewParser = viewParser;
113     }
114     
115     /**
116      * @param nodeService the node service
117      */

118     public void setNodeService(NodeService nodeService)
119     {
120         this.nodeService = nodeService;
121     }
122
123     /**
124      * @param searchService the service to perform path searches
125      */

126     public void setSearchService(SearchService searchService)
127     {
128         this.searchService = searchService;
129     }
130
131     /**
132      * @param contentService the content service
133      */

134     public void setContentService(ContentService contentService)
135     {
136         this.contentService = contentService;
137     }
138     
139     /**
140      * @param dictionaryService the dictionary service
141      */

142     public void setDictionaryService(DictionaryService dictionaryService)
143     {
144         this.dictionaryService = dictionaryService;
145     }
146     
147     /**
148      * @param namespaceService the namespace service
149      */

150     public void setNamespaceService(NamespaceService namespaceService)
151     {
152         this.namespaceService = namespaceService;
153     }
154
155     /**
156      * @param behaviourFilter policy behaviour filter
157      */

158     public void setBehaviourFilter(BehaviourFilter behaviourFilter)
159     {
160         this.behaviourFilter = behaviourFilter;
161     }
162
163     /**
164      * TODO: Remove this in favour of appropriate rule disabling
165      *
166      * @param ruleService rule service
167      */

168     public void setRuleService(RuleService ruleService)
169     {
170         this.ruleService = ruleService;
171     }
172     
173     /**
174      * @param permissionService permissionService
175      */

176     public void setPermissionService(PermissionService permissionService)
177     {
178         this.permissionService = permissionService;
179     }
180     
181     /**
182      * @param authorityService authorityService
183      */

184     public void setAuthorityService(AuthorityService authorityService)
185     {
186         this.authorityService = authorityService;
187     }
188
189     /**
190      * @param authenticationService authenticationService
191      */

192     public void setAuthenticationService(AuthenticationService authenticationService)
193     {
194         this.authenticationService = authenticationService;
195     }
196     
197     /**
198      * @param ownableService ownableService
199      */

200     public void setOwnableService(OwnableService ownableService)
201     {
202         this.ownableService = ownableService;
203     }
204
205     
206     /* (non-Javadoc)
207      * @see org.alfresco.service.cmr.view.ImporterService#importView(java.io.InputStreamReader, org.alfresco.service.cmr.view.Location, java.util.Properties, org.alfresco.service.cmr.view.ImporterProgress)
208      */

209     public void importView(Reader JavaDoc viewReader, Location location, ImporterBinding binding, ImporterProgress progress)
210     {
211         NodeRef nodeRef = getNodeRef(location, binding);
212         parserImport(nodeRef, location.getChildAssocType(), viewReader, new DefaultStreamHandler(), binding, progress);
213     }
214
215     /* (non-Javadoc)
216      * @see org.alfresco.service.cmr.view.ImporterService#importView(org.alfresco.service.cmr.view.ImportPackageHandler, org.alfresco.service.cmr.view.Location, org.alfresco.service.cmr.view.ImporterBinding, org.alfresco.service.cmr.view.ImporterProgress)
217      */

218     public void importView(ImportPackageHandler importHandler, Location location, ImporterBinding binding, ImporterProgress progress) throws ImporterException
219     {
220         importHandler.startImport();
221         Reader JavaDoc dataFileReader = importHandler.getDataStream();
222         NodeRef nodeRef = getNodeRef(location, binding);
223         parserImport(nodeRef, location.getChildAssocType(), dataFileReader, importHandler, binding, progress);
224         importHandler.endImport();
225     }
226     
227     /**
228      * Get Node Reference from Location
229      *
230      * @param location the location to extract node reference from
231      * @param binding import configuration
232      * @return node reference
233      */

234     private NodeRef getNodeRef(Location location, ImporterBinding binding)
235     {
236         ParameterCheck.mandatory("Location", location);
237     
238         // Establish node to import within
239
NodeRef nodeRef = location.getNodeRef();
240         if (nodeRef == null)
241         {
242             // If a specific node has not been provided, default to the root
243
nodeRef = nodeService.getRootNode(location.getStoreRef());
244         }
245         
246         // Resolve to path within node, if one specified
247
String JavaDoc path = location.getPath();
248         if (path != null && path.length() >0)
249         {
250             // Create a valid path and search
251
path = bindPlaceHolder(path, binding);
252             path = createValidPath(path);
253             List JavaDoc<NodeRef> nodeRefs = searchService.selectNodes(nodeRef, path, null, namespaceService, false);
254             if (nodeRefs.size() == 0)
255             {
256                 throw new ImporterException("Path " + path + " within node " + nodeRef + " does not exist - the path must resolve to a valid location");
257             }
258             if (nodeRefs.size() > 1)
259             {
260                 throw new ImporterException("Path " + path + " within node " + nodeRef + " found too many locations - the path must resolve to one location");
261             }
262             nodeRef = nodeRefs.get(0);
263         }
264     
265         // TODO: Check Node actually exists
266

267         return nodeRef;
268     }
269     
270     /**
271      * Bind the specified value to the passed configuration values if it is a place holder
272      *
273      * @param value the value to bind
274      * @param binding the configuration properties to bind to
275      * @return the bound value
276      */

277     private String JavaDoc bindPlaceHolder(String JavaDoc value, ImporterBinding binding)
278     {
279         if (binding != null)
280         {
281             int iStartBinding = value.indexOf(START_BINDING_MARKER);
282             while (iStartBinding != -1)
283             {
284                 int iEndBinding = value.indexOf(END_BINDING_MARKER, iStartBinding + START_BINDING_MARKER.length());
285                 if (iEndBinding == -1)
286                 {
287                     throw new ImporterException("Cannot find end marker " + END_BINDING_MARKER + " within value " + value);
288                 }
289                 
290                 String JavaDoc key = value.substring(iStartBinding + START_BINDING_MARKER.length(), iEndBinding);
291                 String JavaDoc keyValue = binding.getValue(key);
292                 value = StringUtils.replace(value, START_BINDING_MARKER + key + END_BINDING_MARKER, keyValue == null ? "" : keyValue);
293                 iStartBinding = value.indexOf(START_BINDING_MARKER);
294             }
295         }
296         return value;
297     }
298     
299     /**
300      * Create a valid path
301      *
302      * @param path
303      * @return
304      */

305     private String JavaDoc createValidPath(String JavaDoc path)
306     {
307         StringBuffer JavaDoc validPath = new StringBuffer JavaDoc(path.length());
308         String JavaDoc[] segments = StringUtils.delimitedListToStringArray(path, "/");
309         for (int i = 0; i < segments.length; i++)
310         {
311             if (segments[i] != null && segments[i].length() > 0)
312             {
313                 String JavaDoc[] qnameComponents = QName.splitPrefixedQName(segments[i]);
314                 QName segmentQName = QName.createQName(qnameComponents[0], QName.createValidLocalName(qnameComponents[1]), namespaceService);
315                 validPath.append(segmentQName.toPrefixString());
316             }
317             if (i < (segments.length -1))
318             {
319                 validPath.append("/");
320             }
321         }
322         return validPath.toString();
323     }
324     
325     /**
326      * Perform Import via Parser
327      *
328      * @param nodeRef node reference to import under
329      * @param childAssocType the child association type to import under
330      * @param inputStream the input stream to import from
331      * @param streamHandler the content property import stream handler
332      * @param binding import configuration
333      * @param progress import progress
334      */

335     public void parserImport(NodeRef nodeRef, QName childAssocType, Reader JavaDoc viewReader, ImportPackageHandler streamHandler, ImporterBinding binding, ImporterProgress progress)
336     {
337         ParameterCheck.mandatory("Node Reference", nodeRef);
338         ParameterCheck.mandatory("View Reader", viewReader);
339         ParameterCheck.mandatory("Stream Handler", streamHandler);
340         
341         Importer nodeImporter = new NodeImporter(nodeRef, childAssocType, binding, streamHandler, progress);
342         try
343         {
344             nodeImporter.start();
345             viewParser.parse(viewReader, nodeImporter);
346             nodeImporter.end();
347         }
348         catch(RuntimeException JavaDoc e)
349         {
350             nodeImporter.error(e);
351             throw e;
352         }
353     }
354     
355     /**
356      * Perform import via Content Handler
357      *
358      * @param nodeRef node reference to import under
359      * @param childAssocType the child association type to import under
360      * @param handler the import content handler
361      * @param binding import configuration
362      * @param progress import progress
363      * @return content handler to interact with
364      */

365     public ContentHandler JavaDoc handlerImport(NodeRef nodeRef, QName childAssocType, ImportContentHandler handler, ImporterBinding binding, ImporterProgress progress)
366     {
367         ParameterCheck.mandatory("Node Reference", nodeRef);
368
369         DefaultContentHandler defaultHandler = new DefaultContentHandler(handler);
370         ImportPackageHandler streamHandler = new ContentHandlerStreamHandler(defaultHandler);
371         Importer nodeImporter = new NodeImporter(nodeRef, childAssocType, binding, streamHandler, progress);
372         defaultHandler.setImporter(nodeImporter);
373         return defaultHandler;
374     }
375
376     /**
377      * Encapsulate how a node is imported into the repository
378      */

379     public interface NodeImporterStrategy
380     {
381         /**
382          * Import a node
383          *
384          * @param node to import
385          */

386         public NodeRef importNode(ImportNode node);
387     }
388     
389     /**
390      * Default Importer strategy
391      *
392      * @author David Caruana
393      */

394     private class NodeImporter
395         implements Importer
396     {
397         private NodeRef rootRef;
398         private QName rootAssocType;
399         private ImporterBinding binding;
400         private ImporterProgress progress;
401         private ImportPackageHandler streamHandler;
402         private NodeImporterStrategy importStrategy;
403         private UpdateExistingNodeImporterStrategy updateStrategy;
404
405         // Import tracking
406
private List JavaDoc<ImportedNodeRef> nodeRefs = new ArrayList JavaDoc<ImportedNodeRef>();
407
408         /**
409          * Construct
410          *
411          * @param rootRef
412          * @param rootAssocType
413          * @param binding
414          * @param progress
415          */

416         private NodeImporter(NodeRef rootRef, QName rootAssocType, ImporterBinding binding, ImportPackageHandler streamHandler, ImporterProgress progress)
417         {
418             this.rootRef = rootRef;
419             this.rootAssocType = rootAssocType;
420             this.binding = binding;
421             this.progress = progress;
422             this.streamHandler = streamHandler;
423             this.importStrategy = createNodeImporterStrategy(binding == null ? null : binding.getUUIDBinding());
424             this.updateStrategy = new UpdateExistingNodeImporterStrategy();
425         }
426
427         /**
428          * Create Node Importer Strategy
429          *
430          * @param uuidBinding UUID Binding
431          * @return Node Importer Strategy
432          */

433         private NodeImporterStrategy createNodeImporterStrategy(ImporterBinding.UUID_BINDING uuidBinding)
434         {
435             if (uuidBinding == null)
436             {
437                 return new CreateNewNodeImporterStrategy(true);
438             }
439             else if (uuidBinding.equals(UUID_BINDING.CREATE_NEW))
440             {
441                 return new CreateNewNodeImporterStrategy(true);
442             }
443             else if (uuidBinding.equals(UUID_BINDING.REMOVE_EXISTING))
444             {
445                 return new RemoveExistingNodeImporterStrategy();
446             }
447             else if (uuidBinding.equals(UUID_BINDING.REPLACE_EXISTING))
448             {
449                 return new ReplaceExistingNodeImporterStrategy();
450             }
451             else if (uuidBinding.equals(UUID_BINDING.UPDATE_EXISTING))
452             {
453                 return new UpdateExistingNodeImporterStrategy();
454             }
455             else if (uuidBinding.equals(UUID_BINDING.THROW_ON_COLLISION))
456             {
457                 return new ThrowOnCollisionNodeImporterStrategy();
458             }
459             else
460             {
461                 return new CreateNewNodeImporterStrategy(true);
462             }
463         }
464         
465         /* (non-Javadoc)
466          * @see org.alfresco.repo.importer.Importer#getRootRef()
467          */

468         public NodeRef getRootRef()
469         {
470             return rootRef;
471         }
472
473         /* (non-Javadoc)
474          * @see org.alfresco.repo.importer.Importer#getRootAssocType()
475          */

476         public QName getRootAssocType()
477         {
478             return rootAssocType;
479         }
480         
481         /* (non-Javadoc)
482          * @see org.alfresco.repo.importer.Importer#start()
483          */

484         public void start()
485         {
486             reportStarted();
487         }
488        
489         /* (non-Javadoc)
490          * @see org.alfresco.repo.importer.Importer#importMetaData(java.util.Map)
491          */

492         public void importMetaData(Map JavaDoc<QName, String JavaDoc> properties)
493         {
494             // Determine if we're importing a complete repository
495
String JavaDoc path = properties.get(QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "exportOf"));
496             if (path != null && path.equals("/"))
497             {
498                 // Only allow complete repository import into root
499
NodeRef storeRootRef = nodeService.getRootNode(rootRef.getStoreRef());
500                 if (!storeRootRef.equals(rootRef))
501                 {
502                     throw new ImporterException("A complete repository package cannot be imported here");
503                 }
504             }
505         }
506
507         /* (non-Javadoc)
508          * @see org.alfresco.repo.importer.Importer#importNode(org.alfresco.repo.importer.ImportNode)
509          */

510         public NodeRef importNode(ImportNode context)
511         {
512             // import node
513
NodeRef nodeRef;
514             if (context.isReference())
515             {
516                 nodeRef = linkNode(context);
517             }
518             else
519             {
520                 nodeRef = importStrategy.importNode(context);
521             }
522             
523             // apply aspects
524
for (QName aspect : context.getNodeAspects())
525             {
526                 if (nodeService.hasAspect(nodeRef, aspect) == false)
527                 {
528                     nodeService.addAspect(nodeRef, aspect, null); // all properties previously added
529
reportAspectAdded(nodeRef, aspect);
530                 }
531             }
532
533             // import content, if applicable
534
for (Map.Entry JavaDoc<QName,Serializable JavaDoc> property : context.getProperties().entrySet())
535             {
536                 PropertyDefinition propertyDef = dictionaryService.getProperty(property.getKey());
537                 if (propertyDef != null && propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT))
538                 {
539                     importContent(nodeRef, property.getKey(), (String JavaDoc)property.getValue());
540                 }
541             }
542             
543             return nodeRef;
544         }
545
546         /**
547          * Link an existing Node
548          *
549          * @param context node to link in
550          * @return node reference of child linked in
551          */

552         private NodeRef linkNode(ImportNode context)
553         {
554             ImportParent parentContext = context.getParentContext();
555             NodeRef parentRef = parentContext.getParentRef();
556             
557             // determine the node reference to link to
558
String JavaDoc uuid = context.getUUID();
559             if (uuid == null || uuid.length() == 0)
560             {
561                 throw new ImporterException("Node reference does not specify a reference to follow.");
562             }
563             NodeRef referencedRef = new NodeRef(rootRef.getStoreRef(), uuid);
564
565             // Note: do not link references that are defined in the root of the import
566
if (!parentRef.equals(getRootRef()))
567             {
568                 // determine child assoc type
569
QName assocType = getAssocType(context);
570                 AssociationDefinition assocDef = dictionaryService.getAssociation(assocType);
571                 if (assocDef.isChild())
572                 {
573                     // determine child name
574
QName childQName = getChildName(context);
575                     if (childQName == null)
576                     {
577                         String JavaDoc name = (String JavaDoc)nodeService.getProperty(referencedRef, ContentModel.PROP_NAME);
578                         if (name == null || name.length() == 0)
579                         {
580                             throw new ImporterException("Cannot determine node reference child name");
581                         }
582                         String JavaDoc localName = QName.createValidLocalName(name);
583                         childQName = QName.createQName(assocType.getNamespaceURI(), localName);
584                     }
585                 
586                     // create the secondary link
587
nodeService.addChild(parentRef, referencedRef, assocType, childQName);
588                     reportNodeLinked(referencedRef, parentRef, assocType, childQName);
589                 }
590                 else
591                 {
592                     nodeService.createAssociation(parentRef, referencedRef, assocType);
593                     reportNodeLinked(parentRef, referencedRef, assocType, null);
594                 }
595             }
596             
597             // second, perform any specified udpates to the node
598
updateStrategy.importNode(context);
599             return referencedRef;
600         }
601         
602         /**
603          * Import Node Content.
604          * <p>
605          * The content URL, if present, will be a local URL. This import copies the content
606          * from the local URL to a server-assigned location.
607          *
608          * @param nodeRef containing node
609          * @param propertyName the name of the content-type property
610          * @param contentData the identifier of the content to import
611          */

612         private void importContent(NodeRef nodeRef, QName propertyName, String JavaDoc importContentData)
613         {
614             // bind import content data description
615
DataTypeDefinition dataTypeDef = dictionaryService.getDataType(DataTypeDefinition.CONTENT);
616             importContentData = bindPlaceHolder(importContentData, binding);
617             if (importContentData != null && importContentData.length() > 0)
618             {
619                 ContentData contentData = (ContentData)DefaultTypeConverter.INSTANCE.convert(dataTypeDef, importContentData);
620                 String JavaDoc contentUrl = contentData.getContentUrl();
621                 if (contentUrl != null && contentUrl.length() > 0)
622                 {
623                     // import the content from the url
624
InputStream JavaDoc contentStream = streamHandler.importStream(contentUrl);
625                     ContentWriter writer = contentService.getWriter(nodeRef, propertyName, true);
626                     writer.setEncoding(contentData.getEncoding());
627                     writer.setMimetype(contentData.getMimetype());
628                     writer.putContent(contentStream);
629                     reportContentCreated(nodeRef, contentUrl);
630                 }
631             }
632         }
633         
634         /* (non-Javadoc)
635          * @see org.alfresco.repo.importer.Importer#childrenImported(org.alfresco.service.cmr.repository.NodeRef)
636          */

637         public void childrenImported(NodeRef nodeRef)
638         {
639             behaviourFilter.enableBehaviours(nodeRef);
640             ruleService.enableRules(nodeRef);
641         }
642
643         /* (non-Javadoc)
644          * @see org.alfresco.repo.importer.Importer#resolvePath(java.lang.String)
645          */

646         public NodeRef resolvePath(String JavaDoc path)
647         {
648             NodeRef referencedRef = null;
649             if (path != null && path.length() > 0)
650             {
651                 referencedRef = resolveImportedNodeRef(rootRef, path);
652             }
653             return referencedRef;
654         }
655         
656         /* (non-Javadoc)
657          * @see org.alfresco.repo.importer.Importer#end()
658          */

659         public void end()
660         {
661             // Bind all node references to destination space
662
for (ImportedNodeRef importedRef : nodeRefs)
663             {
664                 Serializable JavaDoc refProperty = null;
665                 if (importedRef.value != null)
666                 {
667                     if (importedRef.value instanceof Collection JavaDoc)
668                     {
669                         Collection JavaDoc<String JavaDoc> unresolvedRefs = (Collection JavaDoc<String JavaDoc>)importedRef.value;
670                         List JavaDoc<NodeRef> resolvedRefs = new ArrayList JavaDoc<NodeRef>(unresolvedRefs.size());
671                         for (String JavaDoc unresolvedRef : unresolvedRefs)
672                         {
673                             NodeRef nodeRef = resolveImportedNodeRef(importedRef.context.getNodeRef(), unresolvedRef);
674                             if (nodeRef == null)
675                             {
676                                 // TODO: Probably need an alternative mechanism here e.g. report warning
677
throw new ImporterException("Failed to find item referenced (in property " + importedRef.property + ") as " + importedRef.value);
678                             }
679                             resolvedRefs.add(nodeRef);
680                         }
681                         refProperty = (Serializable JavaDoc)resolvedRefs;
682                     }
683                     else
684                     {
685                         refProperty = resolveImportedNodeRef(importedRef.context.getNodeRef(), (String JavaDoc)importedRef.value);
686                         if (refProperty == null)
687                         {
688                             // TODO: Probably need an alternative mechanism here e.g. report warning
689
throw new ImporterException("Failed to find item referenced (in property " + importedRef.property + ") as " + importedRef.value);
690                         }
691                     }
692                 }
693                 
694                 // Set node reference on source node
695
Set JavaDoc<QName> disabledBehaviours = getDisabledBehaviours(importedRef.context);
696                 try
697                 {
698                     for (QName disabledBehaviour: disabledBehaviours)
699                     {
700                         behaviourFilter.disableBehaviour(importedRef.context.getNodeRef(), disabledBehaviour);
701                     }
702                     nodeService.setProperty(importedRef.context.getNodeRef(), importedRef.property, refProperty);
703                     if (progress != null)
704                     {
705                         progress.propertySet(importedRef.context.getNodeRef(), importedRef.property, refProperty);
706                     }
707                 }
708                 finally
709                 {
710                     behaviourFilter.enableBehaviours(importedRef.context.getNodeRef());
711                 }
712             }
713             
714             reportCompleted();
715         }
716
717         /*
718          * (non-Javadoc)
719          * @see org.alfresco.repo.importer.Importer#error(java.lang.Throwable)
720          */

721         public void error(Throwable JavaDoc e)
722         {
723             behaviourFilter.enableAllBehaviours();
724             reportError(e);
725         }
726
727         /**
728          * Get the child name to import node under
729          *
730          * @param context the node
731          * @return the child name
732          */

733         private QName getChildName(ImportNode context)
734         {
735             QName assocType = getAssocType(context);
736             QName childQName = null;
737     
738             // Determine child name
739
String JavaDoc childName = context.getChildName();
740             if (childName != null)
741             {
742                 childName = bindPlaceHolder(childName, binding);
743                 String JavaDoc[] qnameComponents = QName.splitPrefixedQName(childName);
744                 childQName = QName.createQName(qnameComponents[0], QName.createValidLocalName(qnameComponents[1]), namespaceService);
745             }
746             else
747             {
748                 Map JavaDoc<QName, Serializable JavaDoc> typeProperties = context.getProperties();
749                 String JavaDoc name = (String JavaDoc)typeProperties.get(ContentModel.PROP_NAME);
750                 if (name != null && name.length() > 0)
751                 {
752                     name = bindPlaceHolder(name, binding);
753                     String JavaDoc localName = QName.createValidLocalName(name);
754                     childQName = QName.createQName(assocType.getNamespaceURI(), localName);
755                 }
756             }
757             
758             return childQName;
759         }
760         
761         /**
762          * Get appropriate child association type for node to import under
763          *
764          * @param context node to import
765          * @return child association type name
766          */

767         private QName getAssocType(ImportNode context)
768         {
769             QName assocType = context.getParentContext().getAssocType();
770             if (assocType != null)
771             {
772                 // return explicitly set association type
773
return assocType;
774             }
775             
776             //
777
// Derive association type
778
//
779

780             // build type and aspect list for node
781
List JavaDoc<QName> nodeTypes = new ArrayList JavaDoc<QName>();
782             nodeTypes.add(context.getTypeDefinition().getName());
783             for (QName aspect : context.getNodeAspects())
784             {
785                 nodeTypes.add(aspect);
786             }
787             
788             // build target class types for parent
789
Map JavaDoc<QName, QName> targetTypes = new HashMap JavaDoc<QName, QName>();
790             QName parentType = nodeService.getType(context.getParentContext().getParentRef());
791             ClassDefinition classDef = dictionaryService.getClass(parentType);
792             Map JavaDoc<QName, ChildAssociationDefinition> childAssocDefs = classDef.getChildAssociations();
793             for (ChildAssociationDefinition childAssocDef : childAssocDefs.values())
794             {
795                 targetTypes.put(childAssocDef.getTargetClass().getName(), childAssocDef.getName());
796             }
797             Set JavaDoc<QName> parentAspects = nodeService.getAspects(context.getParentContext().getParentRef());
798             for (QName parentAspect : parentAspects)
799             {
800                 classDef = dictionaryService.getClass(parentAspect);
801                 childAssocDefs = classDef.getChildAssociations();
802                 for (ChildAssociationDefinition childAssocDef : childAssocDefs.values())
803                 {
804                     targetTypes.put(childAssocDef.getTargetClass().getName(), childAssocDef.getName());
805                 }
806             }
807             
808             // find target class that is closest to node type or aspects
809
QName closestAssocType = null;
810             int closestHit = 1;
811             for (QName nodeType : nodeTypes)
812             {
813                 for (QName targetType : targetTypes.keySet())
814                 {
815                     QName testType = nodeType;
816                     int howClose = 1;
817                     while (testType != null)
818                     {
819                         howClose--;
820                         if (targetType.equals(testType) && howClose < closestHit)
821                         {
822                             closestAssocType = targetTypes.get(targetType);
823                             closestHit = howClose;
824                             break;
825                         }
826                         ClassDefinition testTypeDef = dictionaryService.getClass(testType);
827                         testType = (testTypeDef == null) ? null : testTypeDef.getParentName();
828                     }
829                 }
830             }
831             
832             return closestAssocType;
833         }
834         
835         /**
836          * For the given import node, return the behaviours to disable during import
837          *
838          * @param context import node
839          * @return the disabled behaviours
840          */

841         private Set JavaDoc<QName> getDisabledBehaviours(ImportNode context)
842         {
843             Set JavaDoc<QName> classNames = new HashSet JavaDoc<QName>();
844             
845             // disable the type
846
TypeDefinition typeDef = context.getTypeDefinition();
847             classNames.add(typeDef.getName());
848
849             // disable the aspects imported on the node
850
classNames.addAll(context.getNodeAspects());
851             
852             // note: do not disable default aspects that are not imported on the node.
853
// this means they'll be added on import
854

855             return classNames;
856         }
857         
858         /**
859          * Bind properties
860          *
861          * @param properties
862          * @return
863          */

864         private Map JavaDoc<QName, Serializable JavaDoc> bindProperties(ImportNode context)
865         {
866             Map JavaDoc<QName, Serializable JavaDoc> properties = context.getProperties();
867             Map JavaDoc<QName, DataTypeDefinition> datatypes = context.getPropertyDatatypes();
868             Map JavaDoc<QName, Serializable JavaDoc> boundProperties = new HashMap JavaDoc<QName, Serializable JavaDoc>(properties.size());
869             for (QName property : properties.keySet())
870             {
871                 // get property value
872
Serializable JavaDoc value = properties.get(property);
873
874                 // get property datatype
875
DataTypeDefinition valueDataType = datatypes.get(property);
876                 if (valueDataType == null)
877                 {
878                     PropertyDefinition propDef = dictionaryService.getProperty(property);
879                     if (propDef != null)
880                     {
881                         valueDataType = propDef.getDataType();
882                     }
883                 }
884
885                 // filter out content properties (they're imported later)
886
if (valueDataType != null && valueDataType.getName().equals(DataTypeDefinition.CONTENT))
887                 {
888                     continue;
889                 }
890                 
891                 // bind property value to configuration and convert to appropriate type
892
if (value instanceof Collection JavaDoc)
893                 {
894                     List JavaDoc<Serializable JavaDoc> boundCollection = new ArrayList JavaDoc<Serializable JavaDoc>();
895                     for (String JavaDoc collectionValue : (Collection JavaDoc<String JavaDoc>)value)
896                     {
897                         Serializable JavaDoc objValue = bindValue(context, property, valueDataType, collectionValue);
898                         boundCollection.add(objValue);
899                     }
900                     value = (Serializable JavaDoc)boundCollection;
901                 }
902                 else
903                 {
904                     value = bindValue(context, property, valueDataType, (String JavaDoc)value);
905                 }
906
907                 // choose to provide property on node creation or at end of import for lazy binding
908
if (valueDataType != null && (valueDataType.getName().equals(DataTypeDefinition.NODE_REF) || valueDataType.getName().equals(DataTypeDefinition.CATEGORY)))
909                 {
910                     // record node reference for end-of-import binding
911
ImportedNodeRef importedRef = new ImportedNodeRef(context, property, value);
912                     nodeRefs.add(importedRef);
913                 }
914                 else
915                 {
916                     // property ready to be set on Node creation / update
917
boundProperties.put(property, value);
918                 }
919             }
920             
921             return boundProperties;
922         }
923
924         /**
925          * Bind property value
926          *
927          * @param valueType value type
928          * @param value string form of value
929          * @return the bound value
930          */

931         private Serializable JavaDoc bindValue(ImportNode context, QName property, DataTypeDefinition valueType, String JavaDoc value)
932         {
933             Serializable JavaDoc objValue = null;
934             if (value != null && valueType != null)
935             {
936                 String JavaDoc strValue = bindPlaceHolder(value, binding);
937                 if ((valueType.getName().equals(DataTypeDefinition.NODE_REF) || valueType.getName().equals(DataTypeDefinition.CATEGORY)))
938                 {
939                     objValue = strValue;
940                 }
941                 else
942                 {
943                     objValue = (Serializable JavaDoc)DefaultTypeConverter.INSTANCE.convert(valueType, strValue);
944                 }
945                 
946             }
947             return objValue;
948         }
949
950         /**
951          * Resolve imported reference relative to specified node
952          *
953          * @param sourceNodeRef context to resolve within
954          * @param importedRef reference to resolve
955          * @return
956          */

957         private NodeRef resolveImportedNodeRef(NodeRef sourceNodeRef, String JavaDoc importedRef)
958         {
959             // Resolve path to node reference
960
NodeRef nodeRef = null;
961             importedRef = bindPlaceHolder(importedRef, binding);
962
963             if (importedRef.equals("/"))
964             {
965                 nodeRef = sourceNodeRef;
966             }
967             else if (importedRef.startsWith("/"))
968             {
969                 // resolve absolute path
970
SearchParameters searchParameters = new SearchParameters();
971                 searchParameters.addStore(sourceNodeRef.getStoreRef());
972                 searchParameters.setLanguage(SearchService.LANGUAGE_LUCENE);
973                 searchParameters.setQuery("PATH:\"" + importedRef + "\"");
974                 searchParameters.excludeDataInTheCurrentTransaction((binding == null) ? true : !binding.allowReferenceWithinTransaction());
975                 ResultSet resultSet = searchService.query(searchParameters);
976                 try
977                 {
978                     if (resultSet.length() > 0)
979                     {
980                         nodeRef = resultSet.getNodeRef(0);
981                     }
982                 }
983                 finally
984                 {
985                     resultSet.close();
986                 }
987             }
988             else
989             {
990                 // resolve relative path
991
try
992                 {
993                     List JavaDoc<NodeRef> nodeRefs = searchService.selectNodes(sourceNodeRef, importedRef, null, namespaceService, false);
994                     if (nodeRefs.size() > 0)
995                     {
996                         nodeRef = nodeRefs.get(0);
997                     }
998                 }
999                 catch(XPathException e)
1000                {
1001                    // attempt to resolve as a node reference
1002
try
1003                    {
1004                        NodeRef directRef = new NodeRef(importedRef);
1005                        if (nodeService.exists(directRef))
1006                        {
1007                            nodeRef = directRef;
1008                        }
1009                    }
1010                    catch(AlfrescoRuntimeException e1)
1011                    {
1012                        // Note: Invalid reference format
1013
}
1014                }
1015            }
1016            
1017            return nodeRef;
1018        }
1019        
1020        /**
1021         * Helper to report start of import
1022         */

1023        private void reportStarted()
1024        {
1025            if (progress != null)
1026            {
1027                progress.started();
1028            }
1029        }
1030        
1031        /**
1032         * Helper to report end of import
1033         */

1034        private void reportCompleted()
1035        {
1036            if (progress != null)
1037            {
1038                progress.completed();
1039            }
1040        }
1041        
1042        /**
1043         * Helper to report error
1044         *
1045         * @param e
1046         */

1047        private void reportError(Throwable JavaDoc e)
1048        {
1049            if (progress != null)
1050            {
1051                progress.error(e);
1052            }
1053        }
1054        
1055        /**
1056         * Helper to report node created progress
1057         *
1058         * @param progress
1059         * @param childAssocRef
1060         */

1061        private void reportNodeCreated(ChildAssociationRef childAssocRef)
1062        {
1063            if (progress != null)
1064            {
1065                progress.nodeCreated(childAssocRef.getChildRef(), childAssocRef.getParentRef(), childAssocRef.getTypeQName(), childAssocRef.getQName());
1066            }
1067        }
1068
1069        /**
1070         * Helper to report node linked progress
1071         *
1072         * @param progress
1073         * @param childAssocRef
1074         */

1075        private void reportNodeLinked(NodeRef childRef, NodeRef parentRef, QName assocType, QName childName)
1076        {
1077            if (progress != null)
1078            {
1079                progress.nodeLinked(childRef, parentRef, assocType, childName);
1080            }
1081        }
1082
1083        /**
1084         * Helper to report content created progress
1085         *
1086         * @param progress
1087         * @param nodeRef
1088         * @param sourceUrl
1089         */

1090        private void reportContentCreated(NodeRef nodeRef, String JavaDoc sourceUrl)
1091        {
1092            if (progress != null)
1093            {
1094                progress.contentCreated(nodeRef, sourceUrl);
1095            }
1096        }
1097        
1098        /**
1099         * Helper to report aspect added progress
1100         *
1101         * @param progress
1102         * @param nodeRef
1103         * @param aspect
1104         */

1105        private void reportAspectAdded(NodeRef nodeRef, QName aspect)
1106        {
1107            if (progress != null)
1108            {
1109                progress.aspectAdded(nodeRef, aspect);
1110            }
1111        }
1112
1113        /**
1114         * Helper to report property set progress
1115         *
1116         * @param progress
1117         * @param nodeRef
1118         * @param properties
1119         */

1120        private void reportPropertySet(NodeRef nodeRef, Map JavaDoc<QName, Serializable JavaDoc> properties)
1121        {
1122            if (progress != null && properties != null)
1123            {
1124                for (QName property : properties.keySet())
1125                {
1126                    progress.propertySet(nodeRef, property, properties.get(property));
1127                }
1128            }
1129        }
1130
1131        /**
1132         * Helper to report permission set progress
1133         *
1134         * @param nodeRef
1135         * @param permissions
1136         */

1137        private void reportPermissionSet(NodeRef nodeRef, List JavaDoc<AccessPermission> permissions)
1138        {
1139            if (progress != null && permissions != null)
1140            {
1141                for (AccessPermission permission : permissions)
1142                {
1143                    progress.permissionSet(nodeRef, permission);
1144                }
1145            }
1146        }
1147        
1148        /**
1149         * Import strategy where imported nodes are always created regardless of whether a
1150         * node of the same UUID already exists in the repository
1151         */

1152        private class CreateNewNodeImporterStrategy implements NodeImporterStrategy
1153        {
1154            // force allocation of new UUID, even if one already specified
1155
private boolean assignNewUUID;
1156            
1157            /**
1158             * Construct
1159             *
1160             * @param newUUID force allocation of new UUID
1161             */

1162            public CreateNewNodeImporterStrategy(boolean assignNewUUID)
1163            {
1164                this.assignNewUUID = assignNewUUID;
1165            }
1166            
1167            /*
1168             * (non-Javadoc)
1169             * @see org.alfresco.repo.importer.ImporterComponent.NodeImporterStrategy#importNode(org.alfresco.repo.importer.ImportNode)
1170             */

1171            public NodeRef importNode(ImportNode node)
1172            {
1173                TypeDefinition nodeType = node.getTypeDefinition();
1174                NodeRef parentRef = node.getParentContext().getParentRef();
1175                QName assocType = getAssocType(node);
1176                QName childQName = getChildName(node);
1177                if (childQName == null)
1178                {
1179                    throw new ImporterException("Cannot determine child name of node (type: " + nodeType.getName() + ")");
1180                }
1181
1182                // Create initial node (but, first disable behaviour for the node to be created)
1183
Set JavaDoc<QName> disabledBehaviours = getDisabledBehaviours(node);
1184                List JavaDoc<QName> alreadyDisabledBehaviours = new ArrayList JavaDoc<QName>();
1185                for (QName disabledBehaviour: disabledBehaviours)
1186                {
1187                    boolean alreadyDisabled = behaviourFilter.disableBehaviour(disabledBehaviour);
1188                    if (alreadyDisabled)
1189                    {
1190                        alreadyDisabledBehaviours.add(disabledBehaviour);
1191                    }
1192                }
1193                disabledBehaviours.removeAll(alreadyDisabledBehaviours);
1194                
1195                // Build initial map of properties
1196
Map JavaDoc<QName, Serializable JavaDoc> initialProperties = bindProperties(node);
1197                
1198                // Assign UUID if already specified on imported node
1199
if (!assignNewUUID && node.getUUID() != null)
1200                {
1201                    initialProperties.put(ContentModel.PROP_NODE_UUID, node.getUUID());
1202                }
1203                
1204                // Create Node
1205
ChildAssociationRef assocRef = nodeService.createNode(parentRef, assocType, childQName, nodeType.getName(), initialProperties);
1206                NodeRef nodeRef = assocRef.getChildRef();
1207
1208                // Note: non-admin authorities take ownership of new nodes
1209
if (!authorityService.hasAdminAuthority())
1210                {
1211                    ownableService.takeOwnership(nodeRef);
1212                }
1213
1214                // apply permissions
1215
List JavaDoc<AccessPermission> permissions = null;
1216                AccessStatus writePermission = permissionService.hasPermission(nodeRef, PermissionService.CHANGE_PERMISSIONS);
1217                if (authenticationService.isCurrentUserTheSystemUser() || writePermission.equals(AccessStatus.ALLOWED))
1218                {
1219                    permissions = node.getAccessControlEntries();
1220                    for (AccessPermission permission : permissions)
1221                    {
1222                        permissionService.setPermission(nodeRef, permission.getAuthority(), permission.getPermission(), permission.getAccessStatus().equals(AccessStatus.ALLOWED));
1223                    }
1224                    // note: apply inheritance after setting permissions as this may affect whether you can apply permissions
1225
boolean inheritPermissions = node.getInheritPermissions();
1226                    if (!inheritPermissions)
1227                    {
1228                        permissionService.setInheritParentPermissions(nodeRef, false);
1229                    }
1230                }
1231                
1232                // Disable behaviour for the node until the complete node (and its children have been imported)
1233
for (QName disabledBehaviour : disabledBehaviours)
1234                {
1235                    behaviourFilter.enableBehaviour(disabledBehaviour);
1236                }
1237                for (QName disabledBehaviour : disabledBehaviours)
1238                {
1239                    behaviourFilter.disableBehaviour(nodeRef, disabledBehaviour);
1240                }
1241                // TODO: Replace this with appropriate rule/action import handling
1242
ruleService.disableRules(nodeRef);
1243
1244                // Report creation
1245
reportNodeCreated(assocRef);
1246                reportPropertySet(nodeRef, initialProperties);
1247                reportPermissionSet(nodeRef, permissions);
1248
1249                // return newly created node reference
1250
return nodeRef;
1251            }
1252        }
1253        
1254        /**
1255         * Importer strategy where an existing node (one with the same UUID) as a node being
1256         * imported is first removed. The imported node is placed in the location specified
1257         * at import time.
1258         */

1259        private class RemoveExistingNodeImporterStrategy implements NodeImporterStrategy
1260        {
1261            private NodeImporterStrategy createNewStrategy = new CreateNewNodeImporterStrategy(false);
1262            
1263            /*
1264             * (non-Javadoc)
1265             * @see org.alfresco.repo.importer.ImporterComponent.NodeImporterStrategy#importNode(org.alfresco.repo.importer.ImportNode)
1266             */

1267            public NodeRef importNode(ImportNode node)
1268            {
1269                // remove existing node, if node to import has a UUID and an existing node of the same
1270
// uuid already exists
1271
String JavaDoc uuid = node.getUUID();
1272                if (uuid != null && uuid.length() > 0)
1273                {
1274                    NodeRef existingNodeRef = new NodeRef(rootRef.getStoreRef(), uuid);
1275                    if (nodeService.exists(existingNodeRef))
1276                    {
1277                        // remove primary parent link forcing deletion
1278
ChildAssociationRef childAssocRef = nodeService.getPrimaryParent(existingNodeRef);
1279                        
1280                        // TODO: Check for root node
1281
nodeService.removeChild(childAssocRef.getParentRef(), childAssocRef.getChildRef());
1282                    }
1283                }
1284                
1285                // import as if a new node into current import parent location
1286
return createNewStrategy.importNode(node);
1287            }
1288        }
1289
1290        /**
1291         * Importer strategy where an existing node (one with the same UUID) as a node being
1292         * imported is first removed. The imported node is placed under the parent of the removed
1293         * node.
1294         */

1295        private class ReplaceExistingNodeImporterStrategy implements NodeImporterStrategy
1296        {
1297            private NodeImporterStrategy createNewStrategy = new CreateNewNodeImporterStrategy(false);
1298
1299            /*
1300             * (non-Javadoc)
1301             * @see org.alfresco.repo.importer.ImporterComponent.NodeImporterStrategy#importNode(org.alfresco.repo.importer.ImportNode)
1302             */

1303            public NodeRef importNode(ImportNode node)
1304            {
1305                // replace existing node, if node to import has a UUID and an existing node of the same
1306
// uuid already exists
1307
String JavaDoc uuid = node.getUUID();
1308                if (uuid != null && uuid.length() > 0)
1309                {
1310                    NodeRef existingNodeRef = new NodeRef(rootRef.getStoreRef(), uuid);
1311                    if (nodeService.exists(existingNodeRef))
1312                    {
1313                        // remove primary parent link forcing deletion
1314
ChildAssociationRef childAssocRef = nodeService.getPrimaryParent(existingNodeRef);
1315                        nodeService.removeChild(childAssocRef.getParentRef(), childAssocRef.getChildRef());
1316                        
1317                        // update the parent context of the node being imported to the parent of the node just deleted
1318
node.getParentContext().setParentRef(childAssocRef.getParentRef());
1319                        node.getParentContext().setAssocType(childAssocRef.getTypeQName());
1320                    }
1321                }
1322
1323                // import as if a new node
1324
return createNewStrategy.importNode(node);
1325            }
1326        }
1327        
1328        /**
1329         * Import strategy where an error is thrown when importing a node that has the same UUID
1330         * of an existing node in the repository.
1331         */

1332        private class ThrowOnCollisionNodeImporterStrategy implements NodeImporterStrategy
1333        {
1334            private NodeImporterStrategy createNewStrategy = new CreateNewNodeImporterStrategy(false);
1335
1336            /*
1337             * (non-Javadoc)
1338             * @see org.alfresco.repo.importer.ImporterComponent.NodeImporterStrategy#importNode(org.alfresco.repo.importer.ImportNode)
1339             */

1340            public NodeRef importNode(ImportNode node)
1341            {
1342                // if node to import has a UUID and an existing node of the same uuid already exists
1343
// then throw an error
1344
String JavaDoc uuid = node.getUUID();
1345                if (uuid != null && uuid.length() > 0)
1346                {
1347                    NodeRef existingNodeRef = new NodeRef(rootRef.getStoreRef(), uuid);
1348                    if (nodeService.exists(existingNodeRef))
1349                    {
1350                        throw new InvalidNodeRefException("Node " + existingNodeRef + " already exists", existingNodeRef);
1351                    }
1352                }
1353                
1354                // import as if a new node
1355
return createNewStrategy.importNode(node);
1356            }
1357        }
1358        
1359        /**
1360         * Import strategy where imported nodes are updated if a node with the same UUID
1361         * already exists in the repository.
1362         *
1363         * Note: this will only allow incremental update of an existing node - it does not
1364         * delete properties or associations.
1365         */

1366        private class UpdateExistingNodeImporterStrategy implements NodeImporterStrategy
1367        {
1368            private NodeImporterStrategy createNewStrategy = new CreateNewNodeImporterStrategy(false);
1369            
1370            /*
1371             * (non-Javadoc)
1372             * @see org.alfresco.repo.importer.ImporterComponent.NodeImporterStrategy#importNode(org.alfresco.repo.importer.ImportNode)
1373             */

1374            public NodeRef importNode(ImportNode node)
1375            {
1376                // replace existing node, if node to import has a UUID and an existing node of the same
1377
// uuid already exists
1378
String JavaDoc uuid = node.getUUID();
1379                if (uuid != null && uuid.length() > 0)
1380                {
1381                    NodeRef existingNodeRef = new NodeRef(rootRef.getStoreRef(), uuid);
1382                    if (nodeService.exists(existingNodeRef))
1383                    {
1384                        // do the update
1385
Map JavaDoc<QName, Serializable JavaDoc> existingProperties = nodeService.getProperties(existingNodeRef);
1386                        Map JavaDoc<QName, Serializable JavaDoc> updateProperties = bindProperties(node);
1387                        if (updateProperties != null && updateProperties.size() > 0)
1388                        {
1389                            existingProperties.putAll(updateProperties);
1390                            nodeService.setProperties(existingNodeRef, existingProperties);
1391                        }
1392                        
1393                        // Apply permissions
1394
List JavaDoc<AccessPermission> permissions = null;
1395                        AccessStatus writePermission = permissionService.hasPermission(existingNodeRef, PermissionService.CHANGE_PERMISSIONS);
1396                        if (authenticationService.isCurrentUserTheSystemUser() || writePermission.equals(AccessStatus.ALLOWED))
1397                        {
1398                            boolean inheritPermissions = node.getInheritPermissions();
1399                            if (!inheritPermissions)
1400                            {
1401                                permissionService.setInheritParentPermissions(existingNodeRef, false);
1402                            }
1403                            permissions = node.getAccessControlEntries();
1404                            for (AccessPermission permission : permissions)
1405                            {
1406                                permissionService.setPermission(existingNodeRef, permission.getAuthority(), permission.getPermission(), permission.getAccessStatus().equals(AccessStatus.ALLOWED));
1407                            }
1408                        }
1409
1410                        // report update
1411
reportPropertySet(existingNodeRef, updateProperties);
1412                        reportPermissionSet(existingNodeRef, permissions);
1413                        
1414                        return existingNodeRef;
1415                    }
1416                }
1417                
1418                // import as if a new node
1419
return createNewStrategy.importNode(node);
1420            }
1421        }
1422
1423    }
1424
1425    /**
1426     * Imported Node Reference
1427     *
1428     * @author David Caruana
1429     */

1430    private static class ImportedNodeRef
1431    {
1432        /**
1433         * Construct
1434         *
1435         * @param context
1436         * @param property
1437         * @param value
1438         */

1439        private ImportedNodeRef(ImportNode context, QName property, Serializable JavaDoc value)
1440        {
1441            this.context = context;
1442            this.property = property;
1443            this.value = value;
1444        }
1445        
1446        private ImportNode context;
1447        private QName property;
1448        private Serializable JavaDoc value;
1449    }
1450
1451    /**
1452     * Default Import Stream Handler
1453     *
1454     * @author David Caruana
1455     */

1456    private static class DefaultStreamHandler
1457        implements ImportPackageHandler
1458    {
1459        /* (non-Javadoc)
1460         * @see org.alfresco.service.cmr.view.ImportPackageHandler#startImport()
1461         */

1462        public void startImport()
1463        {
1464        }
1465
1466        /* (non-Javadoc)
1467         * @see org.alfresco.service.cmr.view.ImportStreamHandler#importStream(java.lang.String)
1468         */

1469        public InputStream JavaDoc importStream(String JavaDoc content)
1470        {
1471            ResourceLoader loader = new DefaultResourceLoader();
1472            Resource resource = loader.getResource(content);
1473            if (resource.exists() == false)
1474            {
1475                throw new ImporterException("Content URL " + content + " does not exist.");
1476            }
1477            
1478            try
1479            {
1480                return resource.getInputStream();
1481            }
1482            catch(IOException JavaDoc e)
1483            {
1484                throw new ImporterException("Failed to retrieve input stream for content URL " + content);
1485            }
1486        }
1487
1488        /* (non-Javadoc)
1489         * @see org.alfresco.service.cmr.view.ImportPackageHandler#getDataStream()
1490         */

1491        public Reader JavaDoc getDataStream()
1492        {
1493            return null;
1494        }
1495
1496        /* (non-Javadoc)
1497         * @see org.alfresco.service.cmr.view.ImportPackageHandler#endImport()
1498         */

1499        public void endImport()
1500        {
1501        }
1502    }
1503
1504    /**
1505     * Default Import Stream Handler
1506     *
1507     * @author David Caruana
1508     */

1509    private static class ContentHandlerStreamHandler
1510        implements ImportPackageHandler
1511    {
1512        private ImportContentHandler handler;
1513
1514        /**
1515         * Construct
1516         *
1517         * @param handler
1518         */

1519        private ContentHandlerStreamHandler(ImportContentHandler handler)
1520        {
1521            this.handler = handler;
1522        }
1523        
1524        /* (non-Javadoc)
1525         * @see org.alfresco.service.cmr.view.ImportPackageHandler#startImport()
1526         */

1527        public void startImport()
1528        {
1529        }
1530
1531        /* (non-Javadoc)
1532         * @see org.alfresco.service.cmr.view.ImportStreamHandler#importStream(java.lang.String)
1533         */

1534        public InputStream JavaDoc importStream(String JavaDoc content)
1535        {
1536            return handler.importStream(content);
1537        }
1538
1539        /* (non-Javadoc)
1540         * @see org.alfresco.service.cmr.view.ImportPackageHandler#getDataStream()
1541         */

1542        public Reader JavaDoc getDataStream()
1543        {
1544            return null;
1545        }
1546
1547        /* (non-Javadoc)
1548         * @see org.alfresco.service.cmr.view.ImportPackageHandler#endImport()
1549         */

1550        public void endImport()
1551        {
1552        }
1553    }
1554    
1555}
1556
Popular Tags