KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > slide > macro > MacroImpl


1 /*
2  * $Header: /home/cvs/jakarta-slide/src/share/org/apache/slide/macro/MacroImpl.java,v 1.41.2.3 2004/11/08 08:39:18 luetzkendorf Exp $
3  * $Revision: 1.41.2.3 $
4  * $Date: 2004/11/08 08:39:18 $
5  *
6  * ====================================================================
7  *
8  * Copyright 1999-2002 The Apache Software Foundation
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  */

23
24 package org.apache.slide.macro;
25
26 import java.util.Arrays JavaDoc;
27 import java.util.Enumeration JavaDoc;
28 import java.util.HashMap JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import java.util.Map JavaDoc;
31 import java.util.StringTokenizer JavaDoc;
32 import org.apache.slide.common.Domain;
33 import org.apache.slide.common.Namespace;
34 import org.apache.slide.common.NamespaceConfig;
35 import org.apache.slide.common.ServiceAccessException;
36 import org.apache.slide.common.SlideException;
37 import org.apache.slide.common.SlideToken;
38 import org.apache.slide.common.Uri;
39 import org.apache.slide.content.Content;
40 import org.apache.slide.content.NodeProperty;
41 import org.apache.slide.content.NodeRevisionContent;
42 import org.apache.slide.content.NodeRevisionDescriptor;
43 import org.apache.slide.content.NodeRevisionDescriptors;
44 import org.apache.slide.content.NodeRevisionNumber;
45 import org.apache.slide.content.RevisionDescriptorNotFoundException;
46 import org.apache.slide.lock.Lock;
47 import org.apache.slide.lock.NodeLock;
48 import org.apache.slide.lock.ObjectLockedException;
49 import org.apache.slide.macro.CopyRouteRedirector.CopyRoute;
50 import org.apache.slide.security.AccessDeniedException;
51 import org.apache.slide.security.NodePermission;
52 import org.apache.slide.security.Security;
53 import org.apache.slide.store.Store;
54 import org.apache.slide.structure.ActionNode;
55 import org.apache.slide.structure.LinkedObjectNotFoundException;
56 import org.apache.slide.structure.ObjectHasChildrenException;
57 import org.apache.slide.structure.ObjectNode;
58 import org.apache.slide.structure.ObjectNotFoundException;
59 import org.apache.slide.structure.Structure;
60 import org.apache.slide.util.Configuration;
61 import org.apache.slide.event.EventDispatcher;
62 import org.apache.slide.event.MacroEvent;
63 import org.apache.slide.event.VetoException;
64
65 /**
66  * Macro helper class.
67  *
68  * @version $Revision: 1.41.2.3 $
69  */

