001: /*
002: * Copyright 2001-2007 Geert Bevin <gbevin[remove] at uwyn dot com>
003: * Distributed under the terms of either:
004: * - the common development and distribution license (CDDL), v1.0; or
005: * - the GNU Lesser General Public License, v2.1 or later
006: * $Id: Xml2ElementInfo.java 3701 2007-03-18 12:24:23Z gbevin $
007: */
008: package com.uwyn.rife.engine;
009:
010: import com.uwyn.rife.config.Config;
011: import com.uwyn.rife.config.RifeConfig;
012: import com.uwyn.rife.database.Datasources;
013: import com.uwyn.rife.engine.exceptions.EngineException;
014: import com.uwyn.rife.engine.exceptions.NotFoundProcessingErrorException;
015: import com.uwyn.rife.engine.exceptions.ParsingErrorException;
016: import com.uwyn.rife.engine.exceptions.ProcessingErrorException;
017: import com.uwyn.rife.ioc.PropertyValue;
018: import com.uwyn.rife.ioc.PropertyValueList;
019: import com.uwyn.rife.ioc.PropertyValueObject;
020: import com.uwyn.rife.ioc.PropertyValueParticipant;
021: import com.uwyn.rife.ioc.PropertyValueTemplate;
022: import com.uwyn.rife.ioc.exceptions.PropertyConstructionException;
023: import com.uwyn.rife.ioc.exceptions.PropertyValueException;
024: import com.uwyn.rife.resources.ResourceFinder;
025: import com.uwyn.rife.resources.exceptions.ResourceFinderErrorException;
026: import com.uwyn.rife.xml.Xml2Data;
027: import com.uwyn.rife.xml.exceptions.CantFindResourceException;
028: import com.uwyn.rife.xml.exceptions.XmlErrorException;
029: import java.net.URL;
030: import java.util.ArrayList;
031: import java.util.Stack;
032: import org.xml.sax.Attributes;
033: import org.xml.sax.XMLReader;
034:
035: class Xml2ElementInfo implements ElementInfoProcessor {
036: private XMLReader mReader = null;
037:
038: Xml2ElementInfo() {
039: }
040:
041: public void processElementInfo(ElementInfoBuilder builder,
042: String declarationName, ResourceFinder resourceFinder)
043: throws EngineException {
044: XmlElementInfoProcessor processor = new XmlElementInfoProcessor(
045: builder);
046:
047: String processed_path = null;
048: try {
049: // process the element xml file
050: try {
051: processed_path = declarationName;
052: mReader = processor.processXml(processed_path,
053: resourceFinder, mReader);
054: } catch (CantFindResourceException e) {
055: processed_path = DEFAULT_ELEMENTS_PATH
056: + declarationName;
057: mReader = processor.processXml(processed_path,
058: resourceFinder, mReader);
059: }
060: } catch (XmlErrorException e) {
061: throw new ProcessingErrorException("element",
062: declarationName, e);
063: }
064:
065: // obtain the modification time
066: if (RifeConfig.Engine.getSiteAutoReload()) {
067: URL resource = resourceFinder.getResource(processed_path);
068: if (null == resource) {
069: throw new NotFoundProcessingErrorException("element",
070: processed_path, null);
071: }
072:
073: try {
074: builder.addResourceModificationTime(new UrlResource(
075: resource, processed_path), resourceFinder
076: .getModificationTime(resource));
077: } catch (ResourceFinderErrorException e) {
078: throw new ProcessingErrorException(
079: "element",
080: declarationName,
081: "Error while retrieving the modification time.",
082: e);
083: }
084: }
085: }
086: }
087:
088: class XmlElementInfoProcessor extends Xml2Data {
089: private ElementInfoBuilder mElementInfoBuilder = null;
090:
091: private StringBuilder mCharacterData = null;
092:
093: private String mCurrentPropertyName = null;
094:
095: private String mCurrentInput = null;
096: private String mCurrentOutput = null;
097: private String mCurrentIncookie = null;
098: private String mCurrentOutcookie = null;
099: private String mCurrentParameter = null;
100:
101: private ArrayList<String> mDefaults = null;
102:
103: private SubmissionBuilder mSubmissionBuilder = null;
104:
105: private Stack<String> mParticipantNameStack = null;
106: private Stack<PropertyValueList> mPropertyValuesStack = null;
107: private String mCurrentTemplateType = null;
108:
109: XmlElementInfoProcessor(ElementInfoBuilder builder) {
110: mElementInfoBuilder = builder;
111: }
112:
113: public ArrayList<String> getDefaults() {
114: return mDefaults;
115: }
116:
117: public void startDocument() {
118: mCharacterData = null;
119: }
120:
121: public void endDocument() {
122: mCharacterData = null;
123: mParticipantNameStack = null;
124: mPropertyValuesStack = null;
125: }
126:
127: public void startElement(String namespaceURI, String localName,
128: String qName, Attributes atts) {
129: if (qName.equals("element")) {
130: mElementInfoBuilder.setImplementation(
131: atts.getValue("implementation")).extendsFrom(
132: atts.getValue("extends")).setContentType(
133: atts.getValue("contenttype"));
134: String pathinfo = atts.getValue("pathinfo");
135: if (pathinfo != null) {
136: mElementInfoBuilder.setPathInfoMode(PathInfoMode
137: .getMode(atts.getValue("pathinfo")));
138: }
139: } else if (qName.equals("property")) {
140: mCurrentPropertyName = atts.getValue("name");
141: mCharacterData = new StringBuilder();
142: mPropertyValuesStack = new Stack<PropertyValueList>();
143: mPropertyValuesStack.push(new PropertyValueList());
144: } else if (qName.equals("participant")
145: || qName.equals("datasource")) {
146: // store the character data of the previous property value series
147: mPropertyValuesStack.peek().add(
148: new PropertyValueObject(mCharacterData.toString()));
149:
150: // initialize the new nested participant
151: if (null == mParticipantNameStack) {
152: mParticipantNameStack = new Stack<String>();
153: }
154:
155: mCharacterData = new StringBuilder();
156:
157: String name;
158: if (qName.equals("datasource")) {
159: name = Datasources.DEFAULT_PARTICIPANT_NAME;
160: } else {
161: name = atts.getValue("name");
162: }
163: mParticipantNameStack.push(name);
164: mPropertyValuesStack.push(new PropertyValueList());
165: } else if (qName.equals("template")) {
166: // store the character data of the previous property value series
167: mPropertyValuesStack.peek().add(
168: new PropertyValueObject(mCharacterData.toString()));
169:
170: mCurrentTemplateType = atts.getValue("type");
171:
172: mCharacterData = new StringBuilder();
173: mPropertyValuesStack.push(new PropertyValueList());
174: } else if (qName.equals("config")) {
175: mCharacterData.append(Config.getRepInstance().getString(
176: atts.getValue("param"), ""));
177: } else if (qName.equals("input")) {
178: mCurrentInput = atts.getValue("name");
179: mDefaults = new ArrayList<String>();
180: } else if (qName.equals("inbean")) {
181: String classname = atts.getValue("classname");
182: String prefix = atts.getValue("prefix");
183: String name = atts.getValue("name");
184: String group = atts.getValue("group");
185:
186: mElementInfoBuilder.addInBean(classname, prefix, name,
187: group);
188: } else if (qName.equals("output")) {
189: mCurrentOutput = atts.getValue("name");
190: mDefaults = new ArrayList<String>();
191: } else if (qName.equals("outbean")) {
192: String classname = atts.getValue("classname");
193: String prefix = atts.getValue("prefix");
194: String name = atts.getValue("name");
195: String group = atts.getValue("group");
196:
197: mElementInfoBuilder.addOutBean(classname, prefix, name,
198: group);
199: } else if (qName.equals("incookie")) {
200: mCurrentIncookie = atts.getValue("name");
201: mDefaults = new ArrayList<String>();
202: } else if (qName.equals("outcookie")) {
203: mCurrentOutcookie = atts.getValue("name");
204: mDefaults = new ArrayList<String>();
205: } else if (qName.equals("childtrigger")) {
206: mElementInfoBuilder.addChildTrigger(atts.getValue("name"));
207: } else if (qName.equals("submission")) {
208: mSubmissionBuilder = mElementInfoBuilder
209: .enterSubmission(atts.getValue("name"));
210:
211: String continuations_attr = atts.getValue("continuations");
212: if (continuations_attr != null) {
213: mSubmissionBuilder
214: .cancelContinuations(continuations_attr
215: .equals("cancel"));
216: }
217:
218: String scope_attr = atts.getValue("scope");
219: if (scope_attr != null) {
220: mSubmissionBuilder.setScope(Scope.getScope(scope_attr));
221: }
222: } else if (qName.equals("param")) {
223: if (atts.getValue("name") != null
224: && atts.getValue("regexp") != null) {
225: throw new ParsingErrorException(
226: "element",
227: getXmlPath(),
228: "A submission parameter can't have both a name and a regexp attribute.",
229: null);
230: }
231:
232: if (atts.getValue("name") != null) {
233: mCurrentParameter = atts.getValue("name");
234: mDefaults = new ArrayList<String>();
235: } else if (atts.getValue("regexp") != null) {
236: mSubmissionBuilder.addParameterRegexp(atts
237: .getValue("regexp"));
238: mDefaults = null;
239: } else {
240: throw new ParsingErrorException(
241: "element",
242: getXmlPath(),
243: "A submission parameter needs either a name or a regexp attribute.",
244: null);
245: }
246: } else if (qName.equals("bean")) {
247: String classname = atts.getValue("classname");
248: String prefix = atts.getValue("prefix");
249: String name = atts.getValue("name");
250: String group = atts.getValue("group");
251:
252: mSubmissionBuilder.addBean(classname, prefix, name, group);
253: } else if (qName.equals("file")) {
254: if (atts.getValue("name") != null
255: && atts.getValue("regexp") != null) {
256: throw new ParsingErrorException(
257: "element",
258: getXmlPath(),
259: "A submission file can't have both a name and a regexp attribute.",
260: null);
261: }
262:
263: if (atts.getValue("name") != null) {
264: mSubmissionBuilder.addFile(atts.getValue("name"));
265: } else if (atts.getValue("regexp") != null) {
266: mSubmissionBuilder.addFileRegexp(atts
267: .getValue("regexp"));
268: } else {
269: throw new ParsingErrorException(
270: "element",
271: getXmlPath(),
272: "A submission file needs either a name or a regexp attribute.",
273: null);
274: }
275: } else if (qName.equals("default")) {
276: mCharacterData = new StringBuilder();
277: } else if (qName.equals("exit")) {
278: mElementInfoBuilder.addExit(atts.getValue("name"));
279: } else if (qName.equals("pathinfo")) {
280: mElementInfoBuilder.addPathInfoMapping(atts
281: .getValue("mapping"));
282: } else {
283: throw new ParsingErrorException("element", getXmlPath(),
284: "Unsupport element name '" + qName + "'.", null);
285: }
286: }
287:
288: public void endElement(String namespaceURI, String localName,
289: String qName) {
290: if (qName.equals("property")) {
291: PropertyValueList propvals = mPropertyValuesStack.pop();
292:
293: // store the character data to the current property value series
294: propvals.add(new PropertyValueObject(mCharacterData
295: .toString()));
296:
297: try {
298: mElementInfoBuilder.addStaticProperty(
299: mCurrentPropertyName, propvals
300: .makePropertyValue());
301: } catch (PropertyValueException e) {
302: throw new PropertyConstructionException("element",
303: getXmlPath(), mCurrentPropertyName, e);
304: }
305: mCharacterData = null;
306: mCurrentPropertyName = null;
307: mPropertyValuesStack = null;
308: } else if (qName.equals("participant")
309: || qName.equals("datasource")) {
310: PropertyValueList propvals = mPropertyValuesStack.pop();
311:
312: // store the character data to the current property value series
313: propvals.add(new PropertyValueObject(mCharacterData
314: .toString()));
315:
316: try {
317: PropertyValue propval = new PropertyValueParticipant(
318: mParticipantNameStack.pop(), propvals
319: .makePropertyValue());
320: ArrayList<PropertyValue> containing_propval_series = mPropertyValuesStack
321: .peek();
322: containing_propval_series.add(propval);
323: } catch (PropertyValueException e) {
324: throw new PropertyConstructionException("element",
325: getXmlPath(), mCurrentPropertyName, e);
326: }
327:
328: mCharacterData = new StringBuilder();
329: } else if (qName.equals("template")) {
330: PropertyValueList propvals = mPropertyValuesStack.pop();
331:
332: // store the character data to the current property value series
333: propvals.add(new PropertyValueObject(mCharacterData
334: .toString()));
335:
336: try {
337: PropertyValue propval = new PropertyValueTemplate(
338: mCurrentTemplateType, propvals
339: .makePropertyValue().getValueString());
340: ArrayList<PropertyValue> containing_propval_series = mPropertyValuesStack
341: .peek();
342: containing_propval_series.add(propval);
343: } catch (PropertyValueException e) {
344: throw new PropertyConstructionException("element",
345: getXmlPath(), mCurrentPropertyName, e);
346: }
347:
348: mCharacterData = new StringBuilder();
349: } else if (qName.equals("input")) {
350: String[] defaults = null;
351: if (mDefaults.size() > 0) {
352: defaults = new String[mDefaults.size()];
353: defaults = mDefaults.toArray(defaults);
354: }
355: mElementInfoBuilder.addInput(mCurrentInput, defaults);
356: mCurrentInput = null;
357: mDefaults = null;
358: } else if (qName.equals("output")) {
359: String[] defaults = null;
360: if (mDefaults.size() > 0) {
361: defaults = new String[mDefaults.size()];
362: defaults = mDefaults.toArray(defaults);
363: }
364: mElementInfoBuilder.addOutput(mCurrentOutput, defaults);
365: mCurrentOutput = null;
366: mDefaults = null;
367: } else if (qName.equals("incookie")) {
368: String defaultValue = null;
369: if (mDefaults.size() > 0) {
370: defaultValue = mDefaults.get(0);
371: }
372: mElementInfoBuilder.addIncookie(mCurrentIncookie,
373: defaultValue);
374: mCurrentIncookie = null;
375: mDefaults = null;
376: } else if (qName.equals("outcookie")) {
377: String defaultValue = null;
378: if (mDefaults.size() > 0) {
379: defaultValue = mDefaults.get(0);
380: }
381: mElementInfoBuilder.addOutcookie(mCurrentOutcookie,
382: defaultValue);
383: mCurrentOutcookie = null;
384: mDefaults = null;
385: } else if (qName.equals("submission")) {
386: mSubmissionBuilder.leaveSubmission();
387: } else if (qName.equals("param")) {
388: if (mDefaults != null) {
389: String[] defaults = null;
390: if (mDefaults.size() > 0) {
391: defaults = new String[mDefaults.size()];
392: defaults = mDefaults.toArray(defaults);
393: }
394: mSubmissionBuilder.addParameter(mCurrentParameter,
395: defaults);
396: }
397: mCurrentParameter = null;
398: mDefaults = null;
399: } else if (qName.equals("default")) {
400: if (null == mDefaults) {
401: throw new ParsingErrorException(
402: "element",
403: getXmlPath(),
404: "A submission parameter that's defined by a regular expression can't have default values.",
405: null);
406: }
407:
408: mDefaults.add(mCharacterData.toString());
409: mCharacterData = null;
410: }
411: }
412:
413: public void characters(char[] ch, int start, int length) {
414: if (length > 0 && mCharacterData != null) {
415: String text = String.copyValueOf(ch, start, length);
416: mCharacterData.append(text);
417: }
418: }
419: }
|