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: Xml2Site.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.FlowLinkSpecificDataLinkDestIdSpecifiedException;
015: import com.uwyn.rife.engine.exceptions.NotFoundProcessingErrorException;
016: import com.uwyn.rife.engine.exceptions.ParsingErrorException;
017: import com.uwyn.rife.engine.exceptions.ProcessingErrorException;
018: import com.uwyn.rife.ioc.PropertyValue;
019: import com.uwyn.rife.ioc.PropertyValueList;
020: import com.uwyn.rife.ioc.PropertyValueObject;
021: import com.uwyn.rife.ioc.PropertyValueParticipant;
022: import com.uwyn.rife.ioc.PropertyValueTemplate;
023: import com.uwyn.rife.ioc.exceptions.PropertyConstructionException;
024: import com.uwyn.rife.ioc.exceptions.PropertyValueException;
025: import com.uwyn.rife.resources.ResourceFinder;
026: import com.uwyn.rife.resources.exceptions.ResourceFinderErrorException;
027: import com.uwyn.rife.xml.Xml2Data;
028: import com.uwyn.rife.xml.exceptions.CantFindResourceException;
029: import com.uwyn.rife.xml.exceptions.XmlErrorException;
030: import java.net.URL;
031: import java.util.ArrayList;
032: import java.util.Stack;
033: import org.xml.sax.Attributes;
034:
035: class Xml2Site implements SiteProcessor {
036: Xml2Site() {
037: }
038:
039: public void processSite(SiteBuilder builder,
040: String declarationName, ResourceFinder resourceFinder)
041: throws EngineException {
042: XmlProcessor processor = new XmlProcessor(builder);
043:
044: String processed_path = null;
045: try {
046: // process the site xml file
047: try {
048: processed_path = declarationName;
049: processor.processXml(processed_path, resourceFinder);
050: } catch (CantFindResourceException e) {
051: processed_path = SiteProcessor.DEFAULT_SITES_PATH
052: + declarationName;
053: processor.processXml(processed_path, resourceFinder);
054: }
055: } catch (XmlErrorException e) {
056: throw new ProcessingErrorException("site", declarationName,
057: e);
058: }
059:
060: // obtain the modification time
061: if (RifeConfig.Engine.getSiteAutoReload()) {
062: URL resource = resourceFinder.getResource(processed_path);
063: if (null == resource) {
064: throw new NotFoundProcessingErrorException("site",
065: processed_path, null);
066: }
067:
068: try {
069: builder.addResourceModificationTime(new UrlResource(
070: resource, processed_path), resourceFinder
071: .getModificationTime(resource));
072: } catch (ResourceFinderErrorException e) {
073: throw new ProcessingErrorException(
074: "site",
075: declarationName,
076: "Error while retrieving the modification time.",
077: e);
078: }
079: }
080: }
081:
082: private class XmlProcessor extends Xml2Data {
083: private SiteBuilder mSiteBuilder = null;
084:
085: private ElementInfoBuilder mCurrentElementInfoBuilder = null;
086: private XmlElementInfoProcessor mCurrentElementInfoProcessor = null;
087: private FlowLinkBuilder mCurrentFlowLinkBuilder = null;
088:
089: private String mCurrentPropertyName = null;
090:
091: private String mCurrentGlobalVar = null;
092: private ArrayList<String> mCurrentGlobalVarDefaults = null;
093:
094: private String mCurrentGlobalCookie = null;
095: private String mCurrentGlobalCookieDefault = null;
096:
097: private StringBuilder mCharacterData = null;
098:
099: private Stack<String> mParticipantNameStack = null;
100: private Stack<PropertyValueList> mPropertyValuesStack = null;
101: private String mCurrentTemplateType = null;
102:
103: private XmlProcessor(SiteBuilder builder) {
104: mSiteBuilder = builder;
105: }
106:
107: public void startDocument() {
108: mCurrentPropertyName = null;
109:
110: mCurrentGlobalVar = null;
111: mCurrentGlobalVarDefaults = null;
112:
113: mCurrentGlobalCookie = null;
114: mCurrentGlobalCookieDefault = null;
115:
116: mParticipantNameStack = null;
117: mPropertyValuesStack = null;
118: mCharacterData = null;
119: }
120:
121: public void endDocument() {
122: mCurrentGlobalVarDefaults = null;
123: mCharacterData = null;
124: mParticipantNameStack = null;
125: mPropertyValuesStack = null;
126: }
127:
128: public void startElement(String namespaceURI, String localName,
129: String qName, Attributes atts) {
130: if (qName.equals("site")) {
131: mSiteBuilder.setFallback(atts.getValue("fallbackid"));
132: } else if (qName.equals("subsite")) {
133: mSiteBuilder = mSiteBuilder.enterSubsiteDeclaration(
134: atts.getValue("file")).setId(
135: atts.getValue("id")).setUrlPrefix(
136: atts.getValue("urlprefix")).enterSubsite()
137: .setInherits(atts.getValue("inherits")).setPre(
138: atts.getValue("pre"));
139: } else if (qName.equals("group")) {
140: String inherits = atts.getValue("inherits");
141: String pre = atts.getValue("pre");
142:
143: mSiteBuilder.enterGroup().setInherits(inherits).setPre(
144: pre);
145: } else if (qName.equals("globalvar")) {
146: mCurrentGlobalVar = atts.getValue("name");
147: mCurrentGlobalVarDefaults = new ArrayList<String>();
148: } else if (qName.equals("globalcookie")) {
149: mCurrentGlobalCookie = atts.getValue("name");
150: mCurrentGlobalCookieDefault = null;
151: } else if (qName.equals("globalbean")) {
152: String classname = atts.getValue("classname");
153: String prefix = atts.getValue("prefix");
154: String name = atts.getValue("name");
155: String group = atts.getValue("group");
156:
157: mSiteBuilder.addGlobalBean(classname, prefix, name,
158: group);
159: } else if (qName.equals("globalexit")) {
160: String name = atts.getValue("name");
161: String destid = atts.getValue("destid");
162: boolean reflective = false;
163: boolean snapback = false;
164: boolean cancel_inheritance = false;
165: boolean cancel_embedding = false;
166: boolean redirect = false;
167: boolean cancel_continuations = false;
168:
169: if (atts.getValue("reflect") != null
170: && (atts.getValue("reflect").equals("1")
171: || atts.getValue("reflect").equals("t") || atts
172: .getValue("reflect").equals("true"))) {
173: reflective = true;
174: }
175:
176: if (atts.getValue("snapback") != null
177: && (atts.getValue("snapback").equals("1")
178: || atts.getValue("snapback")
179: .equals("t") || atts.getValue(
180: "snapback").equals("true"))) {
181: snapback = true;
182: }
183:
184: if (atts.getValue("redirect") != null
185: && (atts.getValue("redirect").equals("1")
186: || atts.getValue("redirect")
187: .equals("t") || atts.getValue(
188: "redirect").equals("true"))) {
189: redirect = true;
190: }
191:
192: String inheritance = atts.getValue("inheritance");
193: if (inheritance != null && inheritance.equals("cancel")) {
194: cancel_inheritance = true;
195: }
196:
197: String embedding = atts.getValue("embedding");
198: if (embedding != null && embedding.equals("cancel")) {
199: cancel_embedding = true;
200: }
201:
202: String continuations = atts.getValue("continuations");
203: if (continuations != null
204: && continuations.equals("cancel")) {
205: cancel_continuations = true;
206: }
207:
208: mSiteBuilder.addGlobalExit(name, destid, reflective,
209: snapback, cancel_inheritance, cancel_embedding,
210: redirect, cancel_continuations);
211: } else if (qName.equals("arrival")) {
212: boolean redirect = false;
213: if (atts.getValue("redirect") != null
214: && (atts.getValue("redirect").equals("1")
215: || atts.getValue("redirect")
216: .equals("t") || atts.getValue(
217: "redirect").equals("true"))) {
218: redirect = true;
219: }
220:
221: mSiteBuilder.setArrival(atts.getValue("destid"),
222: redirect);
223: } else if (qName.equals("departure")) {
224: mSiteBuilder.addDeparture(atts.getValue("srcid"));
225: } else if (qName.equals("state")) {
226: String state = atts.getValue("store");
227: if (null == state) {
228: state = StateStoreQuery.IDENTIFIER;
229: }
230: mSiteBuilder.enterState(state);
231: } else if (qName.equals("element")) {
232: mCurrentElementInfoBuilder = mSiteBuilder.enterElement(
233: atts.getValue("file")).setId(
234: atts.getValue("id")).setUrl(
235: atts.getValue("url")).setInherits(
236: atts.getValue("inherits")).setPre(
237: atts.getValue("pre"));
238: mCurrentElementInfoProcessor = new XmlElementInfoProcessor(
239: mCurrentElementInfoBuilder);
240: mCurrentElementInfoProcessor.startElement(namespaceURI,
241: localName, qName, atts);
242: String pathinfo = atts.getValue("pathinfo");
243: if (pathinfo != null) {
244: mCurrentElementInfoBuilder
245: .setPathInfoMode(PathInfoMode.getMode(atts
246: .getValue("pathinfo")));
247: }
248: } else if (qName.equals("datalink")) {
249: String srcoutput = atts.getValue("srcoutput");
250: String srcoutbean = atts.getValue("srcoutbean");
251:
252: String dest_id = atts.getValue("destid");
253: boolean snapback = false;
254:
255: String destinput = atts.getValue("destinput");
256: String destinbean = atts.getValue("destinbean");
257:
258: if (atts.getValue("snapback") != null
259: && (atts.getValue("snapback").equals("1")
260: || atts.getValue("snapback")
261: .equals("t") || atts.getValue(
262: "snapback").equals("true"))) {
263: snapback = true;
264: }
265:
266: if (mCurrentFlowLinkBuilder != null) {
267: if (dest_id != null) {
268: throw new FlowLinkSpecificDataLinkDestIdSpecifiedException(
269: getXmlPath(), mCurrentFlowLinkBuilder
270: .getElementInfoBuilder()
271: .getElementDeclaration()
272: .getId(),
273: mCurrentFlowLinkBuilder.getSrcExit());
274: }
275: mCurrentFlowLinkBuilder
276: .addDataLink(srcoutput, srcoutbean,
277: snapback, destinput, destinbean);
278: } else {
279: mCurrentElementInfoBuilder.addDataLink(srcoutput,
280: srcoutbean, dest_id, snapback, destinput,
281: destinbean);
282: }
283: } else if (qName.equals("flowlink")) {
284: String srcexit = atts.getValue("srcexit");
285: String destid = atts.getValue("destid");
286: boolean snapback = false;
287: boolean cancel_inheritance = false;
288: boolean cancel_embedding = false;
289: boolean redirect = false;
290: boolean cancel_continuations = false;
291:
292: if (atts.getValue("snapback") != null
293: && (atts.getValue("snapback").equals("1")
294: || atts.getValue("snapback")
295: .equals("t") || atts.getValue(
296: "snapback").equals("true"))) {
297: snapback = true;
298: }
299:
300: if (atts.getValue("redirect") != null
301: && (atts.getValue("redirect").equals("1")
302: || atts.getValue("redirect")
303: .equals("t") || atts.getValue(
304: "redirect").equals("true"))) {
305: redirect = true;
306: }
307:
308: String inheritance = atts.getValue("inheritance");
309: if (inheritance != null && inheritance.equals("cancel")) {
310: cancel_inheritance = true;
311: }
312:
313: String embedding = atts.getValue("embedding");
314: if (embedding != null && embedding.equals("cancel")) {
315: cancel_embedding = true;
316: }
317:
318: String continuations = atts.getValue("continuations");
319: if (continuations != null
320: && continuations.equals("cancel")) {
321: cancel_continuations = true;
322: }
323:
324: mCurrentFlowLinkBuilder = mCurrentElementInfoBuilder
325: .enterFlowLink(srcexit).destId(destid)
326: .snapback(snapback).cancelInheritance(
327: cancel_inheritance).cancelEmbedding(
328: cancel_embedding).redirect(redirect)
329: .cancelContinuations(cancel_continuations);
330: } else if (qName.equals("autolink")) {
331: String srcexit = atts.getValue("srcexit");
332: String destid = atts.getValue("destid");
333: boolean cancel_inheritance = false;
334: boolean cancel_embedding = false;
335: boolean redirect = false;
336: boolean cancel_continuations = false;
337:
338: if (atts.getValue("redirect") != null
339: && (atts.getValue("redirect").equals("1")
340: || atts.getValue("redirect")
341: .equals("t") || atts.getValue(
342: "redirect").equals("true"))) {
343: redirect = true;
344: }
345:
346: String inheritance = atts.getValue("inheritance");
347: if (inheritance != null && inheritance.equals("cancel")) {
348: cancel_inheritance = true;
349: }
350:
351: String embedding = atts.getValue("embedding");
352: if (embedding != null && embedding.equals("cancel")) {
353: cancel_embedding = true;
354: }
355:
356: String continuations = atts.getValue("continuations");
357: if (continuations != null
358: && continuations.equals("cancel")) {
359: cancel_continuations = true;
360: }
361:
362: mCurrentElementInfoBuilder.addAutoLink(srcexit, destid,
363: cancel_inheritance, cancel_embedding, redirect,
364: cancel_continuations);
365: } else if (qName.equals("property")) {
366: mCurrentPropertyName = atts.getValue("name");
367: mCharacterData = new StringBuilder();
368: mPropertyValuesStack = new Stack<PropertyValueList>();
369: mPropertyValuesStack.push(new PropertyValueList());
370: } else if (qName.equals("participant")
371: || qName.equals("datasource")) {
372: // store the character data of the previous property value series
373: mPropertyValuesStack.peek().add(
374: new PropertyValueObject(mCharacterData
375: .toString()));
376:
377: // initialize the new nested participant
378: if (null == mParticipantNameStack) {
379: mParticipantNameStack = new Stack<String>();
380: }
381:
382: mCharacterData = new StringBuilder();
383:
384: String name;
385: if (qName.equals("datasource")) {
386: name = Datasources.DEFAULT_PARTICIPANT_NAME;
387: } else {
388: name = atts.getValue("name");
389: }
390: mParticipantNameStack.push(name);
391: mPropertyValuesStack.push(new PropertyValueList());
392: } else if (qName.equals("template")) {
393: // store the character data of the previous property value series
394: mPropertyValuesStack.peek().add(
395: new PropertyValueObject(mCharacterData
396: .toString()));
397:
398: mCurrentTemplateType = atts.getValue("type");
399:
400: mCharacterData = new StringBuilder();
401: mPropertyValuesStack.push(new PropertyValueList());
402: } else if (qName.equals("config")) {
403: if (mCurrentElementInfoProcessor != null
404: && mCurrentElementInfoProcessor.getDefaults() != null) {
405: mCurrentElementInfoProcessor.startElement(
406: namespaceURI, localName, qName, atts);
407: } else {
408: if (mCharacterData != null
409: && Config.hasRepInstance()) {
410: mCharacterData.append(Config.getRepInstance()
411: .getString(atts.getValue("param"), ""));
412: }
413: }
414: } else if (qName.equals("default")) {
415: if (mCurrentElementInfoProcessor != null) {
416: mCurrentElementInfoProcessor.startElement(
417: namespaceURI, localName, qName, atts);
418: } else {
419: mCharacterData = new StringBuilder();
420: }
421: } else {
422: if (mCurrentElementInfoProcessor != null) {
423: mCurrentElementInfoProcessor.startElement(
424: namespaceURI, localName, qName, atts);
425: } else {
426: throw new ParsingErrorException("site",
427: getXmlPath(), "Unsupport element name '"
428: + qName + "'.", null);
429: }
430: }
431: }
432:
433: public void endElement(String namespaceURI, String localName,
434: String qName) {
435: if (qName.equals("element")) {
436: mCurrentElementInfoProcessor = null;
437: mCurrentElementInfoBuilder.leaveElement();
438: mCurrentElementInfoBuilder = null;
439: } else if (qName.equals("flowlink")) {
440: mCurrentFlowLinkBuilder.leaveFlowLink();
441: mCurrentFlowLinkBuilder = null;
442: } else if (qName.equals("subsite")) {
443: mSiteBuilder = mSiteBuilder.leaveSubsite()
444: .leaveSubsiteDeclaration();
445: } else if (qName.equals("state")) {
446: mSiteBuilder.leaveState();
447: } else if (qName.equals("group")) {
448: mSiteBuilder.leaveGroup();
449: } else if (qName.equals("globalvar")) {
450: String[] defaults = null;
451: if (mCurrentGlobalVarDefaults.size() > 0) {
452: defaults = new String[mCurrentGlobalVarDefaults
453: .size()];
454: defaults = mCurrentGlobalVarDefaults
455: .toArray(defaults);
456: }
457: mSiteBuilder.addGlobalVar(mCurrentGlobalVar, defaults);
458: mCurrentGlobalVar = null;
459: mCurrentGlobalVarDefaults = null;
460: } else if (qName.equals("globalcookie")) {
461: mSiteBuilder.addGlobalCookie(mCurrentGlobalCookie,
462: mCurrentGlobalCookieDefault);
463: mCurrentGlobalCookie = null;
464: mCurrentGlobalCookieDefault = null;
465: } else if (qName.equals("property")) {
466: PropertyValueList propvals = mPropertyValuesStack.pop();
467:
468: // store the character data to the current property value series
469: propvals.add(new PropertyValueObject(mCharacterData
470: .toString()));
471:
472: try {
473: if (mCurrentElementInfoBuilder != null) {
474: mCurrentElementInfoBuilder.addProperty(
475: mCurrentPropertyName, propvals
476: .makePropertyValue());
477: } else if (mSiteBuilder.getSubsiteDeclaration() != null) {
478: mSiteBuilder.getSubsiteDeclaration()
479: .addProperty(mCurrentPropertyName,
480: propvals.makePropertyValue());
481: } else {
482: mSiteBuilder.addProperty(mCurrentPropertyName,
483: propvals.makePropertyValue());
484: }
485: } catch (PropertyValueException e) {
486: throw new PropertyConstructionException("site",
487: getXmlPath(), mCurrentPropertyName, e);
488: }
489: mCharacterData = null;
490: mCurrentPropertyName = null;
491: mPropertyValuesStack = null;
492: } else if (qName.equals("participant")
493: || qName.equals("datasource")) {
494: PropertyValueList propvals = mPropertyValuesStack.pop();
495:
496: // store the character data to the current property value series
497: propvals.add(new PropertyValueObject(mCharacterData
498: .toString()));
499:
500: try {
501: PropertyValue propval = new PropertyValueParticipant(
502: mParticipantNameStack.pop(), propvals
503: .makePropertyValue());
504: ArrayList<PropertyValue> containing_propval_series = mPropertyValuesStack
505: .peek();
506: containing_propval_series.add(propval);
507: } catch (PropertyValueException e) {
508: throw new PropertyConstructionException("site",
509: getXmlPath(), mCurrentPropertyName, e);
510: }
511:
512: mCharacterData = new StringBuilder();
513: } else if (qName.equals("template")) {
514: PropertyValueList propvals = mPropertyValuesStack.pop();
515:
516: // store the character data to the current property value series
517: propvals.add(new PropertyValueObject(mCharacterData
518: .toString()));
519:
520: try {
521: PropertyValue propval = new PropertyValueTemplate(
522: mCurrentTemplateType, propvals
523: .makePropertyValue()
524: .getValueString());
525: ArrayList<PropertyValue> containing_propval_series = mPropertyValuesStack
526: .peek();
527: containing_propval_series.add(propval);
528: } catch (PropertyValueException e) {
529: throw new PropertyConstructionException("site",
530: getXmlPath(), mCurrentPropertyName, e);
531: }
532:
533: mCharacterData = new StringBuilder();
534: } else if (qName.equals("default")) {
535: if (mCurrentElementInfoProcessor != null) {
536: mCurrentElementInfoProcessor.endElement(
537: namespaceURI, localName, qName);
538: } else {
539: if (null != mCurrentGlobalCookie) {
540: mCurrentGlobalCookieDefault = mCharacterData
541: .toString();
542: } else if (null != mCurrentGlobalVar) {
543: mCurrentGlobalVarDefaults.add(mCharacterData
544: .toString());
545: }
546:
547: mCharacterData = null;
548: }
549: } else {
550: if (mCurrentElementInfoProcessor != null) {
551: mCurrentElementInfoProcessor.endElement(
552: namespaceURI, localName, qName);
553: }
554: }
555: }
556:
557: public void characters(char[] ch, int start, int length) {
558: if (mCurrentElementInfoProcessor != null
559: && mCurrentElementInfoProcessor.getDefaults() != null) {
560: mCurrentElementInfoProcessor.characters(ch, start,
561: length);
562: } else {
563: if (length > 0 && mCharacterData != null) {
564: mCharacterData.append(String.copyValueOf(ch, start,
565: length));
566: }
567: }
568: }
569: }
570: }
|