Source Code Cross Referenced for XMLGroupDatabase.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.
003:
004:            Copyright (C) 2001-2002 Janne Jalkanen (Janne.Jalkanen@iki.fi)
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.authorize;
021:
022:        import java.io.BufferedWriter;
023:        import java.io.File;
024:        import java.io.FileNotFoundException;
025:        import java.io.FileOutputStream;
026:        import java.io.IOException;
027:        import java.io.OutputStreamWriter;
028:        import java.security.Principal;
029:        import java.text.DateFormat;
030:        import java.text.ParseException;
031:        import java.text.SimpleDateFormat;
032:        import java.util.Collection;
033:        import java.util.Date;
034:        import java.util.HashMap;
035:        import java.util.Iterator;
036:        import java.util.Map;
037:        import java.util.Properties;
038:
039:        import javax.xml.parsers.DocumentBuilderFactory;
040:        import javax.xml.parsers.ParserConfigurationException;
041:
042:        import org.apache.commons.lang.StringEscapeUtils;
043:        import org.apache.log4j.Logger;
044:        import org.w3c.dom.Document;
045:        import org.w3c.dom.Element;
046:        import org.w3c.dom.NodeList;
047:        import org.xml.sax.SAXException;
048:
049:        import com.ecyrd.jspwiki.NoRequiredPropertyException;
050:        import com.ecyrd.jspwiki.WikiEngine;
051:        import com.ecyrd.jspwiki.auth.NoSuchPrincipalException;
052:        import com.ecyrd.jspwiki.auth.WikiPrincipal;
053:        import com.ecyrd.jspwiki.auth.WikiSecurityException;
054:
055:        /**
056:         * <p>
057:         * GroupDatabase implementation for loading, persisting and storing wiki groups,
058:         * using an XML file for persistence. Group entries are simple
059:         * <code>&lt;group&gt;</code> elements under the root. Each group member is
060:         * representated by a <code>&lt;member&gt;</code> element. For example:
061:         * </p>
062:         * <blockquote><code>
063:         * &lt;groups&gt;<br/>
064:         * &nbsp;&nbsp;&lt;group name="TV" created="Jun 20, 2006 2:50:54 PM" lastModified="Jan 21, 2006 2:50:54 PM"&gt;<br/>
065:         * &nbsp;&nbsp;&nbsp;&nbsp;&lt;member principal="Archie Bunker" /&gt;<br/>
066:         * &nbsp;&nbsp;&nbsp;&nbsp;&lt;member principal="BullwinkleMoose" /&gt;<br/>
067:         * &nbsp;&nbsp;&nbsp;&nbsp;&lt;member principal="Fred Friendly" /&gt;<br/>
068:         * &nbsp;&nbsp;&lt;/group&gt;<br/>
069:         * &nbsp;&nbsp;&lt;group name="Literature" created="Jun 22, 2006 2:50:54 PM" lastModified="Jan 23, 2006 2:50:54 PM"&gt;<br/>
070:         * &nbsp;&nbsp;&nbsp;&nbsp;&lt;member principal="Charles Dickens" /&gt;<br/>
071:         * &nbsp;&nbsp;&nbsp;&nbsp;&lt;member principal="Homer" /&gt;<br/>
072:         * &nbsp;&nbsp;&lt;/group&gt;<br/>
073:         * &lt;/groups&gt;
074:         * </code></blockquote>
075:         * @author Andrew Jaquith
076:         * @since 2.4.17
077:         */
078:        public class XMLGroupDatabase implements  GroupDatabase {
079:            protected static final Logger log = Logger
080:                    .getLogger(XMLGroupDatabase.class);
081:
082:            /**
083:             * The jspwiki.properties property specifying the file system location of
084:             * the group database.
085:             */
086:            public static final String PROP_DATABASE = "jspwiki.xmlGroupDatabaseFile";
087:
088:            private static final String DEFAULT_DATABASE = "groupdatabase.xml";
089:
090:            private static final String CREATED = "created";
091:
092:            private static final String CREATOR = "creator";
093:
094:            private static final String GROUP_TAG = "group";
095:
096:            private static final String GROUP_NAME = "name";
097:
098:            private static final String LAST_MODIFIED = "lastModified";
099:
100:            private static final String MODIFIER = "modifier";
101:
102:            private static final String MEMBER_TAG = "member";
103:
104:            private static final String PRINCIPAL = "principal";
105:
106:            private Document m_dom = null;
107:
108:            private DateFormat m_defaultFormat = DateFormat
109:                    .getDateTimeInstance();
110:
111:            private DateFormat m_format = new SimpleDateFormat(
112:                    "yyyy.MM.dd 'at' HH:mm:ss:SSS z");
113:
114:            private File m_file = null;
115:
116:            private WikiEngine m_engine = null;
117:
118:            private Map m_groups = new HashMap();
119:
120:            /**
121:             * No-op method that in previous versions of JSPWiki was intended to
122:             * atomically commit changes to the user database. Now, the
123:             * {@link #save(Group, Principal)} and {@link #delete(Group)} methods
124:             * are atomic themselves.
125:             * @throws WikiSecurityException never...
126:             * @deprecated there is no need to call this method because the save and
127:             * delete methods contain their own commit logic
128:             */
129:            public void commit() throws WikiSecurityException {
130:            }
131:
132:            /**
133:             * Looks up and deletes a {@link Group} from the group database. If the
134:             * group database does not contain the supplied Group. this method throws a
135:             * {@link NoSuchPrincipalException}. The method commits the results
136:             * of the delete to persistent storage.
137:             * @param group the group to remove
138:             * @throws WikiSecurityException if the database does not contain the
139:             * supplied group (thrown as {@link NoSuchPrincipalException}) or if
140:             * the commit did not succeed
141:             */
142:            public void delete(Group group) throws WikiSecurityException {
143:                String index = group.getName();
144:                boolean exists = m_groups.containsKey(index);
145:
146:                if (!exists) {
147:                    throw new NoSuchPrincipalException("Not in database: "
148:                            + group.getName());
149:                }
150:
151:                m_groups.remove(index);
152:
153:                // Commit to disk
154:                saveDOM();
155:            }
156:
157:            /**
158:             * Returns all wiki groups that are stored in the GroupDatabase as an array
159:             * of Group objects. If the database does not contain any groups, this
160:             * method will return a zero-length array. This method causes back-end
161:             * storage to load the entire set of group; thus, it should be called
162:             * infrequently (e.g., at initialization time).
163:             * @return the wiki groups
164:             * @throws WikiSecurityException if the groups cannot be returned by the back-end
165:             */
166:            public Group[] groups() throws WikiSecurityException {
167:                buildDOM();
168:                Collection groups = m_groups.values();
169:                return (Group[]) groups.toArray(new Group[groups.size()]);
170:            }
171:
172:            /**
173:             * Initializes the group database based on values from a Properties object.
174:             * The properties object must contain a file path to the XML database file
175:             * whose key is {@link #PROP_DATABASE}.
176:             * @param engine the wiki engine
177:             * @param props the properties used to initialize the group database
178:             * @throws NoRequiredPropertyException if the user database cannot be
179:             *             located, parsed, or opened
180:             * @throws WikiSecurityException if the database could not be initialized successfully
181:             */
182:            public void initialize(WikiEngine engine, Properties props)
183:                    throws NoRequiredPropertyException, WikiSecurityException {
184:                m_engine = engine;
185:
186:                File defaultFile = null;
187:                if (engine.getRootPath() == null) {
188:                    log.warn("Cannot identify JSPWiki root path");
189:                    defaultFile = new File("WEB-INF/" + DEFAULT_DATABASE)
190:                            .getAbsoluteFile();
191:                } else {
192:                    defaultFile = new File(engine.getRootPath() + "/WEB-INF/"
193:                            + DEFAULT_DATABASE);
194:                }
195:
196:                // Get database file location
197:                String file = props.getProperty(PROP_DATABASE);
198:                if (file == null) {
199:                    log.error("XML group database property " + PROP_DATABASE
200:                            + " not found; trying " + defaultFile);
201:                    m_file = defaultFile;
202:                } else {
203:                    m_file = new File(file);
204:                }
205:
206:                log.info("XML group database at " + m_file.getAbsolutePath());
207:
208:                // Read DOM
209:                buildDOM();
210:            }
211:
212:            /**
213:             * Saves a Group to the group database. Note that this method <em>must</em>
214:             * fail, and throw an <code>IllegalArgumentException</code>, if the
215:             * proposed group is the same name as one of the built-in Roles: e.g.,
216:             * Admin, Authenticated, etc. The database is responsible for setting
217:             * create/modify timestamps, upon a successful save, to the Group.
218:             * The method commits the results of the delete to persistent storage.
219:             * @param group the Group to save
220:             * @param modifier the user who saved the Group
221:             * @throws WikiSecurityException if the Group could not be saved successfully
222:             */
223:            public void save(Group group, Principal modifier)
224:                    throws WikiSecurityException {
225:                if (group == null || modifier == null) {
226:                    throw new IllegalArgumentException(
227:                            "Group or modifier cannot be null.");
228:                }
229:
230:                checkForRefresh();
231:
232:                String index = group.getName();
233:                boolean isNew = !(m_groups.containsKey(index));
234:                Date modDate = new Date(System.currentTimeMillis());
235:                if (isNew) {
236:                    // If new, set created info
237:                    group.setCreated(modDate);
238:                    group.setCreator(modifier.getName());
239:                }
240:                group.setModifier(modifier.getName());
241:                group.setLastModified(modDate);
242:
243:                // Add the group to the 'saved' list
244:                m_groups.put(index, group);
245:
246:                // Commit to disk
247:                saveDOM();
248:            }
249:
250:            private void buildDOM() throws WikiSecurityException {
251:                DocumentBuilderFactory factory = DocumentBuilderFactory
252:                        .newInstance();
253:                factory.setValidating(false);
254:                factory.setExpandEntityReferences(false);
255:                factory.setIgnoringComments(true);
256:                factory.setNamespaceAware(false);
257:                try {
258:                    m_dom = factory.newDocumentBuilder().parse(m_file);
259:                    log.debug("Database successfully initialized");
260:                    m_lastModified = m_file.lastModified();
261:                    m_lastCheck = System.currentTimeMillis();
262:                } catch (ParserConfigurationException e) {
263:                    log.error("Configuration error: " + e.getMessage());
264:                } catch (SAXException e) {
265:                    log.error("SAX error: " + e.getMessage());
266:                } catch (FileNotFoundException e) {
267:                    log
268:                            .info("Group database not found; creating from scratch...");
269:                } catch (IOException e) {
270:                    log.error("IO error: " + e.getMessage());
271:                }
272:                if (m_dom == null) {
273:                    try {
274:                        //
275:                        // Create the DOM from scratch
276:                        //
277:                        m_dom = factory.newDocumentBuilder().newDocument();
278:                        m_dom.appendChild(m_dom.createElement("groups"));
279:                    } catch (ParserConfigurationException e) {
280:                        log.fatal("Could not create in-memory DOM");
281:                    }
282:                }
283:
284:                // Ok, now go and read this sucker in
285:                if (m_dom != null) {
286:                    NodeList groupNodes = m_dom.getElementsByTagName(GROUP_TAG);
287:                    for (int i = 0; i < groupNodes.getLength(); i++) {
288:                        Element groupNode = (Element) groupNodes.item(i);
289:                        String groupName = groupNode.getAttribute(GROUP_NAME);
290:                        if (groupName == null) {
291:                            log
292:                                    .warn("Detected null group name in XMLGroupDataBase. Check your group database.");
293:                        } else {
294:                            Group group = buildGroup(groupNode, groupName);
295:                            m_groups.put(groupName, group);
296:                        }
297:                    }
298:                }
299:            }
300:
301:            private long m_lastCheck = 0;
302:            private long m_lastModified = 0;
303:
304:            private void checkForRefresh() {
305:                long time = System.currentTimeMillis();
306:
307:                if (time - m_lastCheck > 60 * 1000L) {
308:                    long lastModified = m_file.lastModified();
309:
310:                    if (lastModified > m_lastModified) {
311:                        try {
312:                            buildDOM();
313:                        } catch (WikiSecurityException e) {
314:                            log.error("Could not refresh DOM", e);
315:                        }
316:                    }
317:                }
318:            }
319:
320:            /**
321:             * Constructs a Group based on a DOM group node.
322:             * @param groupNode the node in the DOM containing the node
323:             * @param name the name of the group
324:             * @throws NoSuchPrincipalException
325:             * @throws WikiSecurityException
326:             */
327:            private Group buildGroup(Element groupNode, String name) {
328:                // It's an error if either param is null (very odd)
329:                if (groupNode == null || name == null) {
330:                    throw new IllegalArgumentException(
331:                            "DOM element or name cannot be null.");
332:                }
333:
334:                // Construct a new group
335:                Group group = new Group(name, m_engine.getApplicationName());
336:
337:                // Get the users for this group, and add them
338:                NodeList members = groupNode.getElementsByTagName(MEMBER_TAG);
339:                for (int i = 0; i < members.getLength(); i++) {
340:                    Element memberNode = (Element) members.item(i);
341:                    String principalName = memberNode.getAttribute(PRINCIPAL);
342:                    Principal member = new WikiPrincipal(principalName);
343:                    group.add(member);
344:                }
345:
346:                // Add the created/last-modified info
347:                String creator = groupNode.getAttribute(CREATOR);
348:                String created = groupNode.getAttribute(CREATED);
349:                String modifier = groupNode.getAttribute(MODIFIER);
350:                String modified = groupNode.getAttribute(LAST_MODIFIED);
351:                try {
352:                    group.setCreated(m_format.parse(created));
353:                    group.setLastModified(m_format.parse(modified));
354:                } catch (ParseException e) {
355:                    // If parsing failed, use the platform default
356:                    try {
357:                        group.setCreated(m_defaultFormat.parse(created));
358:                        group.setLastModified(m_defaultFormat.parse(modified));
359:                    } catch (ParseException e2) {
360:                        log.warn("Could not parse 'created' or 'lastModified' "
361:                                + "attribute for " + " group'"
362:                                + group.getName() + "'."
363:                                + " It may have been tampered with.");
364:                    }
365:                }
366:                group.setCreator(creator);
367:                group.setModifier(modifier);
368:                return group;
369:            }
370:
371:            private void saveDOM() throws WikiSecurityException {
372:                if (m_dom == null) {
373:                    log.fatal("Group database doesn't exist in memory.");
374:                }
375:
376:                File newFile = new File(m_file.getAbsolutePath() + ".new");
377:                try {
378:                    BufferedWriter io = new BufferedWriter(
379:                            new OutputStreamWriter(
380:                                    new FileOutputStream(newFile), "UTF-8"));
381:
382:                    // Write the file header and document root
383:                    io.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
384:                    io.write("<groups>\n");
385:
386:                    // Write each profile as a <group> node
387:                    Collection groups = m_groups.values();
388:                    for (Iterator it = groups.iterator(); it.hasNext();) {
389:                        Group group = (Group) it.next();
390:                        io.write("  <" + GROUP_TAG + " ");
391:                        io.write(GROUP_NAME);
392:                        io.write("=\""
393:                                + StringEscapeUtils.escapeXml(group.getName())
394:                                + "\" ");
395:                        io.write(CREATOR);
396:                        io.write("=\""
397:                                + StringEscapeUtils.escapeXml(group
398:                                        .getCreator()) + "\" ");
399:                        io.write(CREATED);
400:                        io.write("=\"" + m_format.format(group.getCreated())
401:                                + "\" ");
402:                        io.write(MODIFIER);
403:                        io.write("=\"" + group.getModifier() + "\" ");
404:                        io.write(LAST_MODIFIED);
405:                        io.write("=\""
406:                                + m_format.format(group.getLastModified())
407:                                + "\"");
408:                        io.write(">\n");
409:
410:                        // Write each member as a <member> node
411:                        Principal[] members = group.members();
412:                        for (int j = 0; j < members.length; j++) {
413:                            Principal member = members[j];
414:                            io.write("    <" + MEMBER_TAG + " ");
415:                            io.write(PRINCIPAL);
416:                            io.write("=\""
417:                                    + StringEscapeUtils.escapeXml(member
418:                                            .getName()) + "\" ");
419:                            io.write("/>\n");
420:                        }
421:
422:                        // Close tag
423:                        io.write("  </" + GROUP_TAG + ">\n");
424:                    }
425:                    io.write("</groups>");
426:                    io.close();
427:                } catch (IOException e) {
428:                    throw new WikiSecurityException(e.getLocalizedMessage());
429:                }
430:
431:                // Copy new file over old version
432:                File backup = new File(m_file.getAbsolutePath() + ".old");
433:                if (backup.exists()) {
434:                    if (!backup.delete()) {
435:                        log
436:                                .error("Could not delete old group database backup: "
437:                                        + backup);
438:                    }
439:                }
440:                if (!m_file.renameTo(backup)) {
441:                    log.error("Could not create group database backup: "
442:                            + backup);
443:                }
444:                if (!newFile.renameTo(m_file)) {
445:                    log.error("Could not save database: " + backup
446:                            + " restoring backup.");
447:                    if (!backup.renameTo(m_file)) {
448:                        log
449:                                .error("Restore failed. Check the file permissions.");
450:                    }
451:                    log.error("Could not save database: " + m_file
452:                            + ". Check the file permissions");
453:                }
454:            }
455:
456:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.