Source Code Cross Referenced for AclEvaluator.java in  » Content-Management-System » daisy » org » outerj » daisy » repository » serverimpl » acl » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Content Management System » daisy » org.outerj.daisy.repository.serverimpl.acl 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2004 Outerthought bvba and Schaubroeck nv
003:         *
004:         * Licensed under the Apache License, Version 2.0 (the "License");
005:         * you may not use this file except in compliance with the License.
006:         * You may obtain a copy of the License at
007:         *
008:         *     http://www.apache.org/licenses/LICENSE-2.0
009:         *
010:         * Unless required by applicable law or agreed to in writing, software
011:         * distributed under the License is distributed on an "AS IS" BASIS,
012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013:         * See the License for the specific language governing permissions and
014:         * limitations under the License.
015:         */
016:        package org.outerj.daisy.repository.serverimpl.acl;
017:
018:        import org.outerj.daisy.repository.RepositoryException;
019:        import org.outerj.daisy.repository.Document;
020:        import org.outerj.daisy.repository.Repository;
021:        import org.outerj.daisy.repository.query.QueryException;
022:        import org.outerj.daisy.repository.user.Role;
023:        import org.outerj.daisy.repository.acl.*;
024:        import org.outerj.daisy.repository.commonimpl.acl.*;
025:        import org.outerj.daisy.query.model.Tristate;
026:        import org.outerj.daisy.query.model.PredicateExpr;
027:        import org.outerj.daisy.query.model.ExprDocData;
028:        import org.outerj.daisy.query.EvaluationInfo;
029:        import org.outerj.daisy.query.ExtQueryContext;
030:
031:        /**
032:         * Evaluates ACL's. This code has not directly been put into the AclImpl/AclObjectImpl
033:         * classes because those would otherwise have been dependent on code only existing
034:         * in the server implementation.
035:         */
036:        public class AclEvaluator {
037:            private AclStrategy aclStrategy;
038:            private AclImpl.IntimateAccess aclInt;
039:            private AclEvaluationContext aclEvaluationContext;
040:            private Repository repository;
041:
042:            public AclEvaluator(AclImpl acl, AclStrategy aclStrategy,
043:                    AclEvaluationContext aclEvaluationContext,
044:                    Repository repository) {
045:                this .aclStrategy = aclStrategy;
046:                this .aclInt = acl.getIntimateAccess(aclStrategy);
047:                this .aclEvaluationContext = aclEvaluationContext;
048:                this .repository = repository;
049:            }
050:
051:            public boolean hasPotentialWriteAccess(long userId, long[] roleIds,
052:                    long documentTypeId, long collectionId)
053:                    throws RepositoryException {
054:                if (roleIds.length < 1)
055:                    throw new RepositoryException(
056:                            "Checking of potential write access requires at least one role.");
057:
058:                try {
059:                    if (hasRole(roleIds, Role.ADMINISTRATOR)) {
060:                        return true;
061:                    }
062:
063:                    EvaluationInfo evaluationInfo = new EvaluationInfo(
064:                            new ExtQueryContext(repository));
065:
066:                    // the results array will contain the ACL evaluation result for each of the given roles
067:                    boolean[] results = new boolean[roleIds.length]; // initialized to false
068:                    for (AclObjectImpl object : aclInt.getObjects()) {
069:                        // Note: later rules overwrite earlier ones
070:                        checkPotentialWriteAccess(object, results, userId,
071:                                roleIds, documentTypeId, collectionId,
072:                                evaluationInfo);
073:                    }
074:
075:                    // if the result for at least one role is true, then return true
076:                    for (boolean result : results)
077:                        if (result)
078:                            return true;
079:                    return false;
080:                } catch (Throwable e) {
081:                    throw new RepositoryException("Error evaluating ACL.", e);
082:                }
083:            }
084:
085:            private void checkPotentialWriteAccess(AclObjectImpl aclObject,
086:                    boolean[] results, long userId, long[] roleIds,
087:                    long documentTypeId, long collectionId,
088:                    EvaluationInfo evaluationInfo) throws RepositoryException {
089:                AclObjectImpl.IntimateAccess aclObjectInt = aclObject
090:                        .getIntimateAccess(aclStrategy);
091:                assureExpressionCompiled(aclObject, aclObjectInt);
092:                Tristate appliesTo;
093:                try {
094:                    PredicateExpr predicateExpr = (PredicateExpr) aclObjectInt
095:                            .getCompiledExpression();
096:                    appliesTo = predicateExpr.appliesTo(new ExprDocData(
097:                            new DummyDocForAppliesToTest(documentTypeId,
098:                                    collectionId), null), evaluationInfo);
099:                } catch (QueryException e) {
100:                    throw new RepositoryException(
101:                            "Exception evaluating ACL object expression.", e);
102:                }
103:
104:                if (appliesTo == Tristate.NO)
105:                    return;
106:
107:                // NOTE: the logic below is similar to that in completeAclInfo(), so if you adjust
108:                //       it here, keep it in sync over there
109:                for (AclEntryImpl entry : aclObjectInt.getEntries()) {
110:
111:                    for (int r = 0; r < roleIds.length; r++) {
112:                        boolean relevant = false;
113:                        if (entry.getSubjectType() == AclSubjectType.EVERYONE) {
114:                            relevant = true;
115:                        } else if (entry.getSubjectType() == AclSubjectType.ROLE) {
116:                            if (roleIds[r] == entry.getSubjectValue())
117:                                relevant = true;
118:                        } else if (entry.getSubjectType() == AclSubjectType.USER) {
119:                            if (userId != -1
120:                                    && userId == entry.getSubjectValue())
121:                                relevant = true;
122:                        }
123:
124:                        if (relevant) {
125:                            AclActionType entryAction = entry
126:                                    .get(AclPermission.WRITE);
127:                            // granting applies always, denying only if the object expression surely applies (and not 'maybe')
128:                            if (entryAction == AclActionType.GRANT) {
129:                                results[r] = true;
130:                            } else if (entryAction == AclActionType.DENY
131:                                    && appliesTo == Tristate.YES) {
132:                                results[r] = false;
133:                            }
134:                        }
135:                    }
136:                }
137:            }
138:
139:            public AclResultInfo getAclInfo(long userId, long[] roleIds,
140:                    Document document) throws RepositoryException {
141:                if (roleIds.length < 1)
142:                    throw new RepositoryException(
143:                            "Evaluation of ACL requires at least one role");
144:
145:                try {
146:                    AclResultInfo result = new AclResultInfoImpl(userId,
147:                            roleIds, document.getId(), document.getBranchId(),
148:                            document.getLanguageId());
149:
150:                    if (hasRole(roleIds, Role.ADMINISTRATOR)) {
151:                        final String message = "granted because role is Administrator (role id "
152:                                + Role.ADMINISTRATOR + ")";
153:                        for (AclPermission permission : AclPermission.values())
154:                            result.set(permission, AclActionType.GRANT,
155:                                    message, message);
156:                        return result;
157:                    }
158:
159:                    if ((document.isPrivate() && userId == -1)
160:                            || (document.isPrivate() && userId != -1 && document
161:                                    .getOwner() != userId)) {
162:                        final String message = "denied because document is marked as private";
163:                        for (AclPermission permission : AclPermission.values())
164:                            result.set(permission, AclActionType.DENY, message,
165:                                    message);
166:                        return result;
167:                    }
168:
169:                    for (AclPermission permission : AclPermission.values())
170:                        result.set(permission, AclActionType.DENY,
171:                                "denied by default", "denied by default");
172:
173:                    // For the actual ACL evaluation itself, we evaluate it for each role individually and
174:                    // afterwards merge the results to take the most permissive ones (i.e. if at least one
175:                    // role allows it, it is allowed, or vice versa, a permission is only denied if all
176:                    // roles deny it)
177:                    AclResultInfo[] results = new AclResultInfo[roleIds.length];
178:                    for (int i = 0; i < results.length; i++)
179:                        results[i] = result.clone();
180:
181:                    for (AclObjectImpl object : aclInt.getObjects()) {
182:                        completeAclInfo(object, results, userId, roleIds,
183:                                document);
184:                    }
185:
186:                    result = merge(results);
187:
188:                    if (!result.isNonLiveAllowed(AclPermission.READ)
189:                            && document.isRetired()) {
190:                        final String message = "cannot read a retired document if only access to live versions is allowed";
191:                        result.set(AclPermission.READ, AclActionType.DENY,
192:                                message, message);
193:                    }
194:
195:                    if (!result.isFullyAllowed(AclPermission.READ)) {
196:                        if (result.isAllowed(AclPermission.WRITE)) {
197:                            final String message = "cannot have write access if no full read access";
198:                            result.set(AclPermission.WRITE, AclActionType.DENY,
199:                                    message, message);
200:                        }
201:                        if (result.isAllowed(AclPermission.PUBLISH)) {
202:                            final String message = "cannot have publish access if no full read access";
203:                            result.set(AclPermission.PUBLISH,
204:                                    AclActionType.DENY, message, message);
205:                        }
206:                        if (result.isAllowed(AclPermission.DELETE)) {
207:                            final String message = "cannot have delete access if no write access";
208:                            result.set(AclPermission.DELETE,
209:                                    AclActionType.DENY, message, message);
210:                        }
211:                    }
212:
213:                    // Note: the document.getId() == null check below is because:
214:                    //  - new documents have no ID yet
215:                    //  - for a new document, one is always the owner
216:                    //  - so one would always be allowed write access for new documents
217:                    if (document.getId() != null && userId != -1
218:                            && document.getOwner() == userId) {
219:                        final String message = "granted because user is owner of the document";
220:                        result.set(AclPermission.READ, AclActionType.GRANT,
221:                                message, message);
222:                        result.set(AclPermission.WRITE, AclActionType.GRANT,
223:                                message, message);
224:                        result.set(AclPermission.DELETE, AclActionType.GRANT,
225:                                message, message);
226:                        // Note: an owner of a document does not automatically get publish rights, instead
227:                        //       these are determined by the ACL
228:                    }
229:
230:                    return result;
231:                } catch (Throwable e) {
232:                    throw new RepositoryException("Error evaluating ACL.", e);
233:                }
234:            }
235:
236:            private void assureExpressionCompiled(AclObject aclObject,
237:                    AclObjectImpl.IntimateAccess aclObjectInt)
238:                    throws RepositoryException {
239:                if (aclObjectInt.getCompiledExpression() == null) {
240:                    Object compiledExpr = aclEvaluationContext
241:                            .compileObjectExpression(aclObject.getObjectExpr(),
242:                                    repository);
243:                    aclObjectInt.setCompiledExpression(compiledExpr);
244:                }
245:            }
246:
247:            private boolean appliesTo(AclObjectImpl aclObject,
248:                    AclObjectImpl.IntimateAccess aclObjectInt, Document document)
249:                    throws RepositoryException {
250:                assureExpressionCompiled(aclObject, aclObjectInt);
251:                return aclEvaluationContext.checkObjectExpression(aclObjectInt
252:                        .getCompiledExpression(), document, repository);
253:            }
254:
255:            private void completeAclInfo(AclObjectImpl aclObject,
256:                    AclResultInfo[] results, long userId, long[] roleIds,
257:                    Document document) throws RepositoryException {
258:                AclObjectImpl.IntimateAccess aclObjectInt = aclObject
259:                        .getIntimateAccess(aclStrategy);
260:                // NOTE: the logic below is similar to that in hasPotentialWriteAccess(), so if you adjust
261:                //       it here, keep it in sync over there
262:                if (appliesTo(aclObject, aclObjectInt, document)) {
263:                    for (AclEntryImpl entry : aclObjectInt.getEntries()) {
264:
265:                        for (int r = 0; r < roleIds.length; r++) {
266:                            String subjectReason = null;
267:                            if (entry.getSubjectType() == AclSubjectType.EVERYONE) {
268:                                subjectReason = "everyone";
269:                            } else if (entry.getSubjectType() == AclSubjectType.ROLE) {
270:                                if (roleIds[r] == entry.getSubjectValue())
271:                                    subjectReason = "role is "
272:                                            + entry.getSubjectValue();
273:                            } else if (entry.getSubjectType() == AclSubjectType.USER) {
274:                                if (userId != -1
275:                                        && userId == entry.getSubjectValue())
276:                                    subjectReason = "user is " + userId;
277:                            }
278:
279:                            if (subjectReason != null) {
280:                                for (AclPermission permission : AclPermission
281:                                        .values()) {
282:                                    AclActionType entryAction = entry
283:                                            .get(permission);
284:                                    if (entryAction != AclActionType.DO_NOTHING) {
285:                                        // Access details are currently read-permission specific, so makes no
286:                                        // sense to handle them for other permisssions
287:                                        if (permission == AclPermission.READ) {
288:                                            AccessDetails details = entry
289:                                                    .getDetails(permission);
290:                                            AccessDetails newDetails;
291:                                            if (details == null) { // grant with no details => full grant
292:                                                newDetails = new AccessDetailsImpl(
293:                                                        null,
294:                                                        AclActionType.GRANT);
295:                                            } else { // grant with details => merge with previous details
296:                                                newDetails = results[r]
297:                                                        .getAccessDetails(permission);
298:                                                if (newDetails == null)
299:                                                    newDetails = new AccessDetailsImpl(
300:                                                            null,
301:                                                            AclActionType.GRANT);
302:                                                newDetails.overwrite(details);
303:                                            }
304:                                            results[r].set(permission,
305:                                                    entryAction, newDetails,
306:                                                    aclObject.getObjectExpr(),
307:                                                    subjectReason);
308:                                        } else {
309:                                            results[r].set(permission,
310:                                                    entryAction, aclObject
311:                                                            .getObjectExpr(),
312:                                                    subjectReason);
313:                                        }
314:                                    }
315:                                }
316:                            }
317:                        }
318:                    }
319:                }
320:            }
321:
322:            private boolean hasRole(long[] availableRoles, long roleId) {
323:                for (long availableRole : availableRoles)
324:                    if (availableRole == roleId)
325:                        return true;
326:                return false;
327:            }
328:
329:            /**
330:             * Merge the given AclResultInfo's so that the most permissive result is obtained.
331:             * @param results array with at least one entry
332:             */
333:            private AclResultInfo merge(AclResultInfo[] results) {
334:                if (results.length == 1)
335:                    return results[0];
336:
337:                AclResultInfo mergedResult = new AclResultInfoImpl(results[0]
338:                        .getUserId(), results[0].getRoleIds(), results[0]
339:                        .getDocumentId(), results[0].getBranchId(), results[0]
340:                        .getLanguageId());
341:
342:                for (AclPermission permission : AclPermission.values()) {
343:                    for (AclResultInfo result : results) {
344:                        if (result.isAllowed(permission)) {
345:                            AccessDetails details = result
346:                                    .getAccessDetails(permission);
347:                            if (details == null) {
348:                                mergedResult.set(permission,
349:                                        AclActionType.GRANT, result
350:                                                .getObjectExpr(permission),
351:                                        result.getSubjectReason(permission));
352:                                break;
353:                            }
354:
355:                            AccessDetails existingDetails = mergedResult
356:                                    .getAccessDetails(permission);
357:                            if (existingDetails != null) {
358:                                details = new AccessDetailsImpl(null, details);
359:                                details.makeUnion(existingDetails);
360:                            }
361:                            mergedResult.set(permission, AclActionType.GRANT,
362:                                    details, result.getObjectExpr(permission),
363:                                    result.getSubjectReason(permission));
364:                            // if there are details, don't break but search further                                                                                     
365:                        }
366:                    }
367:                }
368:
369:                return mergedResult;
370:            }
371:
372:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.