Source Code Cross Referenced for ClasspathConfigurationProvider.java in  » Web-Framework » struts-2.0.11 » org » apache » struts2 » config » 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 » Web Framework » struts 2.0.11 » org.apache.struts2.config 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * $Id: ClasspathConfigurationProvider.java 501717 2007-01-31 03:51:11Z mrdon $
003:         *
004:         * Licensed to the Apache Software Foundation (ASF) under one
005:         * or more contributor license agreements.  See the NOTICE file
006:         * distributed with this work for additional information
007:         * regarding copyright ownership.  The ASF licenses this file
008:         * to you under the Apache License, Version 2.0 (the
009:         * "License"); you may not use this file except in compliance
010:         * with the License.  You may obtain a copy of the License at
011:         *
012:         *  http://www.apache.org/licenses/LICENSE-2.0
013:         *
014:         * Unless required by applicable law or agreed to in writing,
015:         * software distributed under the License is distributed on an
016:         * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017:         * KIND, either express or implied.  See the License for the
018:         * specific language governing permissions and limitations
019:         * under the License.
020:         */
021:        package org.apache.struts2.config;
022:
023:        import java.lang.annotation.Annotation;
024:        import java.lang.reflect.Modifier;
025:        import java.net.URL;
026:        import java.util.HashMap;
027:        import java.util.Map;
028:        import java.util.Set;
029:
030:        import org.apache.commons.logging.Log;
031:        import org.apache.commons.logging.LogFactory;
032:
033:        import com.opensymphony.xwork2.Action;
034:        import com.opensymphony.xwork2.config.Configuration;
035:        import com.opensymphony.xwork2.config.ConfigurationException;
036:        import com.opensymphony.xwork2.config.ConfigurationProvider;
037:        import com.opensymphony.xwork2.config.entities.ActionConfig;
038:        import com.opensymphony.xwork2.config.entities.PackageConfig;
039:        import com.opensymphony.xwork2.config.entities.ResultConfig;
040:        import com.opensymphony.xwork2.config.entities.ResultTypeConfig;
041:        import com.opensymphony.xwork2.inject.ContainerBuilder;
042:        import com.opensymphony.xwork2.inject.Inject;
043:        import com.opensymphony.xwork2.util.ClassLoaderUtil;
044:        import com.opensymphony.xwork2.util.ResolverUtil;
045:        import com.opensymphony.xwork2.util.TextUtils;
046:        import com.opensymphony.xwork2.util.ResolverUtil.Test;
047:        import com.opensymphony.xwork2.util.location.LocatableProperties;
048:
049:        /**
050:         * ClasspathConfigurationProvider loads the configuration
051:         * by scanning the classpath or selected packages for Action classes.
052:         * <p>
053:         * This provider is only invoked if one or more action packages are passed to the dispatcher,
054:         * usually from the web.xml.
055:         * Configurations are created for objects that either implement Action or have classnames that end with "Action".
056:         */
057:        public class ClasspathConfigurationProvider implements 
058:                ConfigurationProvider {
059:
060:            /**
061:             * The default page prefix (or "path").
062:             * Some applications may place pages under "/WEB-INF" as an extreme security precaution.
063:             */
064:            private static final String DEFAULT_PAGE_PREFIX = "struts.configuration.classpath.defaultPagePrefix";
065:
066:            /**
067:             * The default page prefix (none).
068:             */
069:            private String defaultPagePrefix = "";
070:
071:            /**
072:             * The default page extension,  to use in place of ".jsp".
073:             */
074:            private static final String DEFAULT_PAGE_EXTENSION = "struts.configuration.classpath.defaultPageExtension";
075:
076:            /**
077:             * The defacto default page extension, usually associated with JavaServer Pages.
078:             */
079:            private String defaultPageExtension = ".jsp";
080:
081:            /**
082:             * A setting to indicate a custom default parent package,
083:             * to use in place of "struts-default".
084:             */
085:            private static final String DEFAULT_PARENT_PACKAGE = "struts.configuration.classpath.defaultParentPackage";
086:
087:            /**
088:             * Name of the framework's default configuration package,
089:             * that application configuration packages automatically inherit.
090:             */
091:            private String defaultParentPackage = "struts-default";
092:
093:            /**
094:             * The default page prefix (or "path").
095:             * Some applications may place pages under "/WEB-INF" as an extreme security precaution.
096:             */
097:            private static final String FORCE_LOWER_CASE = "struts.configuration.classpath.forceLowerCase";
098:
099:            /**
100:             * Whether to use a lowercase letter as the initial letter of an action.
101:             * If false, actions will retain the initial uppercase letter from the Action class.
102:             * (<code>view.action</code> (true) versus <code>View.action</code> (false)).
103:             */
104:            private boolean forceLowerCase = true;
105:
106:            /**
107:             * Default suffix that can be used to indicate POJO "Action" classes.
108:             */
109:            private static final String ACTION = "Action";
110:
111:            /**
112:             * Helper class to scan class path for server pages.
113:             */
114:            private PageLocator pageLocator = new ClasspathPageLocator();
115:
116:            /**
117:             * Flag to indicate the packages have been loaded.
118:             *
119:             * @see #loadPackages
120:             * @see #needsReload
121:             */
122:            private boolean initialized = false;
123:
124:            /**
125:             * The list of packages to scan for Action classes.
126:             */
127:            private String[] packages;
128:
129:            /**
130:             * The package configurations for scanned Actions.
131:             *
132:             * @see #loadPackageConfig
133:             */
134:            private Map<String, PackageConfig> loadedPackageConfigs = new HashMap<String, PackageConfig>();
135:
136:            /**
137:             * Logging instance for this class.
138:             */
139:            private static final Log LOG = LogFactory
140:                    .getLog(ClasspathConfigurationProvider.class);
141:
142:            /**
143:             * The XWork Configuration for this application.
144:             *
145:             * @see #init
146:             */
147:            private Configuration configuration;
148:
149:            /**
150:             * Create instance utilizing a list of packages to scan for Action classes.
151:             *
152:             * @param pkgs List of pacaktges to scan for Action Classes.
153:             */
154:            public ClasspathConfigurationProvider(String[] pkgs) {
155:                this .packages = pkgs;
156:            }
157:
158:            /**
159:             * PageLocator defines a locate method that can be used to discover server pages.
160:             */
161:            public static interface PageLocator {
162:                public URL locate(String path);
163:            }
164:
165:            /**
166:             * ClasspathPathLocator searches the classpath for server pages.
167:             */
168:            public static class ClasspathPageLocator implements  PageLocator {
169:                public URL locate(String path) {
170:                    return ClassLoaderUtil.getResource(path, getClass());
171:                }
172:            }
173:
174:            /**
175:             * Register a default parent package for the actions.
176:             *
177:             * @param defaultParentPackage the new defaultParentPackage
178:             */
179:            @Inject(value=DEFAULT_PARENT_PACKAGE,required=false)
180:            public void setDefaultParentPackage(String defaultParentPackage) {
181:                this .defaultParentPackage = defaultParentPackage;
182:            }
183:
184:            /**
185:             * Register a default page extension to use when locating pages.
186:             *
187:             * @param defaultPageExtension the new defaultPageExtension
188:             */
189:            @Inject(value=DEFAULT_PAGE_EXTENSION,required=false)
190:            public void setDefaultPageExtension(String defaultPageExtension) {
191:                this .defaultPageExtension = defaultPageExtension;
192:            }
193:
194:            /**
195:             * Reigster a default page prefix to use when locating pages.
196:             *
197:             * @param defaultPagePrefix the defaultPagePrefix to set
198:             */
199:            @Inject(value=DEFAULT_PAGE_PREFIX,required=false)
200:            public void setDefaultPagePrefix(String defaultPagePrefix) {
201:                this .defaultPagePrefix = defaultPagePrefix;
202:            }
203:
204:            /**
205:             * Whether to use a lowercase letter as the initial letter of an action.
206:             * 
207:             * @param force If false, actions will retain the initial uppercase letter from the Action class.
208:             * (<code>view.action</code> (true) versus <code>View.action</code> (false)).
209:             */
210:            @Inject(value=FORCE_LOWER_CASE,required=false)
211:            public void setForceLowerCase(String force) {
212:                this .forceLowerCase = "true".equals(force);
213:            }
214:
215:            /**
216:             * Register a PageLocation to use to scan for server pages.
217:             *
218:             * @param locator
219:             */
220:            public void setPageLocator(PageLocator locator) {
221:                this .pageLocator = locator;
222:            }
223:
224:            /**
225:             * Scan a list of packages for Action classes.
226:             *
227:             * This method loads classes that implement the Action interface
228:             * or have a class name that ends with the letters "Action".
229:             *
230:             * @param pkgs A list of packages to load
231:             * @see #processActionClass
232:             */
233:            protected void loadPackages(String[] pkgs) {
234:
235:                ResolverUtil<Class> resolver = new ResolverUtil<Class>();
236:                resolver.find(new Test() {
237:                    // Match Action implementations and classes ending with "Action"
238:                    public boolean matches(Class type) {
239:                        // TODO: should also find annotated classes
240:                        return (Action.class.isAssignableFrom(type) || type
241:                                .getSimpleName().endsWith("Action"));
242:                    }
243:
244:                }, pkgs);
245:
246:                Set<? extends Class<? extends Class>> actionClasses = resolver
247:                        .getClasses();
248:                for (Object obj : actionClasses) {
249:                    Class cls = (Class) obj;
250:                    if (!Modifier.isAbstract(cls.getModifiers())) {
251:                        processActionClass(cls, pkgs);
252:                    }
253:                }
254:
255:                for (String key : loadedPackageConfigs.keySet()) {
256:                    configuration.addPackageConfig(key, loadedPackageConfigs
257:                            .get(key));
258:                }
259:            }
260:
261:            /**
262:             * Create a default action mapping for a class instance.
263:             *
264:             * The namespace annotation is honored, if found, otherwise
265:             * the Java package is converted into the namespace
266:             * by changing the dots (".") to slashes ("/").
267:             *
268:             * @param cls Action or POJO instance to process
269:             * @param pkgs List of packages that were scanned for Actions
270:             */
271:            protected void processActionClass(Class cls, String[] pkgs) {
272:                String name = cls.getName();
273:                String actionPackage = cls.getPackage().getName();
274:                String actionNamespace = null;
275:                String actionName = null;
276:                for (String pkg : pkgs) {
277:                    if (name.startsWith(pkg)) {
278:                        if (LOG.isDebugEnabled()) {
279:                            LOG
280:                                    .debug("ClasspathConfigurationProvider: Processing class "
281:                                            + name);
282:                        }
283:                        name = name.substring(pkg.length() + 1);
284:
285:                        actionNamespace = "";
286:                        actionName = name;
287:                        int pos = name.lastIndexOf('.');
288:                        if (pos > -1) {
289:                            actionNamespace = "/"
290:                                    + name.substring(0, pos).replace('.', '/');
291:                            actionName = name.substring(pos + 1);
292:                        }
293:                        break;
294:                    }
295:                }
296:
297:                PackageConfig pkgConfig = loadPackageConfig(actionNamespace,
298:                        actionPackage, cls);
299:
300:                // In case the package changed due to namespace annotation processing
301:                if (!actionPackage.equals(pkgConfig.getName())) {
302:                    actionPackage = pkgConfig.getName();
303:                }
304:
305:                Annotation annotation = cls.getAnnotation(ParentPackage.class);
306:                if (annotation != null) {
307:                    String parent = ((ParentPackage) annotation).value();
308:                    PackageConfig parentPkg = configuration
309:                            .getPackageConfig(parent);
310:                    if (parentPkg == null) {
311:                        throw new ConfigurationException(
312:                                "ClasspathConfigurationProvider: Unable to locate parent package "
313:                                        + parent, annotation);
314:                    }
315:                    pkgConfig.addParent(parentPkg);
316:
317:                    if (!TextUtils.stringSet(pkgConfig.getNamespace())
318:                            && TextUtils.stringSet(parentPkg.getNamespace())) {
319:                        pkgConfig.setNamespace(parentPkg.getNamespace());
320:                    }
321:                }
322:
323:                // Truncate Action suffix if found
324:                if (actionName.endsWith(ACTION)) {
325:                    actionName = actionName.substring(0, actionName.length()
326:                            - ACTION.length());
327:                }
328:
329:                // Force initial letter of action to lowercase, if desired
330:                if ((forceLowerCase) && (actionName.length() > 1)) {
331:                    int lowerPos = actionName.lastIndexOf('/') + 1;
332:                    StringBuilder sb = new StringBuilder();
333:                    sb.append(actionName.substring(0, lowerPos));
334:                    sb.append(Character
335:                            .toLowerCase(actionName.charAt(lowerPos)));
336:                    sb.append(actionName.substring(lowerPos + 1));
337:                    actionName = sb.toString();
338:                }
339:
340:                ActionConfig actionConfig = new ActionConfig();
341:                actionConfig.setClassName(cls.getName());
342:                actionConfig.setPackageName(actionPackage);
343:
344:                actionConfig.setResults(new ResultMap<String, ResultConfig>(
345:                        cls, actionName, pkgConfig));
346:                pkgConfig.addActionConfig(actionName, actionConfig);
347:            }
348:
349:            /**
350:             * Finds or creates the package configuration for an Action class.
351:             *
352:             * The namespace annotation is honored, if found,
353:             * and the namespace is checked for a parent configuration.
354:             *
355:             * @param actionNamespace The configuration namespace
356:             * @param actionPackage The Java package containing our Action classes
357:             * @param actionClass The Action class instance
358:             * @return PackageConfig object for the Action class
359:             */
360:            protected PackageConfig loadPackageConfig(String actionNamespace,
361:                    String actionPackage, Class actionClass) {
362:                PackageConfig parent = null;
363:
364:                if (actionClass != null) {
365:                    Namespace ns = (Namespace) actionClass
366:                            .getAnnotation(Namespace.class);
367:                    if (ns != null) {
368:                        parent = loadPackageConfig(actionNamespace,
369:                                actionPackage, null);
370:                        actionNamespace = ns.value();
371:                        actionPackage = actionClass.getName();
372:                    }
373:                }
374:
375:                PackageConfig pkgConfig = loadedPackageConfigs
376:                        .get(actionPackage);
377:                if (pkgConfig == null) {
378:                    pkgConfig = new PackageConfig();
379:                    pkgConfig.setName(actionPackage);
380:
381:                    if (parent == null) {
382:                        parent = configuration
383:                                .getPackageConfig(defaultParentPackage);
384:                    }
385:
386:                    if (parent == null) {
387:                        throw new ConfigurationException(
388:                                "ClasspathConfigurationProvider: Unable to locate default parent package: "
389:                                        + defaultParentPackage);
390:                    }
391:                    pkgConfig.addParent(parent);
392:
393:                    pkgConfig.setNamespace(actionNamespace);
394:
395:                    loadedPackageConfigs.put(actionPackage, pkgConfig);
396:                }
397:                return pkgConfig;
398:            }
399:
400:            /**
401:             * Default destructor. Override to provide behavior.
402:             */
403:            public void destroy() {
404:
405:            }
406:
407:            /**
408:             * Register this application's configuration.
409:             *
410:             * @param config The configuration for this application.
411:             */
412:            public void init(Configuration config) {
413:                this .configuration = config;
414:            }
415:
416:            /**
417:             * Clears and loads the list of packages registered at construction.
418:             *
419:             * @throws ConfigurationException
420:             */
421:            public void loadPackages() throws ConfigurationException {
422:                loadedPackageConfigs.clear();
423:                loadPackages(packages);
424:                initialized = true;
425:            }
426:
427:            /**
428:             * Indicates whether the packages have been initialized.
429:             *
430:             * @return True if the packages have been initialized
431:             */
432:            public boolean needsReload() {
433:                return !initialized;
434:            }
435:
436:            /**
437:             * Creates ResultConfig objects from result annotations,
438:             * and if a result isn't found, creates it on the fly.
439:             */
440:            class ResultMap<K, V> extends HashMap<K, V> {
441:                private Class actionClass;
442:                private String actionName;
443:                private PackageConfig pkgConfig;
444:
445:                public ResultMap(Class actionClass, String actionName,
446:                        PackageConfig pkgConfig) {
447:                    this .actionClass = actionClass;
448:                    this .actionName = actionName;
449:                    this .pkgConfig = pkgConfig;
450:
451:                    // check if any annotations are around
452:                    while (!actionClass.getName()
453:                            .equals(Object.class.getName())) {
454:                        //noinspection unchecked
455:                        Results results = (Results) actionClass
456:                                .getAnnotation(Results.class);
457:                        if (results != null) {
458:                            // first check here...
459:                            for (int i = 0; i < results.value().length; i++) {
460:                                Result result = results.value()[i];
461:                                ResultConfig config = createResultConfig(result);
462:                                put((K) config.getName(), (V) config);
463:                            }
464:                        }
465:
466:                        // what about a single Result annotation?
467:                        Result result = (Result) actionClass
468:                                .getAnnotation(Result.class);
469:                        if (result != null) {
470:                            ResultConfig config = createResultConfig(result);
471:                            put((K) config.getName(), (V) config);
472:                        }
473:
474:                        actionClass = actionClass.getSuperclass();
475:                    }
476:                }
477:
478:                /**
479:                 * Extracts result name and value and calls {@link #createResultConfig}.
480:                 *
481:                 * @param result Result annotation reference representing result type to create
482:                 * @return New or cached ResultConfig object for result
483:                 */
484:                protected ResultConfig createResultConfig(Result result) {
485:                    Class<? extends Object> cls = result.type();
486:                    if (cls == NullResult.class) {
487:                        cls = null;
488:                    }
489:                    return createResultConfig(result.name(), cls, result
490:                            .value(), createParameterMap(result.params()));
491:                }
492:
493:                protected Map<String, String> createParameterMap(String[] parms) {
494:                    Map<String, String> map = new HashMap<String, String>();
495:                    int subtract = parms.length % 2;
496:                    if (subtract != 0) {
497:                        LOG
498:                                .warn("Odd number of result parameters key/values specified.  The final one will be ignored.");
499:                    }
500:                    for (int i = 0; i < parms.length - subtract; i++) {
501:                        String key = parms[i++];
502:                        String value = parms[i];
503:                        map.put(key, value);
504:                        if (LOG.isDebugEnabled()) {
505:                            LOG.debug("Adding parmeter[" + key + ":" + value
506:                                    + "] to result.");
507:                        }
508:                    }
509:                    return map;
510:                }
511:
512:                /**
513:                 * Creates a default ResultConfig,
514:                 * using either the resultClass or the default ResultType for configuration package
515:                 * associated this ResultMap class.
516:                 *
517:                 * @param key The result type name
518:                 * @param resultClass The class for the result type
519:                 * @param location Path to the resource represented by this type
520:                 * @return A ResultConfig for key mapped to location
521:                 */
522:                private ResultConfig createResultConfig(Object key,
523:                        Class<? extends Object> resultClass, String location,
524:                        Map<? extends Object, ? extends Object> configParams) {
525:                    if (resultClass == null) {
526:                        String defaultResultType = pkgConfig
527:                                .getFullDefaultResultType();
528:                        ResultTypeConfig resultType = pkgConfig
529:                                .getAllResultTypeConfigs().get(
530:                                        defaultResultType);
531:                        configParams = resultType.getParams();
532:                        String className = resultType.getClazz();
533:                        try {
534:                            resultClass = ClassLoaderUtil.loadClass(className,
535:                                    getClass());
536:                        } catch (ClassNotFoundException ex) {
537:                            throw new ConfigurationException(
538:                                    "ClasspathConfigurationProvider: Unable to locate result class "
539:                                            + className, actionClass);
540:                        }
541:                    }
542:
543:                    String defaultParam;
544:                    try {
545:                        defaultParam = (String) resultClass.getField(
546:                                "DEFAULT_PARAM").get(null);
547:                    } catch (Exception e) {
548:                        // not sure why this happened, but let's just use a sensible choice
549:                        defaultParam = "location";
550:                    }
551:
552:                    HashMap params = new HashMap();
553:                    if (configParams != null) {
554:                        params.putAll(configParams);
555:                    }
556:
557:                    params.put(defaultParam, location);
558:                    return new ResultConfig((String) key,
559:                            resultClass.getName(), params);
560:                }
561:            }
562:
563:            // See superclass for Javadoc
564:            public void register(ContainerBuilder builder,
565:                    LocatableProperties props) throws ConfigurationException {
566:                // Override to provide functionality
567:            }
568:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.