jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Text.java
changeset 12457 c348e06f0e82
parent 6 7f561c08de6b
equal deleted inserted replaced
12324:1d7e6da6adc8 12457:c348e06f0e82
       
     1 /*
       
     2  * reserved comment block
       
     3  * DO NOT REMOVE OR ALTER!
       
     4  */
       
     5 /*
       
     6  * Copyright 2001-2004 The Apache Software Foundation.
       
     7  *
       
     8  * Licensed under the Apache License, Version 2.0 (the "License");
       
     9  * you may not use this file except in compliance with the License.
       
    10  * You may obtain a copy of the License at
       
    11  *
       
    12  *     http://www.apache.org/licenses/LICENSE-2.0
       
    13  *
       
    14  * Unless required by applicable law or agreed to in writing, software
       
    15  * distributed under the License is distributed on an "AS IS" BASIS,
       
    16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       
    17  * See the License for the specific language governing permissions and
       
    18  * limitations under the License.
       
    19  */
       
    20 /*
       
    21  * $Id: Text.java,v 1.2.4.1 2005/09/12 11:33:09 pvedula Exp $
       
    22  */
       
    23 
       
    24 package com.sun.org.apache.xalan.internal.xsltc.compiler;
       
    25 
       
    26 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
       
    27 import com.sun.org.apache.bcel.internal.generic.GETSTATIC;
       
    28 import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE;
       
    29 import com.sun.org.apache.bcel.internal.generic.InstructionList;
       
    30 import com.sun.org.apache.bcel.internal.generic.PUSH;
       
    31 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
       
    32 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
       
    33 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
       
    34 
       
    35 /**
       
    36  * @author Jacek Ambroziak
       
    37  * @author Santiago Pericas-Geertsen
       
    38  * @author Morten Jorgensen
       
    39  */
       
    40 final class Text extends Instruction {
       
    41 
       
    42     private String _text;
       
    43     private boolean _escaping = true;
       
    44     private boolean _ignore = false;
       
    45     private boolean _textElement = false;
       
    46 
       
    47     /**
       
    48      * Create a blank Text syntax tree node.
       
    49      */
       
    50     public Text() {
       
    51         _textElement = true;
       
    52     }
       
    53 
       
    54     /**
       
    55      * Create text syntax tree node.
       
    56      * @param text is the text to put in the node.
       
    57      */
       
    58     public Text(String text) {
       
    59         _text = text;
       
    60     }
       
    61 
       
    62     /**
       
    63      * Returns the text wrapped inside this node
       
    64      * @return The text wrapped inside this node
       
    65      */
       
    66     protected String getText() {
       
    67         return _text;
       
    68     }
       
    69 
       
    70     /**
       
    71      * Set the text for this node. Appends the given text to any already
       
    72      * existing text (using string concatenation, so use only when needed).
       
    73      * @param text is the text to wrap inside this node.
       
    74      */
       
    75     protected void setText(String text) {
       
    76         if (_text == null)
       
    77             _text = text;
       
    78         else
       
    79             _text = _text + text;
       
    80     }
       
    81 
       
    82     public void display(int indent) {
       
    83         indent(indent);
       
    84         Util.println("Text");
       
    85         indent(indent + IndentIncrement);
       
    86         Util.println(_text);
       
    87     }
       
    88 
       
    89     public void parseContents(Parser parser) {
       
    90         final String str = getAttribute("disable-output-escaping");
       
    91         if ((str != null) && (str.equals("yes"))) _escaping = false;
       
    92 
       
    93         parseChildren(parser);
       
    94 
       
    95         if (_text == null) {
       
    96             if (_textElement) {
       
    97                 _text = EMPTYSTRING;
       
    98             }
       
    99             else {
       
   100                 _ignore = true;
       
   101             }
       
   102         }
       
   103         else if (_textElement) {
       
   104             if (_text.length() == 0) _ignore = true;
       
   105         }
       
   106         else if (getParent() instanceof LiteralElement) {
       
   107             LiteralElement element = (LiteralElement)getParent();
       
   108             String space = element.getAttribute("xml:space");
       
   109             if ((space == null) || (!space.equals("preserve")))
       
   110         {
       
   111             int i;
       
   112             final int textLength = _text.length();
       
   113             for (i = 0; i < textLength; i++) {
       
   114                 char c = _text.charAt(i);
       
   115                 if (!isWhitespace(c))
       
   116                     break;
       
   117             }
       
   118             if (i == textLength)
       
   119                 _ignore = true;
       
   120         }
       
   121         }
       
   122         else {
       
   123         int i;
       
   124         final int textLength = _text.length();
       
   125         for (i = 0; i < textLength; i++)
       
   126         {
       
   127             char c = _text.charAt(i);
       
   128             if (!isWhitespace(c))
       
   129                 break;
       
   130         }
       
   131         if (i == textLength)
       
   132             _ignore = true;
       
   133         }
       
   134     }
       
   135 
       
   136     public void ignore() {
       
   137         _ignore = true;
       
   138     }
       
   139 
       
   140     public boolean isIgnore() {
       
   141         return _ignore;
       
   142     }
       
   143 
       
   144     public boolean isTextElement() {
       
   145         return _textElement;
       
   146     }
       
   147 
       
   148     protected boolean contextDependent() {
       
   149         return false;
       
   150     }
       
   151 
       
   152     private static boolean isWhitespace(char c)
       
   153     {
       
   154         return (c == 0x20 || c == 0x09 || c == 0x0A || c == 0x0D);
       
   155     }
       
   156 
       
   157     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
       
   158         final ConstantPoolGen cpg = classGen.getConstantPool();
       
   159         final InstructionList il = methodGen.getInstructionList();
       
   160 
       
   161         if (!_ignore) {
       
   162             // Turn off character escaping if so is wanted.
       
   163             final int esc = cpg.addInterfaceMethodref(OUTPUT_HANDLER,
       
   164                                                       "setEscaping", "(Z)Z");
       
   165             if (!_escaping) {
       
   166                 il.append(methodGen.loadHandler());
       
   167                 il.append(new PUSH(cpg, false));
       
   168                 il.append(new INVOKEINTERFACE(esc, 2));
       
   169             }
       
   170 
       
   171             il.append(methodGen.loadHandler());
       
   172 
       
   173             // Call characters(String) or characters(char[],int,int), as
       
   174             // appropriate.
       
   175             if (!canLoadAsArrayOffsetLength()) {
       
   176                 final int characters = cpg.addInterfaceMethodref(OUTPUT_HANDLER,
       
   177                                                            "characters",
       
   178                                                            "("+STRING_SIG+")V");
       
   179                 il.append(new PUSH(cpg, _text));
       
   180                 il.append(new INVOKEINTERFACE(characters, 2));
       
   181             } else {
       
   182                 final int characters = cpg.addInterfaceMethodref(OUTPUT_HANDLER,
       
   183                                                                  "characters",
       
   184                                                                  "([CII)V");
       
   185                 loadAsArrayOffsetLength(classGen, methodGen);
       
   186                 il.append(new INVOKEINTERFACE(characters, 4));
       
   187             }
       
   188 
       
   189             // Restore character escaping setting to whatever it was.
       
   190             // Note: setEscaping(bool) returns the original (old) value
       
   191             if (!_escaping) {
       
   192                 il.append(methodGen.loadHandler());
       
   193                 il.append(SWAP);
       
   194                 il.append(new INVOKEINTERFACE(esc, 2));
       
   195                 il.append(POP);
       
   196             }
       
   197         }
       
   198         translateContents(classGen, methodGen);
       
   199     }
       
   200 
       
   201     /**
       
   202      * Check whether this Text node can be stored in a char[] in the translet.
       
   203      * Calling this is precondition to calling loadAsArrayOffsetLength.
       
   204      * @see #loadAsArrayOffsetLength(ClassGenerator,MethodGenerator)
       
   205      * @return true if this Text node can be
       
   206      */
       
   207     public boolean canLoadAsArrayOffsetLength() {
       
   208         // Magic number!  21845*3 == 65535.  BCEL uses a DataOutputStream to
       
   209         // serialize class files.  The Java run-time places a limit on the size
       
   210         // of String data written using a DataOutputStream - it cannot require
       
   211         // more than 64KB when represented as UTF-8.  The number of bytes
       
   212         // required to represent a Java string as UTF-8 cannot be greater
       
   213         // than three times the number of char's in the string, hence the
       
   214         // check for 21845.
       
   215 
       
   216         return (_text.length() <= 21845);
       
   217     }
       
   218 
       
   219     /**
       
   220      * Generates code that loads the array that will contain the character
       
   221      * data represented by this Text node, followed by the offset of the
       
   222      * data from the start of the array, and then the length of the data.
       
   223      *
       
   224      * The pre-condition to calling this method is that
       
   225      * canLoadAsArrayOffsetLength() returns true.
       
   226      * @see #canLoadArrayOffsetLength()
       
   227      */
       
   228     public void loadAsArrayOffsetLength(ClassGenerator classGen,
       
   229                                         MethodGenerator methodGen) {
       
   230         final ConstantPoolGen cpg = classGen.getConstantPool();
       
   231         final InstructionList il = methodGen.getInstructionList();
       
   232         final XSLTC xsltc = classGen.getParser().getXSLTC();
       
   233 
       
   234         // The XSLTC object keeps track of character data
       
   235         // that is to be stored in char arrays.
       
   236         final int offset = xsltc.addCharacterData(_text);
       
   237         final int length = _text.length();
       
   238         String charDataFieldName =
       
   239             STATIC_CHAR_DATA_FIELD + (xsltc.getCharacterDataCount()-1);
       
   240 
       
   241         il.append(new GETSTATIC(cpg.addFieldref(xsltc.getClassName(),
       
   242                                        charDataFieldName,
       
   243                                        STATIC_CHAR_DATA_FIELD_SIG)));
       
   244         il.append(new PUSH(cpg, offset));
       
   245         il.append(new PUSH(cpg, _text.length()));
       
   246     }
       
   247 }