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


001:        /*
002:            JSPWiki - a JSP-based WikiWiki clone.
003:
004:            Copyright (C) 2001-2007 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.ui;
021:
022:        import java.io.IOException;
023:        import java.util.HashMap;
024:        import java.util.Iterator;
025:        import java.util.Map;
026:        import java.util.Properties;
027:
028:        import javax.servlet.http.HttpServletRequest;
029:
030:        import org.apache.log4j.Logger;
031:
032:        import com.ecyrd.jspwiki.InternalWikiException;
033:        import com.ecyrd.jspwiki.TextUtil;
034:        import com.ecyrd.jspwiki.WikiEngine;
035:        import com.ecyrd.jspwiki.WikiPage;
036:        import com.ecyrd.jspwiki.WikiProvider;
037:        import com.ecyrd.jspwiki.auth.GroupPrincipal;
038:        import com.ecyrd.jspwiki.parser.MarkupParser;
039:        import com.ecyrd.jspwiki.providers.ProviderException;
040:        import com.ecyrd.jspwiki.url.URLConstructor;
041:
042:        /**
043:         * <p>Resolves special pages, JSPs and Commands on behalf of a
044:         * WikiEngine. CommandResolver will automatically resolve page names
045:         * with singular/plural variants. It can also detect the correct Command
046:         * based on parameters supplied in an HTTP request, or due to the
047:         * JSP being accessed.</p>
048:         * <p>
049:         * <p>CommandResolver's static {@link #findCommand(String)} method is
050:         * the simplest method; it looks up and returns the Command matching
051:         * a supplied wiki context. For example, looking up the request context
052:         * <code>view</code> returns {@link PageCommand#VIEW}. Use this method
053:         * to obtain static Command instances that aren't targeted at a particular
054:         * page or group.</p>
055:         * <p>For more complex lookups in which the caller supplies an HTTP
056:         * request, {@link #findCommand(HttpServletRequest, String)} will
057:         * look up and return the correct Command. The String parameter
058:         * <code>defaultContext</code> supplies the request context to use
059:         * if it cannot be detected. However, note that the default wiki
060:         * context may be over-ridden if the request was for a "special page."</p>
061:         * <p>For example, suppose the WikiEngine's properties specify a
062:         * special page called <code>UserPrefs</code>
063:         * that redirects to <code>UserPreferences.jsp</code>. The ordinary
064:         * lookup method {@linkplain #findCommand(String)} using a supplied
065:         * context <code>view</code> would return {@link PageCommand#VIEW}. But
066:         * the {@linkplain #findCommand(HttpServletRequest, String)} method,
067:         * when passed the same context (<code>view</code>) and an HTTP request
068:         * containing the page parameter value <code>UserPrefs</code>,
069:         * will instead return {@link WikiCommand#PREFS}.</p>
070:         * @author Andrew Jaquith
071:         * @since 2.4.22
072:         */
073:        public final class CommandResolver {
074:            /** Prefix in jspwiki.properties signifying special page keys. */
075:            private static final String PROP_SPECIALPAGE = "jspwiki.specialPage.";
076:
077:            /** Private map with request contexts as keys, Commands as values */
078:            private static final Map CONTEXTS;
079:
080:            /** Private map with JSPs as keys, Commands as values */
081:            private static final Map JSPS;
082:
083:            /** Store the JSP-to-Command and context-to-Command mappings */
084:            static {
085:                CONTEXTS = new HashMap();
086:                JSPS = new HashMap();
087:                Command[] commands = AbstractCommand.allCommands();
088:                for (int i = 0; i < commands.length; i++) {
089:                    JSPS.put(commands[i].getJSP(), commands[i]);
090:                    CONTEXTS.put(commands[i].getRequestContext(), commands[i]);
091:                }
092:            }
093:
094:            private final Logger m_log = Logger
095:                    .getLogger(CommandResolver.class);
096:
097:            private final WikiEngine m_engine;
098:
099:            /** If true, we'll also consider english plurals (+s) a match. */
100:            private final boolean m_matchEnglishPlurals;
101:
102:            /** Stores special page names as keys, and Commands as values. */
103:            private final Map m_specialPages;
104:
105:            /**
106:             * Constructs a CommandResolver for a given WikiEngine. This constructor
107:             * will extract the special page references for this wiki and store them in
108:             * a cache used for resolution.
109:             * @param engine the wiki engine
110:             * @param properties the properties used to initialize the wiki
111:             */
112:            public CommandResolver(WikiEngine engine, Properties properties) {
113:                m_engine = engine;
114:                m_specialPages = new HashMap();
115:
116:                // Skim through the properties and look for anything with
117:                // the "special page" prefix. Create maps that allow us
118:                // look up the correct Command based on special page name.
119:                // If a matching command isn't found, create a RedirectCommand.
120:                for (Iterator i = properties.entrySet().iterator(); i.hasNext();) {
121:                    Map.Entry entry = (Map.Entry) i.next();
122:                    String key = (String) entry.getKey();
123:                    if (key.startsWith(PROP_SPECIALPAGE)) {
124:                        String specialPage = key.substring(PROP_SPECIALPAGE
125:                                .length());
126:                        String jsp = (String) entry.getValue();
127:                        if (specialPage != null && jsp != null) {
128:                            specialPage = specialPage.trim();
129:                            jsp = jsp.trim();
130:                            Command command = (Command) JSPS.get(jsp);
131:                            if (command == null) {
132:                                Command redirect = RedirectCommand.REDIRECT;
133:                                command = redirect.targetedCommand(jsp);
134:                            }
135:                            m_specialPages.put(specialPage, command);
136:                        }
137:                    }
138:                }
139:
140:                // Do we match plurals?
141:                m_matchEnglishPlurals = TextUtil.getBooleanProperty(properties,
142:                        WikiEngine.PROP_MATCHPLURALS, true);
143:            }
144:
145:            /**
146:             * Attempts to locate a wiki command for a supplied request context.
147:             * The resolution technique is simple: we examine the list of
148:             * Commands returned by {@link AbstractCommand#allCommands()} and
149:             * return the one whose <code>requestContext</code> matches the
150:             * supplied context. If the supplied context does not resolve to a known
151:             * Command, this method throws an {@link IllegalArgumentException}.
152:             * @param context the request context
153:             * @return the resolved context
154:             */
155:            public static Command findCommand(String context) {
156:                Command command = (Command) CONTEXTS.get(context);
157:                if (command == null) {
158:                    throw new IllegalArgumentException(
159:                            "Unsupported wiki context: " + context + ".");
160:                }
161:                return command;
162:            }
163:
164:            /**
165:             * <p>
166:             * Attempts to locate a Command for a supplied wiki context and HTTP
167:             * request, incorporating the correct WikiPage into the command if reqiured.
168:             * This method will first determine what page the user requested by
169:             * delegating to {@link #extractPageFromParameter(String, HttpServletRequest)}. If
170:             * this page equates to a special page, we return the Command
171:             * corresponding to that page. Otherwise, this method simply returns the
172:             * Command for the supplied request context.
173:             * </p>
174:             * <p>
175:             * The reason this method attempts to resolve against special pages is
176:             * because some of them resolve to contexts that may be different from the
177:             * one supplied. For example, a VIEW request context for the special page
178:             * "UserPreferences" should return a PREFS context instead.
179:             * </p>
180:             * <p>
181:             * When the caller supplies a request context and HTTP request that
182:             * specifies an actual wiki page (rather than a special page), this method
183:             * will return a "targeted" Command that includes the resolved WikiPage
184:             * as the target. (See {@link #resolvePage(HttpServletRequest, String)}
185:             * for the resolution algorithm). Specifically, the Command will
186:             * return a non-<code>null</code> value for its {@link AbstractCommand#getTarget()} method.
187:             * </p>
188:             * <p><em>Note: if this method determines that the Command is the VIEW PageCommand,
189:             * then the Command returned will always be targeted to the front page.</em></p>
190:             * @param request the HTTP request; if <code>null</code>, delegates
191:             * to {@link #findCommand(String)}
192:             * @param defaultContext the request context to use by default
193:             * @return the resolved wiki command
194:             */
195:            public final Command findCommand(HttpServletRequest request,
196:                    String defaultContext) {
197:                // Corner case if request is null
198:                if (request == null) {
199:                    return findCommand(defaultContext);
200:                }
201:
202:                Command command = null;
203:
204:                // Determine the name of the page (which may be null)
205:                String pageName = extractPageFromParameter(defaultContext,
206:                        request);
207:
208:                // Can we find a special-page command matching the extracted page?
209:                if (pageName != null) {
210:                    command = (AbstractCommand) m_specialPages.get(pageName);
211:                }
212:
213:                // If we haven't found a matching command yet, extract the JSP path
214:                // and compare to our list of special pages
215:                if (command == null) {
216:                    command = extractCommandFromPath(request);
217:
218:                    // Otherwise: use the default context
219:                    if (command == null) {
220:                        command = (AbstractCommand) CONTEXTS
221:                                .get(defaultContext);
222:                        if (command == null) {
223:                            throw new IllegalArgumentException("Wiki context "
224:                                    + defaultContext + " is illegal.");
225:                        }
226:                    }
227:                }
228:
229:                // For PageCommand.VIEW, default to front page if a page wasn't supplied
230:                if (PageCommand.VIEW.equals(command) && pageName == null) {
231:                    pageName = m_engine.getFrontPage();
232:                }
233:
234:                // These next blocks handle targeting requirements
235:
236:                // If we were passed a page parameter, try to resolve it
237:                if (command instanceof  PageCommand && pageName != null) {
238:                    // If there's a matching WikiPage, "wrap" the command
239:                    WikiPage page = resolvePage(request, pageName);
240:                    if (page != null) {
241:                        return command.targetedCommand(page);
242:                    }
243:                }
244:
245:                // If "create group" command, target this wiki
246:                String wiki = m_engine.getApplicationName();
247:                if (WikiCommand.CREATE_GROUP.equals(command)) {
248:                    return WikiCommand.CREATE_GROUP.targetedCommand(wiki);
249:                }
250:
251:                // If group command, see if we were passed a group name
252:                if (command instanceof  GroupCommand) {
253:                    String groupName = request.getParameter("group");
254:                    groupName = TextUtil.replaceEntities(groupName);
255:                    if (groupName != null && groupName.length() > 0) {
256:                        GroupPrincipal group = new GroupPrincipal(groupName);
257:                        return command.targetedCommand(group);
258:                    }
259:                }
260:
261:                // No page provided; return an "ordinary" command
262:                return command;
263:            }
264:
265:            /**
266:             * <p>
267:             * Returns the correct page name, or <code>null</code>, if no such page can be found.
268:             * Aliases are considered.
269:             * </p>
270:             * <p>
271:             * In some cases, page names can refer to other pages. For example, when you
272:             * have matchEnglishPlurals set, then a page name "Foobars" will be
273:             * transformed into "Foobar", should a page "Foobars" not exist, but the
274:             * page "Foobar" would. This method gives you the correct page name to refer
275:             * to.
276:             * </p>
277:             * <p>
278:             * This facility can also be used to rewrite any page name, for example, by
279:             * using aliases. It can also be used to check the existence of any page.
280:             * </p>
281:             * @since 2.4.20
282:             * @param page the page name.
283:             * @return The rewritten page name, or <code>null</code>, if the page does not exist.
284:             * @throws ProviderException if the underlyng page provider that locates pages
285:             * throws an exception
286:             */
287:            public final String getFinalPageName(String page)
288:                    throws ProviderException {
289:                boolean isThere = simplePageExists(page);
290:                String finalName = page;
291:
292:                if (!isThere && m_matchEnglishPlurals) {
293:                    if (page.endsWith("s")) {
294:                        finalName = page.substring(0, page.length() - 1);
295:                    } else {
296:                        finalName += "s";
297:                    }
298:
299:                    isThere = simplePageExists(finalName);
300:                }
301:
302:                if (!isThere) {
303:                    finalName = MarkupParser.wikifyLink(page);
304:                    isThere = simplePageExists(finalName);
305:
306:                    if (!isThere && m_matchEnglishPlurals) {
307:                        if (finalName.endsWith("s")) {
308:                            finalName = finalName.substring(0, finalName
309:                                    .length() - 1);
310:                        } else {
311:                            finalName += "s";
312:                        }
313:
314:                        isThere = simplePageExists(finalName);
315:                    }
316:                }
317:
318:                return isThere ? finalName : null;
319:            }
320:
321:            /**
322:             * <p>
323:             * If the page is a special page, this method returns a direct URL to that
324:             * page; otherwise, it returns <code>null</code>.
325:             * </p>
326:             * <p>
327:             * Special pages are non-existant references to other pages. For example,
328:             * you could define a special page reference "RecentChanges" which would
329:             * always be redirected to "RecentChanges.jsp" instead of trying to find a
330:             * Wiki page called "RecentChanges".
331:             * </p>
332:             * @param page the page name ro search for
333:             * @return the URL of the special page, if the supplied page is one, or <code>null</code>
334:             */
335:            public final String getSpecialPageReference(String page) {
336:                Command command = (Command) m_specialPages.get(page);
337:
338:                if (command != null) {
339:                    return m_engine.getURLConstructor().makeURL(
340:                            command.getRequestContext(),
341:                            command.getURLPattern(), true, null);
342:                }
343:
344:                return null;
345:            }
346:
347:            /**
348:             * Extracts a Command based on the JSP path of an HTTP request.
349:             * If the JSP requested matches a Command's <code>getJSP()</code>
350:             * value, that Command is returned.
351:             * @param request the HTTP request
352:             * @return the resolved Command, or <code>null</code> if not found
353:             */
354:            protected final Command extractCommandFromPath(
355:                    HttpServletRequest request) {
356:                String jsp = request.getServletPath();
357:
358:                // Take everything to right of initial / and left of # or ?
359:                int hashMark = jsp.indexOf('#');
360:                if (hashMark != -1) {
361:                    jsp = jsp.substring(0, hashMark);
362:                }
363:                int questionMark = jsp.indexOf('?');
364:                if (questionMark != -1) {
365:                    jsp = jsp.substring(0, questionMark);
366:                }
367:                if (jsp.startsWith("/")) {
368:                    jsp = jsp.substring(1);
369:                }
370:
371:                // Find special page reference?
372:                for (Iterator i = m_specialPages.entrySet().iterator(); i
373:                        .hasNext();) {
374:                    Map.Entry entry = (Map.Entry) i.next();
375:                    Command specialCommand = (Command) entry.getValue();
376:                    if (specialCommand.getJSP().equals(jsp)) {
377:                        return specialCommand;
378:                    }
379:                }
380:
381:                // Still haven't found a matching command?
382:                // Ok, see if we match against our standard list of JSPs
383:                if (jsp.length() > 0 && JSPS.containsKey(jsp)) {
384:                    return (Command) JSPS.get(jsp);
385:                }
386:
387:                return null;
388:            }
389:
390:            /**
391:             * Determines the correct wiki page based on a supplied request context and
392:             * HTTP request. This method attempts to determine the page requested by a
393:             * user, taking into acccount special pages. The resolution algorithm will:
394:             * <ul>
395:             * <li>Extract the page name from the URL according to the rules for the
396:             * current {@link URLConstructor}. If a page name was
397:             * passed in the request, return the correct name after taking into account
398:             * potential plural matches.</li>
399:             * <li>If the extracted page name is <code>null</code>, attempt to see
400:             * if a "special page" was intended by examining the servlet path. For
401:             * example, the request path "/UserPreferences.jsp" will resolve to
402:             * "UserPreferences."</li>
403:             * <li>If neither of these methods work, this method returns
404:             * <code>null</code></li>
405:             * </ul>
406:             * @param requestContext the request context
407:             * @param request the HTTP request
408:             * @return the resolved page name
409:             */
410:            protected final String extractPageFromParameter(
411:                    String requestContext, HttpServletRequest request) {
412:                String page;
413:
414:                // Extract the page name from the URL directly
415:                try {
416:                    page = m_engine.getURLConstructor().parsePage(
417:                            requestContext, request,
418:                            m_engine.getContentEncoding());
419:                    if (page != null) {
420:                        try {
421:                            // Look for singular/plural variants; if one
422:                            // not found, take the one the user supplied
423:                            String finalPage = getFinalPageName(page);
424:                            if (finalPage != null) {
425:                                page = finalPage;
426:                            }
427:                        } catch (ProviderException e) {
428:                            // FIXME: Should not ignore!
429:                        }
430:                        return page;
431:                    }
432:                } catch (IOException e) {
433:                    m_log.error("Unable to create context", e);
434:                    throw new InternalWikiException(
435:                            "Big internal booboo, please check logs.");
436:                }
437:
438:                // Didn't resolve; return null
439:                return null;
440:            }
441:
442:            /**
443:             * Looks up and returns the correct, versioned WikiPage based on a supplied
444:             * page name and optional <code>version</code> parameter passed in an HTTP
445:             * request. If the <code>version</code> parameter does not exist in the
446:             * request, the latest version is returned.
447:             * @param request the HTTP request
448:             * @param page the name of the page to look up; this page <em>must</em> exist
449:             * @return the wiki page
450:             */
451:            protected final WikiPage resolvePage(HttpServletRequest request,
452:                    String page) {
453:                // See if the user included a version parameter
454:                WikiPage wikipage;
455:                int version = WikiProvider.LATEST_VERSION;
456:                String rev = request.getParameter("version");
457:
458:                if (rev != null) {
459:                    version = Integer.parseInt(rev);
460:                }
461:
462:                wikipage = m_engine.getPage(page, version);
463:
464:                if (wikipage == null) {
465:                    page = MarkupParser.cleanLink(page);
466:                    wikipage = new WikiPage(m_engine, page);
467:                }
468:                return wikipage;
469:            }
470:
471:            /**
472:             * Determines whether a "page" exists by examining the list of special pages
473:             * and querying the page manager.
474:             * @param page the page to seek
475:             * @return <code>true</code> if the page exists, <code>false</code>
476:             *         otherwise
477:             * @throws ProviderException if the underlyng page provider that locates pages
478:             * throws an exception
479:             */
480:            protected final boolean simplePageExists(String page)
481:                    throws ProviderException {
482:                if (m_specialPages.containsKey(page)) {
483:                    return true;
484:                }
485:                return m_engine.getPageManager().pageExists(page);
486:            }
487:
488:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.