KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > repo > security > permissions > impl > acegi > ACLEntryAfterInvocationProvider


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.security.permissions.impl.acegi;
18
19 import java.util.ArrayList JavaDoc;
20 import java.util.BitSet JavaDoc;
21 import java.util.Collection JavaDoc;
22 import java.util.HashSet JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.List JavaDoc;
25 import java.util.Set JavaDoc;
26 import java.util.StringTokenizer JavaDoc;
27
28 import net.sf.acegisecurity.AccessDeniedException;
29 import net.sf.acegisecurity.Authentication;
30 import net.sf.acegisecurity.ConfigAttribute;
31 import net.sf.acegisecurity.ConfigAttributeDefinition;
32 import net.sf.acegisecurity.afterinvocation.AfterInvocationProvider;
33
34 import org.alfresco.repo.search.SimpleResultSetMetaData;
35 import org.alfresco.repo.security.permissions.impl.SimplePermissionReference;
36 import org.alfresco.service.cmr.repository.ChildAssociationRef;
37 import org.alfresco.service.cmr.repository.NodeRef;
38 import org.alfresco.service.cmr.repository.NodeService;
39 import org.alfresco.service.cmr.repository.StoreRef;
40 import org.alfresco.service.cmr.search.LimitBy;
41 import org.alfresco.service.cmr.search.PermissionEvaluationMode;
42 import org.alfresco.service.cmr.search.ResultSet;
43 import org.alfresco.service.cmr.security.AccessStatus;
44 import org.alfresco.service.cmr.security.AuthenticationService;
45 import org.alfresco.service.cmr.security.PermissionService;
46 import org.alfresco.service.namespace.NamespacePrefixResolver;
47 import org.alfresco.service.namespace.QName;
48 import org.aopalliance.intercept.MethodInvocation;
49 import org.apache.commons.logging.Log;
50 import org.apache.commons.logging.LogFactory;
51 import org.springframework.beans.factory.InitializingBean;
52
53 public class ACLEntryAfterInvocationProvider implements AfterInvocationProvider, InitializingBean
54 {
55     private static Log log = LogFactory.getLog(ACLEntryAfterInvocationProvider.class);
56
57     private static final String JavaDoc AFTER_ACL_NODE = "AFTER_ACL_NODE";
58
59     private static final String JavaDoc AFTER_ACL_PARENT = "AFTER_ACL_PARENT";
60
61     private PermissionService permissionService;
62
63     private NamespacePrefixResolver nspr;
64
65     private NodeService nodeService;
66
67     private AuthenticationService authenticationService;
68
69     public ACLEntryAfterInvocationProvider()
70     {
71         super();
72     }
73
74     public void setPermissionService(PermissionService permissionService)
75     {
76         this.permissionService = permissionService;
77     }
78
79     public PermissionService getPermissionService()
80     {
81         return permissionService;
82     }
83
84     public NamespacePrefixResolver getNamespacePrefixResolver()
85     {
86         return nspr;
87     }
88
89     public void setNamespacePrefixResolver(NamespacePrefixResolver nspr)
90     {
91         this.nspr = nspr;
92     }
93
94     public NodeService getNodeService()
95     {
96         return nodeService;
97     }
98
99     public void setNodeService(NodeService nodeService)
100     {
101         this.nodeService = nodeService;
102     }
103
104     public AuthenticationService getAuthenticationService()
105     {
106         return authenticationService;
107     }
108
109     public void setAuthenticationService(AuthenticationService authenticationService)
110     {
111         this.authenticationService = authenticationService;
112     }
113
114     public void afterPropertiesSet() throws Exception JavaDoc
115     {
116         if (permissionService == null)
117         {
118             throw new IllegalArgumentException JavaDoc("There must be a permission service");
119         }
120         if (nspr == null)
121         {
122             throw new IllegalArgumentException JavaDoc("There must be a namespace service");
123         }
124         if (nodeService == null)
125         {
126             throw new IllegalArgumentException JavaDoc("There must be a node service");
127         }
128         if (authenticationService == null)
129         {
130             throw new IllegalArgumentException JavaDoc("There must be an authentication service");
131         }
132
133     }
134
135     public Object JavaDoc decide(Authentication authentication, Object JavaDoc object, ConfigAttributeDefinition config,
136             Object JavaDoc returnedObject) throws AccessDeniedException
137     {
138         if (log.isDebugEnabled())
139         {
140             MethodInvocation mi = (MethodInvocation) object;
141             log.debug("Method: " + mi.getMethod().toString());
142         }
143         try
144         {
145             if (authenticationService.isCurrentUserTheSystemUser())
146             {
147                 if (log.isDebugEnabled())
148                 {
149                     log.debug("Allowing system user access");
150                 }
151                 return returnedObject;
152             }
153             else if (returnedObject == null)
154             {
155                 if (log.isDebugEnabled())
156                 {
157                     log.debug("Allowing null object access");
158                 }
159                 return null;
160             }
161             else if (StoreRef.class.isAssignableFrom(returnedObject.getClass()))
162             {
163                 if (log.isDebugEnabled())
164                 {
165                     log.debug("Store access");
166                 }
167                 return decide(authentication, object, config, nodeService.getRootNode((StoreRef) returnedObject))
168                         .getStoreRef();
169             }
170             else if (NodeRef.class.isAssignableFrom(returnedObject.getClass()))
171             {
172                 if (log.isDebugEnabled())
173                 {
174                     log.debug("Node access");
175                 }
176                 return decide(authentication, object, config, (NodeRef) returnedObject);
177             }
178             else if (ChildAssociationRef.class.isAssignableFrom(returnedObject.getClass()))
179             {
180                 if (log.isDebugEnabled())
181                 {
182                     log.debug("Child Association access");
183                 }
184                 return decide(authentication, object, config, (ChildAssociationRef) returnedObject);
185             }
186             else if (ResultSet.class.isAssignableFrom(returnedObject.getClass()))
187             {
188                 if (log.isDebugEnabled())
189                 {
190                     log.debug("Result Set access");
191                 }
192                 return decide(authentication, object, config, (ResultSet) returnedObject);
193             }
194             else if (Collection JavaDoc.class.isAssignableFrom(returnedObject.getClass()))
195             {
196                 if (log.isDebugEnabled())
197                 {
198                     log.debug("Collection Access");
199                 }
200                 return decide(authentication, object, config, (Collection JavaDoc) returnedObject);
201             }
202             else if (returnedObject.getClass().isArray())
203             {
204                 if (log.isDebugEnabled())
205                 {
206                     log.debug("Array Access");
207                 }
208                 return decide(authentication, object, config, (Object JavaDoc[]) returnedObject);
209             }
210             else
211             {
212                 if (log.isDebugEnabled())
213                 {
214                     log.debug("Uncontrolled object - access allowed for " + object.getClass().getName());
215                 }
216                 return returnedObject;
217             }
218         }
219         catch (AccessDeniedException ade)
220         {
221             if (log.isDebugEnabled())
222             {
223                 log.debug("Access denied");
224                 ade.printStackTrace();
225             }
226             throw ade;
227         }
228         catch (RuntimeException JavaDoc re)
229         {
230             if (log.isDebugEnabled())
231             {
232                 log.debug("Access denied by runtime exception");
233                 re.printStackTrace();
234             }
235             throw re;
236         }
237
238     }
239
240     public NodeRef decide(Authentication authentication, Object JavaDoc object, ConfigAttributeDefinition config,
241             NodeRef returnedObject) throws AccessDeniedException
242
243     {
244         if (returnedObject == null)
245         {
246             return null;
247         }
248
249         List JavaDoc<ConfigAttributeDefintion> supportedDefinitions = extractSupportedDefinitions(config);
250
251         if (supportedDefinitions.size() == 0)
252         {
253             return returnedObject;
254         }
255
256         for (ConfigAttributeDefintion cad : supportedDefinitions)
257         {
258             NodeRef testNodeRef = null;
259
260             if (cad.typeString.equals(AFTER_ACL_NODE))
261             {
262                 testNodeRef = returnedObject;
263             }
264             else if (cad.typeString.equals(AFTER_ACL_PARENT))
265             {
266                 testNodeRef = nodeService.getPrimaryParent(returnedObject).getParentRef();
267             }
268
269             if ((testNodeRef != null)
270                     && (permissionService.hasPermission(testNodeRef, cad.required.toString()) == AccessStatus.DENIED))
271             {
272                 throw new AccessDeniedException("Access Denied");
273             }
274
275         }
276
277         return returnedObject;
278     }
279
280     private List JavaDoc<ConfigAttributeDefintion> extractSupportedDefinitions(ConfigAttributeDefinition config)
281     {
282         List JavaDoc<ConfigAttributeDefintion> definitions = new ArrayList JavaDoc<ConfigAttributeDefintion>();
283         Iterator JavaDoc iter = config.getConfigAttributes();
284
285         while (iter.hasNext())
286         {
287             ConfigAttribute attr = (ConfigAttribute) iter.next();
288
289             if (this.supports(attr))
290             {
291                 definitions.add(new ConfigAttributeDefintion(attr));
292             }
293
294         }
295         return definitions;
296     }
297
298     public ChildAssociationRef decide(Authentication authentication, Object JavaDoc object, ConfigAttributeDefinition config,
299             ChildAssociationRef returnedObject) throws AccessDeniedException
300
301     {
302         if (returnedObject == null)
303         {
304             return null;
305         }
306
307         List JavaDoc<ConfigAttributeDefintion> supportedDefinitions = extractSupportedDefinitions(config);
308
309         if (supportedDefinitions.size() == 0)
310         {
311             return returnedObject;
312         }
313
314         for (ConfigAttributeDefintion cad : supportedDefinitions)
315         {
316             NodeRef testNodeRef = null;
317
318             if (cad.typeString.equals(AFTER_ACL_NODE))
319             {
320                 testNodeRef = ((ChildAssociationRef) returnedObject).getChildRef();
321             }
322             else if (cad.typeString.equals(AFTER_ACL_PARENT))
323             {
324                 testNodeRef = ((ChildAssociationRef) returnedObject).getParentRef();
325             }
326
327             if ((testNodeRef != null)
328                     && (permissionService.hasPermission(testNodeRef, cad.required.toString()) == AccessStatus.DENIED))
329             {
330                 throw new AccessDeniedException("Access Denied");
331             }
332
333         }
334
335         return returnedObject;
336     }
337
338     public ResultSet decide(Authentication authentication, Object JavaDoc object, ConfigAttributeDefinition config,
339             ResultSet returnedObject) throws AccessDeniedException
340
341     {
342         if (returnedObject == null)
343         {
344             return null;
345         }
346         
347         FilteringResultSet filteringResultSet = new FilteringResultSet(returnedObject);
348
349        
350         List JavaDoc<ConfigAttributeDefintion> supportedDefinitions = extractSupportedDefinitions(config);
351
352         Integer JavaDoc maxSize = null;
353         if(returnedObject.getResultSetMetaData().getSearchParameters().getLimitBy() == LimitBy.FINAL_SIZE)
354         {
355             maxSize = new Integer JavaDoc(returnedObject.getResultSetMetaData().getSearchParameters().getLimit());
356         }
357         
358         if (supportedDefinitions.size() == 0)
359         {
360             if(maxSize == null)
361             {
362                return returnedObject;
363             }
364             else if (returnedObject.length() > maxSize.intValue())
365             {
366                 for(int i = 0; i < maxSize.intValue(); i++)
367                 {
368                     filteringResultSet.setIncluded(i, true);
369                 }
370                 filteringResultSet.setResultSetMetaData(new SimpleResultSetMetaData(LimitBy.FINAL_SIZE, PermissionEvaluationMode.EAGER, returnedObject.getResultSetMetaData().getSearchParameters()));
371             }
372             else
373             {
374                 for(int i = 0; i < maxSize.intValue(); i++)
375                 {
376                     filteringResultSet.setIncluded(i, true);
377                 }
378                 filteringResultSet.setResultSetMetaData(new SimpleResultSetMetaData(LimitBy.UNLIMITED, PermissionEvaluationMode.EAGER, returnedObject.getResultSetMetaData().getSearchParameters()));
379             }
380         }
381
382        
383         
384         for (int i = 0; i < returnedObject.length(); i++)
385         {
386             // All permission checks must pass
387
filteringResultSet.setIncluded(i, true);
388             
389             for (ConfigAttributeDefintion cad : supportedDefinitions)
390             {
391                 NodeRef testNodeRef = null;
392                 if (cad.typeString.equals(AFTER_ACL_NODE))
393                 {
394                     testNodeRef = returnedObject.getNodeRef(i);
395                 }
396                 else if (cad.typeString.equals(AFTER_ACL_PARENT))
397                 {
398                     testNodeRef = returnedObject.getChildAssocRef(i).getParentRef();
399                 }
400
401                 if (filteringResultSet.getIncluded(i)
402                         && (testNodeRef != null)
403                         && (permissionService.hasPermission(testNodeRef, cad.required.toString()) == AccessStatus.DENIED))
404                 {
405                     filteringResultSet.setIncluded(i, false);
406                 }
407             }
408             
409             // Bug out if we are limiting by size
410

411             if((maxSize != null) && (filteringResultSet.length() > maxSize.intValue()))
412             {
413                 // Renove the last match to fix the correct size
414
filteringResultSet.setIncluded(i, false);
415                 filteringResultSet.setResultSetMetaData(new SimpleResultSetMetaData(LimitBy.FINAL_SIZE, PermissionEvaluationMode.EAGER, returnedObject.getResultSetMetaData().getSearchParameters()));
416                 return filteringResultSet;
417             }
418         }
419         filteringResultSet.setResultSetMetaData(new SimpleResultSetMetaData(LimitBy.UNLIMITED, PermissionEvaluationMode.EAGER, returnedObject.getResultSetMetaData().getSearchParameters()));
420         return filteringResultSet;
421     }
422
423     public Collection JavaDoc decide(Authentication authentication, Object JavaDoc object, ConfigAttributeDefinition config,
424             Collection JavaDoc returnedObject) throws AccessDeniedException
425
426     {
427         if (returnedObject == null)
428         {
429             return null;
430         }
431
432         List JavaDoc<ConfigAttributeDefintion> supportedDefinitions = extractSupportedDefinitions(config);
433
434         if (supportedDefinitions.size() == 0)
435         {
436             return returnedObject;
437         }
438
439         Set JavaDoc<Object JavaDoc> removed = new HashSet JavaDoc<Object JavaDoc>();
440
441         if (log.isDebugEnabled())
442         {
443             log.debug("Entries are " + supportedDefinitions);
444         }
445
446         for (Object JavaDoc nextObject : returnedObject)
447         {
448             boolean allowed = true;
449             for (ConfigAttributeDefintion cad : supportedDefinitions)
450             {
451                 NodeRef testNodeRef = null;
452
453                 if (cad.typeString.equals(AFTER_ACL_NODE))
454                 {
455                     if (StoreRef.class.isAssignableFrom(nextObject.getClass()))
456                     {
457                         testNodeRef = nodeService.getRootNode((StoreRef) nextObject);
458                         if (log.isDebugEnabled())
459                         {
460                             log.debug("\tNode Test on store " + nodeService.getPath(testNodeRef));
461                         }
462                     }
463                     else if (NodeRef.class.isAssignableFrom(nextObject.getClass()))
464                     {
465                         testNodeRef = (NodeRef) nextObject;
466                         if (log.isDebugEnabled())
467                         {
468                             log.debug("\tNode Test on node " + nodeService.getPath(testNodeRef));
469                         }
470                     }
471                     else if (ChildAssociationRef.class.isAssignableFrom(nextObject.getClass()))
472                     {
473                         testNodeRef = ((ChildAssociationRef) nextObject).getChildRef();
474                         if (log.isDebugEnabled())
475                         {
476                             log.debug("\tNode Test on child association ref using " + nodeService.getPath(testNodeRef));
477                         }
478                     }
479                     else
480                     {
481                         throw new ACLEntryVoterException(
482                                 "The specified parameter is not a collection of NodeRefs or ChildAssociationRefs");
483                     }
484                 }
485                 else if (cad.typeString.equals(AFTER_ACL_PARENT))
486                 {
487                     if (StoreRef.class.isAssignableFrom(nextObject.getClass()))
488                     {
489                         // Will be allowed
490
testNodeRef = null;
491                         if (log.isDebugEnabled())
492                         {
493                             log.debug("\tParent Test on store ");
494                         }
495                     }
496                     else if (NodeRef.class.isAssignableFrom(nextObject.getClass()))
497                     {
498                         testNodeRef = nodeService.getPrimaryParent((NodeRef) nextObject).getParentRef();
499                         if (log.isDebugEnabled())
500                         {
501                             log.debug("\tParent test on node " + nodeService.getPath(testNodeRef));
502                         }
503                     }
504                     else if (ChildAssociationRef.class.isAssignableFrom(nextObject.getClass()))
505                     {
506                         testNodeRef = ((ChildAssociationRef) nextObject).getParentRef();
507                         if (log.isDebugEnabled())
508                         {
509                             log.debug("\tParent Test on child association ref using "
510                                     + nodeService.getPath(testNodeRef));
511                         }
512                     }
513                     else
514                     {
515                         throw new ACLEntryVoterException(
516                                 "The specified parameter is not a collection of NodeRefs or ChildAssociationRefs");
517                     }
518                 }
519
520                 if (allowed
521                         && (testNodeRef != null)
522                         && (permissionService.hasPermission(testNodeRef, cad.required.toString()) == AccessStatus.DENIED))
523                 {
524                     allowed = false;
525                 }
526             }
527             if (!allowed)
528             {
529                 removed.add(nextObject);
530             }
531         }
532         for (Object JavaDoc toRemove : removed)
533         {
534             while (returnedObject.remove(toRemove))
535                 ;
536         }
537         return returnedObject;
538     }
539
540     public Object JavaDoc[] decide(Authentication authentication, Object JavaDoc object, ConfigAttributeDefinition config,
541             Object JavaDoc[] returnedObject) throws AccessDeniedException
542
543     {
544         BitSet JavaDoc incudedSet = new BitSet JavaDoc(returnedObject.length);
545
546         if (returnedObject == null)
547         {
548             return null;
549         }
550
551         List JavaDoc<ConfigAttributeDefintion> supportedDefinitions = extractSupportedDefinitions(config);
552
553         if (supportedDefinitions.size() == 0)
554         {
555             return returnedObject;
556         }
557
558         for (int i = 0, l = returnedObject.length; i < l; i++)
559         {
560             Object JavaDoc current = returnedObject[i];
561             for (ConfigAttributeDefintion cad : supportedDefinitions)
562             {
563                 incudedSet.set(i, true);
564                 NodeRef testNodeRef = null;
565                 if (cad.typeString.equals(AFTER_ACL_NODE))
566                 {
567                     if (StoreRef.class.isAssignableFrom(current.getClass()))
568                     {
569                         testNodeRef = nodeService.getRootNode((StoreRef) current);
570                     }
571                     else if (NodeRef.class.isAssignableFrom(current.getClass()))
572                     {
573                         testNodeRef = (NodeRef) current;
574                     }
575                     else if (ChildAssociationRef.class.isAssignableFrom(current.getClass()))
576                     {
577                         testNodeRef = ((ChildAssociationRef) current).getChildRef();
578                     }
579                     else
580                     {
581                         throw new ACLEntryVoterException("The specified array is not of NodeRef or ChildAssociationRef");
582                     }
583                 }
584
585                 else if (cad.typeString.equals(AFTER_ACL_PARENT))
586                 {
587                     if (StoreRef.class.isAssignableFrom(current.getClass()))
588                     {
589                         testNodeRef = null;
590                     }
591                     else if (NodeRef.class.isAssignableFrom(current.getClass()))
592                     {
593                         testNodeRef = nodeService.getPrimaryParent((NodeRef) current).getParentRef();
594                     }
595                     else if (ChildAssociationRef.class.isAssignableFrom(current.getClass()))
596                     {
597                         testNodeRef = ((ChildAssociationRef) current).getParentRef();
598                     }
599                     else
600                     {
601                         throw new ACLEntryVoterException("The specified array is not of NodeRef or ChildAssociationRef");
602                     }
603                 }
604
605                 if (incudedSet.get(i)
606                         && (testNodeRef != null)
607                         && (permissionService.hasPermission(testNodeRef, cad.required.toString()) == AccessStatus.DENIED))
608                 {
609                     incudedSet.set(i, false);
610                 }
611
612             }
613         }
614
615         if (incudedSet.cardinality() == returnedObject.length)
616         {
617             return returnedObject;
618         }
619         else
620         {
621             Object JavaDoc[] answer = new Object JavaDoc[incudedSet.cardinality()];
622             for (int i = incudedSet.nextSetBit(0), p = 0; i >= 0; i = incudedSet.nextSetBit(++i), p++)
623             {
624                 answer[p] = returnedObject[i];
625             }
626             return answer;
627         }
628     }
629
630     public boolean supports(ConfigAttribute attribute)
631     {
632         if ((attribute.getAttribute() != null)
633                 && (attribute.getAttribute().startsWith(AFTER_ACL_NODE) || attribute.getAttribute().startsWith(
634                         AFTER_ACL_PARENT)))
635         {
636             return true;
637         }
638         else
639         {
640             return false;
641         }
642     }
643
644     public boolean supports(Class JavaDoc clazz)
645     {
646         return (MethodInvocation.class.isAssignableFrom(clazz));
647     }
648
649     private class ConfigAttributeDefintion
650     {
651
652         String JavaDoc typeString;
653
654         SimplePermissionReference required;
655
656         ConfigAttributeDefintion(ConfigAttribute attr)
657         {
658
659             StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(attr.getAttribute(), ".", false);
660             if (st.countTokens() != 3)
661             {
662                 throw new ACLEntryVoterException("There must be three . separated tokens in each config attribute");
663             }
664             typeString = st.nextToken();
665             String JavaDoc qNameString = st.nextToken();
666             String JavaDoc permissionString = st.nextToken();
667
668             if (!(typeString.equals(AFTER_ACL_NODE) || typeString.equals(AFTER_ACL_PARENT)))
669             {
670                 throw new ACLEntryVoterException("Invalid type: must be ACL_NODE or ACL_PARENT");
671             }
672
673             QName qName = QName.createQName(qNameString, nspr);
674
675             required = new SimplePermissionReference(qName, permissionString);
676         }
677     }
678 }
679
Popular Tags