1 16 package org.apache.cocoon.generation; 17 18 import java.io.BufferedInputStream ; 19 import java.io.ByteArrayInputStream ; 20 import java.io.IOException ; 21 import java.io.InputStream ; 22 import java.io.PrintWriter ; 23 import java.io.StringWriter ; 24 import java.util.Map ; 25 import java.util.Properties ; 26 27 import javax.servlet.http.HttpServletRequest ; 28 29 import org.apache.avalon.framework.activity.Disposable; 30 import org.apache.avalon.framework.configuration.Configurable; 31 import org.apache.avalon.framework.configuration.Configuration; 32 import org.apache.avalon.framework.configuration.ConfigurationException; 33 import org.apache.avalon.framework.parameters.Parameters; 34 import org.apache.avalon.framework.service.ServiceException; 35 import org.apache.avalon.framework.service.ServiceManager; 36 import org.apache.cocoon.ProcessingException; 37 import org.apache.cocoon.caching.CacheableProcessingComponent; 38 import org.apache.cocoon.components.source.SourceUtil; 39 import org.apache.cocoon.environment.ObjectModelHelper; 40 import org.apache.cocoon.environment.Request; 41 import org.apache.cocoon.environment.SourceResolver; 42 import org.apache.cocoon.environment.http.HttpEnvironment; 43 import org.apache.cocoon.util.PostInputStream; 44 import org.apache.cocoon.xml.XMLUtils; 45 import org.apache.cocoon.xml.dom.DOMStreamer; 46 import org.apache.excalibur.source.Source; 47 import org.apache.excalibur.source.SourceException; 48 import org.apache.excalibur.source.SourceValidity; 49 import org.apache.excalibur.xml.xpath.XPathProcessor; 50 import org.w3c.dom.NodeList ; 51 import org.w3c.tidy.Tidy; 52 import org.xml.sax.SAXException ; 53 54 74 public class HTMLGenerator extends ServiceableGenerator 75 implements Configurable, CacheableProcessingComponent, Disposable { 76 77 78 public static final String FORM_NAME = "form-name"; 79 80 81 private Source inputSource; 82 83 84 private InputStream requestStream; 85 86 87 private String xpath = null; 88 89 90 private XPathProcessor processor = null; 91 92 93 private Properties properties; 94 95 public void service(ServiceManager manager) 96 throws ServiceException { 97 super.service( manager ); 98 this.processor = (XPathProcessor)this.manager.lookup(XPathProcessor.ROLE); 99 } 100 101 public void configure(Configuration config) throws ConfigurationException { 102 103 String configUrl = config.getChild("jtidy-config").getValue(null); 104 105 if(configUrl != null) { 106 org.apache.excalibur.source.SourceResolver resolver = null; 107 Source configSource = null; 108 try { 109 resolver = (org.apache.excalibur.source.SourceResolver)this.manager.lookup(org.apache.excalibur.source.SourceResolver.ROLE); 110 configSource = resolver.resolveURI(configUrl); 111 if (getLogger().isDebugEnabled()) { 112 getLogger().debug("Loading configuration from " + configSource.getURI()); 113 } 114 115 this.properties = new Properties (); 116 this.properties.load(configSource.getInputStream()); 117 118 } catch (Exception e) { 119 getLogger().warn("Cannot load configuration from " + configUrl); 120 throw new ConfigurationException("Cannot load configuration from " + configUrl, e); 121 } finally { 122 if ( null != resolver ) { 123 this.manager.release(resolver); 124 resolver.release(configSource); 125 } 126 } 127 } 128 } 129 130 134 public void recycle() { 135 if (this.inputSource != null) { 136 this.resolver.release( this.inputSource ); 137 this.inputSource = null; 138 this.requestStream = null; 139 } 140 this.xpath = null; 141 super.recycle(); 142 } 143 144 148 public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par) 149 throws ProcessingException, SAXException , IOException { 150 super.setup(resolver, objectModel, src, par); 151 152 Request request = ObjectModelHelper.getRequest(objectModel); 153 154 if (src == null) { 155 159 String contentType = request.getContentType(); 160 161 if (contentType == null ) { 162 throw new IOException ("Content-type was not specified for this request"); 163 } else if (contentType.startsWith("application/x-www-form-urlencoded") || 164 contentType.startsWith("multipart/form-data")) { 165 String requested = parameters.getParameter(FORM_NAME, null); 166 if (requested == null) { 167 throw new ProcessingException( 168 "HtmlGenerator with no \"src\" parameter expects a sitemap parameter called '" + 169 FORM_NAME + "' for handling form data" 170 ); 171 } 172 173 String sXml = request.getParameter(requested); 174 175 requestStream = new ByteArrayInputStream (sXml.getBytes()); 176 177 } else if (contentType.startsWith("text/plain") || 178 contentType.startsWith("text/xml") || 179 contentType.startsWith("application/xml")) { 180 181 HttpServletRequest httpRequest = (HttpServletRequest ) objectModel.get(HttpEnvironment.HTTP_REQUEST_OBJECT); 182 if ( httpRequest == null ) { 183 throw new ProcessingException("This functionality only works in an http environment."); 184 } 185 int len = request.getContentLength(); 186 if (len > 0) { 187 requestStream = new PostInputStream(httpRequest.getInputStream(), len); 188 } else { 189 throw new IOException ("getContentLen() == 0"); 190 } 191 } else { 192 throw new IOException ("Unexpected getContentType(): " + request.getContentType()); 193 } 194 195 196 } 197 198 xpath = request.getParameter("xpath"); 199 if (xpath == null) { 200 xpath = par.getParameter("xpath",null); 201 } 202 203 if (par.getParameterAsBoolean("copy-parameters", false) 205 && request.getQueryString() != null) { 206 StringBuffer query = new StringBuffer (super.source); 207 query.append(super.source.indexOf("?") == -1 ? '?' : '&'); 208 query.append(request.getQueryString()); 209 super.source = query.toString(); 210 } 211 212 try { 213 if (source != null) { 214 this.inputSource = resolver.resolveURI(super.source); 215 } 216 } catch (SourceException se) { 217 throw SourceUtil.handle("Unable to resolve " + super.source, se); 218 } 219 } 220 221 229 public java.io.Serializable getKey() { 230 if (this.inputSource == null) { 231 return null; 232 } 233 234 if (this.xpath != null) { 235 StringBuffer buffer = new StringBuffer (this.inputSource.getURI()); 236 buffer.append(':').append(this.xpath); 237 return buffer.toString(); 238 } else { 239 return this.inputSource.getURI(); 240 } 241 } 242 243 251 public SourceValidity getValidity() { 252 if (this.inputSource == null) { 253 return null; 254 } 255 return this.inputSource.getValidity(); 256 } 257 258 261 public void generate() 262 throws IOException , SAXException , ProcessingException { 263 try { 264 Tidy tidy = new Tidy(); 266 tidy.setXmlOut(true); 267 268 if (this.properties == null) { 269 tidy.setXHTML(true); 270 } else { 271 tidy.setConfigurationFromProps(this.properties); 272 } 273 274 tidy.setShowWarnings(getLogger().isWarnEnabled()); 276 tidy.setQuiet(!getLogger().isInfoEnabled()); 278 StringWriter stringWriter = new StringWriter (); 280 PrintWriter errorWriter = new PrintWriter (stringWriter); 281 tidy.setErrout(errorWriter); 282 283 285 if (inputSource != null) 286 requestStream = this.inputSource.getInputStream(); 287 288 org.w3c.dom.Document doc = tidy.parseDOM(new BufferedInputStream (requestStream), null); 289 290 XMLUtils.stripDuplicateAttributes(doc, null); 293 294 errorWriter.flush(); 295 errorWriter.close(); 296 if(getLogger().isWarnEnabled()) { 297 getLogger().warn(stringWriter.toString()); 298 } 299 300 DOMStreamer domStreamer = new DOMStreamer(this.contentHandler, 301 this.lexicalHandler); 302 this.contentHandler.startDocument(); 303 304 if(xpath != null) { 305 NodeList nl = processor.selectNodeList(doc, xpath); 306 int length = nl.getLength(); 307 for(int i=0; i < length; i++) { 308 domStreamer.stream(nl.item(i)); 309 } 310 } else { 311 domStreamer.stream(doc.getDocumentElement()); 315 } 316 this.contentHandler.endDocument(); 317 } catch (SAXException e){ 318 SourceUtil.handleSAXException(this.inputSource.getURI(), e); 319 } 320 } 321 322 323 public void dispose() { 324 if (this.manager != null) { 325 this.manager.release(this.processor); 326 this.manager = null; 327 } 328 this.processor = null; 329 super.dispose(); 330 } 331 } 332 | Popular Tags |