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


001:        /*
002:         * JSPWiki - a JSP-based WikiWiki clone. Copyright (C) 2001-2003 Janne Jalkanen
003:         * (Janne.Jalkanen@iki.fi) This program is free software; you can redistribute
004:         * it and/or modify it under the terms of the GNU Lesser General Public License
005:         * as published by the Free Software Foundation; either version 2.1 of the
006:         * License, or (at your option) any later version. This program is distributed
007:         * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
008:         * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
009:         * See the GNU Lesser General Public License for more details. You should have
010:         * received a copy of the GNU Lesser General Public License along with this
011:         * program; if not, write to the Free Software Foundation, Inc., 59 Temple
012:         * Place, Suite 330, Boston, MA 02111-1307 USA
013:         */
014:        package com.ecyrd.jspwiki.auth.authorize;
015:
016:        import java.security.Principal;
017:        import java.util.HashMap;
018:        import java.util.HashSet;
019:        import java.util.Map;
020:        import java.util.Properties;
021:        import java.util.Set;
022:        import java.util.StringTokenizer;
023:
024:        import javax.servlet.http.HttpServletRequest;
025:
026:        import org.apache.commons.lang.ArrayUtils;
027:        import org.apache.log4j.Logger;
028:
029:        import com.ecyrd.jspwiki.NoRequiredPropertyException;
030:        import com.ecyrd.jspwiki.WikiContext;
031:        import com.ecyrd.jspwiki.WikiEngine;
032:        import com.ecyrd.jspwiki.WikiException;
033:        import com.ecyrd.jspwiki.WikiSession;
034:        import com.ecyrd.jspwiki.auth.*;
035:        import com.ecyrd.jspwiki.auth.user.UserProfile;
036:        import com.ecyrd.jspwiki.event.WikiEvent;
037:        import com.ecyrd.jspwiki.event.WikiEventListener;
038:        import com.ecyrd.jspwiki.event.WikiEventManager;
039:        import com.ecyrd.jspwiki.event.WikiSecurityEvent;
040:        import com.ecyrd.jspwiki.ui.InputValidator;
041:        import com.ecyrd.jspwiki.util.ClassUtil;
042:
043:        /**
044:         * <p>
045:         * Facade class for storing, retrieving and managing wiki groups on behalf of
046:         * AuthorizationManager, JSPs and other presentation-layer classes. GroupManager
047:         * works in collaboration with a back-end {@link GroupDatabase}, which persists
048:         * groups to permanent storage.
049:         * </p>
050:         * <p>
051:         * <em>Note: prior to JSPWiki 2.4.19, GroupManager was an interface; it
052:         * is now a concrete, final class. The aspects of GroupManager which previously
053:         * extracted group information from storage (e.g., wiki pages) have been
054:         * refactored into the GroupDatabase interface.</em>
055:         * </p>
056:         * @author Andrew Jaquith
057:         * @since 2.4.19
058:         */
059:        public final class GroupManager implements  Authorizer,
060:                WikiEventListener {
061:            /** Key used for adding UI messages to a user's WikiSession. */
062:            public static final String MESSAGES_KEY = "group";
063:
064:            private static final String PROP_GROUPDATABASE = "jspwiki.groupdatabase";
065:
066:            static final Logger log = Logger.getLogger(GroupManager.class);
067:
068:            protected WikiEngine m_engine;
069:
070:            protected WikiEventListener m_groupListener;
071:
072:            private GroupDatabase m_groupDatabase = null;
073:
074:            /** Map with GroupPrincipals as keys, and Groups as values */
075:            private final Map m_groups = new HashMap();
076:
077:            /**
078:             * <p>
079:             * Returns a GroupPrincipal matching a given name. If a group cannot be
080:             * found, return <code>null</code>.
081:             * </p>
082:             * @param name Name of the group. This is case-sensitive.
083:             * @return A DefaultGroup instance.
084:             */
085:            public Principal findRole(String name) {
086:                try {
087:                    Group group = getGroup(name);
088:                    return group.getPrincipal();
089:                } catch (NoSuchPrincipalException e) {
090:                    return null;
091:                }
092:            }
093:
094:            /**
095:             * Returns the Group matching a given name. If the group cannot be found,
096:             * this method throws a <code>NoSuchPrincipalException</code>.
097:             * @param name the name of the group to find
098:             * @return the group
099:             * @throws NoSuchPrincipalException if the group cannot be found
100:             */
101:            public final Group getGroup(String name)
102:                    throws NoSuchPrincipalException {
103:                Group group = (Group) m_groups.get(new GroupPrincipal(name));
104:                if (group != null) {
105:                    return group;
106:                }
107:                throw new NoSuchPrincipalException("Group " + name
108:                        + " not found.");
109:            }
110:
111:            /**
112:             * Returns the current external {@link GroupDatabase} in use. This method
113:             * is guaranteed to return a properly-initialized GroupDatabase, unless
114:             * it could not be initialized. In that case, this method throws
115:             * a {@link com.ecyrd.jspwiki.WikiException}. The GroupDatabase
116:             * is lazily initialized.
117:             * @throws com.ecyrd.jspwiki.auth.WikiSecurityException if the GroupDatabase could
118:             * not be initialized
119:             * @return the current GroupDatabase
120:             * @since 2.3
121:             */
122:            public final GroupDatabase getGroupDatabase()
123:                    throws WikiSecurityException {
124:                if (m_groupDatabase != null) {
125:                    return m_groupDatabase;
126:                }
127:
128:                String dbClassName = "<unknown>";
129:                String dbInstantiationError = null;
130:                Throwable cause = null;
131:                try {
132:                    Properties props = m_engine.getWikiProperties();
133:                    dbClassName = props.getProperty(PROP_GROUPDATABASE);
134:                    if (dbClassName == null) {
135:                        dbClassName = XMLGroupDatabase.class.getName();
136:                    }
137:                    log.info("Attempting to load group database class "
138:                            + dbClassName);
139:                    Class dbClass = ClassUtil.findClass(
140:                            "com.ecyrd.jspwiki.auth.authorize", dbClassName);
141:                    m_groupDatabase = (GroupDatabase) dbClass.newInstance();
142:                    m_groupDatabase.initialize(m_engine, m_engine
143:                            .getWikiProperties());
144:                    log.info("Group database initialized.");
145:                } catch (ClassNotFoundException e) {
146:                    log.error("GroupDatabase class " + dbClassName
147:                            + " cannot be found.", e);
148:                    dbInstantiationError = "Failed to locate GroupDatabase class "
149:                            + dbClassName;
150:                    cause = e;
151:                } catch (InstantiationException e) {
152:                    log.error("GroupDatabase class " + dbClassName
153:                            + " cannot be created.", e);
154:                    dbInstantiationError = "Failed to create GroupDatabase class "
155:                            + dbClassName;
156:                    cause = e;
157:                } catch (IllegalAccessException e) {
158:                    log.error(
159:                            "You are not allowed to access group database class "
160:                                    + dbClassName + ".", e);
161:                    dbInstantiationError = "Access GroupDatabase class "
162:                            + dbClassName + " denied";
163:                    cause = e;
164:                } catch (NoRequiredPropertyException e) {
165:                    log.error("Missing property: " + e.getMessage() + ".");
166:                    dbInstantiationError = "Missing property: "
167:                            + e.getMessage();
168:                    cause = e;
169:                }
170:
171:                if (dbInstantiationError != null) {
172:                    throw new WikiSecurityException(dbInstantiationError
173:                            + " Cause: "
174:                            + (cause != null ? cause.getMessage() : ""));
175:                }
176:
177:                return m_groupDatabase;
178:            }
179:
180:            /**
181:             * Returns an array of GroupPrincipals this GroupManager knows about. This
182:             * method will return an array of GroupPrincipal objects corresponding to
183:             * the wiki groups managed by this class. This method actually returns a
184:             * defensive copy of an internally stored hashmap.
185:             * @return an array of Principals representing the roles
186:             */
187:            public final Principal[] getRoles() {
188:                return (Principal[]) m_groups.keySet().toArray(
189:                        new Principal[m_groups.size()]);
190:            }
191:
192:            /**
193:             * Initializes the group cache by initializing the group database and
194:             * obtaining a list of all of the groups it stores.
195:             * @param engine the wiki engine
196:             * @param props the properties used to initialize the wiki engine
197:             * @see GroupDatabase#initialize(com.ecyrd.jspwiki.WikiEngine,
198:             *      java.util.Properties)
199:             * @see GroupDatabase#groups()
200:             * @throws WikiSecurityException if GroupManager cannot be initialized
201:             */
202:            public final void initialize(WikiEngine engine, Properties props)
203:                    throws WikiSecurityException {
204:                m_engine = engine;
205:
206:                try {
207:                    m_groupDatabase = getGroupDatabase();
208:                } catch (WikiException e) {
209:                    throw new WikiSecurityException(e.getMessage());
210:                }
211:
212:                // Load all groups from the database into the cache
213:                Group[] groups = m_groupDatabase.groups();
214:                synchronized (m_groups) {
215:                    for (int i = 0; i < groups.length; i++) {
216:                        Group group = groups[i];
217:                        // Add new group to cache; fire GROUP_ADD event
218:                        m_groups.put(group.getPrincipal(), group);
219:                        fireEvent(WikiSecurityEvent.GROUP_ADD, group);
220:                    }
221:                }
222:
223:                // Make the GroupManager listen for WikiEvents (WikiSecurityEvents for changed user profiles)
224:                engine.getUserManager().addWikiEventListener(this );
225:
226:                // Success!
227:                log
228:                        .info("Authorizer GroupManager initialized successfully; loaded "
229:                                + groups.length + " group(s).");
230:
231:            }
232:
233:            /**
234:             * <p>
235:             * Determines whether the Subject associated with a WikiSession is in a
236:             * particular role. This method takes two parameters: the WikiSession
237:             * containing the subject and the desired role ( which may be a Role or a
238:             * Group). If either parameter is <code>null</code>, or if the user is
239:             * not authenticated, this method returns <code>false</code>.
240:             * </p>
241:             * <p>
242:             * With respect to this implementation, the supplied Principal must be a
243:             * GroupPrincipal. The Subject posesses the "role" if it the session is
244:             * authenticated <em>and</em> a Subject's principal is a member of the
245:             * corresponding Group. This method simply finds the Group in question, then
246:             * delegates to {@link Group#isMember(Principal)} for each of the principals
247:             * in the Subject's principal set.
248:             * </p>
249:             * @param session the current WikiSession
250:             * @param role the role to check
251:             * @return <code>true</code> if the user is considered to be in the role,
252:             *         <code>false</code> otherwise
253:             */
254:            public final boolean isUserInRole(WikiSession session,
255:                    Principal role) {
256:                // Always return false if session/role is null, or if
257:                // role isn't a GroupPrincipal
258:                if (session == null || role == null
259:                        || !(role instanceof  GroupPrincipal)
260:                        || !session.isAuthenticated()) {
261:                    return false;
262:                }
263:
264:                // Get the group we're examining
265:                Group group = (Group) m_groups.get(role);
266:                if (group == null) {
267:                    return false;
268:                }
269:
270:                // Check each user principal to see if it belongs to the group
271:                Principal[] principals = session.getPrincipals();
272:                for (int i = 0; i < principals.length; i++) {
273:                    if (AuthenticationManager.isUserPrincipal(principals[i])
274:                            && group.isMember(principals[i])) {
275:                        return true;
276:                    }
277:                }
278:                return false;
279:            }
280:
281:            /**
282:             * <p>
283:             * Extracts group name and members from passed parameters and populates an
284:             * existing Group with them. The Group will either be a copy of an existing
285:             * Group (if one can be found), or a new, unregistered Group (if not).
286:             * Optionally, this method can throw a WikiSecurityException if the Group
287:             * does not yet exist in the GroupManager cache.
288:             * </p>
289:             * <p>
290:             * The <code>group</code> parameter in the HTTP request contains the Group
291:             * name to look up and populate. The <code>members</code> parameter
292:             * contains the member list. If these differ from those in the existing
293:             * group, the passed values override the old values.
294:             * </p>
295:             * <p>
296:             * This method does not commit the new Group to the GroupManager cache. To
297:             * do that, use {@link #setGroup(WikiSession, Group)}.
298:             * </p>
299:             * @param name the name of the group to construct
300:             * @param memberLine the line of text containing the group membership list
301:             * @param create whether this method should create a new, empty Group if one
302:             *            with the requested name is not found. If <code>false</code>,
303:             *            groups that do not exist will cause a
304:             *            <code>NoSuchPrincipalException</code> to be thrown
305:             * @return a new, populated group
306:             * @see com.ecyrd.jspwiki.auth.authorize.Group#RESTRICTED_GROUPNAMES
307:             * @throws WikiSecurityException if the group name isn't allowed, or if
308:             * <code>create</code> is <code>false</code>
309:             * and the Group named <code>name</code> does not exist
310:             */
311:            public final Group parseGroup(String name, String memberLine,
312:                    boolean create) throws WikiSecurityException {
313:                // If null name parameter, it's because someone's creating a new group
314:                if (name == null) {
315:                    if (create) {
316:                        name = "MyGroup";
317:                    } else {
318:                        throw new WikiSecurityException(
319:                                "Group name cannot be blank.");
320:                    }
321:                } else if (ArrayUtils.contains(Group.RESTRICTED_GROUPNAMES,
322:                        name)) {
323:                    // Certain names are forbidden
324:                    throw new WikiSecurityException("Illegal group name: "
325:                            + name);
326:                }
327:                name = name.trim();
328:
329:                // Normalize the member line
330:                if (InputValidator.isBlank(memberLine)) {
331:                    memberLine = "";
332:                }
333:                memberLine = memberLine.trim();
334:
335:                // Create or retrieve the group (may have been previously cached)
336:                Group group = new Group(name, m_engine.getApplicationName());
337:                try {
338:                    Group existingGroup = getGroup(name);
339:
340:                    // If existing, clone it
341:                    group.setCreator(existingGroup.getCreator());
342:                    group.setCreated(existingGroup.getCreated());
343:                    group.setModifier(existingGroup.getModifier());
344:                    group.setLastModified(existingGroup.getLastModified());
345:                    Principal[] existingMembers = existingGroup.members();
346:                    for (int i = 0; i < existingMembers.length; i++) {
347:                        group.add(existingMembers[i]);
348:                    }
349:                } catch (NoSuchPrincipalException e) {
350:                    // It's a new group.... throw error if we don't create new ones
351:                    if (!create) {
352:                        throw new NoSuchPrincipalException("Group '" + name
353:                                + "' does not exist.");
354:                    }
355:                }
356:
357:                // If passed members not empty, overwrite
358:                String[] members = extractMembers(memberLine);
359:                if (members.length > 0) {
360:                    group.clear();
361:                    for (int i = 0; i < members.length; i++) {
362:                        group.add(new WikiPrincipal(members[i]));
363:                    }
364:                }
365:
366:                return group;
367:            }
368:
369:            /**
370:             * <p>
371:             * Extracts group name and members from the HTTP request and populates an
372:             * existing Group with them. The Group will either be a copy of an existing
373:             * Group (if one can be found), or a new, unregistered Group (if not).
374:             * Optionally, this method can throw a WikiSecurityException if the Group
375:             * does not yet exist in the GroupManager cache.
376:             * </p>
377:             * <p>
378:             * The <code>group</code> parameter in the HTTP request contains the Group
379:             * name to look up and populate. The <code>members</code> parameter
380:             * contains the member list. If these differ from those in the existing
381:             * group, the passed values override the old values.
382:             * </p>
383:             * <p>
384:             * This method does not commit the new Group to the GroupManager cache. To
385:             * do that, use {@link #setGroup(WikiSession, Group)}.
386:             * </p>
387:             * @param context the current wiki context
388:             * @param create whether this method should create a new, empty Group if one
389:             *            with the requested name is not found. If <code>false</code>,
390:             *            groups that do not exist will cause a
391:             *            <code>NoSuchPrincipalException</code> to be thrown
392:             * @return a new, populated group
393:             * @throws WikiSecurityException if the group name isn't allowed, or if
394:             * <code>create</code> is <code>false</code>
395:             * and the Group does not exist
396:             */
397:            public final Group parseGroup(WikiContext context, boolean create)
398:                    throws WikiSecurityException {
399:                // Extract parameters
400:                HttpServletRequest request = context.getHttpRequest();
401:                String name = request.getParameter("group");
402:                String memberLine = request.getParameter("members");
403:
404:                // Create the named group; we pass on any NoSuchPrincipalExceptions
405:                // that may be thrown if create == false, or WikiSecurityExceptions
406:                Group group = parseGroup(name, memberLine, create);
407:
408:                // If no members, add the current user by default
409:                if (group.members().length == 0) {
410:                    group.add(context.getWikiSession().getUserPrincipal());
411:                }
412:
413:                return group;
414:            }
415:
416:            /**
417:             * Removes a named Group from the group database. If not found, throws a
418:             * <code>NoSuchPrincipalException</code>. After removal, this method will
419:             * commit the delete to the back-end group database. It will also fire a
420:             * {@link com.ecyrd.jspwiki.event.WikiSecurityEvent#GROUP_REMOVE} event with
421:             * the GroupManager instance as the source and the Group as target.
422:             * If <code>index</code> is <code>null</code>, this method throws
423:             * an {@link IllegalArgumentException}.
424:             * @param index the group to remove
425:             * @throws WikiSecurityException if the Group cannot be removed by
426:             * the back-end
427:             * @see com.ecyrd.jspwiki.auth.authorize.GroupDatabase#delete(Group)
428:             */
429:            public final void removeGroup(String index)
430:                    throws WikiSecurityException {
431:                if (index == null) {
432:                    throw new IllegalArgumentException("Group cannot be null.");
433:                }
434:
435:                Group group = (Group) m_groups.get(new GroupPrincipal(index));
436:                if (group == null) {
437:                    throw new NoSuchPrincipalException("Group " + index
438:                            + " not found");
439:                }
440:
441:                // Delete the group
442:                // TODO: need rollback procedure
443:                synchronized (m_groups) {
444:                    m_groups.remove(group.getPrincipal());
445:                }
446:                m_groupDatabase.delete(group);
447:                fireEvent(WikiSecurityEvent.GROUP_REMOVE, group);
448:            }
449:
450:            /**
451:             * <p>
452:             * Saves the {@link Group} created by a user in a wiki session. This method
453:             * registers the Group with the GroupManager and saves it to the back-end
454:             * database. If an existing Group with the same name already exists, the new
455:             * group will overwrite it. After saving the Group, the group database
456:             * changes are committed.
457:             * </p>
458:             * <p>
459:             * This method fires the following events:
460:             * </p>
461:             * <ul>
462:             * <li><strong>When creating a new Group</strong>, this method fires a
463:             * {@link com.ecyrd.jspwiki.event.WikiSecurityEvent#GROUP_ADD} with the
464:             * GroupManager instance as its source and the new Group as the target.</li>
465:             * <li><strong>When overwriting an existing Group</strong>, this method
466:             * fires a new {@link com.ecyrd.jspwiki.event.WikiSecurityEvent#GROUP_REMOVE}
467:             * with this GroupManager instance as the source, and the new Group as the
468:             * target. It then fires a
469:             * {@link com.ecyrd.jspwiki.event.WikiSecurityEvent#GROUP_ADD} event with the
470:             * same source and target.</li>
471:             * </ul>
472:             * <p>
473:             * In addition, if the save or commit actions fail, this method will attempt
474:             * to restore the older version of the wiki group if it exists. This will
475:             * result in a <code>GROUP_REMOVE</code> event (for the new version of the
476:             * Group) followed by a <code>GROUP_ADD</code> event (to indicate
477:             * restoration of the old version).
478:             * </p>
479:             * <p>
480:             * This method will register the new Group with the GroupManager. For example,
481:             * {@link com.ecyrd.jspwiki.auth.AuthenticationManager} attaches each
482:             * WikiSession as a GroupManager listener. Thus, the act of registering a
483:             * Group with <code>setGroup</code> means that all WikiSessions will
484:             * automatically receive group add/change/delete events immediately.
485:             * </p>
486:             * @param session the wiki session, which may not be <code>null</code>
487:             * @param group the Group, which may not be <code>null</code>
488:             * @throws WikiSecurityException if the Group cannot be saved by the back-end
489:             */
490:            public final void setGroup(WikiSession session, Group group)
491:                    throws WikiSecurityException {
492:                // TODO: check for appropriate permissions
493:
494:                // If group already exists, delete it; fire GROUP_REMOVE event
495:                Group oldGroup = (Group) m_groups.get(group.getPrincipal());
496:                if (oldGroup != null) {
497:                    fireEvent(WikiSecurityEvent.GROUP_REMOVE, oldGroup);
498:                    synchronized (m_groups) {
499:                        m_groups.remove(oldGroup.getPrincipal());
500:                    }
501:                }
502:
503:                // Copy existing modifier info & timestamps
504:                if (oldGroup != null) {
505:                    group.setCreator(oldGroup.getCreator());
506:                    group.setCreated(oldGroup.getCreated());
507:                    group.setModifier(oldGroup.getModifier());
508:                    group.setLastModified(oldGroup.getLastModified());
509:                }
510:
511:                // Add new group to cache; announce GROUP_ADD event
512:                synchronized (m_groups) {
513:                    m_groups.put(group.getPrincipal(), group);
514:                }
515:                fireEvent(WikiSecurityEvent.GROUP_ADD, group);
516:
517:                // Save the group to back-end database; if it fails,
518:                // roll back to previous state. Note that the back-end
519:                // MUST timestammp the create/modify fields in the Group.
520:                try {
521:                    m_groupDatabase.save(group, session.getUserPrincipal());
522:                }
523:
524:                // We got an exception! Roll back...
525:                catch (WikiSecurityException e) {
526:                    if (oldGroup != null) {
527:                        // Restore previous version, re-throw...
528:                        fireEvent(WikiSecurityEvent.GROUP_REMOVE, group);
529:                        fireEvent(WikiSecurityEvent.GROUP_ADD, oldGroup);
530:                        synchronized (m_groups) {
531:                            m_groups.put(oldGroup.getPrincipal(), oldGroup);
532:                        }
533:                        throw new WikiSecurityException(e.getMessage()
534:                                + " (rolled back to previous version).");
535:                    }
536:                    // Re-throw security exception
537:                    throw new WikiSecurityException(e.getMessage());
538:                }
539:            }
540:
541:            /**
542:             * Validates a Group, and appends any errors to the session errors list. Any
543:             * validation errors are added to the wiki session's messages collection
544:             * (see {@link WikiSession#getMessages()}.
545:             * @param context the current wiki context
546:             * @param group the supplied Group
547:             */
548:            public final void validateGroup(WikiContext context, Group group) {
549:                WikiSession session = context.getWikiSession();
550:                InputValidator validator = new InputValidator(MESSAGES_KEY,
551:                        session);
552:
553:                // Name cannot be null or one of the restricted names
554:                try {
555:                    checkGroupName(session, group.getName());
556:                } catch (WikiSecurityException e) {
557:
558:                }
559:
560:                // Member names must be "safe" strings
561:                Principal[] members = group.members();
562:                for (int i = 0; i < members.length; i++) {
563:                    validator.validateNotNull(members[i].getName(),
564:                            "Full name", InputValidator.ID);
565:                }
566:            }
567:
568:            /**
569:             * Extracts carriage-return separated members into a Set of String objects.
570:             * @param memberLine the list of members
571:             * @return the list of members
572:             */
573:            protected final String[] extractMembers(String memberLine) {
574:                Set members = new HashSet();
575:                if (memberLine != null) {
576:                    StringTokenizer tok = new StringTokenizer(memberLine, "\n");
577:                    while (tok.hasMoreTokens()) {
578:                        String uid = tok.nextToken().trim();
579:                        if (uid != null && uid.length() > 0) {
580:                            members.add(uid);
581:                        }
582:                    }
583:                }
584:                return (String[]) members.toArray(new String[members.size()]);
585:            }
586:
587:            /**
588:             * Checks if a String is blank or a restricted Group name, and if it is,
589:             * appends an error to the WikiSession's message list.
590:             * @param session the wiki session
591:             * @param name the Group name to test
592:             * @throws WikiSecurityException if <code>session</code> is
593:             * <code>null</code> or the Group name is illegal
594:             * @see Group#RESTRICTED_GROUPNAMES
595:             */
596:            protected final void checkGroupName(WikiSession session, String name)
597:                    throws WikiSecurityException {
598:                //TODO: groups cannot have the same name as a user
599:
600:                if (session == null) {
601:                    throw new WikiSecurityException("Session cannot be null.");
602:                }
603:
604:                // Name cannot be null
605:                InputValidator validator = new InputValidator(MESSAGES_KEY,
606:                        session);
607:                validator.validateNotNull(name, "Group name");
608:
609:                // Name cannot be one of the restricted names either
610:                if (ArrayUtils.contains(Group.RESTRICTED_GROUPNAMES, name)) {
611:                    throw new WikiSecurityException("The group name '" + name
612:                            + "' is illegal. Choose another.");
613:                }
614:            }
615:
616:            // events processing .......................................................
617:
618:            /**
619:             * Registers a WikiEventListener with this instance.
620:             * This is a convenience method.
621:             * @param listener the event listener
622:             */
623:            public final synchronized void addWikiEventListener(
624:                    WikiEventListener listener) {
625:                WikiEventManager.addWikiEventListener(this , listener);
626:            }
627:
628:            /**
629:             * Un-registers a WikiEventListener with this instance.
630:             * This is a convenience method.
631:             * @param listener the event listener
632:             */
633:            public final synchronized void removeWikiEventListener(
634:                    WikiEventListener listener) {
635:                WikiEventManager.removeWikiEventListener(this , listener);
636:            }
637:
638:            /**
639:             *  Fires a WikiSecurityEvent of the provided type, Principal and target Object
640:             *  to all registered listeners.
641:             *
642:             * @see com.ecyrd.jspwiki.event.WikiSecurityEvent
643:             * @param type       the event type to be fired
644:             * @param target     the changed Object, which may be <code>null</code>
645:             */
646:            protected final void fireEvent(int type, Object target) {
647:                if (WikiEventManager.isListening(this )) {
648:                    WikiEventManager.fireEvent(this , new WikiSecurityEvent(
649:                            this , type, target));
650:                }
651:            }
652:
653:            /**
654:             * Listens for {@link com.ecyrd.jspwiki.event.WikiSecurityEvent#PROFILE_NAME_CHANGED}
655:             * events. If a user profile's name changes, each group is inspected. If an entry contains
656:             * a name that has changed, it is replaced with the new one. No group events are emitted
657:             * as a consequence of this method, because the group memberships are still the same; it is
658:             * only the representations of the names within that are changing.
659:             * @param event the incoming event
660:             */
661:            public void actionPerformed(WikiEvent event) {
662:                if (!(event instanceof  WikiSecurityEvent)) {
663:                    return;
664:                }
665:
666:                WikiSecurityEvent se = (WikiSecurityEvent) event;
667:                if (se.getType() == WikiSecurityEvent.PROFILE_NAME_CHANGED) {
668:                    WikiSession session = (WikiSession) se.getSource();
669:                    UserProfile[] profiles = (UserProfile[]) se.getTarget();
670:                    Principal[] oldPrincipals = new Principal[] {
671:                            new WikiPrincipal(profiles[0].getLoginName()),
672:                            new WikiPrincipal(profiles[0].getFullname()),
673:                            new WikiPrincipal(profiles[0].getWikiName()) };
674:                    Principal newPrincipal = new WikiPrincipal(profiles[1]
675:                            .getFullname());
676:
677:                    // Examine each group
678:                    int groupsChanged = 0;
679:                    try {
680:                        Group[] groups = m_groupDatabase.groups();
681:                        for (int i = 0; i < groups.length; i++) {
682:                            boolean groupChanged = false;
683:                            Group group = groups[i];
684:                            for (int j = 0; j < oldPrincipals.length; j++) {
685:                                if (group.isMember(oldPrincipals[j])) {
686:                                    group.remove(oldPrincipals[j]);
687:                                    group.add(newPrincipal);
688:                                    groupChanged = true;
689:                                }
690:                            }
691:                            if (groupChanged) {
692:                                setGroup(session, group);
693:                                groupsChanged++;
694:                            }
695:                        }
696:                    } catch (WikiException e) {
697:                        // Oooo! This is really bad...
698:                        log
699:                                .error("Could not change user name in Group lists because of GroupDatabase error:"
700:                                        + e.getMessage());
701:                    }
702:                    log.info("Profile name change for '"
703:                            + newPrincipal.toString() + "' caused "
704:                            + groupsChanged + " groups to change also.");
705:                }
706:            }
707:
708:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.