1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Licensed to the Apache Software Foundation (ASF) under one or more
   7  * contributor license agreements.  See the NOTICE file distributed with
   8  * this work for additional information regarding copyright ownership.
   9  * The ASF licenses this file to You under the Apache License, Version 2.0
  10  * (the "License"); you may not use this file except in compliance with
  11  * the License.  You may obtain a copy of the License at
  12  *
  13  *      http://www.apache.org/licenses/LICENSE-2.0
  14  *
  15  * Unless required by applicable law or agreed to in writing, software
  16  * distributed under the License is distributed on an "AS IS" BASIS,
  17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18  * See the License for the specific language governing permissions and
  19  * limitations under the License.
  20  */
  21 
  22 package com.sun.org.apache.xalan.internal.xsltc.compiler;
  23 
  24 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
  25 import com.sun.org.apache.bcel.internal.generic.InstructionList;
  26 import com.sun.org.apache.bcel.internal.generic.PUSH;
  27 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
  28 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
  29 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
  30 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
  31 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
  32 
  33 import com.sun.org.apache.xml.internal.serializer.ElemDesc;
  34 import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
  35 
  36 /**
  37  * @author Jacek Ambroziak
  38  * @author Santiago Pericas-Geertsen
  39  * @author Morten Jorgensen
  40  */
  41 final class LiteralAttribute extends Instruction {
  42 
  43     private final String  _name;         // Attribute name (incl. prefix)
  44     private final AttributeValue _value; // Attribute value
  45 
  46     /**
  47      * Creates a new literal attribute (but does not insert it into the AST).
  48      * @param name the attribute name (incl. prefix) as a String.
  49      * @param value the attribute value.
  50      * @param parser the XSLT parser (wraps XPath parser).
  51      */
  52     public LiteralAttribute(String name, String value, Parser parser,
  53         SyntaxTreeNode parent)
  54     {
  55         _name = name;
  56         setParent(parent);
  57         _value = AttributeValue.create(this, value, parser);
  58     }
  59 
  60     public void display(int indent) {
  61         indent(indent);
  62         Util.println("LiteralAttribute name=" + _name + " value=" + _value);
  63     }
  64 
  65     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
  66         _value.typeCheck(stable);
  67         typeCheckContents(stable);
  68         return Type.Void;
  69     }
  70 
  71     protected boolean contextDependent() {
  72         return _value.contextDependent();
  73     }
  74 
  75     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
  76         final ConstantPoolGen cpg = classGen.getConstantPool();
  77         final InstructionList il = methodGen.getInstructionList();
  78 
  79         // push handler
  80         il.append(methodGen.loadHandler());
  81         // push attribute name - namespace prefix set by parent node
  82         il.append(new PUSH(cpg, _name));
  83         // push attribute value
  84         _value.translate(classGen, methodGen);
  85 
  86         // Generate code that calls SerializationHandler.addUniqueAttribute()
  87         // if all attributes are unique.
  88         SyntaxTreeNode parent = getParent();
  89         if (parent instanceof LiteralElement
  90             && ((LiteralElement)parent).allAttributesUnique()) {
  91 
  92             int flags = 0;
  93             boolean isHTMLAttrEmpty = false;
  94             ElemDesc elemDesc = ((LiteralElement)parent).getElemDesc();
  95 
  96             // Set the HTML flags
  97             if (elemDesc != null) {
  98                 if (elemDesc.isAttrFlagSet(_name, ElemDesc.ATTREMPTY)) {
  99                     flags = flags | SerializationHandler.HTML_ATTREMPTY;
 100                     isHTMLAttrEmpty = true;
 101                 }
 102                 else if (elemDesc.isAttrFlagSet(_name, ElemDesc.ATTRURL)) {
 103                     flags = flags | SerializationHandler.HTML_ATTRURL;
 104                 }
 105             }
 106 
 107             if (_value instanceof SimpleAttributeValue) {
 108                 String attrValue = ((SimpleAttributeValue)_value).toString();
 109 
 110                 if (!hasBadChars(attrValue) && !isHTMLAttrEmpty) {
 111                     flags = flags | SerializationHandler.NO_BAD_CHARS;
 112                 }
 113             }
 114 
 115             il.append(new PUSH(cpg, flags));
 116             il.append(methodGen.uniqueAttribute());
 117         }
 118         else {
 119             // call attribute
 120             il.append(methodGen.attribute());
 121         }
 122     }
 123 
 124     /**
 125      * Return true if at least one character in the String is considered to
 126      * be a "bad" character. A bad character is one whose code is:
 127      * less than 32 (a space),
 128      * or greater than 126,
 129      * or it is one of '<', '>', '&' or '\"'.
 130      * This helps the serializer to decide whether the String needs to be escaped.
 131      */
 132     private boolean hasBadChars(String value) {
 133         char[] chars = value.toCharArray();
 134         int size = chars.length;
 135         for (int i = 0; i < size; i++) {
 136             char ch = chars[i];
 137             if (ch < 32 || 126 < ch || ch == '<' || ch == '>' || ch == '&' || ch == '\"')
 138                 return true;
 139         }
 140         return false;
 141     }
 142 
 143     /**
 144      * Return the name of the attribute
 145      */
 146     public String getName() {
 147         return _name;
 148     }
 149 
 150     /**
 151      * Return the value of the attribute
 152      */
 153     public AttributeValue getValue() {
 154         return _value;
 155     }
 156 
 157 }