001: /*
002: * JFolder, Copyright 2001-2006 Gary Steinmetz
003: *
004: * Distributable under LGPL license.
005: * See terms of license at gnu.org.
006: */
007:
008: package org.jfolder.common.function;
009:
010: //base classes
011: import java.io.IOException;
012: import java.util.ArrayList;
013: import java.util.HashMap;
014: import javax.servlet.ServletException;
015: import javax.servlet.jsp.JspException;
016: import javax.servlet.jsp.PageContext;
017: import javax.servlet.jsp.tagext.BodyContent;
018: import javax.servlet.jsp.tagext.BodyTag;
019: import javax.servlet.jsp.tagext.IterationTag;
020: import javax.servlet.jsp.tagext.Tag;
021: import javax.xml.parsers.ParserConfigurationException;
022: import org.w3c.dom.Document;
023: import org.w3c.dom.Node;
024: import org.xml.sax.SAXException;
025:
026: //project specific classes
027: import org.jfolder.common.StandardDataTypes;
028: import org.jfolder.common.UnexpectedSystemException;
029: import org.jfolder.common.tagging.ConceptTagCharacteristic;
030: import org.jfolder.common.tagging.ConceptTagCharacteristicHolder;
031: import org.jfolder.common.tagging.ConceptTagFlagsHelper;
032: import org.jfolder.common.tagging.ConceptTagPreferences;
033: import org.jfolder.common.tagging.ConceptTagPreferencesHelper;
034: import org.jfolder.common.tagging.ConceptTagSetContext;
035: import org.jfolder.common.tagging.ConceptTagSetHolder;
036: import org.jfolder.common.tagging.DetermineClassConceptTagContext;
037: import org.jfolder.common.tagging.DetermineValueAndClassConceptTagContext;
038: import org.jfolder.common.tagging.DetermineValueAndClassConceptTagException;
039: import org.jfolder.common.tagging.ReturnableConceptTag;
040: import org.jfolder.common.tagging.RootConceptTagHolder;
041: import org.jfolder.common.tagging.ValueAndClassForConceptTag;
042: import org.jfolder.common.utils.misc.MiscHelper;
043: import org.jfolder.common.utils.xml.XMLHelper;
044: import org.jfolder.platforms.stores.base.ApplicationDataSourceResolver;
045: import org.jfolder.platforms.stores.base.SystemStoreFactory;
046: import org.jfolder.platforms.stores.base.SystemStoreSessionManager;
047: import org.jfolder.platforms.stores.base.SystemStoreSessionWithinWebPage;
048: import org.jfolder.services.config.ConfigServiceCaller;
049: import org.jfolder.services.config.ConfigServiceCallerFactory;
050:
051: //other classes
052:
053: public abstract class BaseWebPageTag implements BodyTag,
054: ReturnableConceptTag {
055: //
056: private final static String NAMESPACE_PREFIX = "a1";
057: private final static String DOUBLE_LEFT = "<<";
058: private final static String DOUBLE_RIGHT = ">>";
059: //
060: private BodyContent bc = null;
061: private StringBuffer alternateBc = null;
062: private Tag tag = null;
063: private PageContext pc = null;
064: //
065: private HashMap attrs = null;
066: private boolean rootWebTag = false;
067: //
068: private String namespace = null;
069: private String name = null;
070: //
071: private static ArrayList cachedXml = null;
072: private static ArrayList cachedRcth = null;
073:
074: //
075: protected BaseWebPageTag() {
076: //
077: this .init();
078: }
079:
080: //
081: public void doInitBody() {
082: printStatus("doInitBody", "Only");
083: //possibly determine and render tag
084: //Object o = getBodyContent();//used to write tag start
085: }
086:
087: //
088: public int doAfterBody() {
089:
090: //try {
091: int outValue = IterationTag.SKIP_BODY;
092: //printStatus("doAfterBody", "Only");
093: //return IterationTag.EVAL_BODY_AGAIN;
094: //MiscHelper.println(this.name + " = " + this.bc.getString());
095: if (this .bc != null) {
096: String className = this .getClass().getName();
097: if (className.equals(BaseStaticWebPageTag.class.getName())) {
098: //this.alternateBc.append(
099: // XMLHelper.fromStringToCData(this.bc.getString()));
100: MiscHelper
101: .println("BaseWebPageTag STATIC (After Body) = '"
102: + this .bc.getString() + "'");
103: this .alternateBc.append(this .bc.getString());
104: } else {
105: this .alternateBc.append(this .bc.getString());
106: }
107: }
108:
109: return outValue;
110: //}
111: //catch (IOException ioe) {
112: // throw new UnexpectedSystemException(ioe);
113: //}
114: }
115:
116: //
117: public void setBodyContent(BodyContent inBc) {
118: printStatus("setBodyContent", "Only");
119: //MiscHelper.println(
120: // "BaseWebTag.setBodyContent = " + this.getClass().getName());
121: this .bc = inBc;
122: }
123:
124: //
125: public void release() {
126: printStatus("release", "Only");
127: //
128: //this.init();
129: }
130:
131: //
132: private void init() {
133: //
134: this .bc = null;
135: this .tag = null;
136: this .pc = null;
137: //
138: this .alternateBc = new StringBuffer();
139: //
140: this .attrs = new HashMap();
141: //this.rootWebTag = false;
142: //
143: //this.cachedXml = new ArrayList();
144: //this.cachedRcth = new ArrayList();
145: //
146: //TO DO: improve performance of below
147: String className = this .getClass().getName();
148: if (className.equals(BaseCompoundWebPageTag.class.getName())) {
149: //TO DO: try to merge both of these functions
150: //TO DO: improve performance of below!
151: ConfigServiceCaller csc = ConfigServiceCallerFactory
152: .getConfigServiceCaller(null);
153: //
154: //ConceptTagSetHolder webCtsh =
155: // cm.getWebTagSet(ConceptTagSetContext.newInstance());
156: RootConceptTagHolder sampleRcth = WebPageTagHelper
157: .getRootHolder((Node) null, ConceptTagSetContext
158: .newInstance());
159: ConceptTagPreferences webCtp = sampleRcth.getPreferences();
160: this .namespace = webCtp.getCompoundNamespace();
161: this .name = webCtp.getCompoundName();
162: //
163: //cm.close();
164: //
165: } else if (className.equals(BaseStaticWebPageTag.class
166: .getName())) {
167: //TO DO: try to merge both of these functions
168: //TO DO: improve performance of below!
169: ConfigServiceCaller csc = ConfigServiceCallerFactory
170: .getConfigServiceCaller(null);
171: //ConfigLifecycle cm = ConfigLifecycleFactory.getConfigLifecycle();
172: //
173: //ConceptTagSetHolder webCtsh =
174: // cm.getWebTagSet(ConceptTagSetContext.newInstance());
175: RootConceptTagHolder sampleRcth = WebPageTagHelper
176: .getRootHolder((Node) null, ConceptTagSetContext
177: .newInstance());
178: ConceptTagPreferences webCtp = sampleRcth.getPreferences();
179: this .namespace = webCtp.getStaticNamespace();
180: this .name = webCtp.getStaticName();
181: //
182: //cm.close();
183: //
184: } else if (!className.equals(UnknownWebPageTag.class.getName())) {
185: ConceptTagSetHolder ctsh = WebPageTagPreferences
186: .getCachedSetHol();
187: this .namespace = ctsh.getConceptTagNamespace(className);
188: this .name = ctsh.getConceptTagName(className);
189: //
190: }
191: //else {
192: // UnknownWebTag uwt = (UnknownWebTag)this;
193: // this.namespace = uwt.getUnknownNamespace();
194: // this.name = uwt.getUnknownName();
195: //}
196: //
197: }
198:
199: //
200: public int doStartTag() throws JspException {
201:
202: //try {
203: int outValue = BodyTag.EVAL_BODY_BUFFERED;
204:
205: printStatus("doStartTag", "Start");
206: //
207: //this.bc.clearBody();
208: this .rootWebTag = this .isRootWebTag();
209: this .attrs
210: .put("xmlns:" + NAMESPACE_PREFIX, this .getNamespace());
211: String startElement = (DOUBLE_LEFT + NAMESPACE_PREFIX + ":"
212: + this .name + " " + XMLHelper.convertAttrs(this .attrs) + DOUBLE_RIGHT);
213: //if (this.bc != null) {
214: // this.bc.print(startElement);
215: //}
216: //else {
217: this .alternateBc.append(startElement);
218: //}
219: //
220: printStatus("doStartTag", "End");
221:
222: //String className = this.getClass().getName();
223: //if (className.equals(BaseStaticWebPageTag.class.getName())) {
224: // outValue = BodyTag.EVAL_BODY_INCLUDE;
225: //}
226:
227: return outValue;
228: //return Tag.EVAL_BODY_INCLUDE;
229: //return Tag.SKIP_BODY;
230: //}
231: //catch (IOException ioe) {
232: // throw new JspException(ioe);
233: //}
234: }
235:
236: //
237: public int doEndTag() throws JspException {
238:
239: try {
240: int outValue = Tag.EVAL_PAGE;
241: printStatus("doEndTag", "Start");
242: //
243: //this.bc.clearBody();
244: String endElement = (DOUBLE_LEFT + "/" + NAMESPACE_PREFIX
245: + ":" + this .name + DOUBLE_RIGHT);
246: //if (this.bc != null) {
247: // this.bc.print(endElement);
248: //}
249: //else {
250: this .alternateBc.append(endElement);
251: //}
252: if (this .rootWebTag) {
253: //MiscHelper.println((new java.util.Date())
254: // + " startProcessing");
255: String content = revertCData(this .alternateBc
256: .toString());
257: //}
258:
259: String c = this .getClass().getName();
260: RootConceptTagHolder rcth = getCachedRcth(content, c);
261:
262: //MiscHelper.println(
263: // (new java.util.Date()) + " created rcth");
264: ConceptTagCharacteristicHolder rootCtcharh = rcth
265: .getRootCharacteristicHolder();
266: ConceptTagPreferences localCtp = rcth.getPreferences();
267: String rootCon = localCtp.getRootConstraint();
268: //
269: ConceptTagCharacteristic rootCtchar = null;
270: if (!rootCon.equals(localCtp.getUnconstrainedSymbol())) {
271: rootCtchar = rootCtcharh.getCharacteristic(rootCon);
272: } else {
273: rootCtchar = rootCtcharh
274: .getUndefinedCharacteristic();
275: }
276: //ConceptTagInitializer rootCti =
277: // rootCtchar.getInitializer(0);
278: Object rootRctObj = rootCtchar.getValueAsConceptTag(0,
279: null);
280: ReturnableConceptTag rootRct = (ReturnableConceptTag) rootRctObj;
281: WebPageTagPreferences wptp = (WebPageTagPreferences) rcth
282: .getPreferences();
283: //
284: //
285: //
286: DetermineValueAndClassConceptTagContext dvacctc = null;
287: //
288: SystemStoreSessionWithinWebPage ssswwp = SystemStoreSessionManager
289: .getSystemStoreSessionWithinWebPage(this .pc
290: .getRequest());
291: if (ssswwp
292: .isDetermineValueAndClassConceptTagContextPresent()) {
293: dvacctc = ssswwp
294: .getDetermineValueAndClassConceptTagContext();
295: } else {
296: dvacctc = new ReturnValueAndClassForWebPageTagContext(
297: wptp, this .pc);
298: ssswwp
299: .setDetermineValueAndClassConceptTagContext(dvacctc);
300: }
301: //
302: //
303: //MiscHelper.println(
304: // (new java.util.Date()) + " before wtifc");
305: //WebPageTagInstanceFormatContext wptifc =
306: // new WebPageTagInstanceFormatContext(rootCtchar, dvacctc);
307: //rootRct.appraise(wptifc);
308: //MiscHelper.println(
309: // (new java.util.Date()) + " after wtifc");
310: //if (wptifc.isTouched()) {
311: // //
312: // this.pc.getOut().write(wptifc.getContent());
313: //}
314: //else {
315: //
316: //MiscHelper.println(
317: // (new java.util.Date()) + " before vac");
318: ConceptTagFlagsHelper.showCurrentVariables(dvacctc,
319: "BasWebPagTag before call = " + rootRct);
320: ValueAndClassForConceptTag vac = rootCtchar
321: .getDetermineValueAndClass(0, dvacctc);
322: ConceptTagFlagsHelper.showCurrentVariables(dvacctc,
323: "BasWebPagTag after call = " + rootRct);
324: //
325: //
326: if (!ConceptTagFlagsHelper
327: .isForwardToLocalWebPagePresent(dvacctc)) {
328: //
329: processResult(dvacctc, vac);
330: } else {
331: //
332: String forwardToLocalWebPage = ConceptTagFlagsHelper
333: .getForwardToLocalWebPage(dvacctc);
334: //
335: ApplicationDataSourceResolver adsr = SystemStoreFactory
336: .getApplicationDataSourceResolver();
337: //
338: forwardToLocalWebPage = adsr
339: .getRelativeWebPageLocation(forwardToLocalWebPage);
340: //
341: //
342: ConceptTagFlagsHelper
343: .removeForwardToLocalPage(dvacctc);
344: //
345: outValue = Tag.SKIP_PAGE;
346: //
347: this .pc.forward(forwardToLocalWebPage);
348: }
349: //
350: //
351: //if (!StandardDataTypes.getNothingClass().equals(
352: // vac.getValueClass())) {
353: // //
354: // this.pc.getOut().write(vac.getValue() + "");
355: //}
356: //MiscHelper.println(
357: // (new java.util.Date()) + " after vac");
358: //}
359:
360: //if (rvacfwtc.isForwardInvoked()) {
361: // outValue = Tag.SKIP_PAGE;
362: //}
363: MiscHelper
364: .println("BasWebPagTag 'forward' not implemented");
365: //MiscHelper.println((new java.util.Date()) + " endProcessing");
366: } else {
367: //String className = this.getClass().getName();
368: //if (className.equals(BaseStaticWebPageTag.class.getName())) {
369: // MiscHelper.println(
370: // "BaseWebPageTag STATIC = '" + this.alternateBc + "'");
371: //}
372: this .pc.getOut().write(this .alternateBc.toString());
373: }
374: //reinitialize
375: this .alternateBc = new StringBuffer();//TO DO: check wholelifecycle
376: this .attrs = new HashMap();
377: //
378: printStatus("doEndTag", "End");
379: return outValue;
380: //return Tag.SKIP_PAGE;
381: } catch (ServletException se) {
382: throw new JspException(se);
383: } catch (ParserConfigurationException pce) {
384: throw new JspException(pce);
385: } catch (SAXException saxe) {
386: throw new JspException(saxe);
387: } catch (IOException ioe) {
388: throw new JspException(ioe);
389: } catch (DetermineValueAndClassConceptTagException rcte) {
390: throw new JspException(rcte);
391: }
392: }
393:
394: private void processResult(
395: DetermineValueAndClassConceptTagContext inDvacctc,
396: ValueAndClassForConceptTag inVacfct)
397: throws DetermineValueAndClassConceptTagException,
398: IOException {
399: //
400: ConceptTagFlagsHelper.showCurrentVariables(inDvacctc,
401: "BaseWebPageTag processResult");
402: int ic = ConceptTagFlagsHelper
403: .getDetermineVacResultsCount(inDvacctc);
404: for (int i = 0; i < ic; i++) {
405: //
406: ValueAndClassForConceptTag nextVacfct = ConceptTagFlagsHelper
407: .getDetermineVacResult(inDvacctc, i);
408: //
409: MiscHelper.println("BaseWebPageTag iter(" + i + ") = '"
410: + nextVacfct.getValue() + "'");
411: //
412: reformatAndPrintText(nextVacfct);
413: }
414: //
415: //
416: reformatAndPrintText(inVacfct);
417: //if (!StandardDataTypes.getNothingClass().equals(
418: // inVacfct.getValueClass())) {
419: // //
420: // this.pc.getOut().write(inVacfct.getValue() + "");
421: //}
422: }
423:
424: private void reformatAndPrintText(
425: ValueAndClassForConceptTag inVacfct) throws IOException {
426: //
427: //
428: //
429: if (StandardDataTypes.getNothingClass().equals(
430: inVacfct.getValueClass())) {
431: //
432: //display nothing
433: } else if (StandardDataTypes.getHtmlClass().equals(
434: inVacfct.getValueClass())) {
435: //
436: this .pc.getOut().write(inVacfct.getValue() + "");
437: } else {
438: //
439: String s = (inVacfct.getValue() + "");
440: s = XMLHelper.reformatTextForWebPage(s);
441: //
442: this .pc.getOut().write(s);
443: }
444: }
445:
446: //
447: public final static synchronized RootConceptTagHolder getCachedRcth(
448: String inXml, String inClass) throws SAXException,
449: ParserConfigurationException, IOException {
450:
451: RootConceptTagHolder outValue = null;
452:
453: int index = 0;
454:
455: if (cachedXml == null) {
456: cachedXml = new ArrayList();
457: }
458: if (cachedRcth == null) {
459: cachedRcth = new ArrayList();
460: }
461:
462: if ((index = cachedXml.indexOf(inXml)) != -1) {
463: //MiscHelper.println("BaseWebTag getting cached rcth");
464: outValue = (RootConceptTagHolder) cachedRcth.get(index);
465: } else {
466: ConceptTagSetContext ctsc = ConceptTagSetContext
467: .newInstance();
468: MiscHelper
469: .println("BaseWebPageTag inXml = '" + inXml + "'");
470: Document doc = XMLHelper.loadDocument(inXml);
471: outValue = WebPageTagHelper.getRootConceptTagHolder(doc,
472: inClass, ctsc);
473: if (cachedXml.size() > 50) {
474: cachedXml.remove(0);
475: cachedRcth.remove(0);
476: }
477: cachedXml.add(inXml);
478: cachedRcth.add(outValue);
479: }
480:
481: //WebTagPreferences wtp = new WebTagPreferences(
482: // this.getClass().getName(), ctsc, this.bc);
483: //printStatus("doEndTag", "PreContent");
484: //MiscHelper.println("bpreContent = "
485: // + this.alternateBc.toString());
486: //MiscHelper.println(
487: // (new java.util.Date()) + " preContent = " + preContent);
488: //MiscHelper.println(
489: // (new java.util.Date()) + " created doc");
490: //java.io.StringWriter sw = new java.io.StringWriter();
491: //XMLHelper.writeDocument(doc, sw);
492: //MiscHelper.println("preContent = " + preContent);
493: //MiscHelper.println("doc = " + sw);
494:
495: return outValue;
496: }
497:
498: //
499: private final static String revertCData(String inCData)
500: throws IOException {
501:
502: StringBuffer outValue = new StringBuffer();
503:
504: MiscHelper.println("BaseWebPageTag revertCData s = '" + inCData
505: + "'");
506:
507: int currentIndex = 0;
508: int leftIndex = 0;
509: int rightIndex = 0;
510:
511: while ((leftIndex = inCData.indexOf(DOUBLE_LEFT, currentIndex)) != -1) {
512:
513: int leftAdjust = leftIndex + DOUBLE_LEFT.length();
514:
515: rightIndex = inCData.indexOf(DOUBLE_RIGHT, leftAdjust);
516:
517: if (rightIndex != -1) {
518: String nextCData = inCData.substring(currentIndex,
519: leftIndex);
520: outValue.append(XMLHelper.fromStringToCData(nextCData));
521: outValue.append("<");
522: outValue.append(inCData.substring(leftAdjust,
523: rightIndex));
524: outValue.append(">");
525: currentIndex = rightIndex + DOUBLE_RIGHT.length();
526: } else {
527: throw UnexpectedSystemException.unknownState();
528: }
529:
530: }
531:
532: MiscHelper.println("BaseWebPageTag revertCData o = '" + inCData
533: + "'");
534:
535: return outValue.toString();
536: }
537:
538: //
539: //TO DO: remove below
540: private void printStatus(String inMethod, String inState) {
541: //MiscHelper.println("<!-----------" + inMethod + "--------->");
542: //MiscHelper.println("inState = " + inState);
543: //MiscHelper.println("getName() = " + getName());
544: //MiscHelper.println("getNamespace() = " + getNamespace());
545: //MiscHelper.println("this.rootWebTag = " + this.rootWebTag);
546: //MiscHelper.println("this.alternateBc = " + this.alternateBc);
547: //MiscHelper.println("this.bc = " + this.bc);
548: //MiscHelper.println("<!----------------------------------->");
549: }
550:
551: //
552: public void setParent(Tag inParent) {
553: this .tag = inParent;
554: }
555:
556: //
557: public Tag getParent() {
558: return this .tag;
559: }
560:
561: //
562: public void setPageContext(PageContext inPc) {
563: this .pc = inPc;
564: }
565:
566: //
567: public void setConstraint(String inCon) {
568: registerAttribute(
569: ConceptTagPreferencesHelper.CTP_PREF_CONSTRAINT_LOCAL_NAME__COMMON,
570: inCon);
571: }
572:
573: protected void registerAttribute(String inName, String inValue) {
574: this .attrs.put(XMLHelper.fromStringToCData(inName), XMLHelper
575: .fromStringToCData(inValue));
576: }
577:
578: private boolean isRootWebTag() {
579:
580: boolean outValue = true;
581:
582: Tag currentParent = this .getParent();
583:
584: while (currentParent != null) {
585: if (currentParent instanceof BaseWebPageTag) {
586: outValue = false;
587: break;
588: } else {
589: currentParent = currentParent.getParent();
590: }
591: }
592:
593: return outValue;
594: }
595:
596: protected String getNamespace() {
597: return this .namespace;
598: }
599:
600: protected String getName() {
601: return this .name;
602: }
603:
604: public void determineValueAndClass(
605: DetermineValueAndClassConceptTagContext inRvacfctc) {
606:
607: inRvacfctc
608: .setDetermineException(new DetermineValueAndClassConceptTagException(
609: "Studio Only Tag"));
610: }
611:
612: public void determineClass(DetermineClassConceptTagContext inDcctc) {
613:
614: inDcctc.setDetermineClass(StandardDataTypes.getStringClass());
615: }
616:
617: }
|