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 }