70 public final class MacroImpl implements Macro {
71     
72     private Namespace namespace;
73     private NamespaceConfig namespaceConfig;
74     private Content contentHelper;
75     private Structure structureHelper;
76     private Security securityHelper;
77     private Lock lockHelper;
78     
79     /**
80      * Constructor.
81      *
82      * @param namespace Namespace
83      * @param namespaceConfig Namespace configuration
84      * @param contentHelper Access to content
85      * @param structureHelper Access to structure
86      */

87     public MacroImpl(Namespace namespace, NamespaceConfig namespaceConfig,
88                      Security securityHelper, Content contentHelper,
89                      Structure structureHelper,
90                      Lock lockHelper) {
91         this.namespace = namespace;
92         this.namespaceConfig = namespaceConfig;
93         this.securityHelper = securityHelper;
94         this.contentHelper = contentHelper;
95         this.structureHelper = structureHelper;
96         this.lockHelper = lockHelper;
97     }
98     
99     /**
100      * Recursive copy with overwrite macro.
101      *
102      * @param token Credentials token
103      * @param sourceUri Uri of the source
104      * @param destinationUri Uri of the destination
105      * @exception CopyMacroException Generic Slide exception
106      */

107     public void copy(SlideToken token, String JavaDoc sourceUri,
108                      String JavaDoc destinationUri)
109         throws CopyMacroException, DeleteMacroException {
110         copy(token, sourceUri, destinationUri,
111                  (CopyRouteRedirector)null, (CopyListener)null,
112                  (DeleteTargetRedirector)null, (DeleteListener)null);
113     }
114     
115     /**
116      * Recursive copy with overwrite macro.
117      *
118      * @param token Credentials token
119      * @param sourceUri Uri of the source
120      * @param destinationUri Uri of the destination
121      * @param copyRedirector the CopyRoutRedirector may be used to redirect
122      * the source and/or destination URI of the
123      * <code>copy</code> operation.
124      * (May be <code>null</code>.)
125      * @param copyListener the CopyListener that will be notified
126      * before and after copying a resource.
127      * (May be <code>null</code>)
128      * @param deleteRedirector the DeleteTargetRedirector may be used to redirect
129      * the <code>delete</code> operation to a different
130      * target. (May be <code>null</code>.)
131      * @param deleteListener the DeleteListener that will be notified
132      * before and after deleting a destination
133      * that will be overwritten by the copy.
134      * (May be <code>null</code>)
135      * @exception CopyMacroException Generic Slide exception
136      */

137     public void copy(SlideToken token, String JavaDoc sourceUri,
138                      String JavaDoc destinationUri, CopyRouteRedirector copyRedirector, CopyListener copyListener,
139                      DeleteTargetRedirector deleteRedirector, DeleteListener deleteListener)
140         throws CopyMacroException, DeleteMacroException {
141         
142         this.copy(token, sourceUri, destinationUri,
143                   RECURSIVE_OVERWRITE_PARAMETERS, copyRedirector, copyListener,
144                   deleteRedirector, deleteListener);
145     }
146     
147     
148     /**
149      * Copy macro.
150      *
151      * @param token Credentials token
152      * @param sourceUri Uri of the source
153      * @param destinationUri Uri of the destination
154      * @param parameters Macro parameters
155      * @exception CopyMacroException Generic Slide exception
156      */

157     public void copy(SlideToken token, String JavaDoc sourceUri,
158                      String JavaDoc destinationUri, MacroParameters parameters)
159         throws CopyMacroException, DeleteMacroException {
160         copy(token, sourceUri, destinationUri, parameters, null, null, null, null);
161     }
162     
163     /**
164      * Copy macro.
165      *
166      * @param token Credentials token
167      * @param sourceUri Uri of the source
168      * @param destinationUri Uri of the destination
169      * @param parameters Macro parameters
170      * @param copyRedirector the CopyRoutRedirector may be used to redirect
171      * the source and/or destination URI of the
172      * <code>copy</code> operation.
173      * (May be <code>null</code>.)
174      * @param copyListener the CopyListener that will be notified
175      * before and after copying a resource.
176      * (May be <code>null</code>)
177      * @param deleteRedirector the DeleteTargetRedirector may be used to redirect
178      * the <code>delete</code> operation to a different
179      * target. (May be <code>null</code>.)
180      * @param deleteListener the DeleteListener that will be notified
181      * before and after deleting a destination
182      * that will be overwritten by the copy.
183      * (May be <code>null</code>)
184      * @exception CopyMacroException Generic Slide exception
185      */

186     public void copy(SlideToken token, String JavaDoc sourceUri,
187                      String JavaDoc destinationUri, MacroParameters parameters,
188                      CopyRouteRedirector copyRedirector, CopyListener copyListener,
189                      DeleteTargetRedirector deleteRedirector, DeleteListener deleteListener)
190         throws CopyMacroException, DeleteMacroException {
191         
192         Domain.debug("Copy " + sourceUri + " to " + destinationUri);
193         
194         // Now performing the actual copy
195
CopyMacroException e = new CopyMacroException("Copy failed");
196         
197         //----------------
198
// handle the case that source and destination are identical
199
if (sourceUri.equals(destinationUri)) {
200             e.addException(new ForbiddenException(sourceUri));
201             throw e;
202         }
203         
204         Map JavaDoc alreadyCopied = new HashMap JavaDoc(); // maps source-UURI -> destination-URI
205
parameters.setParameter( ALREADY_COPIED, alreadyCopied );
206         
207         copyObject(token, sourceUri, destinationUri, parameters, true, e,
208                    copyRedirector, copyListener, deleteRedirector, deleteListener);
209         
210         // If there were errors, we throw the nested exception
211
if (!e.isEmpty()) {
212             throw e;
213         }
214
215         try {
216             if ( MacroEvent.COPY.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(MacroEvent.COPY, new MacroEvent(this, token, namespace, sourceUri, destinationUri));
217         } catch ( VetoException ve ) {
218             throw new CopyMacroException(ve.getMessage());
219         }
220     }
221     
222     protected void recursiveAccessCheck(Uri uri, ActionNode action) throws SlideException,
223     AccessDeniedException {
224         try {
225             ObjectNode node = uri.getStore().retrieveObject(uri);
226             securityHelper.checkCredentials(uri.getToken(), node, action);
227             Iterator JavaDoc i = node.getChildren().iterator();
228             while (i.hasNext()) {
229                 String JavaDoc child = (String JavaDoc) i.next();
230                 Uri childUri = namespace.getUri(uri.getToken(), child);
231                 recursiveAccessCheck(childUri, action);
232             }
233         } catch (ObjectNotFoundException onfe) {
234             // if it is not there it access can not be denied
235
}
236     }
237
238     protected void recursiveLockCheck(Uri uri) throws SlideException,
239             ObjectLockedException
240     {
241         try {
242             ObjectNode node = uri.getStore().retrieveObject(uri);
243             ActionNode action = namespaceConfig.getCreateObjectAction();
244             lockHelper.checkLock(uri.getToken(), node, action);
245             Iterator JavaDoc i = node.getChildren().iterator();
246             while (i.hasNext()) {
247                 String JavaDoc child = (String JavaDoc) i.next();
248                 Uri childUri = namespace.getUri(uri.getToken(), child);
249                 recursiveLockCheck(childUri);
250             }
251         } catch (ObjectNotFoundException onfe) {
252             // if it is not there it can not be locked
253
}
254     }
255     
256     // TODO: copyRedirector not used
257
public void rebind(SlideToken token, String JavaDoc sourceUri,
258                        String JavaDoc destinationUri, MacroParameters parameters,
259                        CopyRouteRedirector copyRedirector, CopyListener copyListener,
260                        DeleteTargetRedirector deleteRedirector, DeleteListener deleteListener)
261         throws CopyMacroException, DeleteMacroException {
262         
263         CopyMacroException e = new CopyMacroException("Rebind failed");
264         
265         //----------------
266
// handle the case that source and destination are identical
267
if (sourceUri.equals(destinationUri)) {
268             e.addException(new ForbiddenException(sourceUri));
269             throw e;
270         }
271         
272         Uri source = namespace.getUri(token, sourceUri);
273         Uri destination = namespace.getUri(token, destinationUri);
274         try {
275             recursiveLockCheck(source);
276             recursiveLockCheck(destination);
277         } catch (SlideException ex) {
278             e.addException(ex);
279             throw e;
280         }
281
282         if (parameters.isDeleteCreate()) {
283             try {
284                 // If the object we want to overwrite exists, we delete is first
285
structureHelper.retrieve(token, destinationUri);
286                 delete(token, destinationUri, deleteRedirector, deleteListener);
287             } catch(ObjectNotFoundException onf) {
288                 // Silent catch, the target doesn't exist
289
} catch(DeleteMacroException s) {
290                 throw s;
291             } catch(SlideException s) {
292                 e.addException(s);
293                 throw e;
294             }
295         }
296         //----------------
297

298         UriHandler destinationUh = new UriHandler(destinationUri);
299         UriHandler destinationParentUh = destinationUh.getParent();
300         ObjectNode destinationParentNode = null;
301         String JavaDoc destinationSegment = destinationUh.getLastSegment();
302         UriHandler sourceUh = new UriHandler(sourceUri);
303         UriHandler sourceParentUh = sourceUh.getParent();
304         ObjectNode sourceParentNode = null;
305         String JavaDoc sourceSegment = sourceUh.getLastSegment();
306         ObjectNode sourceNode = null;
307         
308         try {
309             try {
310                 destinationParentNode =
311                     structureHelper.retrieve(token, destinationParentUh.toString(), false );
312             }
313             catch (ObjectNotFoundException ex) {
314                 throw new ConflictException(destinationParentUh.toString());
315             }
316             sourceParentNode =
317                 structureHelper.retrieve(token, sourceParentUh.toString(), false );
318             sourceNode =
319                 structureHelper.retrieve(token, sourceUri, false );
320         }
321         catch (SlideException x) {
322             e.addException(x);
323             throw e;
324         }
325         
326         try {
327             // notify Listeners
328
if (copyListener != null) {
329                 copyListener.beforeCopy(sourceUri, destinationUri, true);
330             }
331             structureHelper.addBinding( token, destinationParentNode, destinationSegment, sourceNode );
332             structureHelper.removeBinding( token, sourceParentNode, sourceSegment );
333         }
334         catch (SlideException x) {
335             e.addException(x);
336             throw e;
337         }
338     }
339     
340     /**
341      * Recursive move with overwrite macro.
342      *
343      * @param token Credentials token
344      * @param sourceUri Uri of the source
345      * @param destinationUri Uri of the destination
346      * @exception CopyMacroException Exception occured during copy
347      * @exception DeleteMacroException Exception occured during deletion
348      */

349     public void move(SlideToken token, String JavaDoc sourceUri,
350                      String JavaDoc destinationUri)
351         throws CopyMacroException, DeleteMacroException {
352         move(token, sourceUri, destinationUri,
353                  (CopyRouteRedirector)null, (CopyListener)null,
354                  (DeleteTargetRedirector)null, (DeleteListener)null);
355     }
356     
357     /**
358      * Recursive move with overwrite macro.
359      *
360      * @param token Credentials token
361      * @param sourceUri Uri of the source
362      * @param destinationUri Uri of the destination
363      * @param copyRedirector the CopyRoutRedirector may be used to redirect
364      * the source and/or destination URI of the
365      * <code>copy</code> operation.
366      * (May be <code>null</code>.)
367      * @param copyListener the CopyListener that will be notified
368      * before and after copying a resource.
369      * (May be <code>null</code>)
370      * @param deleteRedirector the DeleteTargetRedirector may be used to redirect
371      * the <code>delete</code> operation to a different
372      * target. (May be <code>null</code>.)
373      * @param deleteListener the DeleteListener that will be notified
374      * before and after deleting a resource.
375      * (May be <code>null</code>)
376      * @exception CopyMacroException Exception occured during copy
377      * @exception DeleteMacroException Exception occured during deletion
378      */

379     public void move(SlideToken token, String JavaDoc sourceUri,
380                      String JavaDoc destinationUri, CopyRouteRedirector copyRedirector, CopyListener copyListener,
381                      DeleteTargetRedirector deleteRedirector, DeleteListener deleteListener)
382         throws CopyMacroException, DeleteMacroException {
383         
384         move(token, sourceUri, destinationUri,
385              RECURSIVE_OVERWRITE_PARAMETERS,
386              copyRedirector, copyListener, deleteRedirector, deleteListener);
387     }
388     
389     
390     /**
391      * Move macro.
392      *
393      * @param token Credentials token
394      * @param sourceUri Uri of the source
395      * @param destinationUri Uri of the destination
396      * @param parameters Macro parameters
397      * @exception CopyMacroException Exception occured during copy
398      * @exception DeleteMacroException Exception occured during deletion
399      */

400     public void move(SlideToken token, String JavaDoc sourceUri,
401                      String JavaDoc destinationUri, MacroParameters parameters)
402         throws CopyMacroException, DeleteMacroException {
403         move(token, sourceUri, destinationUri, parameters, null, null, null, null);
404     }
405     
406     /**
407      * Move macro.
408      *
409      * @param token Credentials token
410      * @param sourceUri Uri of the source
411      * @param destinationUri Uri of the destination
412      * @param parameters Macro parameters
413      * @param copyRedirector the CopyRoutRedirector may be used to redirect
414      * the source and/or destination URI of the
415      * <code>copy</code> operation.
416      * (May be <code>null</code>.)
417      * @param copyListener the CopyListener that will be notified
418      * before and after copying a resource.
419      * (May be <code>null</code>)
420      * @param deleteRedirector the DeleteTargetRedirector may be used to redirect
421      * the <code>delete</code> operation to a different
422      * target. (May be <code>null</code>.)
423      * @param deleteListener the DeleteListener that will be notified
424      * before and after deleting a resource.
425      * (May be <code>null</code>)
426      * @exception CopyMacroException Exception occured during copy
427      * @exception DeleteMacroException Exception occured during deletion
428      */

429     public void move(SlideToken token, String JavaDoc sourceUri,
430                      String JavaDoc destinationUri, MacroParameters parameters,
431                      CopyRouteRedirector copyRedirector, CopyListener copyListener,
432                      DeleteTargetRedirector deleteRedirector, DeleteListener deleteListener)
433         throws CopyMacroException, DeleteMacroException {
434         
435         if (Configuration.useBinding(namespace.getUri(token, sourceUri).getStore()) &&
436             Configuration.useBinding(namespace.getUri(token, destinationUri).getStore()) &&
437             sameStore(token, sourceUri, destinationUri)) {
438             rebind(token, sourceUri, destinationUri, parameters,
439                    copyRedirector, copyListener, deleteRedirector, deleteListener);
440         }
441         else {
442             copy(token, sourceUri, destinationUri, parameters,
443                  copyRedirector, copyListener, deleteRedirector, deleteListener);
444             delete(token, sourceUri, parameters, deleteRedirector, deleteListener);
445         }
446
447         try {
448             if ( MacroEvent.MOVE.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(MacroEvent.MOVE, new MacroEvent(this, token, namespace, sourceUri, destinationUri));
449         } catch ( VetoException ve ) {
450             throw new CopyMacroException(ve.getMessage()); // FIXME: Where is the MoveMacroException?
451
}
452     }
453     
454     /**
455      * Recursive delete.
456      *
457      * @param token Credentials token
458      * @param targetUri Uri of the object to delete
459      * @exception DeleteMacroException Generic Slide exception
460      */

461     public void delete(SlideToken token, String JavaDoc targetUri)
462         throws DeleteMacroException {
463         delete(token, targetUri, (DeleteTargetRedirector)null, (DeleteListener)null);
464     }
465     
466     /**
467      * Recursive delete.
468      *
469      * @param token Credentials token
470      * @param targetUri Uri of the object to delete
471      * @param deleteRedirector the DeleteTargetRedirector may be used to redirect
472      * the <code>delete</code> operation to a different
473      * target. (May be <code>null</code>.)
474      * @param deleteListener the DeleteListener that will be notified
475      * before and after deleting a resource.
476      * (May be <code>null</code>)
477      * @exception DeleteMacroException Generic Slide exception
478      */

479     public void delete(SlideToken token, String JavaDoc targetUri,
480                        DeleteTargetRedirector deleteRedirector, DeleteListener deleteListener)
481         throws DeleteMacroException {
482         delete(token, targetUri, RECURSIVE_OVERWRITE_PARAMETERS, deleteRedirector, deleteListener);
483     }
484     
485     
486     /**
487      * Delete macro.
488      *
489      * @param token Credentials token
490      * @param targetUri Uri of the source
491      * @param parameters Macro parameters, not used right now,
492      * so it can be null
493      * @exception DeleteMacroException Generic Slide exception
494      */

495     public void delete(SlideToken token, String JavaDoc targetUri,
496                        MacroParameters parameters)
497         throws DeleteMacroException {
498         delete(token, targetUri, parameters, null, null);
499     }
500     
501     /**
502      * Delete macro.
503      *
504      * @param token Credentials token
505      * @param targetUri Uri of the source
506      * @param parameters Macro parameters, not used right now,
507      * so it can be null
508      * @param deleteRedirector the DeleteTargetRedirector may be used to redirect
509      * the <code>delete</code> operation to a different
510      * target. (May be <code>null</code>.)
511      * @param deleteListener the DeleteListener that will be notified
512      * before and after deleting a resource.
513      * (May be <code>null</code>)
514      * @exception DeleteMacroException Generic Slide exception
515      */

516     public void delete(SlideToken token, String JavaDoc targetUri, MacroParameters parameters,
517                        DeleteTargetRedirector deleteRedirector, DeleteListener deleteListener)
518         throws DeleteMacroException {
519         
520         Domain.debug("Delete " + targetUri);
521         
522         DeleteMacroException e = new DeleteMacroException("Delete failed");
523         
524         deleteObject(token, targetUri, e, deleteRedirector, deleteListener);
525         
526         // If there were errors, we throw the nested exception
527
if (!e.isEmpty()) {
528             throw e;
529         }
530
531         try {
532             if ( MacroEvent.DELETE.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(MacroEvent.DELETE, new MacroEvent(this, token, namespace, targetUri));
533         } catch ( VetoException ve ) {
534             throw new DeleteMacroException(ve.getMessage());
535         }
536     }
537     
538     
539     // -------------------------------------------------------- Private Methods
540

541     
542     /**
543      * Copy object.
544      *
545      * @param token Credentials token
546      * @param sourceUri Uri of the source
547      * @param destinationUri Uri of the destination
548      * @param parameters Macro parameters
549      * @param copyRedirector the CopyRoutRedirector may be used to redirect
550      * the source and/or destination URI of the
551      * <code>copy</code> operation.
552      * (May be <code>null</code>.)
553      * @param copyListener the CopyListener that will be notified
554      * before and after copying a resource.
555      * (May be <code>null</code>)
556      * @param CopyMacroException Exception occured during copy
557      */

558     private void copyObject(SlideToken token, String JavaDoc sourceUri,
559                             String JavaDoc destinationUri, MacroParameters parameters, boolean isRootOfCopy,
560                             CopyMacroException e, CopyRouteRedirector copyRedirector, CopyListener copyListener,
561                             DeleteTargetRedirector deleteRedirector, DeleteListener deleteListener
562                            ) {
563         
564         Domain.debug("Copy object : from " + sourceUri + " to "
565                          + destinationUri);
566         
567         try {
568             // check for lock-null
569
if (isLockNull(token, sourceUri)) {
570                 // skip
571
return;
572             }
573             
574             // Remember children of orginal source
575
ObjectNode sourceNode =
576                 structureHelper.retrieve(token, sourceUri, false);
577             Enumeration JavaDoc sourceNodeChildren = sourceNode.enumerateChildren();
578             ObjectNode destinationNode = null;
579             
580             // now let the client redirect
581
if (copyRedirector != null) { // TODO: dump re-directing
582
CopyRoute copyRoute = new CopyRoute(sourceUri, destinationUri);
583                 copyRoute = copyRedirector.getRedirectedCopyRoute(copyRoute);
584                 sourceUri = copyRoute.getSourceUri();
585                 destinationUri = copyRoute.getDestinationUri();
586                 sourceNode = structureHelper.retrieve(token, sourceUri, false);
587                 // note that childrenList is *not* re-assigned. This might be a bug ...
588
}
589             
590             // notify CopyListener
591
if (copyListener != null) {
592                 copyListener.beforeCopy(sourceUri, destinationUri, isRootOfCopy );
593             }
594             
595             // delete target if it is the root of the copied tree
596
if (isRootOfCopy && parameters.isDeleteCreate()) {
597                 try {
598                     // We make sure the object we want to overwrite exists
599
structureHelper.retrieve(token, destinationUri);
600                     if (parameters.getParameter(PARENT_BINDINGS) != null) {
601                         Map JavaDoc parentBindings = (Map JavaDoc)parameters.getParameter(PARENT_BINDINGS);
602                         Iterator JavaDoc i = parentBindings.entrySet().iterator();
603                         while (i.hasNext()) {
604                             Map.Entry JavaDoc me = (Map.Entry JavaDoc)i.next();
605                             String JavaDoc uriToDelete = (String JavaDoc)me.getKey()+"/"+(String JavaDoc)me.getValue();
606                             delete(token, uriToDelete, deleteRedirector, deleteListener);
607                         }
608                     }
609                     else {
610                         delete(token, destinationUri, deleteRedirector, deleteListener);
611                     }
612                 } catch(ObjectNotFoundException onf) {
613                     // Silent catch, the target doesn't exist
614
} catch(DeleteMacroException s) {
615                     Enumeration JavaDoc en = s.enumerateExceptions();
616                     if (en.hasMoreElements()) {
617                         throw (SlideException)en.nextElement();
618                     }
619                 }
620             }
621             
622             boolean destinationExists = destinationExists(token, destinationUri);
623             
624             // Creating the copy
625
if (parameters.isDeleteCreate() || !destinationExists) {
626                 try {
627                     Map JavaDoc alreadyCopied = (Map JavaDoc)parameters.getParameter( ALREADY_COPIED );
628                     
629                     if (alreadyCopied.containsKey(sourceNode.getUuri())) {
630                         // If a COPY request would cause a new resource to be created
631
// as a copy of an existing resource, and that COPY request
632
// has already created a copy of that existing resource,
633
// the COPY request instead creates another binding to the
634
// previous copy, instead of creating a new resource.
635
UriHandler destinationUh = new UriHandler(destinationUri);
636                         UriHandler destinationParentUh = destinationUh.getParent();
637                         String JavaDoc segment = destinationUh.getLastSegment();
638                         destinationNode = structureHelper.retrieve( token, (String JavaDoc)alreadyCopied.get(sourceNode.getUuri()) );
639                         ObjectNode destinationParentNode = structureHelper.retrieve( token, destinationParentUh.toString() );
640                         structureHelper.addBinding( token, destinationParentNode, segment, destinationNode );
641                     }
642                     else {
643                         structureHelper.create(token, sourceNode.copyObject(),
644                                                destinationUri);
645                         destinationNode = structureHelper.retrieve( token, destinationUri );
646                         alreadyCopied.put( sourceNode.getUuri(), destinationNode.getUri() );
647                     }
648                 } catch (ObjectNotFoundException s){
649                     throw new ConflictException(s.getObjectUri());
650                 }
651             }
652             
653             // Trying to recreate permissions
654
try {
655                 
656                 Enumeration JavaDoc sourcePermissions = securityHelper
657                     .enumeratePermissions(token, sourceNode);
658                 
659                 while (sourcePermissions.hasMoreElements()) {
660                     NodePermission permission =
661                         (NodePermission) sourcePermissions.nextElement();
662                     NodePermission newPermission =
663                         new NodePermission(destinationUri,
664                                            permission.getSubjectUri(),
665                                            permission.getActionUri(),
666                                            permission.isInheritable(),
667                                            permission.isNegative());
668                     securityHelper.grantPermission(token, newPermission);
669                 }
670                 
671             } catch (AccessDeniedException ex) {
672                 // Means that we don't have modifyPermissions rights
673
// (root access) on the target.
674
// The copy should definitely succeed anyway,
675
// so we silently catch the exception.
676
}
677             
678             // Now copying revision descriptors and content
679
NodeRevisionDescriptors sourceNrds =
680                 contentHelper.retrieve(token, sourceNode.getUri());
681             if (sourceNrds.hasRevisions()) {
682                 NodeRevisionDescriptor sourceNrd =
683                     contentHelper.retrieve(token, sourceNrds);
684                 NodeRevisionContent sourceNrc = null;
685                 if (sourceNrd.getContentLength() > 0) {
686                     sourceNrc =
687                         contentHelper.retrieve(token, sourceNrds, sourceNrd);
688                 }
689                 
690                 if (parameters.isDeleteCreate() || !destinationExists) {
691                     contentHelper.create(token, destinationUri, sourceNrd, sourceNrc);
692                 }
693                 else {
694                     NodeRevisionDescriptor destinationNrd =
695                         contentHelper.retrieve(token,
696                                                contentHelper.retrieve(token, destinationUri));
697                     Enumeration JavaDoc sourceProps = sourceNrd.enumerateProperties();
698                     while (sourceProps.hasMoreElements()) {
699                         destinationNrd.setProperty( (NodeProperty)sourceProps.nextElement() );
700                     }
701                     contentHelper.store(token, destinationUri, destinationNrd, sourceNrc);
702                 }
703             }
704             
705             // notify CopyListener
706
if (copyListener != null) {
707                 copyListener.afterCopy(sourceUri, destinationUri, isRootOfCopy, destinationExists);
708             }
709             
710             // We copy each of this object's children
711
if (parameters.isRecursive()) {
712                 while(sourceNodeChildren.hasMoreElements()) {
713                     String JavaDoc childUri = (String JavaDoc) sourceNodeChildren.nextElement();
714                     String JavaDoc childDestinationUri = destinationUri + childUri
715                         .substring(sourceNode.getUri().length());
716                     copyObject(token, childUri, childDestinationUri,
717                                parameters, false, e, copyRedirector, copyListener,
718                                deleteRedirector, deleteListener
719                               );
720                 }
721             }
722             
723         } catch(SlideException ex) {
724             // ex.printStackTrace(); //the exception is packed and
725
// (hopefully) reported in the response
726
e.addException(ex);
727         }
728         
729     }
730     
731     private boolean destinationExists(SlideToken token, String JavaDoc destinationUri) throws ServiceAccessException, LinkedObjectNotFoundException, RevisionDescriptorNotFoundException, ObjectLockedException, AccessDeniedException, VetoException {
732         boolean destinationExists = true;
733         try {
734             contentHelper.retrieve(token, contentHelper.retrieve(
735                     token, destinationUri));
736         }
737         catch (ObjectNotFoundException x) {
738             destinationExists = false;
739         }
740         return destinationExists;
741     }
742     
743     
744     /**
745      * Delete object function. Recursive for now.
746      *
747      * @param token Credentials token
748      * @param targetUri Uri of the source
749      * @param parameters Macro parameters, not used right now, so it can
750      * be null
751      * @param e Nested exception
752      * @param deleteRedirector the DeleteTargetRedirector may be used to redirect
753      * the <code>delete</code> operation to a different
754      * target. (May be <code>null</code>.)
755      * @param deleteListener the DeleteListener that will be notified
756      * before and after deleting a resource.
757      * (May be <code>null</code>)
758      */

759     private void deleteObject(SlideToken token, String JavaDoc targetUri, MacroException e,
760                               DeleteTargetRedirector deleteRedirector, DeleteListener deleteListener) {
761         
762         Domain.debug("Delete object : " + targetUri);
763         
764         try {
765             ObjectNode currentObject =
766                 structureHelper.retrieve(token, targetUri, false);
767             
768             if (!Configuration.useBinding(namespace.getUri(token, targetUri).getStore()) || currentObject.numberOfParentBindings() < 2) {
769                 // Removing children objects
770
if (currentObject.hasChildren()) {
771                     Enumeration JavaDoc children = currentObject.enumerateChildren();
772                     while (children.hasMoreElements()) {
773                         String JavaDoc childUri = (String JavaDoc)children.nextElement();
774                         deleteObject(token, childUri, e, deleteRedirector, deleteListener);
775                     }
776                 }
777
778                 // Removing links objects
779
if (currentObject.hasLinks()) {
780                     Enumeration JavaDoc links = currentObject.enumerateLinks();
781                     while (links.hasMoreElements()) {
782                         String JavaDoc linkUri = (String JavaDoc)links.nextElement();
783                         deleteObject(token, linkUri, e, deleteRedirector, deleteListener);
784                     }
785                 }
786                 
787                 
788                 // now let the client redirect
789
if (deleteRedirector != null) {
790                     targetUri = deleteRedirector.getRedirectedTargetUri(targetUri);
791                     currentObject = structureHelper.retrieve(token, targetUri, false);
792                 }
793                 
794                 // notify DeleteListener
795
if (deleteListener != null) {
796                     deleteListener.beforeDelete(targetUri);
797                 }
798                 
799                 NodeRevisionDescriptors revisionDescriptors =
800                     contentHelper.retrieve(token, currentObject.getUri());
801                
802                 // remove the associated locks
803
Enumeration JavaDoc locks = lockHelper.enumerateLocks
804                     (token, currentObject.getUri(), false);
805                 while (locks.hasMoreElements()) {
806                     lockHelper.unlock(token, (NodeLock) locks.nextElement());
807                 }
808                 // remove the associated security
809
Enumeration JavaDoc permissions = securityHelper.enumeratePermissions
810                     (token, currentObject);
811                 while (permissions.hasMoreElements()) {
812                     NodePermission permission =
813                         (NodePermission) permissions.nextElement();
814                     securityHelper.revokePermission(token, permission);
815                 }
816                 
817                 // remove all revisions
818
if( !revisionDescriptors.isRedirected() ) {
819                     Enumeration JavaDoc revisionNumberEnum =
820                         revisionDescriptors.enumerateRevisionNumbers();
821                     if (revisionNumberEnum != null) {
822                         while (revisionNumberEnum.hasMoreElements()) {
823                             contentHelper.remove
824                                 (token, currentObject.getUri(),
825                                      (NodeRevisionNumber)revisionNumberEnum.nextElement());
826                         }
827                     }
828                     removeHiddenRevisions( token, targetUri );
829                     
830                     // remove the NodeRevisionDescriptors object
831
contentHelper.remove(token, revisionDescriptors);
832                 }
833             }
834             
835             // Removing object.
836
structureHelper.remove(token, currentObject);
837             
838             // notify DeleteListener
839
if (deleteListener != null) {
840                 deleteListener.afterDelete(targetUri);
841             }
842             
843         } catch (ObjectHasChildrenException ex) {
844             // ignore, the object has children because something else failed
845
// (one of the children is locked, for example), and the
846
// corresponding exception has already been added the the
847
// MacroException
848
} catch (SlideException ex) {
849             e.addException(ex);
850         }
851         
852     }
853     
854     /**
855      * Removes all <i>hidden</i> revisions for the specified URI. Currently there are hidden
856      * revisions only at 0.0.
857      */

858     private void removeHiddenRevisions( SlideToken token, String JavaDoc targetUri ) throws ServiceAccessException, ObjectNotFoundException, LinkedObjectNotFoundException, AccessDeniedException, ObjectLockedException, VetoException {
859         
860         // Can this piece of code be moved to MoveMethod.afterDelete() and DeleteMethod.afterDelete?
861
// It would look more consistent (the copying of hidden revisions is there!!)
862
// BUT: I dont think it's a good idea because the deleteObject() method would delete
863
// the NRDS while hidden revisions remain.
864

865         try {
866             contentHelper.remove(token, targetUri, NodeRevisionNumber.HIDDEN_0_0 );
867         }
868         catch (RevisionDescriptorNotFoundException ne) {
869             // ignore
870
}
871     }
872     
873     /**
874      ** Uri handler.
875      **
876      **/

877     private static class UriHandler {
878         
879         /** The path tokens */
880         String JavaDoc[] tokens = null;
881         final String JavaDoc uriDelimiter = "/";
882         
883         /**
884          ** Default constructor.
885          **/

886         UriHandler( String JavaDoc uri ) {
887             StringTokenizer JavaDoc ut = new StringTokenizer JavaDoc( uri, uriDelimiter );
888             int ntok = ut.countTokens();
889             this.tokens = new String JavaDoc[ntok];
890             for( int i = 0; i < ntok; i++ )
891                 tokens[i] = ut.nextToken();
892         }
893         
894         /**
895          ** Default constructor.
896          **/

897         UriHandler( String JavaDoc[] toks ) {
898             this.tokens = new String JavaDoc[toks.length];
899             for( int i = 0; i < toks.length; i++ )
900                 tokens[i] = toks[i];
901         }
902         
903         /**
904          ** Default constructor.
905          ** @pre number <= toks.length
906          **/

907         UriHandler( String JavaDoc[] toks, int number ) {
908             this.tokens = new String JavaDoc[number];
909             for( int i = 0; i < number; i++ )
910                 tokens[i] = toks[i];
911         }
912         
913         /**
914          ** Check whether this is the root.
915          **/

916         boolean isRoot() {
917             return (tokens.length == 0);
918         }
919         
920         /**
921          * Return the parent.
922          * Example: for /a/b/c returns: /a/b
923          */

924         UriHandler getParent() {
925             if( isRoot() )
926                 return null;
927             return new UriHandler( tokens, tokens.length - 1 );
928         }
929         
930         /**
931          * Checks this URI is parent of the specified URI
932          */

933         boolean isParentOf( UriHandler uh ) {
934             return equals( uh.getParent() );
935         }
936         
937         /**
938          * Returns the node name (last token), e.g. "c" for /a/b/c
939          */

940         String JavaDoc getLastSegment() {
941             return tokens[tokens.length - 1];
942         }
943         
944         /**
945          *
946          */

947         public boolean equals( Object JavaDoc o ) {
948             if( o instanceof UriHandler ) {
949                 UriHandler ouh = (UriHandler)o;
950                 return Arrays.equals( tokens, ouh.tokens );
951             }
952             return false;
953         }
954         
955         /**
956          *
957          */

958         public int hashCode() {
959             return tokens.length;
960         }
961         
962         /**
963          * Return string representation.
964          */

965         public String JavaDoc toString() {
966             StringBuffer JavaDoc b = new StringBuffer JavaDoc();
967             if( tokens.length == 0 )
968                 b.append( uriDelimiter );
969             for( int i = 0; i < tokens.length; i++ )
970                 b.append( uriDelimiter ).append( tokens[i] );
971             return b.toString();
972         }
973     }
974     
975     private boolean sameStore(SlideToken token, String JavaDoc leftUri, String JavaDoc rightUri) {
976         Store leftStore = namespace.getUri(token, leftUri).getStore();
977         Store rightStore = namespace.getUri(token, rightUri).getStore();
978         if (leftStore == null || rightStore == null) {
979             throw new IllegalStateException JavaDoc("Got null store: leftStore="+leftStore+", rightStore="+rightStore);
980         }
981         return leftStore == rightStore;
982     }
983     
984     private boolean isLockNull( SlideToken slideToken, String JavaDoc uriStr ) throws ServiceAccessException {
985         boolean isLockNull = false;
986         try {
987             NodeRevisionDescriptor nrd =
988                 contentHelper.retrieve(slideToken, contentHelper.retrieve(slideToken, uriStr));
989             isLockNull = isLockNull( nrd );
990         }
991         catch (ServiceAccessException x) {
992             throw x;
993         }
994         catch (SlideException x) {
995             // ignore silently
996
}
997         return isLockNull;
998     }
999     
1000    private boolean isLockNull( NodeRevisionDescriptor nrd ) {
1001        return nrd.propertyValueContains("resourcetype", "lock-null");
1002    }
1003}
1004
1005
1006
1007
Popular Tags