001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.wicket.markup.transformer; 018 019import org.apache.wicket.Component; 020import org.apache.wicket.Page; 021import org.apache.wicket.WicketRuntimeException; 022import org.apache.wicket.behavior.Behavior; 023import org.apache.wicket.protocol.http.BufferedWebResponse; 024import org.apache.wicket.request.Response; 025import org.apache.wicket.request.cycle.RequestCycle; 026import org.apache.wicket.request.http.WebResponse; 027 028/** 029 * A {@link Behavior} which can be added to any component. It allows to post-process (transform) the 030 * markup generated by the component. 031 * 032 * @see org.apache.wicket.markup.transformer.AbstractOutputTransformerContainer 033 * 034 * @author Juergen Donnerstag 035 */ 036public abstract class AbstractTransformerBehavior extends Behavior implements ITransformer 037{ 038 private static final long serialVersionUID = 1L; 039 040 /** 041 * The request cycle's response before the transformation. 042 */ 043 private transient Response originalResponse; 044 045 /** 046 * Create a new response object which is used to store the markup generated by the child 047 * objects. 048 * 049 * @param originalResponse 050 * the original web response or {@code null} if it isn't a {@link WebResponse} 051 * 052 * @return Response object. Must not be null 053 */ 054 protected BufferedWebResponse newResponse(final WebResponse originalResponse) 055 { 056 return new BufferedWebResponse(originalResponse); 057 } 058 059 @Override 060 public void beforeRender(Component component) 061 { 062 super.beforeRender(component); 063 064 final RequestCycle requestCycle = RequestCycle.get(); 065 066 // Temporarily replace the web response with a String response 067 originalResponse = requestCycle.getResponse(); 068 069 WebResponse origResponse = (WebResponse)((originalResponse instanceof WebResponse) 070 ? originalResponse : null); 071 BufferedWebResponse tempResponse = newResponse(origResponse); 072 073 // temporarily set StringResponse to collect the transformed output 074 requestCycle.setResponse(tempResponse); 075 } 076 077 @Override 078 public void afterRender(final Component component) 079 { 080 final RequestCycle requestCycle = RequestCycle.get(); 081 082 try 083 { 084 BufferedWebResponse tempResponse = (BufferedWebResponse)requestCycle.getResponse(); 085 086 if (component instanceof Page && originalResponse instanceof WebResponse) 087 { 088 tempResponse.writeMetaData((WebResponse) originalResponse); 089 } 090 091 // Transform the data 092 CharSequence output = transform(component, tempResponse.getText()); 093 originalResponse.write(output); 094 } 095 catch (Exception ex) 096 { 097 throw new WicketRuntimeException("Error while transforming the output of component: " + 098 component, ex); 099 } 100 finally 101 { 102 // Restore the original response object 103 requestCycle.setResponse(originalResponse); 104 } 105 } 106 107 @Override 108 public void detach(Component component) 109 { 110 originalResponse = null; 111 super.detach(component); 112 } 113 114 @Override 115 public abstract CharSequence transform(final Component component, final CharSequence output) 116 throws Exception; 117}