001 // Copyright 2004, 2005 The Apache Software Foundation
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014
015 package org.apache.tapestry.contrib.ajax;
016
017 import java.io.IOException;
018 import java.io.OutputStream;
019 import java.io.StringWriter;
020 import java.util.HashMap;
021 import java.util.Map;
022
023 import javax.xml.parsers.DocumentBuilder;
024 import javax.xml.parsers.DocumentBuilderFactory;
025 import javax.xml.transform.OutputKeys;
026 import javax.xml.transform.Transformer;
027 import javax.xml.transform.TransformerFactory;
028 import javax.xml.transform.dom.DOMSource;
029 import javax.xml.transform.stream.StreamResult;
030
031 import org.apache.hivemind.ApplicationRuntimeException;
032 import org.apache.hivemind.util.Defense;
033 import org.apache.tapestry.IComponent;
034 import org.apache.tapestry.IPage;
035 import org.apache.tapestry.IRequestCycle;
036 import org.apache.tapestry.engine.IEngineService;
037 import org.apache.tapestry.engine.ILink;
038 import org.apache.tapestry.error.RequestExceptionReporter;
039 import org.apache.tapestry.services.LinkFactory;
040 import org.apache.tapestry.services.ServiceConstants;
041 import org.apache.tapestry.util.ContentType;
042 import org.apache.tapestry.web.WebResponse;
043 import org.w3c.dom.Document;
044 import org.w3c.dom.Node;
045
046 /**
047 * @author mindbridge
048 * @author Paul Green
049 * @since 4.0
050 */
051 public class XTileService implements IEngineService
052 {
053 public static final String SERVICE_NAME = "xtile";
054
055 private RequestExceptionReporter _exceptionReporter;
056
057 private WebResponse _response;
058
059 private LinkFactory _linkFactory;
060
061 public String getName()
062 {
063 return SERVICE_NAME;
064 }
065
066 public ILink getLink(boolean post, Object parameter)
067 {
068 Defense.isAssignable(parameter, IComponent.class, "parameter");
069
070 IComponent component = (IComponent) parameter;
071
072 Map parameters = new HashMap();
073 parameters.put(ServiceConstants.PAGE, component.getPage().getPageName());
074 parameters.put(ServiceConstants.COMPONENT, component.getIdPath());
075
076 return _linkFactory.constructLink(this, false, parameters, true);
077 }
078
079 public void service(IRequestCycle cycle) throws IOException
080 {
081 String pageName = cycle.getParameter(ServiceConstants.PAGE);
082 String componentId = cycle.getParameter(ServiceConstants.COMPONENT);
083
084 IPage componentPage = cycle.getPage(pageName);
085 IComponent component = componentPage.getNestedComponent(componentId);
086
087 if (!(component instanceof IXTile))
088 throw new ApplicationRuntimeException("Incorrect component type: was "
089 + component.getClass() + " but must be " + IXTile.class, component, null, null);
090
091 IXTile xtile = (IXTile) component;
092
093 String[] params = cycle.getParameters(ServiceConstants.PARAMETER);
094 cycle.setListenerParameters(params);
095
096 xtile.trigger(cycle);
097
098 // do not squeeze on output either
099 Object[] args = cycle.getListenerParameters();
100 String strArgs = generateOutputString(args);
101 if (strArgs != null)
102 {
103 OutputStream output = _response.getOutputStream(new ContentType("text/xml"));
104 output.write(strArgs.getBytes("utf-8"));
105 }
106 }
107
108 protected String generateOutputString(Object[] args)
109 {
110 try
111 {
112 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
113 dbf.setValidating(false);
114 DocumentBuilder db = dbf.newDocumentBuilder();
115 Document doc = db.newDocument();
116
117 Node rootNode = doc.createElement("data");
118 doc.appendChild(rootNode);
119
120 if (args != null)
121 {
122 for (int i = 0; i < args.length; i++)
123 {
124 Object value = args[i];
125
126 Node spNode = doc.createElement("sp");
127 rootNode.appendChild(spNode);
128
129 Node valueNode = doc.createTextNode(value.toString());
130 spNode.appendChild(valueNode);
131 }
132 }
133
134 TransformerFactory trf = TransformerFactory.newInstance();
135 Transformer tr = trf.newTransformer();
136 tr.setOutputProperty(OutputKeys.INDENT, "yes");
137
138 DOMSource domSrc = new DOMSource(doc);
139 StringWriter writer = new StringWriter();
140 StreamResult res = new StreamResult(writer);
141 tr.transform(domSrc, res);
142 writer.close();
143
144 return writer.toString();
145 }
146 catch (Exception e)
147 {
148 _exceptionReporter.reportRequestException("Cannot generate XML", e);
149 return null;
150 }
151 }
152
153 public void setExceptionReporter(RequestExceptionReporter exceptionReporter)
154 {
155 _exceptionReporter = exceptionReporter;
156 }
157
158 public void setResponse(WebResponse response)
159 {
160 _response = response;
161 }
162
163 public void setLinkFactory(LinkFactory linkFactory)
164 {
165 _linkFactory = linkFactory;
166 }
167
168 }