Coverage Report - org.apache.myfaces.shared.util.StringCharArrayAccessor
 
Classes in this File Line Coverage Branch Coverage Complexity
StringCharArrayAccessor
8%
6/69
8%
1/12
2.667
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one
 3  
  * or more contributor license agreements.  See the NOTICE file
 4  
  * distributed with this work for additional information
 5  
  * regarding copyright ownership.  The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the
 7  
  * "License"); you may not use this file except in compliance
 8  
  * with the License.  You may obtain a copy of the License at
 9  
  *
 10  
  *   http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing,
 13  
  * software distributed under the License is distributed on an
 14  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15  
  * KIND, either express or implied.  See the License for the
 16  
  * specific language governing permissions and limitations
 17  
  * under the License.
 18  
  */
 19  
 package org.apache.myfaces.shared.util;
 20  
 
 21  
 import java.io.IOException;
 22  
 import java.io.Writer;
 23  
 import java.lang.reflect.Field;
 24  
 
 25  
 /**
 26  
  * Provides optimized access to java.lang.String internals
 27  
  *
 28  
  * - Optimized way of creating java.lang.String by reusing a char[] buffer
 29  
  * - Optimized way of writing String to java.io.Writer
 30  
  *
 31  
  * java.lang.String creation reusing a char[] buffer requires Java 1.5+
 32  
  *
 33  
  * System property "oam.stringchararrayaccessor.enabled" enables this hack.
 34  
  * -Doam.stringchararrayaccessor.enabled=true
 35  
  *
 36  
  * Read JSR-133, "9.1.1 Post-Construction Modification of Final Fields"
 37  
  * http://www.cs.umd.edu/~pugh/java/memoryModel/jsr133.pdf
 38  
  *
 39  
  * @author Lari Hotari, Sagire Software Oy
 40  
  * @see org.codehaus.groovy.grails.web.util.StreamCharBuffer
 41  
  *      file licensed under ASL v2.0 
 42  
  *      Copyright 2009 the original author or authors.
 43  
  */
 44  0
 public class StringCharArrayAccessor
 45  
 {
 46  
 
 47  
     //static volatile boolean enabled = !Boolean
 48  
     //        .getBoolean("oam.stringchararrayaccessor.disabled");
 49  
     // In Google Application Engine this hack is not valid. We should
 50  
     // set this one as default disabled.
 51  1
     static volatile boolean enabled = Boolean
 52  
             .getBoolean("oam.stringchararrayaccessor.enabled");
 53  
 
 54  
     static Field valueField;
 55  
     static Field countField;
 56  
     static Field offsetField;
 57  
 
 58  
     static
 59  
     {
 60  1
         if (enabled)
 61  
         {
 62  
             try
 63  
             {
 64  0
                 valueField = String.class.getDeclaredField("value");
 65  0
                 valueField.setAccessible(true);
 66  
 
 67  0
                 countField = String.class.getDeclaredField("count");
 68  0
                 countField.setAccessible(true);
 69  
 
 70  0
                 offsetField = String.class.getDeclaredField("offset");
 71  0
                 offsetField.setAccessible(true);
 72  
             }
 73  0
             catch (Exception e)
 74  
             {
 75  0
                 enabled = false;
 76  0
                 System.err
 77  
                         .println("Unable to use direct char[] access of java.lang.String");
 78  0
                 e.printStackTrace();
 79  0
             }
 80  
         }
 81  1
     }
 82  
 
 83  
     /**
 84  
      * Writes a portion of a string to a target java.io.Writer with direct access to the char[] of the java.lang.String
 85  
      *
 86  
      * @param  writer
 87  
      *            target java.io.Writer for output
 88  
      *
 89  
      * @param  str
 90  
      *         A String
 91  
      *
 92  
      * @throws  IOException
 93  
      *          If an I/O error occurs
 94  
      */
 95  
     static public void writeStringAsCharArray(Writer writer, String str)
 96  
             throws IOException
 97  
     {
 98  0
         writeStringAsCharArray(writer, str, 0, str.length());
 99  0
     }
 100  
 
 101  
     /**
 102  
      * Writes a portion of a string to a target java.io.Writer with direct access to the char[] of the java.lang.String
 103  
      *
 104  
      * @param  writer
 105  
      *            target java.io.Writer for output
 106  
      *
 107  
      * @param  str
 108  
      *         A String
 109  
      *
 110  
      * @param  off
 111  
      *         Offset from which to start writing characters
 112  
      *
 113  
      * @param  len
 114  
      *         Number of characters to write
 115  
      *
 116  
      * @throws  IOException
 117  
      *          If an I/O error occurs
 118  
      */
 119  
     static public void writeStringAsCharArray(Writer writer, String str,
 120  
             int off, int len) throws IOException
 121  
     {
 122  0
         if (!enabled)
 123  
         {
 124  0
             writeStringFallback(writer, str, off, len);
 125  0
             return;
 126  
         }
 127  
 
 128  
         char[] value;
 129  
         int internalOffset;
 130  
         try
 131  
         {
 132  0
             value = (char[]) valueField.get(str);
 133  0
             internalOffset = offsetField.getInt(str);
 134  
         }
 135  0
         catch (Exception e)
 136  
         {
 137  0
             handleError(e);
 138  0
             writeStringFallback(writer, str, off, len);
 139  0
             return;
 140  0
         }
 141  0
         writer.write(value, internalOffset + off, len);
 142  0
     }
 143  
 
 144  
     private static void writeStringFallback(Writer writer, String str, int off,
 145  
             int len) throws IOException
 146  
     {
 147  0
         writer.write(str, off, len);
 148  0
     }
 149  
 
 150  
     static char[] getValue(String str)
 151  
     {
 152  0
         if (!enabled)
 153  
         {
 154  0
             return getValueFallback(str);
 155  
         }
 156  
 
 157  0
         char[] value = null;
 158  0
         int internalOffset = 0;
 159  
         try
 160  
         {
 161  0
             value = (char[]) valueField.get(str);
 162  0
             internalOffset = offsetField.getInt(str);
 163  
         }
 164  0
         catch (Exception e)
 165  
         {
 166  0
             handleError(e);
 167  0
         }
 168  0
         if (value != null && internalOffset == 0)
 169  
         {
 170  0
             return value;
 171  
         }
 172  
 
 173  0
         return getValueFallback(str);
 174  
     }
 175  
 
 176  
     static char[] getValueFallback(String str)
 177  
     {
 178  0
         return str.toCharArray();
 179  
     }
 180  
 
 181  
     /**
 182  
      * creates a new java.lang.String by setting the char array directly to the String instance with reflection.
 183  
      *
 184  
      * @param charBuf
 185  
      *        char array to be used as java.lang.String content, don't modify it after passing it.
 186  
      * @return new java.lang.String
 187  
      */
 188  
     public static String createString(char[] charBuf)
 189  
     {
 190  7
         if (!enabled)
 191  
         {
 192  7
             return createStringFallback(charBuf);
 193  
         }
 194  
 
 195  0
         String str = new String();
 196  
         try
 197  
         {
 198  
             // try to prevent possible final field setting execution reordering in JIT 
 199  
             // (JSR-133/JMM, "9.1.1 Post-Construction Modification of Final Fields")
 200  
             // it was a bit unclear for me if this could ever happen in a single thread
 201  0
             synchronized (str)
 202  
             {
 203  0
                 valueField.set(str, charBuf);
 204  0
                 countField.set(str, charBuf.length);
 205  0
             }
 206  0
             synchronized (str)
 207  
             {
 208  
                 // safety check, just to be sure that setting the final fields went ok
 209  0
                 if (str.length() != charBuf.length)
 210  
                 {
 211  0
                     throw new IllegalStateException(
 212  
                             "Fast java.lang.String construction failed.");
 213  
                 }
 214  0
             }
 215  
         }
 216  0
         catch (Exception e)
 217  
         {
 218  0
             handleError(e);
 219  0
             str = createStringFallback(charBuf);
 220  0
         }
 221  0
         return str;
 222  
     }
 223  
 
 224  
     private static String createStringFallback(char[] charBuf)
 225  
     {
 226  7
         return new String(charBuf);
 227  
     }
 228  
 
 229  
     private static synchronized void handleError(Exception e)
 230  
     {
 231  0
         enabled = false;
 232  0
         System.err
 233  
                 .println("Unable to use direct char[] access of java.lang.String. Disabling this method.");
 234  0
         valueField = null;
 235  0
         countField = null;
 236  0
         offsetField = null;
 237  0
         e.printStackTrace();
 238  0
     }
 239  
 
 240  
     static public boolean isEnabled()
 241  
     {
 242  0
         return enabled;
 243  
     }
 244  
 }