org.apache.myfaces.shared_tomahawk.util.StringCharArrayAccessor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tomahawk21 Show documentation
Show all versions of tomahawk21 Show documentation
JSF components and utilities that can be used with any JSF implementation.
This library is based on the JSF1.1 version of Tomahawk, but with minor source code and build
changes to take advantage of JSF2.1 features. A JSF2.1 implementation is required to use this
version of the Tomahawk library.
The newest version!
/*
* 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.myfaces.shared_tomahawk.util;
import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Field;
/**
* Provides optimized access to java.lang.String internals
*
* - Optimized way of creating java.lang.String by reusing a char[] buffer
* - Optimized way of writing String to java.io.Writer
*
* java.lang.String creation reusing a char[] buffer requires Java 1.5+
*
* System property "oam.stringchararrayaccessor.enabled" enables this hack.
* -Doam.stringchararrayaccessor.enabled=true
*
* Read JSR-133, "9.1.1 Post-Construction Modification of Final Fields"
* http://www.cs.umd.edu/~pugh/java/memoryModel/jsr133.pdf
*
* @author Lari Hotari, Sagire Software Oy
* @see org.codehaus.groovy.grails.web.util.StreamCharBuffer
* file licensed under ASL v2.0
* Copyright 2009 the original author or authors.
*/
public class StringCharArrayAccessor
{
//static volatile boolean enabled = !Boolean
// .getBoolean("oam.stringchararrayaccessor.disabled");
// In Google Application Engine this hack is not valid. We should
// set this one as default disabled.
static volatile boolean enabled = Boolean
.getBoolean("oam.stringchararrayaccessor.enabled");
static Field valueField;
static Field countField;
static Field offsetField;
static
{
if (enabled)
{
try
{
valueField = String.class.getDeclaredField("value");
valueField.setAccessible(true);
countField = String.class.getDeclaredField("count");
countField.setAccessible(true);
offsetField = String.class.getDeclaredField("offset");
offsetField.setAccessible(true);
}
catch (Exception e)
{
enabled = false;
System.err
.println("Unable to use direct char[] access of java.lang.String");
e.printStackTrace();
}
}
}
/**
* Writes a portion of a string to a target java.io.Writer with direct access to the char[] of the java.lang.String
*
* @param writer
* target java.io.Writer for output
*
* @param str
* A String
*
* @throws IOException
* If an I/O error occurs
*/
static public void writeStringAsCharArray(Writer writer, String str)
throws IOException
{
writeStringAsCharArray(writer, str, 0, str.length());
}
/**
* Writes a portion of a string to a target java.io.Writer with direct access to the char[] of the java.lang.String
*
* @param writer
* target java.io.Writer for output
*
* @param str
* A String
*
* @param off
* Offset from which to start writing characters
*
* @param len
* Number of characters to write
*
* @throws IOException
* If an I/O error occurs
*/
static public void writeStringAsCharArray(Writer writer, String str,
int off, int len) throws IOException
{
if (!enabled)
{
writeStringFallback(writer, str, off, len);
return;
}
char[] value;
int internalOffset;
try
{
value = (char[]) valueField.get(str);
internalOffset = offsetField.getInt(str);
}
catch (Exception e)
{
handleError(e);
writeStringFallback(writer, str, off, len);
return;
}
writer.write(value, internalOffset + off, len);
}
private static void writeStringFallback(Writer writer, String str, int off,
int len) throws IOException
{
writer.write(str, off, len);
}
static char[] getValue(String str)
{
if (!enabled)
{
return getValueFallback(str);
}
char[] value = null;
int internalOffset = 0;
try
{
value = (char[]) valueField.get(str);
internalOffset = offsetField.getInt(str);
}
catch (Exception e)
{
handleError(e);
}
if (value != null && internalOffset == 0)
{
return value;
}
return getValueFallback(str);
}
static char[] getValueFallback(String str)
{
return str.toCharArray();
}
/**
* creates a new java.lang.String by setting the char array directly to the String instance with reflection.
*
* @param charBuf
* char array to be used as java.lang.String content, don't modify it after passing it.
* @return new java.lang.String
*/
public static String createString(char[] charBuf)
{
if (!enabled)
{
return createStringFallback(charBuf);
}
String str = new String();
try
{
// try to prevent possible final field setting execution reordering in JIT
// (JSR-133/JMM, "9.1.1 Post-Construction Modification of Final Fields")
// it was a bit unclear for me if this could ever happen in a single thread
synchronized (str)
{
valueField.set(str, charBuf);
countField.set(str, charBuf.length);
}
synchronized (str)
{
// safety check, just to be sure that setting the final fields went ok
if (str.length() != charBuf.length)
{
throw new IllegalStateException(
"Fast java.lang.String construction failed.");
}
}
}
catch (Exception e)
{
handleError(e);
str = createStringFallback(charBuf);
}
return str;
}
private static String createStringFallback(char[] charBuf)
{
return new String(charBuf);
}
private static synchronized void handleError(Exception e)
{
enabled = false;
System.err
.println("Unable to use direct char[] access of java.lang.String. Disabling this method.");
valueField = null;
countField = null;
offsetField = null;
e.printStackTrace();
}
static public boolean isEnabled()
{
return enabled;
}
}