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.request.RequestContext; 040 import org.apache.tapestry.services.LinkFactory; 041 import org.apache.tapestry.services.ServiceConstants; 042 import org.apache.tapestry.util.ContentType; 043 import org.apache.tapestry.web.WebResponse; 044 import org.w3c.dom.Document; 045 import org.w3c.dom.Node; 046 047 /** 048 * @author mindbridge 049 * @author Paul Green 050 * @since 4.0 051 */ 052 public class XTileService implements IEngineService 053 { 054 public static final String SERVICE_NAME = "xtile"; 055 056 private RequestExceptionReporter _exceptionReporter; 057 058 private WebResponse _response; 059 060 private LinkFactory _linkFactory; 061 062 public String getName() 063 { 064 return SERVICE_NAME; 065 } 066 067 public ILink getLink(boolean post, Object parameter) 068 { 069 Defense.isAssignable(parameter, IComponent.class, "parameter"); 070 071 IComponent component = (IComponent) parameter; 072 073 Map parameters = new HashMap(); 074 parameters.put(ServiceConstants.PAGE, component.getPage().getPageName()); 075 parameters.put(ServiceConstants.COMPONENT, component.getIdPath()); 076 077 return _linkFactory.constructLink(this, false, parameters, false); 078 } 079 080 public void service(IRequestCycle cycle) throws IOException 081 { 082 String pageName = cycle.getParameter(ServiceConstants.PAGE); 083 String componentId = cycle.getParameter(ServiceConstants.COMPONENT); 084 085 IPage componentPage = cycle.getPage(pageName); 086 IComponent component = componentPage.getNestedComponent(componentId); 087 088 if (!(component instanceof IXTile)) 089 throw new ApplicationRuntimeException("Incorrect component type: was " 090 + component.getClass() + " but must be " + IXTile.class, component, null, null); 091 092 IXTile xtile = (IXTile) component; 093 094 // do not squeeze on input 095 RequestContext context = cycle.getRequestContext(); 096 String[] params = context.getParameters(ServiceConstants.PARAMETER); 097 cycle.setServiceParameters(params); 098 xtile.trigger(cycle); 099 100 // do not squeeze on output either 101 Object[] args = cycle.getServiceParameters(); 102 String strArgs = generateOutputString(args); 103 if (strArgs != null) 104 { 105 OutputStream output = _response.getOutputStream(new ContentType("text/xml")); 106 output.write(strArgs.getBytes("utf-8")); 107 } 108 } 109 110 protected String generateOutputString(Object[] args) 111 { 112 try 113 { 114 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 115 dbf.setValidating(false); 116 DocumentBuilder db = dbf.newDocumentBuilder(); 117 Document doc = db.newDocument(); 118 119 Node rootNode = doc.createElement("data"); 120 doc.appendChild(rootNode); 121 122 if (args != null) 123 { 124 for (int i = 0; i < args.length; i++) 125 { 126 Object value = args[i]; 127 128 Node spNode = doc.createElement("sp"); 129 rootNode.appendChild(spNode); 130 131 Node valueNode = doc.createTextNode(value.toString()); 132 spNode.appendChild(valueNode); 133 } 134 } 135 136 TransformerFactory trf = TransformerFactory.newInstance(); 137 Transformer tr = trf.newTransformer(); 138 tr.setOutputProperty(OutputKeys.INDENT, "yes"); 139 140 DOMSource domSrc = new DOMSource(doc); 141 StringWriter writer = new StringWriter(); 142 StreamResult res = new StreamResult(writer); 143 tr.transform(domSrc, res); 144 writer.close(); 145 146 return writer.toString(); 147 } 148 catch (Exception e) 149 { 150 _exceptionReporter.reportRequestException("Cannot generate XML", e); 151 return null; 152 } 153 } 154 155 public void setExceptionReporter(RequestExceptionReporter exceptionReporter) 156 { 157 _exceptionReporter = exceptionReporter; 158 } 159 160 public void setResponse(WebResponse response) 161 { 162 _response = response; 163 } 164 165 public static void main(String[] args) 166 { 167 XTileService objService = new XTileService(); 168 System.out.println(objService.generateOutputString(new Object[] 169 { "test > work", new Integer(20) })); 170 } 171 172 public void setLinkFactory(LinkFactory linkFactory) 173 { 174 _linkFactory = linkFactory; 175 } 176 177 }