001: /*
002: * Copyright (c) 2002-2006 by OpenSymphony
003: * All rights reserved.
004: */
005: package com.opensymphony.xwork.config.providers;
006:
007: import com.opensymphony.util.FileManager;
008: import com.opensymphony.util.ClassLoaderUtil;
009: import com.opensymphony.util.TextUtils;
010: import com.opensymphony.xwork.Action;
011: import com.opensymphony.xwork.ActionSupport;
012: import com.opensymphony.xwork.ObjectFactory;
013: import com.opensymphony.xwork.XworkException;
014: import com.opensymphony.xwork.config.*;
015: import com.opensymphony.xwork.config.entities.*;
016: import com.opensymphony.xwork.util.DomHelper;
017: import com.opensymphony.xwork.util.location.Location;
018:
019: import org.apache.commons.logging.Log;
020: import org.apache.commons.logging.LogFactory;
021: import org.w3c.dom.Document;
022: import org.w3c.dom.Element;
023: import org.w3c.dom.Node;
024: import org.w3c.dom.NodeList;
025: import org.xml.sax.*;
026:
027: import java.io.IOException;
028: import java.io.InputStream;
029: import java.util.*;
030: import java.lang.reflect.Modifier;
031:
032: /**
033: * Looks in the classpath for "xwork.xml" and uses it for the XWork configuration.
034: *
035: * @author tmjee
036: * @author Rainer Hermanns
037: * @author Neo
038: * @version $Revision: 1539 $
039: */
040: public class XmlConfigurationProvider implements ConfigurationProvider {
041:
042: private static final Log LOG = LogFactory
043: .getLog(XmlConfigurationProvider.class);
044:
045: private Configuration configuration;
046: private Set includedFileNames = new TreeSet();
047: private String configFileName = "xwork.xml";
048:
049: public XmlConfigurationProvider() {
050: }
051:
052: public XmlConfigurationProvider(String filename) {
053: this .configFileName = filename;
054: }
055:
056: public void destroy() {
057: }
058:
059: public boolean equals(Object o) {
060: if (this == o) {
061: return true;
062: }
063:
064: if (!(o instanceof XmlConfigurationProvider)) {
065: return false;
066: }
067:
068: final XmlConfigurationProvider xmlConfigurationProvider = (XmlConfigurationProvider) o;
069:
070: if ((configFileName != null) ? (!configFileName
071: .equals(xmlConfigurationProvider.configFileName))
072: : (xmlConfigurationProvider.configFileName != null)) {
073: return false;
074: }
075:
076: return true;
077: }
078:
079: public int hashCode() {
080: return ((configFileName != null) ? configFileName.hashCode()
081: : 0);
082: }
083:
084: public void init(Configuration configuration) {
085: this .configuration = configuration;
086: includedFileNames.clear();
087:
088: try {
089: loadConfigurationFile(configFileName, null);
090: } catch (ConfigurationException e) {
091: throw e;
092: } catch (Exception e) {
093: LOG.fatal(
094: "Could not load XWork configuration file, failing",
095: e);
096: throw new ConfigurationException(
097: "Error loading configuration file "
098: + configFileName, e);
099: }
100: }
101:
102: /**
103: * Tells whether the ConfigurationProvider should reload its configuration. This method should only be called
104: * if ConfigurationManager.isReloadingConfigs() is true.
105: *
106: * @return true if the file has been changed since the last time we read it
107: */
108: public boolean needsReload() {
109: boolean needsReload = FileManager
110: .fileNeedsReloading(configFileName);
111: Iterator fileNameIterator = includedFileNames.iterator();
112:
113: while (!needsReload && (fileNameIterator.hasNext())) {
114: String fileName = (String) fileNameIterator.next();
115: needsReload = FileManager.fileNeedsReloading(fileName);
116: }
117:
118: return needsReload;
119: }
120:
121: protected InputStream getInputStream(String fileName) {
122: return FileManager.loadFile(fileName, this .getClass());
123: }
124:
125: protected void addAction(Element actionElement,
126: PackageConfig packageContext) throws ConfigurationException {
127: String name = actionElement.getAttribute("name");
128: String className = actionElement.getAttribute("class");
129: String methodName = actionElement.getAttribute("method");
130: Location location = DomHelper.getLocationObject(actionElement);
131:
132: //methodName should be null if it's not set
133: methodName = (methodName.trim().length() > 0) ? methodName
134: .trim() : null;
135:
136: // if you don't specify a class on <action/>, it defaults to ActionSupport
137: if (!TextUtils.stringSet(className)) {
138: className = ActionSupport.class.getName();
139: }
140:
141: if (!verifyAction(className, name, location)) {
142: return;
143: }
144:
145: Map actionParams = XmlHelper.getParams(actionElement);
146:
147: Map results;
148:
149: try {
150: results = buildResults(actionElement, packageContext);
151: } catch (ConfigurationException e) {
152: throw new ConfigurationException(
153: "Error building results for action " + name
154: + " in namespace "
155: + packageContext.getNamespace(), e,
156: actionElement);
157: }
158:
159: List interceptorList = buildInterceptorList(actionElement,
160: packageContext);
161:
162: List externalrefs = buildExternalRefs(actionElement,
163: packageContext);
164:
165: List exceptionMappings = buildExceptionMappings(actionElement,
166: packageContext);
167:
168: ActionConfig actionConfig = new ActionConfig(methodName,
169: className, actionParams, results, interceptorList,
170: externalrefs, exceptionMappings, packageContext
171: .getName());
172: actionConfig.setLocation(location);
173: packageContext.addActionConfig(name, actionConfig);
174:
175: if (LOG.isDebugEnabled()) {
176: LOG.debug("Loaded "
177: + (TextUtils.stringSet(packageContext
178: .getNamespace()) ? (packageContext
179: .getNamespace() + "/") : "") + name
180: + " in '" + packageContext.getName() + "' package:"
181: + actionConfig);
182: }
183: }
184:
185: protected boolean verifyAction(String className, String name,
186: Location loc) {
187: try {
188: Class clazz = ObjectFactory.getObjectFactory()
189: .getClassInstance(className);
190: if (ObjectFactory.getObjectFactory()
191: .isNoArgConstructorRequired()) {
192: if (!Modifier.isPublic(clazz.getModifiers())) {
193: LOG.error("Action class [" + className
194: + "] is not public, skipping action ["
195: + name + "]");
196: return false;
197: }
198: clazz.getConstructor(new Class[] {});
199: }
200: return true;
201: } catch (ClassNotFoundException e) {
202: LOG.error("Action class [" + className
203: + "] not found, skipping action [" + name + "] at "
204: + loc, e);
205: return false;
206: } catch (NoSuchMethodException e) {
207: LOG.error("Action class [" + className
208: + "] does not have a public no-arg constructor,"
209: + " skipping action [" + name + "] at " + loc, e);
210: return false;
211: } catch (Exception ex) {
212: throw new ConfigurationException(ex, loc);
213: }
214: }
215:
216: /**
217: * Create a PackageConfig from an XML element representing it.
218: */
219: protected void addPackage(Element packageElement)
220: throws ConfigurationException {
221: PackageConfig newPackage = buildPackageContext(packageElement);
222:
223: if (LOG.isDebugEnabled()) {
224: LOG.debug("Loaded " + newPackage);
225: }
226:
227: // add result types (and default result) to this package
228: addResultTypes(newPackage, packageElement);
229:
230: // load the interceptors and interceptor stacks for this package
231: loadInterceptors(newPackage, packageElement);
232:
233: // load the default interceptor reference for this package
234: loadDefaultInterceptorRef(newPackage, packageElement);
235:
236: // load the global result list for this package
237: loadGlobalResults(newPackage, packageElement);
238:
239: // load the global exception handler list for this package
240: loadGobalExceptionMappings(newPackage, packageElement);
241:
242: // get actions
243: NodeList actionList = packageElement
244: .getElementsByTagName("action");
245:
246: for (int i = 0; i < actionList.getLength(); i++) {
247: Element actionElement = (Element) actionList.item(i);
248: addAction(actionElement, newPackage);
249: }
250:
251: // load the default action reference for this package
252: loadDefaultActionRef(newPackage, packageElement);
253:
254: configuration
255: .addPackageConfig(newPackage.getName(), newPackage);
256: }
257:
258: protected void addResultTypes(PackageConfig packageContext,
259: Element element) {
260: NodeList resultTypeList = element
261: .getElementsByTagName("result-type");
262:
263: for (int i = 0; i < resultTypeList.getLength(); i++) {
264: Element resultTypeElement = (Element) resultTypeList
265: .item(i);
266: String name = resultTypeElement.getAttribute("name");
267: String className = resultTypeElement.getAttribute("class");
268: String def = resultTypeElement.getAttribute("default");
269:
270: Location loc = DomHelper
271: .getLocationObject(resultTypeElement);
272:
273: Class clazz = verifyResultType(className, loc);
274: if (clazz != null) {
275: String paramName = null;
276: try {
277: paramName = (String) clazz
278: .getField("DEFAULT_PARAM").get(null);
279: } catch (Throwable t) {
280: // if we get here, the result type doesn't have a default param defined.
281: }
282: ResultTypeConfig resultType = new ResultTypeConfig(
283: name, className, paramName);
284: resultType.setLocation(DomHelper
285: .getLocationObject(resultTypeElement));
286:
287: Map params = XmlHelper.getParams(resultTypeElement);
288:
289: if (!params.isEmpty()) {
290: resultType.setParams(params);
291: }
292: packageContext.addResultTypeConfig(resultType);
293:
294: // set the default result type
295: if ("true".equals(def)) {
296: packageContext.setDefaultResultType(name);
297: }
298: }
299: }
300: }
301:
302: protected Class verifyResultType(String className, Location loc) {
303: try {
304: return ObjectFactory.getObjectFactory().getClassInstance(
305: className);
306: } catch (ClassNotFoundException e) {
307: LOG.warn("Result class [" + className
308: + "] doesn't exist (ClassNotFoundException) at "
309: + loc.toString() + ", ignoring", e);
310: } catch (NoClassDefFoundError e) {
311: LOG.warn("Result class [" + className
312: + "] doesn't exist (NoClassDefFoundError) at "
313: + loc.toString() + ", ignoring", e);
314: }
315:
316: return null;
317: }
318:
319: protected List buildExternalRefs(Element element,
320: PackageConfig context) throws ConfigurationException {
321: List refs = new ArrayList();
322: NodeList externalRefList = element
323: .getElementsByTagName("external-ref");
324:
325: String refName;
326: String refValue = null;
327: String requiredTemp;
328: boolean required;
329:
330: for (int i = 0; i < externalRefList.getLength(); i++) {
331: Element refElement = (Element) externalRefList.item(i);
332:
333: if (refElement.getParentNode().equals(element)
334: || refElement.getParentNode().getNodeName().equals(
335: element.getNodeName())) {
336: refName = refElement.getAttribute("name");
337:
338: //If the external ref is not declared explicitly, we can introspect the
339: //reference type using it's name and try resolving the reference using it's class type
340: if (refElement.getChildNodes().getLength() > 0) {
341: refValue = XmlHelper.getContent(refElement);
342: }
343:
344: requiredTemp = refElement.getAttribute("required");
345:
346: if ((requiredTemp == null) || "".equals(requiredTemp)) {
347: required = true;
348: } else {
349: required = Boolean.valueOf(requiredTemp)
350: .booleanValue();
351: }
352:
353: refs.add(new ExternalReference(refName, refValue,
354: required));
355: }
356: }
357:
358: return refs;
359: }
360:
361: protected List buildInterceptorList(Element element,
362: PackageConfig context) throws ConfigurationException {
363: List interceptorList = new ArrayList();
364: NodeList interceptorRefList = element
365: .getElementsByTagName("interceptor-ref");
366:
367: for (int i = 0; i < interceptorRefList.getLength(); i++) {
368: Element interceptorRefElement = (Element) interceptorRefList
369: .item(i);
370:
371: if (interceptorRefElement.getParentNode().equals(element)
372: || interceptorRefElement.getParentNode()
373: .getNodeName()
374: .equals(element.getNodeName())) {
375: List interceptors = lookupInterceptorReference(context,
376: interceptorRefElement);
377: interceptorList.addAll(interceptors);
378: }
379: }
380:
381: return interceptorList;
382: }
383:
384: /**
385: * This method builds a package context by looking for the parents of this new package.
386: * <p/>
387: * If no parents are found, it will return a root package.
388: */
389: protected PackageConfig buildPackageContext(Element packageElement) {
390: String parent = packageElement.getAttribute("extends");
391: String abstractVal = packageElement.getAttribute("abstract");
392: boolean isAbstract = Boolean.valueOf(abstractVal)
393: .booleanValue();
394: String name = TextUtils.noNull(packageElement
395: .getAttribute("name"));
396: String namespace = TextUtils.noNull(packageElement
397: .getAttribute("namespace"));
398:
399: //RM* Load the ExternalReferenceResolver if one has been set
400: ExternalReferenceResolver erResolver = null;
401:
402: String externalReferenceResolver = TextUtils
403: .noNull(packageElement
404: .getAttribute("externalReferenceResolver"));
405:
406: PackageConfig cfg = null;
407: if (!("".equals(externalReferenceResolver))) {
408: try {
409: erResolver = (ExternalReferenceResolver) ObjectFactory
410: .getObjectFactory().buildBean(
411: externalReferenceResolver, null);
412: } catch (ClassNotFoundException e) {
413: //TODO this should be localized
414: String msg = "Could not find External Reference Resolver: "
415: + externalReferenceResolver
416: + ". "
417: + e.getMessage();
418: LOG.error(msg);
419: throw new ConfigurationException(msg, e, packageElement);
420: } catch (Exception e) {
421: //TODO this should be localized
422: String msg = "Could not create External Reference Resolver: "
423: + externalReferenceResolver
424: + ". "
425: + e.getMessage();
426: LOG.error(msg);
427: throw new ConfigurationException(msg, e, packageElement);
428: }
429: }
430:
431: if (!TextUtils.stringSet(TextUtils.noNull(parent))) { // no parents
432:
433: cfg = new PackageConfig(name, namespace, isAbstract,
434: erResolver);
435: } else { // has parents, let's look it up
436:
437: List parents = ConfigurationUtil.buildParentsFromString(
438: configuration, parent);
439:
440: if (parents.size() <= 0) {
441: LOG.error("Unable to find parent packages " + parent);
442:
443: cfg = new PackageConfig(name, namespace, isAbstract,
444: erResolver);
445: } else {
446: cfg = new PackageConfig(name, namespace, isAbstract,
447: erResolver, parents);
448: }
449: }
450:
451: if (cfg != null) {
452: cfg
453: .setLocation(DomHelper
454: .getLocationObject(packageElement));
455: }
456: return cfg;
457: }
458:
459: /**
460: * Build a map of ResultConfig objects from below a given XML element.
461: */
462: protected Map buildResults(Element element,
463: PackageConfig packageContext) {
464: NodeList resultEls = element.getElementsByTagName("result");
465:
466: Map results = new LinkedHashMap();
467:
468: for (int i = 0; i < resultEls.getLength(); i++) {
469: Element resultElement = (Element) resultEls.item(i);
470:
471: if (resultElement.getParentNode().equals(element)
472: || resultElement.getParentNode().getNodeName()
473: .equals(element.getNodeName())) {
474: String resultName = resultElement.getAttribute("name");
475: String resultType = resultElement.getAttribute("type");
476:
477: // if you don't specify a name on <result/>, it defaults to "success"
478: if (!TextUtils.stringSet(resultName)) {
479: resultName = Action.SUCCESS;
480: }
481:
482: // there is no result type, so let's inherit from the parent package
483: if (!TextUtils.stringSet(resultType)) {
484: resultType = packageContext
485: .getFullDefaultResultType();
486:
487: // now check if there is a result type now
488: if (!TextUtils.stringSet(resultType)) {
489: // uh-oh, we have a problem
490: LOG
491: .error("No result type specified for result named '"
492: + resultName
493: + "', perhaps the parent package does not specify the result type?");
494: }
495: }
496:
497: ResultTypeConfig config = (ResultTypeConfig) packageContext
498: .getAllResultTypeConfigs().get(resultType);
499:
500: if (config == null) {
501: throw new ConfigurationException(
502: "There is no result type defined for type '"
503: + resultType
504: + "' mapped with name '"
505: + resultName + "'", resultElement);
506: }
507:
508: String resultClass = config.getClazz();
509:
510: // invalid result type specified in result definition
511: if (resultClass == null) {
512: LOG
513: .error("Result type '"
514: + resultType
515: + "' is invalid. Modify your xwork.xml file.");
516: }
517:
518: Map resultParams = XmlHelper.getParams(resultElement);
519:
520: if (resultParams.size() == 0) // maybe we just have a body - therefore a default parameter
521: {
522: // if <result ...>something</result> then we add a parameter of 'something' as this is the most used result param
523: if ((resultElement.getChildNodes().getLength() >= 1)
524: && (resultElement.getChildNodes().item(0)
525: .getNodeType() == Node.TEXT_NODE)) {
526: resultParams = new LinkedHashMap();
527:
528: String paramName = config
529: .getDefaultResultParam();
530: if (paramName != null) {
531: String val = XmlHelper
532: .getContent(resultElement);
533: if (val.length() > 0) {
534: resultParams.put(paramName, val);
535: }
536: } else {
537: LOG
538: .warn("no default parameter defined for result of type "
539: + config.getName());
540: }
541: }
542: }
543:
544: // create new param map, so that the result param can override the config param
545: Map params = new LinkedHashMap();
546: Map configParams = config.getParams();
547: if (configParams != null) {
548: params.putAll(configParams);
549: }
550: params.putAll(resultParams);
551:
552: ResultConfig resultConfig = new ResultConfig(
553: resultName, resultClass, params);
554: resultConfig.setLocation(DomHelper
555: .getLocationObject(element));
556: results.put(resultConfig.getName(), resultConfig);
557: }
558: }
559:
560: return results;
561: }
562:
563: /**
564: * Build a map of ResultConfig objects from below a given XML element.
565: */
566: protected List buildExceptionMappings(Element element,
567: PackageConfig packageContext) {
568: NodeList exceptionMappingEls = element
569: .getElementsByTagName("exception-mapping");
570:
571: List exceptionMappings = new ArrayList();
572:
573: for (int i = 0; i < exceptionMappingEls.getLength(); i++) {
574: Element ehElement = (Element) exceptionMappingEls.item(i);
575:
576: if (ehElement.getParentNode().equals(element)
577: || ehElement.getParentNode().getNodeName().equals(
578: element.getNodeName())) {
579: String emName = ehElement.getAttribute("name");
580: String exceptionClassName = ehElement
581: .getAttribute("exception");
582: String exceptionResult = ehElement
583: .getAttribute("result");
584:
585: Map params = XmlHelper.getParams(ehElement);
586:
587: if (!TextUtils.stringSet(emName)) {
588: emName = exceptionResult;
589: }
590:
591: ExceptionMappingConfig ehConfig = new ExceptionMappingConfig(
592: emName, exceptionClassName, exceptionResult,
593: params);
594: ehConfig.setLocation(DomHelper
595: .getLocationObject(ehElement));
596: exceptionMappings.add(ehConfig);
597: }
598: }
599:
600: return exceptionMappings;
601: }
602:
603: protected void loadDefaultInterceptorRef(
604: PackageConfig packageContext, Element element) {
605: NodeList resultTypeList = element
606: .getElementsByTagName("default-interceptor-ref");
607:
608: if (resultTypeList.getLength() > 0) {
609: Element defaultRefElement = (Element) resultTypeList
610: .item(0);
611: packageContext.setDefaultInterceptorRef(defaultRefElement
612: .getAttribute("name"));
613: }
614: }
615:
616: protected void loadDefaultActionRef(PackageConfig packageContext,
617: Element element) {
618: NodeList resultTypeList = element
619: .getElementsByTagName("default-action-ref");
620:
621: if (resultTypeList.getLength() > 0) {
622: Element defaultRefElement = (Element) resultTypeList
623: .item(0);
624: packageContext.setDefaultActionRef(defaultRefElement
625: .getAttribute("name"));
626: }
627: }
628:
629: /**
630: * Load all of the global results for this package from the XML element.
631: */
632: protected void loadGlobalResults(PackageConfig packageContext,
633: Element packageElement) {
634: NodeList globalResultList = packageElement
635: .getElementsByTagName("global-results");
636:
637: if (globalResultList.getLength() > 0) {
638: Element globalResultElement = (Element) globalResultList
639: .item(0);
640: Map results = buildResults(globalResultElement,
641: packageContext);
642: packageContext.addGlobalResultConfigs(results);
643: }
644: }
645:
646: /**
647: * Load all of the global results for this package from the XML element.
648: */
649: protected void loadGobalExceptionMappings(
650: PackageConfig packageContext, Element packageElement) {
651: NodeList globalExceptionMappingList = packageElement
652: .getElementsByTagName("global-exception-mappings");
653:
654: if (globalExceptionMappingList.getLength() > 0) {
655: Element globalExceptionMappingElement = (Element) globalExceptionMappingList
656: .item(0);
657: List exceptionMappings = buildExceptionMappings(
658: globalExceptionMappingElement, packageContext);
659: packageContext
660: .addGlobalExceptionMappingConfigs(exceptionMappings);
661: }
662: }
663:
664: // protected void loadIncludes(Element rootElement, DocumentBuilder db) throws Exception {
665: // NodeList includeList = rootElement.getElementsByTagName("include");
666: //
667: // for (int i = 0; i < includeList.getLength(); i++) {
668: // Element includeElement = (Element) includeList.item(i);
669: // String fileName = includeElement.getAttribute("file");
670: // includedFileNames.add(fileName);
671: // loadConfigurationFile(fileName, db);
672: // }
673: // }
674: protected InterceptorStackConfig loadInterceptorStack(
675: Element element, PackageConfig context)
676: throws ConfigurationException {
677: String name = element.getAttribute("name");
678:
679: InterceptorStackConfig config = new InterceptorStackConfig(name);
680: config.setLocation(DomHelper.getLocationObject(element));
681: NodeList interceptorRefList = element
682: .getElementsByTagName("interceptor-ref");
683:
684: for (int j = 0; j < interceptorRefList.getLength(); j++) {
685: Element interceptorRefElement = (Element) interceptorRefList
686: .item(j);
687: List interceptors = lookupInterceptorReference(context,
688: interceptorRefElement);
689: config.addInterceptors(interceptors);
690: }
691:
692: return config;
693: }
694:
695: protected void loadInterceptorStacks(Element element,
696: PackageConfig context) throws ConfigurationException {
697: NodeList interceptorStackList = element
698: .getElementsByTagName("interceptor-stack");
699:
700: for (int i = 0; i < interceptorStackList.getLength(); i++) {
701: Element interceptorStackElement = (Element) interceptorStackList
702: .item(i);
703:
704: InterceptorStackConfig config = loadInterceptorStack(
705: interceptorStackElement, context);
706:
707: context.addInterceptorStackConfig(config);
708: }
709: }
710:
711: protected void loadInterceptors(PackageConfig context,
712: Element element) throws ConfigurationException {
713: NodeList interceptorList = element
714: .getElementsByTagName("interceptor");
715:
716: for (int i = 0; i < interceptorList.getLength(); i++) {
717: Element interceptorElement = (Element) interceptorList
718: .item(i);
719: String name = interceptorElement.getAttribute("name");
720: String className = interceptorElement.getAttribute("class");
721:
722: Map params = XmlHelper.getParams(interceptorElement);
723: InterceptorConfig config = new InterceptorConfig(name,
724: className, params);
725: config.setLocation(DomHelper
726: .getLocationObject(interceptorElement));
727:
728: context.addInterceptorConfig(config);
729: }
730:
731: loadInterceptorStacks(element, context);
732: }
733:
734: // protected void loadPackages(Element rootElement) throws ConfigurationException {
735: // NodeList packageList = rootElement.getElementsByTagName("package");
736: //
737: // for (int i = 0; i < packageList.getLength(); i++) {
738: // Element packageElement = (Element) packageList.item(i);
739: // addPackage(packageElement);
740: // }
741: // }
742: private void loadConfigurationFile(String fileName,
743: Element includeElement) {
744: if (!includedFileNames.contains(fileName)) {
745: if (LOG.isDebugEnabled()) {
746: LOG.debug("Loading xwork configuration from: "
747: + fileName);
748: }
749:
750: includedFileNames.add(fileName);
751:
752: Document doc = null;
753: InputStream is = null;
754:
755: try {
756: is = getInputStream(fileName);
757:
758: if (is == null) {
759: throw new Exception("Could not open file "
760: + fileName);
761: }
762:
763: InputSource in = new InputSource(is);
764:
765: //FIXME: we shouldn't be doing this lookup twice
766: in.setSystemId(ClassLoaderUtil.getResource(fileName,
767: getClass()).toString());
768:
769: Map dtdMappings = new HashMap();
770: dtdMappings.put(
771: "-//OpenSymphony Group//XWork 1.1.1//EN",
772: "xwork-1.1.1.dtd");
773: dtdMappings.put("-//OpenSymphony Group//XWork 1.1//EN",
774: "xwork-1.1.dtd");
775: dtdMappings.put("-//OpenSymphony Group//XWork 1.0//EN",
776: "xwork-1.0.dtd");
777:
778: doc = DomHelper.parse(in, dtdMappings);
779: } catch (XworkException e) {
780: if (includeElement != null) {
781: throw new ConfigurationException(e, includeElement);
782: } else {
783: throw new ConfigurationException(e);
784: }
785: } catch (Exception e) {
786: final String s = "Caught exception while loading file "
787: + fileName;
788: LOG.error(s, e);
789: throw new ConfigurationException(s, e, includeElement);
790: } finally {
791: if (is != null) {
792: try {
793: is.close();
794: } catch (IOException e) {
795: LOG.error("Unable to close input stream", e);
796: }
797: }
798: }
799:
800: Element rootElement = doc.getDocumentElement();
801: NodeList children = rootElement.getChildNodes();
802: int childSize = children.getLength();
803:
804: for (int i = 0; i < childSize; i++) {
805: Node childNode = children.item(i);
806:
807: if (childNode instanceof Element) {
808: Element child = (Element) childNode;
809:
810: final String nodeName = child.getNodeName();
811:
812: if (nodeName.equals("package")) {
813: addPackage(child);
814: } else if (nodeName.equals("include")) {
815: String includeFileName = child
816: .getAttribute("file");
817: loadConfigurationFile(includeFileName, child);
818: }
819: }
820: }
821:
822: if (LOG.isDebugEnabled()) {
823: LOG.debug("Loaded xwork configuration from: "
824: + fileName);
825: }
826: }
827: }
828:
829: /**
830: * Looks up the Interceptor Class from the interceptor-ref name and creates an instance, which is added to the
831: * provided List, or, if this is a ref to a stack, it adds the Interceptor instances from the List to this stack.
832: *
833: * @param interceptorRefElement Element to pull interceptor ref data from
834: * @param context The PackageConfig to lookup the interceptor from
835: * @return A list of Interceptor objects
836: */
837: private List lookupInterceptorReference(PackageConfig context,
838: Element interceptorRefElement)
839: throws ConfigurationException {
840: String refName = interceptorRefElement.getAttribute("name");
841: Map refParams = XmlHelper.getParams(interceptorRefElement);
842:
843: return InterceptorBuilder.constructInterceptorReference(
844: context, refName, refParams);
845: }
846: }
|