2009/05/20 - Apache Shale has been retired.

For more information, please explore the Attic.

Coverage Report - org.apache.shale.validator.faces.ValidatorCommandRenderer
 
Classes in this File Line Coverage Branch Coverage Complexity
ValidatorCommandRenderer
0% 
0% 
1.778
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to you under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  *
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 
 18  
 package org.apache.shale.validator.faces;
 19  
 
 20  
 import java.io.IOException;
 21  
 import java.io.StringWriter;
 22  
 import javax.faces.component.UICommand;
 23  
 import javax.faces.component.UIComponent;
 24  
 import javax.faces.context.FacesContext;
 25  
 import javax.faces.context.ResponseWriter;
 26  
 import javax.faces.convert.ConverterException;
 27  
 import javax.faces.render.Renderer;
 28  
 
 29  
 /**
 30  
  * <p>This Renderer is a hybrid renderer decorator that is dynamically
 31  
  * registered by {@link ValidatorRenderKit}
 32  
  * for component renderers in the "javax.faces.Command" family.</p>
 33  
  */
 34  
 public class ValidatorCommandRenderer extends Renderer {
 35  
 
 36  
 
 37  
     /**
 38  
      * <p>The Original Renderer.</p>
 39  
      */
 40  0
     private Renderer defaultRenderer = null;
 41  
 
 42  
 
 43  
     /**
 44  
      * <p>The overloaded constructor is passed the original
 45  
      * <code>Renderer</code> for the family and component type.</p>
 46  
      *
 47  
      * @param defaultRenderer The default Renderer we should delegate to
 48  
      */
 49  0
     public ValidatorCommandRenderer(Renderer defaultRenderer) {
 50  0
        this.defaultRenderer = defaultRenderer;
 51  0
     }
 52  
 
 53  
 
 54  
     /**
 55  
      * <p>Attribute name used to override the default behavior of how the immediate
 56  
      * attribute effects the execution of client side javascript validation.</p>
 57  
      */
 58  
     public static final String OVERRIDE_IMMEDIATE = "org.apache.shale.validator.immediate";
 59  
 
 60  
     private static final int ENCODE_BEGIN = 0;
 61  
 
 62  
     private static final int ENCODE_CHILDREN = 1;
 63  
 
 64  
     private static final int ENCODE_END = 2;
 65  
 
 66  
 
 67  
     /**
 68  
      * <b>Interrogates the component's immediate property and the component's
 69  
      * immediate override attribute to determine if client side validation is
 70  
      * invoked. If either the property or attribute override is false, client
 71  
      * side validation is invoked. Otherwise, the response writer is hijacked
 72  
      * and the original render is invoked. The result is buffered and a
 73  
      * statement of javascript is injected into the onclick event which cancels
 74  
      * client side validation. The original response writer is restored and the
 75  
      * modified markup is written to the response writer. The
 76  
      * <code>encodeSwitch</code> determines if the encodeBegin, encodeChildren
 77  
      * or encodeEnd methods should be invoked on the decorated renderer.</b>
 78  
      *
 79  
      * @param context FacesContext for the current request
 80  
      * @param component UIComponent being rendered
 81  
      * @param encodeSwitch FIXME - encode switch?
 82  
      *
 83  
      * @exception IOException if an input/output error occurs
 84  
      */
 85  
     protected void encode(FacesContext context, UIComponent component,
 86  
             int encodeSwitch) throws IOException {
 87  
 
 88  0
         UICommand command = (UICommand) component;
 89  
 
 90  
         // look for a override to the default
 91  0
         boolean immediateOverride = true;
 92  0
         String attr = (String) component.getAttributes()
 93  
                 .get(OVERRIDE_IMMEDIATE);
 94  0
         if (attr != null) {
 95  0
             immediateOverride = Boolean.valueOf(attr).booleanValue();
 96  
         }
 97  
 
 98  0
         if (command.isImmediate() && immediateOverride) {
 99  
 
 100  0
             ResponseWriter hijackedWriter = context.getResponseWriter();
 101  
             // builds a buffer to write the page to
 102  0
             StringWriter writer = new StringWriter();
 103  
             // create a buffered response writer
 104  0
             ResponseWriter buffResponsewriter = context.getRenderKit()
 105  
                     .createResponseWriter(writer, null,
 106  
                             hijackedWriter.getCharacterEncoding());
 107  
             // push buffered writer to the faces context
 108  0
             context.setResponseWriter(buffResponsewriter);
 109  
 
 110  0
             if (encodeSwitch == ENCODE_BEGIN) {
 111  0
                 defaultRenderer.encodeBegin(context, component);
 112  0
             } else if (encodeSwitch == ENCODE_CHILDREN) {
 113  0
                 defaultRenderer.encodeChildren(context, component);
 114  0
             } else {
 115  0
                 defaultRenderer.encodeEnd(context, component);
 116  
             }
 117  
 
 118  0
             buffResponsewriter.write(' ');
 119  0
             buffResponsewriter.flush();
 120  0
             buffResponsewriter.close();
 121  0
             writer.flush();
 122  0
             writer.close();
 123  0
             StringBuffer buff = writer.getBuffer();
 124  0
             int i = buff.indexOf("onclick=\"");
 125  0
             if (i > 0) {
 126  0
                 buff.insert(i + "onclick=\"".length(), "bCancel=true;");
 127  
             }
 128  
 
 129  0
             hijackedWriter.write(buff.toString());
 130  0
             context.setResponseWriter(hijackedWriter);
 131  
 
 132  0
         } else {
 133  
 
 134  0
             if (encodeSwitch == ENCODE_BEGIN) {
 135  0
                 defaultRenderer.encodeBegin(context, component);
 136  0
             } else if (encodeSwitch == ENCODE_CHILDREN) {
 137  0
                 defaultRenderer.encodeChildren(context, component);
 138  0
             } else {
 139  0
                 defaultRenderer.encodeEnd(context, component);
 140  
             }
 141  
 
 142  
         }
 143  
 
 144  0
     }
 145  
 
 146  
 
 147  
     /** {@inheritDoc} */
 148  
     public String convertClientId(FacesContext context, String id) {
 149  0
         return defaultRenderer.convertClientId(context, id);
 150  
     }
 151  
 
 152  
 
 153  
     /** {@inheritDoc} */
 154  
     public Object getConvertedValue(FacesContext context, UIComponent component, Object o) throws ConverterException {
 155  0
         return defaultRenderer.getConvertedValue(context, component, o);
 156  
     }
 157  
 
 158  
 
 159  
     /** {@inheritDoc} */
 160  
     public void decode(FacesContext context, UIComponent component) {
 161  0
         defaultRenderer.decode(context, component);
 162  0
     }
 163  
 
 164  
 
 165  
     /**
 166  
      * <p>
 167  
      * Invokes the <code>encode</code> method passing
 168  
      * <code>ENCODE_BEGIN</code> for the encodeSwitch parameter.
 169  
      * </p>
 170  
      *
 171  
      * @param context FacesContext for the current request
 172  
      * @param component UIComponent being rendered
 173  
      *
 174  
      * @exception IOException if an input/output error occurs
 175  
      */
 176  
     public void encodeBegin(FacesContext context, UIComponent component)
 177  
             throws IOException {
 178  0
         encode(context, component, ENCODE_BEGIN);
 179  0
     }
 180  
 
 181  
 
 182  
     /**
 183  
      * <p>Invokes the <code>encode</code> method passing
 184  
      * <code>ENCODE_CHILDREN</code> for the encodeSwitch parameter.</p>
 185  
      *
 186  
      * @param context FacesContext for the current request
 187  
      * @param component UIComponent being rendered
 188  
      *
 189  
      * @exception IOException if an input/output error occurs
 190  
      */
 191  
     public void encodeChildren(FacesContext context, UIComponent component)
 192  
             throws IOException {
 193  0
         encode(context, component, ENCODE_CHILDREN);
 194  0
     }
 195  
 
 196  
 
 197  
     /**
 198  
      * <p>Invokes the <code>encode</code> method passing <code>ENCODE_END</code>
 199  
      * for the encodeSwitch parameter.</p>
 200  
      *
 201  
      * @param context FacesContext for the current reqauest
 202  
      * @param component UIComponent being rendered
 203  
      *
 204  
      * @exception IOException if an input/output error occurs
 205  
      */
 206  
     public void encodeEnd(FacesContext context, UIComponent component)
 207  
             throws IOException {
 208  0
         encode(context, component, ENCODE_END);
 209  0
     }
 210  
 
 211  
 
 212  
     /** {@inheritDoc} */
 213  
     public boolean getRendersChildren() {
 214  0
         return defaultRenderer.getRendersChildren();
 215  
     }
 216  
 
 217  
 
 218  
 }