| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.sling.rewriter.impl; |
| |
| import java.io.IOException; |
| import java.io.PrintWriter; |
| import java.io.Writer; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.apache.sling.adapter.annotations.Adaptable; |
| import org.apache.sling.adapter.annotations.Adapter; |
| import org.apache.sling.api.SlingException; |
| import org.apache.sling.api.SlingHttpServletRequest; |
| import org.apache.sling.api.SlingHttpServletResponse; |
| import org.apache.sling.api.wrappers.SlingHttpServletResponseWrapper; |
| import org.apache.sling.rewriter.ProcessingContext; |
| import org.apache.sling.rewriter.Processor; |
| import org.apache.sling.rewriter.ProcessorConfiguration; |
| import org.apache.sling.rewriter.ProcessorManager; |
| import org.xml.sax.ContentHandler; |
| |
| /** |
| * This response is used to pass the output through the rewriter pipeline. |
| */ |
| @Adaptable(adaptableClass=SlingHttpServletResponse.class, adapters={ |
| @Adapter(value=ContentHandler.class, |
| condition="When the response is being processed through the Sling Rewriter filter.") |
| }) |
| class RewriterResponse |
| extends SlingHttpServletResponseWrapper { |
| |
| /** The current request. */ |
| private final SlingHttpServletRequest request; |
| |
| /** The processor. */ |
| private Processor processor; |
| |
| /** wrapped rewriter/servlet writer */ |
| private PrintWriter writer; |
| |
| /** response content type */ |
| private String contentType; |
| |
| /** The processor manager. */ |
| private final ProcessorManager processorManager; |
| |
| /** |
| * Initializes a new instance. |
| * @param request The sling request. |
| * @param delegatee The SlingHttpServletResponse wrapped by this instance. |
| */ |
| public RewriterResponse(SlingHttpServletRequest request, |
| SlingHttpServletResponse delegatee, |
| ProcessorManager processorManager) { |
| super(delegatee); |
| this.processorManager = processorManager; |
| this.request = request; |
| } |
| |
| /** |
| * @see javax.servlet.ServletResponseWrapper#setContentType(java.lang.String) |
| */ |
| public void setContentType(String type) { |
| this.contentType = type; |
| super.setContentType(type); |
| } |
| |
| /** |
| * Wraps the underlying writer by a rewriter pipeline. |
| * |
| * @see javax.servlet.ServletResponseWrapper#getWriter() |
| */ |
| public PrintWriter getWriter() throws IOException { |
| if ( this.processor != null && this.writer == null ) { |
| return new PrintWriter(new Writer() { |
| |
| @Override |
| public void close() throws IOException { |
| // nothing to do |
| } |
| |
| @Override |
| public void flush() throws IOException { |
| // nothing to do |
| } |
| |
| @Override |
| public void write(char[] cbuf, int off, int len) |
| throws IOException { |
| // nothing to do |
| } |
| }); |
| } |
| if (writer == null) { |
| this.processor = this.getProcessor(); |
| if ( this.processor != null ) { |
| this.writer = this.processor.getWriter(); |
| } |
| if ( this.writer == null ) { |
| this.writer = super.getWriter(); |
| } |
| } |
| return writer; |
| } |
| |
| /** |
| * @see javax.servlet.ServletResponseWrapper#flushBuffer() |
| */ |
| public void flushBuffer() throws IOException { |
| if (writer != null) { |
| writer.flush(); |
| } else { |
| super.flushBuffer(); |
| } |
| } |
| |
| /** |
| * Inform this response that the request processing is finished. |
| * @throws IOException |
| */ |
| public void finished(final boolean errorOccured) throws IOException { |
| if ( this.processor != null ) { |
| this.processor.finished(errorOccured); |
| this.processor = null; |
| } |
| } |
| |
| /** |
| * If we have a pipeline configuration for the current request, |
| * we can adapt this response to a content handler. |
| * @see org.apache.sling.api.adapter.Adaptable#adaptTo(java.lang.Class) |
| */ |
| public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) { |
| if ( type == ContentHandler.class ) { |
| this.processor = this.getProcessor(); |
| if ( this.processor != null ) { |
| @SuppressWarnings("unchecked") |
| final AdapterType object = (AdapterType)this.processor.getContentHandler(); |
| return object; |
| } |
| } |
| return super.adaptTo(type); |
| } |
| |
| /** |
| * Search the first matching processor |
| */ |
| private Processor getProcessor() { |
| final ProcessingContext processorContext = new ServletProcessingContext(this.request, this, this.getSlingResponse(), this.contentType); |
| Processor found = null; |
| final List<ProcessorConfiguration> processorConfigs = this.processorManager.getProcessorConfigurations(); |
| final Iterator<ProcessorConfiguration> i = processorConfigs.iterator(); |
| while ( found == null && i.hasNext() ) { |
| final ProcessorConfiguration config = i.next(); |
| if ( config.match(processorContext) ) { |
| try { |
| found = this.processorManager.getProcessor(config, processorContext); |
| this.request.getRequestProgressTracker().log("Found processor for post processing {0}", config); |
| } catch (final SlingException se) { |
| // if an exception occurs during setup of the pipeline and we are currently |
| // already processing an error, we ignore this! |
| if ( processorContext.getRequest().getAttribute("javax.servlet.error.status_code") != null ) { |
| this.request.getRequestProgressTracker().log("Ignoring found processor for post processing {0}" + |
| " as an error occured ({1}) during setup while processing another error.", config, se); |
| } else { |
| throw se; |
| } |
| } |
| } |
| } |
| return found; |
| } |
| } |