Source Code Cross Referenced for GroupPermission.java in  » Wiki-Engine » JSPWiki » com » ecyrd » jspwiki » auth » permissions » 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 » Wiki Engine » JSPWiki » com.ecyrd.jspwiki.auth.permissions 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:          JSPWiki - a JSP-based WikiWiki clone.
003:
004:          Copyright (C) 2001-2006 JSPWiki Development Team
005:
006:          This program is free software; you can redistribute it and/or modify
007:          it under the terms of the GNU Lesser General Public License as published by
008:          the Free Software Foundation; either version 2.1 of the License, or
009:          (at your option) any later version.
010:
011:          This program is distributed in the hope that it will be useful,
012:          but WITHOUT ANY WARRANTY; without even the implied warranty of
013:          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014:          GNU Lesser General Public License for more details.
015:
016:          You should have received a copy of the GNU Lesser General Public License
017:          along with this program; if not, write to the Free Software
018:          Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
019:         */
020:        package com.ecyrd.jspwiki.auth.permissions;
021:
022:        import java.security.AccessControlContext;
023:        import java.security.AccessController;
024:        import java.security.DomainCombiner;
025:        import java.security.Permission;
026:        import java.security.Principal;
027:        import java.util.Arrays;
028:        import java.util.Iterator;
029:        import java.util.Set;
030:
031:        import javax.security.auth.Subject;
032:        import javax.security.auth.SubjectDomainCombiner;
033:
034:        import com.ecyrd.jspwiki.auth.GroupPrincipal;
035:
036:        /**
037:         * <p>
038:         * Permission to perform an operation on a group in a given wiki. Permission
039:         * actions include: <code>view</code>, <code>edit</code>, <code>delete</code>.
040:         * </p>
041:         * <p>
042:         * The target of a permission is a single group or collection in a given wiki.
043:         * The syntax for the target is the wiki name, followed by a colon (:) and the
044:         * name of the group. &#8220;All wikis&#8221; can be specified using a wildcard (*). Group
045:         * collections may also be specified using a wildcard. For groups, the wildcard
046:         * may be a prefix, suffix, or all by itself. Examples of targets include:
047:         * </p>
048:         * <blockquote><code>*:*<br/>
049:         * *:TestPlanners<br/>
050:         * *:*Planners<br/>
051:         * *:Test*<br/>
052:         * mywiki:TestPlanners<br/>
053:         * mywiki:*Planners<br/>
054:         * mywiki:Test*</code>
055:         * </blockquote>
056:         * <p>
057:         * For a given target, certain permissions imply others:
058:         * </p>
059:         * <ul>
060:         * <li><code>edit</code>&nbsp;implies&nbsp;<code>view</code></li>
061:         * <li><code>delete</code>&nbsp;implies&nbsp;<code>edit</code> and
062:         * <code>view</code></li>
063:         * </ul>
064:         * <P>Targets that do not include a wiki prefix <em>never </em> imply others.</p>
065:         * <p>
066:         * GroupPermission accepts a special target called
067:         * <code>&lt;groupmember&gt;</code> that means &#8220;all groups that a user is a
068:         * member of.&#8221; When included in a policy file <code>grant</code> block, it
069:         * functions like a wildcard. Thus, this block:
070:         *
071:         * <pre>
072:         *  grant signedBy &quot;jspwiki&quot;,
073:         *    principal com.ecyrd.jspwiki.auth.authorize.Role &quot;Authenticated&quot; {
074:         *      permission com.ecyrd.jspwiki.auth.permissions.GroupPermission &quot;*:&lt;groupmember&gt;&quot;, &quot;edit&quot;;
075:         * </pre>
076:         *
077:         * means, &#8220;allow Authenticated users to edit any groups they are members of.&#8221;
078:         * The wildcard target (*) does <em>not</em> imply <code>&lt;groupmember&gt;</code>; it
079:         * must be granted explicitly.
080:         * @author Andrew Jaquith
081:         * @since 2.4.17
082:         */
083:        public final class GroupPermission extends Permission {
084:            /** Special target token that denotes all groups that a Subject's Principals are members of. */
085:            public static final String MEMBER_TOKEN = "<groupmember>";
086:
087:            private static final long serialVersionUID = 1L;
088:
089:            /** Action for deleting a group or collection of groups. */
090:            public static final String DELETE_ACTION = "delete";
091:
092:            /** Action for editing a group or collection of groups. */
093:            public static final String EDIT_ACTION = "edit";
094:
095:            /** Action for viewing a group or collection of groups. */
096:            public static final String VIEW_ACTION = "view";
097:
098:            protected static final int DELETE_MASK = 0x4;
099:
100:            protected static final int EDIT_MASK = 0x2;
101:
102:            protected static final int VIEW_MASK = 0x1;
103:
104:            /** Convenience constant that denotes <code>GroupPermission( "*:*, "delete" )</code>. */
105:            public static final GroupPermission DELETE = new GroupPermission(
106:                    DELETE_ACTION);
107:
108:            /** Convenience constant that denotes <code>GroupPermission( "*:*, "edit" )</code>. */
109:            public static final GroupPermission EDIT = new GroupPermission(
110:                    EDIT_ACTION);
111:
112:            /** Convenience constant that denotes <code>GroupPermission( "*:*, "view" )</code>. */
113:            public static final GroupPermission VIEW = new GroupPermission(
114:                    VIEW_ACTION);
115:
116:            private static final String ACTION_SEPARATOR = ",";
117:
118:            private static final String WILDCARD = "*";
119:
120:            private static final String WIKI_SEPARATOR = ":";
121:
122:            private final String m_actionString;
123:
124:            private final int m_mask;
125:
126:            private final String m_group;
127:
128:            private final String m_wiki;
129:
130:            /**
131:             * Private convenience constructor that creates a new GroupPermission for
132:             * all wikis and groups (*:*) and set of actions.
133:             * @param actions
134:             */
135:            private GroupPermission(String actions) {
136:                this (WILDCARD + WIKI_SEPARATOR + WILDCARD, actions);
137:            }
138:
139:            /**
140:             * Creates a new GroupPermission for a specified group and set of actions.
141:             * Group should include a prepended wiki name followed by a colon (:). If
142:             * the wiki name is not supplied or starts with a colon, the group refers to
143:             * all wikis.
144:             * @param group the wiki group
145:             * @param actions the allowed actions for this group
146:             */
147:            public GroupPermission(String group, String actions) {
148:                super (group);
149:
150:                // Parse wiki and group (which may include wiki name and group)
151:                // Strip out attachment separator; it is irrelevant.
152:                String[] pathParams = group.split(WIKI_SEPARATOR);
153:                String groupName;
154:                if (pathParams.length >= 2) {
155:                    m_wiki = pathParams[0].length() > 0 ? pathParams[0] : null;
156:                    groupName = pathParams[1];
157:                } else {
158:                    m_wiki = WILDCARD;
159:                    groupName = pathParams[0];
160:                }
161:                m_group = groupName;
162:
163:                // Parse actions
164:                String[] groupActions = actions.toLowerCase().split(
165:                        ACTION_SEPARATOR);
166:                Arrays.sort(groupActions, String.CASE_INSENSITIVE_ORDER);
167:                m_mask = createMask(actions);
168:                StringBuffer buffer = new StringBuffer();
169:                for (int i = 0; i < groupActions.length; i++) {
170:                    buffer.append(groupActions[i]);
171:                    if (i < (groupActions.length - 1)) {
172:                        buffer.append(ACTION_SEPARATOR);
173:                    }
174:                }
175:                m_actionString = buffer.toString();
176:            }
177:
178:            /**
179:             * Two PagePermission objects are considered equal if their actions (after
180:             * normalization), wiki and target are equal.
181:             * @param obj the object to compare
182:             * @return the result of the comparison
183:             * @see java.lang.Object#equals(java.lang.Object)
184:             */
185:            public final boolean equals(Object obj) {
186:                if (!(obj instanceof  GroupPermission)) {
187:                    return false;
188:                }
189:                GroupPermission p = (GroupPermission) obj;
190:                return p.m_mask == m_mask && p.m_group.equals(m_group)
191:                        && p.m_wiki != null && p.m_wiki.equals(m_wiki);
192:            }
193:
194:            /**
195:             * Returns the actions for this permission: &#8220;view&#8221;, &#8220;edit&#8221;, or &#8220;delete&#8221;. The
196:             * actions will always be sorted in alphabetic order, and will always appear
197:             * in lower case.
198:             * @return the actions
199:             * @see java.security.Permission#getActions()
200:             */
201:            public final String getActions() {
202:                return m_actionString;
203:            }
204:
205:            /**
206:             * Returns the name of the wiki group represented by this permission.
207:             * @return the page name
208:             */
209:            public final String getGroup() {
210:                return m_group;
211:            }
212:
213:            /**
214:             * Returns the name of the wiki containing the group represented by this
215:             * permission; may return the wildcard string.
216:             * @return the wiki
217:             */
218:            public final String getWiki() {
219:                return m_wiki;
220:            }
221:
222:            /**
223:             * Returns the hash code for this GroupPermission.
224:             * @return the hash code
225:             * @see java.lang.Object#hashCode()
226:             */
227:            public final int hashCode() {
228:                // If the wiki has not been set, uses a dummy value for the hashcode
229:                // calculation. This may occur if the page given does not refer
230:                // to any particular wiki
231:                String wiki = m_wiki != null ? m_wiki : "dummy_value";
232:                return m_mask
233:                        + ((13 * m_actionString.hashCode()) * 23 * wiki
234:                                .hashCode());
235:            }
236:
237:            /**
238:             * <p>
239:             * GroupPermissions can only imply other GroupPermissions; no other
240:             * permission types are implied. One GroupPermission implies another if its
241:             * actions if three conditions are met:
242:             * </p>
243:             * <ol>
244:             * <li>The other GroupPermission&#8217;s wiki is equal to, or a subset of, that
245:             * of this permission. This permission&#8217;s wiki is considered a superset of
246:             * the other if it contains a matching prefix plus a wildcard, or a wildcard
247:             * followed by a matching suffix.</li>
248:             * <li>The other GroupPermission&#8217;s target is equal to, or a subset of, the
249:             * target specified by this permission. This permission&#8217;s target is
250:             * considered a superset of the other if it contains a matching prefix plus
251:             * a wildcard, or a wildcard followed by a matching suffix.</li>
252:             * <li>All of other GroupPermission&#8217;s actions are equal to, or a subset of,
253:             * those of this permission</li>
254:             * </ol>
255:             * @param permission the Permission to examine
256:             * @return <code>true</code> if the GroupPermission implies the
257:             * supplied Permission; <code>false</code> otherwise
258:             * @see java.security.Permission#implies(java.security.Permission)
259:             */
260:            public final boolean implies(Permission permission) {
261:                // Permission must be a GroupPermission
262:                if (!(permission instanceof  GroupPermission)) {
263:                    return false;
264:                }
265:
266:                // Build up an "implied mask"
267:                GroupPermission p = (GroupPermission) permission;
268:                int impliedMask = impliedMask(m_mask);
269:
270:                // If actions aren't a proper subset, return false
271:                if ((impliedMask & p.m_mask) != p.m_mask) {
272:                    return false;
273:                }
274:
275:                // See if the tested permission's wiki is implied
276:                boolean impliedWiki = PagePermission.isSubset(m_wiki, p.m_wiki);
277:
278:                // If this page is "*", the tested permission's
279:                // group is implied, unless implied permission has <groupmember> token
280:                boolean impliedGroup;
281:                if (MEMBER_TOKEN.equals(p.m_group)) {
282:                    impliedGroup = MEMBER_TOKEN.equals(m_group);
283:                } else {
284:                    impliedGroup = PagePermission.isSubset(m_group, p.m_group);
285:                }
286:
287:                // See if this permission is <groupmember> and Subject possesses
288:                // GroupPrincipal matching the implied GroupPermission's group
289:                boolean impliedMember = impliesMember(p);
290:
291:                return impliedWiki && (impliedGroup || impliedMember);
292:            }
293:
294:            /**
295:             * Prints a human-readable representation of this permission.
296:             * @return the string
297:             * @see java.lang.Object#toString()
298:             */
299:            public final String toString() {
300:                String wiki = (m_wiki == null) ? "" : m_wiki;
301:                return "(\"" + this .getClass().getName() + "\",\"" + wiki
302:                        + WIKI_SEPARATOR + m_group + "\",\"" + getActions()
303:                        + "\")";
304:            }
305:
306:            /**
307:             * Creates an &#8220;implied mask&#8221; based on the actions originally assigned: for
308:             * example, delete implies edit; edit implies view.
309:             * @param mask binary mask for actions
310:             * @return binary mask for implied actions
311:             */
312:            protected static final int impliedMask(int mask) {
313:                if ((mask & DELETE_MASK) > 0) {
314:                    mask |= EDIT_MASK;
315:                }
316:                if ((mask & EDIT_MASK) > 0) {
317:                    mask |= VIEW_MASK;
318:                }
319:                return mask;
320:            }
321:
322:            /**
323:             * Protected method that creates a binary mask based on the actions specified.
324:             * This is used by {@link #implies(Permission)}.
325:             * @param actions the actions for this permission, separated by commas
326:             * @return the binary actions mask
327:             */
328:            protected static final int createMask(String actions) {
329:                if (actions == null || actions.length() == 0) {
330:                    throw new IllegalArgumentException(
331:                            "Actions cannot be blank or null");
332:                }
333:                int mask = 0;
334:                String[] actionList = actions.split(ACTION_SEPARATOR);
335:                for (int i = 0; i < actionList.length; i++) {
336:                    String action = actionList[i];
337:                    if (action.equalsIgnoreCase(VIEW_ACTION)) {
338:                        mask |= VIEW_MASK;
339:                    } else if (action.equalsIgnoreCase(EDIT_ACTION)) {
340:                        mask |= EDIT_MASK;
341:                    } else if (action.equalsIgnoreCase(DELETE_ACTION)) {
342:                        mask |= DELETE_MASK;
343:                    } else {
344:                        throw new IllegalArgumentException(
345:                                "Unrecognized action: " + action);
346:                    }
347:                }
348:                return mask;
349:            }
350:
351:            /**
352:             * <p>
353:             * Returns <code>true</code> if this GroupPermission was created with the
354:             * token <code>&lt;groupmember&gt;</code>
355:             * <em>and</em> the current
356:             * thread&#8217;s Subject is a member of the Group indicated by the implied
357:             * GroupPermission. Thus, a GroupPermission with the group
358:             * <code>&lt;groupmember&gt;</code> implies GroupPermission for group
359:             * "TestGroup" only if the Subject is a member of TestGroup.
360:             * </p>
361:             * <p>
362:             * We make this determination by obtaining the current {@link Thread}&#8217;s
363:             * {@link java.security.AccessControlContext} and requesting the
364:             * {@link javax.security.auth.SubjectDomainCombiner}. If the combiner is
365:             * not <code>null</code>, then we know that the access check was
366:             * requested using a {@link javax.security.auth.Subject}; that is, that an
367:             * upstream caller caused a Subject to be associated with the Thread&#8217;s
368:             * ProtectionDomain by executing a
369:             * {@link javax.security.auth.Subject#doAs(Subject, java.security.PrivilegedAction)}
370:             * operation.
371:             * </p>
372:             * <p>
373:             * If a SubjectDomainCombiner exists, determining group membership is
374:             * simple: just iterate through the Subject&#8217;s Principal set and look for all
375:             * Principals of type {@link com.ecyrd.jspwiki.auth.GroupPrincipal}. If the
376:             * name of any Principal matches the value of the implied Permission&#8217;s
377:             * {@link GroupPermission#getGroup()} value, then the Subject is a member of
378:             * this group -- and therefore this <code>impliesMember</code> call
379:             * returns <code>true</code>.
380:             * </p>
381:             * <p>
382:             * This may sound complicated, but it really isn&#8217;t. Consider the following
383:             * examples:
384:             * </p>
385:             * <table border="1"> <thead>
386:             * <tr>
387:             * <th width="25%">This object</th>
388:             * <th width="25%"><code>impliesMember</code> parameter</th>
389:             * <th width="25%">Calling Subject&#8217;s Principals
390:             * <th width="25%">Result</th>
391:             * </tr>
392:             * <tr>
393:             * <td><code>GroupPermission ("&lt;groupmember&gt;")</code></td>
394:             * <td><code>GroupPermission ("*:TestGroup")</code></td>
395:             * <td><code>WikiPrincipal ("Biff"),<br/>GroupPrincipal ("TestGroup")</code></td>
396:             * <td><code>true</code></td>
397:             * </tr>
398:             * <tr>
399:             * <td><code>GroupPermission ("*:TestGroup")</code></td>
400:             * <td><code>GroupPermission ("*:TestGroup")</code></td>
401:             * <td><code>WikiPrincipal ("Biff"),<br/>GroupPrincipal ("TestGroup")</code></td>
402:             * <td><code>false</code> - this object does not contain
403:             * <code>&lt;groupmember&gt;</code></td>
404:             * </tr>
405:             * <tr>
406:             * <td><code>GroupPermission ("&lt;groupmember&gt;")</code></td>
407:             * <td><code>GroupPermission ("*:TestGroup")</code></td>
408:             * <td><code>WikiPrincipal ("Biff"),<br/>GroupPrincipal ("FooGroup")</code></td>
409:             * <td><code>false</code> - Subject does not contain GroupPrincipal
410:             * matching implied Permission&#8217;s group (TestGroup)</td>
411:             * </tr>
412:             * <tr>
413:             * <td><code>GroupPermission ("&lt;groupmember&gt;")</code></td>
414:             * <td><code>WikiPermission ("*:createGroups")</code></td>
415:             * <td><code>WikiPrincipal ("Biff"),<br/>GroupPrincipal ("TestGroup")</code></td>
416:             * <td><code>false</code> - implied permission not of type
417:             * GroupPermission</td>
418:             * </tr>
419:             * <tr>
420:             * <td><code>GroupPermission ("&lt;groupmember&gt;")</code></td>
421:             * <td><code>GroupPermission ("*:TestGroup")</code></td>
422:             * <td>-</td>
423:             * <td><code>false</code> - <code>Subject.doAs()</code> not called
424:             * upstream</td>
425:             * </tr>
426:             * </table>
427:             * <p>
428:             * Note that JSPWiki&#8217;s access control checks are made inside of
429:             * {@link com.ecyrd.jspwiki.auth.AuthorizationManager#checkPermission(com.ecyrd.jspwiki.WikiSession, Permission)},
430:             * which performs a <code>Subject.doAs()</code> call. Thus, this
431:             * Permission functions exactly the way it should during normal
432:             * operations.
433:             * </p>
434:             * @param permission the implied permission
435:             * @return <code>true</code> if the calling Thread&#8217;s Subject contains a
436:             *         GroupPrincipal matching the implied GroupPermission&#8217;s group;
437:             *         <code>false</code> otherwise
438:             */
439:            protected final boolean impliesMember(Permission permission) {
440:                if (!(permission instanceof  GroupPermission)) {
441:                    return false;
442:                }
443:                GroupPermission gp = (GroupPermission) permission;
444:                if (!MEMBER_TOKEN.equals(m_group)) {
445:                    return false;
446:                }
447:
448:                // For the current thread, retrieve the SubjectDomainCombiner
449:                // (if one was used to create current AccessControlContext )
450:                AccessControlContext acc = AccessController.getContext();
451:                DomainCombiner dc = acc.getDomainCombiner();
452:                if (dc != null && dc instanceof  SubjectDomainCombiner) {
453:                    // <member> implies permission if subject possesses
454:                    // GroupPrincipal with same name as target
455:                    Subject subject = ((SubjectDomainCombiner) dc).getSubject();
456:                    Set principals = subject
457:                            .getPrincipals(GroupPrincipal.class);
458:                    for (Iterator it = principals.iterator(); it.hasNext();) {
459:                        Principal principal = (Principal) it.next();
460:                        if (principal.getName().equals(gp.m_group)) {
461:                            return true;
462:                        }
463:                    }
464:                }
465:                return false;
466:            }
467:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.