001: package org.enhydra.util.chiba;
002:
003: import java.util.HashMap;
004: import java.util.Map;
005:
006: import org.chiba.adapter.AbstractChibaAdapter;
007: import org.chiba.adapter.ChibaEvent;
008: import org.chiba.xml.xforms.events.XFormsEvent;
009: import org.chiba.xml.xforms.events.XFormsEventFactory;
010: import org.chiba.xml.xforms.exception.XFormsException;
011: import org.chiba.xml.xforms.ui.Repeat;
012: import org.w3c.dom.Element;
013: import org.w3c.dom.events.Event;
014: import org.w3c.dom.events.EventListener;
015: import org.w3c.dom.events.EventTarget;
016:
017: /**
018: * Adapter for processing DWR calls and building appropriate responses. This
019: * class is not exposed through DWR. Instead a Facadeclass 'FluxFacade' will be
020: * exposed that only allows to use the dispatch method. All other methods will
021: * be hidden for security.
022: *
023: * @author Joern Turner, Slobodan Vujasinovic
024: * @version $Id: ScriptAdapter.java,v 1.2 2007-05-17 12:52:55 sinisa Exp $
025: */
026: public class ScriptAdapter extends BaseAdapter implements EventListener {
027:
028: private EventLog eventLog;
029: private EventTarget root;
030: private HttpRequestHandler handler;
031:
032: public ScriptAdapter() {
033: this .chibaBean = createXFormsProcessor();
034: this .context = new HashMap();
035: chibaBean.setContext(this .context);
036: this .eventLog = new EventLog();
037: }
038:
039: /**
040: * initialize the Adapter. This is necessary cause often the using
041: * application will need to configure the Adapter before actually using it.
042: *
043: * @throws org.chiba.xml.xforms.exception.XFormsException
044: */
045: public void init() throws XFormsException {
046: try {
047: // get docuent root as event target in order to capture all events
048: this .root = (EventTarget) this .chibaBean.getXMLContainer()
049: .getDocumentElement();
050:
051: // interaction events my occur during init so we have to register before
052: this .root.addEventListener(
053: XFormsEventFactory.CHIBA_LOAD_URI, this , true);
054: this .root
055: .addEventListener(
056: XFormsEventFactory.CHIBA_RENDER_MESSAGE,
057: this , true);
058: this .root.addEventListener(
059: XFormsEventFactory.CHIBA_REPLACE_ALL, this , true);
060:
061: // init processor
062: this .chibaBean.init();
063:
064: // todo: add getter for event log
065: setContextParam("EVENT-LOG", this .eventLog);
066:
067: // register for notification events
068: this .root.addEventListener(
069: XFormsEventFactory.CHIBA_STATE_CHANGED, this , true);
070: this .root.addEventListener(
071: XFormsEventFactory.CHIBA_PROTOTYPE_CLONED, this ,
072: true);
073: this .root.addEventListener(
074: XFormsEventFactory.CHIBA_ID_GENERATED, this , true);
075: this .root.addEventListener(
076: XFormsEventFactory.CHIBA_ITEM_INSERTED, this , true);
077: this .root.addEventListener(
078: XFormsEventFactory.CHIBA_ITEM_DELETED, this , true);
079: this .root.addEventListener(
080: XFormsEventFactory.CHIBA_INDEX_CHANGED, this , true);
081: this .root
082: .addEventListener(
083: XFormsEventFactory.CHIBA_SWITCH_TOGGLED,
084: this , true);
085:
086: this .handler = getNewInteractionHandler();
087: setClean(false);
088: } catch (Exception e) {
089: throw new XFormsException(e);
090: }
091: }
092:
093: /**
094: * Dispatch a ChibaEvent to trigger some XForms processing such as updating
095: * of values or execution of triggers.
096: *
097: * @param event an application specific event
098: * @throws org.chiba.xml.xforms.exception.XFormsException
099: * @see org.chiba.adapter.DefaultChibaEventImpl
100: */
101: public void dispatch(ChibaEvent event) throws XFormsException {
102: this .eventLog.flush();
103: String targetId = event.getId();
104:
105: if (event.getEventName().equals(
106: ScriptFacade.FLUX_ACTIVATE_EVENT)) {
107: chibaBean.dispatch(targetId,
108: XFormsEventFactory.DOM_ACTIVATE);
109: } else if (event.getEventName().equals("SETINDEX")) {
110: int position = Integer.parseInt((String) event
111: .getContextInfo());
112: Repeat repeat = (Repeat) this .chibaBean.lookup(targetId);
113: repeat.setIndex(position);
114: } else if (event.getEventName().equals("SETVALUE")) {
115: this .chibaBean.updateControlValue(targetId, (String) event
116: .getContextInfo());
117: } else if (event.getEventName()
118: .equalsIgnoreCase("http-request")) {
119: handler.execute(event);
120: } else {
121: throw new XFormsException("Unknown or illegal event type");
122: }
123: }
124:
125: /**
126: * listen to processor and add a DefaultChibaEventImpl object to the
127: * EventQueue.
128: *
129: * @param event the handled DOMEvent
130: */
131: public void handleEvent(Event event) {
132: try {
133: if (event instanceof XFormsEvent) {
134: XFormsEvent xformsEvent = (XFormsEvent) event;
135: String type = xformsEvent.getType();
136: if (XFormsEventFactory.CHIBA_REPLACE_ALL.equals(type)) {
137: // get event properties
138: Element target = (Element) event.getTarget();
139: String targetId = target.getAttributeNS(null, "id");
140: String targetName = target.getLocalName();
141:
142: // add event properties to log
143: this .eventLog.add(type, targetId, targetName);
144: } else {
145: // add event to log
146: this .eventLog.add(xformsEvent);
147: }
148: }
149: } catch (Exception e) {
150: try {
151: this .chibaBean.getContainer().handleEventException(e);
152: } catch (XFormsException xfe) {
153: xfe.printStackTrace();
154: }
155: }
156: }
157:
158: /**
159: * terminates the XForms processing. right place to do cleanup of
160: * resources.
161: *
162: * @throws org.chiba.xml.xforms.exception.XFormsException
163: */
164: public void shutdown() throws XFormsException {
165: if (isClean())
166: return;
167: try {
168: // deregister for notification events
169: this .root.removeEventListener(
170: XFormsEventFactory.CHIBA_STATE_CHANGED, this , true);
171: this .root.removeEventListener(
172: XFormsEventFactory.CHIBA_PROTOTYPE_CLONED, this ,
173: true);
174: this .root.removeEventListener(
175: XFormsEventFactory.CHIBA_ID_GENERATED, this , true);
176: this .root.removeEventListener(
177: XFormsEventFactory.CHIBA_ITEM_INSERTED, this , true);
178: this .root.removeEventListener(
179: XFormsEventFactory.CHIBA_ITEM_DELETED, this , true);
180: this .root.removeEventListener(
181: XFormsEventFactory.CHIBA_INDEX_CHANGED, this , true);
182: this .root
183: .removeEventListener(
184: XFormsEventFactory.CHIBA_SWITCH_TOGGLED,
185: this , true);
186:
187: // shutdown processor
188: this .chibaBean.shutdown();
189: this .chibaBean = null;
190:
191: // deregister for interaction events
192: this .root.removeEventListener(
193: XFormsEventFactory.CHIBA_LOAD_URI, this , true);
194: this .root
195: .removeEventListener(
196: XFormsEventFactory.CHIBA_RENDER_MESSAGE,
197: this , true);
198: this .root.removeEventListener(
199: XFormsEventFactory.CHIBA_REPLACE_ALL, this , true);
200:
201: this .root = null;
202:
203: setClean(true);
204:
205: // no explicite GC calls
206: // System.gc();
207: } catch (Exception e) {
208: throw new XFormsException(e);
209: }
210: }
211:
212: /**
213: * set the upload location. This string represents the destination
214: * (data-sink) for uploads.
215: *
216: * @param destination a String representing the location where to store
217: * uploaded files/data.
218: */
219: public void setUploadDestination(String destination) {
220: this .uploadDestination = destination;
221: //todo: this should be moved to parent class. it's duplicated in both Adapters
222: setContextParam(ServletAdapter.HTTP_UPLOAD_DIR,
223: this .uploadDestination);
224: }
225:
226: protected String escape(String string) {
227: if (string == null) {
228: return string;
229: }
230:
231: StringBuffer buffer = new StringBuffer(string.length());
232: char c;
233: for (int index = 0; index < string.length(); index++) {
234: c = string.charAt(index);
235: switch (c) {
236: case '\n':
237: buffer.append('\\').append('n');
238: break;
239: case '\r':
240: buffer.append('\\').append('r');
241: break;
242: case '\t':
243: buffer.append('\\').append('t');
244: break;
245: case '\'':
246: buffer.append('\\').append('\'');
247: break;
248: case '\"':
249: buffer.append('\\').append('\"');
250: break;
251: default:
252: buffer.append(c);
253: break;
254: }
255: }
256:
257: return buffer.toString();
258: }
259:
260: /**
261: * return a new InteractionHandler.
262: * <p/>
263: * This method returns a new HttpRequestHandler.
264: *
265: * @return returns a new
266: */
267: protected HttpRequestHandler getNewInteractionHandler()
268: throws XFormsException {
269: return new HttpRequestHandler(this .chibaBean);
270: }
271:
272: /**
273: * passes Map containing arbitrary context parameters to the Adapter.
274: *
275: * @param contextParams Map of arbitrary params passed to the processor
276: */
277: public void setContext(Map contextParams) {
278: this.context = contextParams;
279: chibaBean.setContext(contextParams);
280: }
281:
282: }
|