Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » jasper » compiler » [javadoc | source]
    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.jasper.compiler;
   19   
   20   import java.io.CharArrayWriter;
   21   import java.io.IOException;
   22   import java.io.InputStream;
   23   import java.io.InputStreamReader;
   24   import java.io.UnsupportedEncodingException;
   25   import java.util.Vector;
   26   import java.util.jar.JarFile;
   27   import java.util.zip.ZipEntry;
   28   
   29   import javax.el.FunctionMapper;
   30   import javax.servlet.jsp.el.ExpressionEvaluator;
   31   
   32   
   33   import org.apache.el.ExpressionFactoryImpl;
   34   import org.apache.jasper.Constants;
   35   import org.apache.jasper.JasperException;
   36   import org.apache.jasper.JspCompilationContext;
   37   import org.apache.jasper.el.ExpressionEvaluatorImpl;
   38   import org.xml.sax.Attributes;
   39   
   40   /** 
   41    * This class has all the utility method(s).
   42    * Ideally should move all the bean containers here.
   43    *
   44    * @author Mandar Raje.
   45    * @author Rajiv Mordani.
   46    * @author Danno Ferrin
   47    * @author Pierre Delisle
   48    * @author Shawn Bayern
   49    * @author Mark Roth
   50    */
   51   public class JspUtil {
   52   
   53       private static final String WEB_INF_TAGS = "/WEB-INF/tags/";
   54       private static final String META_INF_TAGS = "/META-INF/tags/";
   55   
   56       // Delimiters for request-time expressions (JSP and XML syntax)
   57       private static final String OPEN_EXPR  = "<%=";
   58       private static final String CLOSE_EXPR = "%>";
   59       private static final String OPEN_EXPR_XML  = "%=";
   60       private static final String CLOSE_EXPR_XML = "%";
   61   
   62       private static int tempSequenceNumber = 0;
   63       
   64       //private static ExpressionEvaluatorImpl expressionEvaluator
   65       //= new ExpressionEvaluatorImpl();
   66       
   67       //tc6
   68       private final static ExpressionEvaluator expressionEvaluator =
   69           new ExpressionEvaluatorImpl(new ExpressionFactoryImpl());
   70   
   71       private static final String javaKeywords[] = {
   72           "abstract", "assert", "boolean", "break", "byte", "case",
   73           "catch", "char", "class", "const", "continue",
   74           "default", "do", "double", "else", "enum", "extends",
   75           "final", "finally", "float", "for", "goto",
   76           "if", "implements", "import", "instanceof", "int",
   77           "interface", "long", "native", "new", "package",
   78           "private", "protected", "public", "return", "short",
   79           "static", "strictfp", "super", "switch", "synchronized",
   80           "this", "throws", "transient", "try", "void",
   81           "volatile", "while" };
   82   
   83       public static final int CHUNKSIZE = 1024;
   84           
   85       public static char[] removeQuotes(char []chars) {
   86           CharArrayWriter caw = new CharArrayWriter();
   87           for (int i = 0; i < chars.length; i++) {
   88               if (chars[i] == '%' && chars[i+1] == '\\' &&
   89                   chars[i+2] == '>') {
   90                   caw.write('%');
   91                   caw.write('>');
   92                   i = i + 2;
   93               } else {
   94                   caw.write(chars[i]);
   95               }
   96           }
   97           return caw.toCharArray();
   98       }
   99   
  100       public static char[] escapeQuotes (char []chars) {
  101           // Prescan to convert %\> to %>
  102           String s = new String(chars);
  103           while (true) {
  104               int n = s.indexOf("%\\>");
  105               if (n < 0)
  106                   break;
  107               StringBuffer sb = new StringBuffer(s.substring(0, n));
  108               sb.append("%>");
  109               sb.append(s.substring(n + 3));
  110               s = sb.toString();
  111           }
  112           chars = s.toCharArray();
  113           return (chars);
  114   
  115   
  116           // Escape all backslashes not inside a Java string literal
  117           /*
  118           CharArrayWriter caw = new CharArrayWriter();
  119           boolean inJavaString = false;
  120           for (int i = 0; i < chars.length; i++) {
  121               if (chars[i] == '"') inJavaString = !inJavaString;
  122               // escape out the escape character
  123               if (!inJavaString && (chars[i] == '\\')) caw.write('\\');
  124               caw.write(chars[i]);
  125           }
  126           return caw.toCharArray();
  127           */
  128       }
  129   
  130       /**
  131        * Checks if the token is a runtime expression.
  132        * In standard JSP syntax, a runtime expression starts with '<%' and
  133        * ends with '%>'. When the JSP document is in XML syntax, a runtime
  134        * expression starts with '%=' and ends with '%'.
  135        *
  136        * @param token The token to be checked
  137        * return whether the token is a runtime expression or not.
  138        */
  139       public static boolean isExpression(String token, boolean isXml) {
  140       String openExpr;
  141       String closeExpr;
  142       if (isXml) {
  143           openExpr = OPEN_EXPR_XML;
  144           closeExpr = CLOSE_EXPR_XML;
  145       } else {
  146           openExpr = OPEN_EXPR;
  147           closeExpr = CLOSE_EXPR;
  148       }
  149       if (token.startsWith(openExpr) && token.endsWith(closeExpr)) {
  150           return true;
  151       } else {
  152           return false;
  153       }
  154       }
  155   
  156       /**
  157        * @return the "expression" part of a runtime expression, 
  158        * taking the delimiters out.
  159        */
  160       public static String getExpr (String expression, boolean isXml) {
  161       String returnString;
  162       String openExpr;
  163       String closeExpr;
  164       if (isXml) {
  165           openExpr = OPEN_EXPR_XML;
  166           closeExpr = CLOSE_EXPR_XML;
  167       } else {
  168           openExpr = OPEN_EXPR;
  169           closeExpr = CLOSE_EXPR;
  170       }
  171       int length = expression.length();
  172       if (expression.startsWith(openExpr) && 
  173                   expression.endsWith(closeExpr)) {
  174           returnString = expression.substring(
  175                                  openExpr.length(), length - closeExpr.length());
  176       } else {
  177           returnString = "";
  178       }
  179       return returnString;
  180       }
  181   
  182       /**
  183        * Takes a potential expression and converts it into XML form
  184        */
  185       public static String getExprInXml(String expression) {
  186           String returnString;
  187           int length = expression.length();
  188   
  189           if (expression.startsWith(OPEN_EXPR) 
  190                   && expression.endsWith(CLOSE_EXPR)) {
  191               returnString = expression.substring (1, length - 1);
  192           } else {
  193               returnString = expression;
  194           }
  195   
  196           return escapeXml(returnString.replace(Constants.ESC, '$'));
  197       }
  198   
  199       /**
  200        * Checks to see if the given scope is valid.
  201        *
  202        * @param scope The scope to be checked
  203        * @param n The Node containing the 'scope' attribute whose value is to be
  204        * checked
  205        * @param err error dispatcher
  206        *
  207        * @throws JasperException if scope is not null and different from
  208        * &quot;page&quot;, &quot;request&quot;, &quot;session&quot;, and
  209        * &quot;application&quot;
  210        */
  211       public static void checkScope(String scope, Node n, ErrorDispatcher err)
  212               throws JasperException {
  213       if (scope != null && !scope.equals("page") && !scope.equals("request")
  214           && !scope.equals("session") && !scope.equals("application")) {
  215           err.jspError(n, "jsp.error.invalid.scope", scope);
  216       }
  217       }
  218   
  219       /**
  220        * Checks if all mandatory attributes are present and if all attributes
  221        * present have valid names.  Checks attributes specified as XML-style
  222        * attributes as well as attributes specified using the jsp:attribute
  223        * standard action. 
  224        */
  225       public static void checkAttributes(String typeOfTag,
  226                          Node n,
  227                          ValidAttribute[] validAttributes,
  228                          ErrorDispatcher err)
  229                   throws JasperException {
  230           Attributes attrs = n.getAttributes();
  231           Mark start = n.getStart();
  232       boolean valid = true;
  233   
  234           // AttributesImpl.removeAttribute is broken, so we do this...
  235           int tempLength = (attrs == null) ? 0 : attrs.getLength();
  236       Vector temp = new Vector(tempLength, 1);
  237           for (int i = 0; i < tempLength; i++) {
  238               String qName = attrs.getQName(i);
  239               if ((!qName.equals("xmlns")) && (!qName.startsWith("xmlns:")))
  240                   temp.addElement(qName);
  241           }
  242   
  243           // Add names of attributes specified using jsp:attribute
  244           Node.Nodes tagBody = n.getBody();
  245           if( tagBody != null ) {
  246               int numSubElements = tagBody.size();
  247               for( int i = 0; i < numSubElements; i++ ) {
  248                   Node node = tagBody.getNode( i );
  249                   if( node instanceof Node.NamedAttribute ) {
  250                       String attrName = node.getAttributeValue( "name" );
  251                       temp.addElement( attrName );
  252               // Check if this value appear in the attribute of the node
  253               if (n.getAttributeValue(attrName) != null) {
  254               err.jspError(n, "jsp.error.duplicate.name.jspattribute",
  255                       attrName);
  256               }
  257                   }
  258                   else {
  259                       // Nothing can come before jsp:attribute, and only
  260                       // jsp:body can come after it.
  261                       break;
  262                   }
  263               }
  264           }
  265   
  266       /*
  267        * First check to see if all the mandatory attributes are present.
  268        * If so only then proceed to see if the other attributes are valid
  269        * for the particular tag.
  270        */
  271       String missingAttribute = null;
  272   
  273       for (int i = 0; i < validAttributes.length; i++) {
  274           int attrPos;    
  275           if (validAttributes[i].mandatory) {
  276                   attrPos = temp.indexOf(validAttributes[i].name);
  277           if (attrPos != -1) {
  278               temp.remove(attrPos);
  279               valid = true;
  280           } else {
  281               valid = false;
  282               missingAttribute = validAttributes[i].name;
  283               break;
  284           }
  285           }
  286       }
  287   
  288       // If mandatory attribute is missing then the exception is thrown
  289       if (!valid)
  290           err.jspError(start, "jsp.error.mandatory.attribute", typeOfTag,
  291                missingAttribute);
  292   
  293       // Check to see if there are any more attributes for the specified tag.
  294           int attrLeftLength = temp.size();
  295       if (attrLeftLength == 0)
  296           return;
  297   
  298       // Now check to see if the rest of the attributes are valid too.
  299       String attribute = null;
  300   
  301       for (int j = 0; j < attrLeftLength; j++) {
  302           valid = false;
  303           attribute = (String) temp.elementAt(j);
  304           for (int i = 0; i < validAttributes.length; i++) {
  305           if (attribute.equals(validAttributes[i].name)) {
  306               valid = true;
  307               break;
  308           }
  309           }
  310           if (!valid)
  311           err.jspError(start, "jsp.error.invalid.attribute", typeOfTag,
  312                    attribute);
  313       }
  314       // XXX *could* move EL-syntax validation here... (sb)
  315       }
  316       
  317       public static String escapeQueryString(String unescString) {
  318       if ( unescString == null )
  319           return null;
  320       
  321       String escString    = "";
  322       String shellSpChars = "\\\"";
  323       
  324       for(int index=0; index<unescString.length(); index++) {
  325           char nextChar = unescString.charAt(index);
  326           
  327           if( shellSpChars.indexOf(nextChar) != -1 )
  328           escString += "\\";
  329           
  330           escString += nextChar;
  331       }
  332       return escString;
  333       }
  334    
  335       /**
  336        *  Escape the 5 entities defined by XML.
  337        */
  338       public static String escapeXml(String s) {
  339           if (s == null) return null;
  340           StringBuffer sb = new StringBuffer();
  341           for(int i=0; i<s.length(); i++) {
  342               char c = s.charAt(i);
  343               if (c == '<') {
  344                   sb.append("&lt;");
  345               } else if (c == '>') {
  346                   sb.append("&gt;");
  347               } else if (c == '\'') {
  348                   sb.append("&apos;");
  349               } else if (c == '&') {
  350                   sb.append("&amp;");
  351               } else if (c == '"') {
  352                   sb.append("&quot;");
  353               } else {
  354                   sb.append(c);
  355               }
  356           }
  357           return sb.toString();
  358       }
  359   
  360       /**
  361        * Replaces any occurrences of the character <tt>replace</tt> with the
  362        * string <tt>with</tt>.
  363        */
  364       public static String replace(String name, char replace, String with) {
  365       StringBuffer buf = new StringBuffer();
  366       int begin = 0;
  367       int end;
  368       int last = name.length();
  369   
  370       while (true) {
  371           end = name.indexOf(replace, begin);
  372           if (end < 0) {
  373           end = last;
  374           }
  375           buf.append(name.substring(begin, end));
  376           if (end == last) {
  377           break;
  378           }
  379           buf.append(with);
  380           begin = end + 1;
  381       }
  382       
  383       return buf.toString();
  384       }
  385   
  386       public static class ValidAttribute {
  387       String name;
  388       boolean mandatory;
  389       boolean rtexprvalue;    // not used now
  390   
  391       public ValidAttribute (String name, boolean mandatory,
  392               boolean rtexprvalue )
  393           {
  394           this.name = name;
  395           this.mandatory = mandatory;
  396               this.rtexprvalue = rtexprvalue;
  397           }
  398   
  399          public ValidAttribute (String name, boolean mandatory) {
  400               this( name, mandatory, false );
  401       }
  402   
  403       public ValidAttribute (String name) {
  404           this (name, false);
  405       }
  406       }
  407       
  408       /**
  409        * Convert a String value to 'boolean'.
  410        * Besides the standard conversions done by
  411        * Boolean.valueOf(s).booleanValue(), the value "yes"
  412        * (ignore case) is also converted to 'true'. 
  413        * If 's' is null, then 'false' is returned.
  414        *
  415        * @param s the string to be converted
  416        * @return the boolean value associated with the string s
  417        */
  418       public static boolean booleanValue(String s) {
  419       boolean b = false;
  420       if (s != null) {
  421           if (s.equalsIgnoreCase("yes")) {
  422           b = true;
  423           } else {
  424           b = Boolean.valueOf(s).booleanValue();
  425           }
  426       }
  427       return b;
  428       }
  429   
  430       /**
  431        * Returns the <tt>Class</tt> object associated with the class or
  432        * interface with the given string name.
  433        *
  434        * <p> The <tt>Class</tt> object is determined by passing the given string
  435        * name to the <tt>Class.forName()</tt> method, unless the given string
  436        * name represents a primitive type, in which case it is converted to a
  437        * <tt>Class</tt> object by appending ".class" to it (e.g., "int.class").
  438        */
  439       public static Class toClass(String type, ClassLoader loader)
  440           throws ClassNotFoundException {
  441   
  442       Class c = null;
  443       int i0 = type.indexOf('[');
  444       int dims = 0;
  445       if (i0 > 0) {
  446           // This is an array.  Count the dimensions
  447           for (int i = 0; i < type.length(); i++) {
  448           if (type.charAt(i) == '[')
  449               dims++;
  450           }
  451           type = type.substring(0, i0);
  452       }
  453   
  454       if ("boolean".equals(type))
  455           c = boolean.class;
  456       else if ("char".equals(type))
  457           c = char.class;
  458       else if ("byte".equals(type))
  459           c =  byte.class;
  460       else if ("short".equals(type))
  461           c = short.class;
  462       else if ("int".equals(type))
  463           c = int.class;
  464       else if ("long".equals(type))
  465           c = long.class;
  466       else if ("float".equals(type))
  467           c = float.class;
  468       else if ("double".equals(type))
  469           c = double.class;
  470       else if (type.indexOf('[') < 0)
  471           c = loader.loadClass(type);
  472   
  473       if (dims == 0)
  474           return c;
  475   
  476       if (dims == 1)
  477           return java.lang.reflect.Array.newInstance(c, 1).getClass();
  478   
  479       // Array of more than i dimension
  480       return java.lang.reflect.Array.newInstance(c, new int[dims]).getClass();
  481       }
  482       
  483       /**
  484        * Produces a String representing a call to the EL interpreter.
  485        * @param expression a String containing zero or more "${}" expressions
  486        * @param expectedType the expected type of the interpreted result
  487        * @param fnmapvar Variable pointing to a function map.
  488        * @param XmlEscape True if the result should do XML escaping
  489        * @return a String representing a call to the EL interpreter.
  490        */
  491       public static String interpreterCall(boolean isTagFile,
  492                        String expression,
  493                                            Class expectedType,
  494                                            String fnmapvar,
  495                                            boolean XmlEscape ) 
  496       {
  497           /*
  498            * Determine which context object to use.
  499            */
  500       String jspCtxt = null;
  501       if (isTagFile)
  502           jspCtxt = "this.getJspContext()";
  503       else
  504           jspCtxt = "_jspx_page_context";
  505   
  506       /*
  507            * Determine whether to use the expected type's textual name
  508        * or, if it's a primitive, the name of its correspondent boxed
  509        * type.
  510            */
  511       String targetType = expectedType.getName();
  512       String primitiveConverterMethod = null;
  513       if (expectedType.isPrimitive()) {
  514           if (expectedType.equals(Boolean.TYPE)) {
  515           targetType = Boolean.class.getName();
  516           primitiveConverterMethod = "booleanValue";
  517           } else if (expectedType.equals(Byte.TYPE)) {
  518           targetType = Byte.class.getName();
  519           primitiveConverterMethod = "byteValue";
  520           } else if (expectedType.equals(Character.TYPE)) {
  521           targetType = Character.class.getName();
  522           primitiveConverterMethod = "charValue";
  523           } else if (expectedType.equals(Short.TYPE)) {
  524           targetType = Short.class.getName();
  525           primitiveConverterMethod = "shortValue";
  526           } else if (expectedType.equals(Integer.TYPE)) {
  527           targetType = Integer.class.getName();
  528           primitiveConverterMethod = "intValue";
  529           } else if (expectedType.equals(Long.TYPE)) {
  530           targetType = Long.class.getName();
  531           primitiveConverterMethod = "longValue";
  532           } else if (expectedType.equals(Float.TYPE)) {
  533           targetType = Float.class.getName();
  534           primitiveConverterMethod = "floatValue";
  535           } else if (expectedType.equals(Double.TYPE)) { 
  536           targetType = Double.class.getName();
  537           primitiveConverterMethod = "doubleValue";
  538           }
  539       }
  540    
  541       if (primitiveConverterMethod != null) {
  542           XmlEscape = false;
  543       }
  544   
  545       /*
  546            * Build up the base call to the interpreter.
  547            */
  548           // XXX - We use a proprietary call to the interpreter for now
  549           // as the current standard machinery is inefficient and requires
  550           // lots of wrappers and adapters.  This should all clear up once
  551           // the EL interpreter moves out of JSTL and into its own project.
  552           // In the future, this should be replaced by code that calls
  553           // ExpressionEvaluator.parseExpression() and then cache the resulting
  554           // expression objects.  The interpreterCall would simply select
  555           // one of the pre-cached expressions and evaluate it.
  556           // Note that PageContextImpl implements VariableResolver and
  557           // the generated Servlet/SimpleTag implements FunctionMapper, so
  558           // that machinery is already in place (mroth).
  559       targetType = toJavaSourceType(targetType);
  560       StringBuffer call = new StringBuffer(
  561                "(" + targetType + ") "
  562                  + "org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate"
  563                  + "(" + Generator.quote(expression) + ", "
  564                  +       targetType + ".class, "
  565              +       "(PageContext)" + jspCtxt 
  566                  +       ", " + fnmapvar
  567              + ", " + XmlEscape
  568                  + ")");
  569    
  570       /*
  571            * Add the primitive converter method if we need to.
  572            */
  573       if (primitiveConverterMethod != null) {
  574           call.insert(0, "(");
  575           call.append(")." + primitiveConverterMethod + "()");
  576       }
  577    
  578       return call.toString();
  579       }
  580   
  581       /**
  582        * Validates the syntax of all ${} expressions within the given string.
  583        * @param where the approximate location of the expressions in the JSP page
  584        * @param expressions a string containing zero or more "${}" expressions
  585        * @param err an error dispatcher to use
  586        * @deprecated now delegated to the org.apache.el Package
  587        */
  588       public static void validateExpressions(Mark where,
  589                                              String expressions,
  590                                              Class expectedType,
  591                                              FunctionMapper functionMapper,
  592                                              ErrorDispatcher err)
  593               throws JasperException {
  594   
  595   //        try {
  596   //            
  597   //            JspUtil.expressionEvaluator.parseExpression( expressions, 
  598   //                expectedType, functionMapper );
  599   //        }
  600   //        catch( ELParseException e ) {
  601   //            err.jspError(where, "jsp.error.invalid.expression", expressions,
  602   //                e.toString() );
  603   //        }
  604   //        catch( ELException e ) {
  605   //            err.jspError(where, "jsp.error.invalid.expression", expressions,
  606   //                e.toString() );
  607   //        }
  608       }
  609   
  610       /**
  611        * Resets the temporary variable name.
  612        * (not thread-safe)
  613        */
  614       public static void resetTemporaryVariableName() {
  615           tempSequenceNumber = 0;
  616       }
  617   
  618       /**
  619        * Generates a new temporary variable name.
  620        * (not thread-safe)
  621        */
  622       public static String nextTemporaryVariableName() {
  623           return Constants.TEMP_VARIABLE_NAME_PREFIX + (tempSequenceNumber++);
  624       }
  625   
  626       public static String coerceToPrimitiveBoolean(String s,
  627                             boolean isNamedAttribute) {
  628       if (isNamedAttribute) {
  629           return "org.apache.jasper.runtime.JspRuntimeLibrary.coerceToBoolean(" + s + ")";
  630       } else {
  631           if (s == null || s.length() == 0)
  632           return "false";
  633           else
  634           return Boolean.valueOf(s).toString();
  635       }
  636       }
  637   
  638       public static String coerceToBoolean(String s, boolean isNamedAttribute) {
  639       if (isNamedAttribute) {
  640           return "(Boolean) org.apache.jasper.runtime.JspRuntimeLibrary.coerce(" + s + ", Boolean.class)";
  641       } else {
  642           if (s == null || s.length() == 0) {
  643           return "new Boolean(false)";
  644           } else {
  645           // Detect format error at translation time
  646           return "new Boolean(" + Boolean.valueOf(s).toString() + ")";
  647           }
  648       }
  649       }
  650   
  651       public static String coerceToPrimitiveByte(String s,
  652                              boolean isNamedAttribute) {
  653       if (isNamedAttribute) {
  654           return "org.apache.jasper.runtime.JspRuntimeLibrary.coerceToByte(" + s + ")";
  655       } else {
  656           if (s == null || s.length() == 0)
  657           return "(byte) 0";
  658           else
  659           return "((byte)" + Byte.valueOf(s).toString() + ")";
  660       }
  661       }
  662   
  663       public static String coerceToByte(String s, boolean isNamedAttribute) {
  664       if (isNamedAttribute) {
  665           return "(Byte) org.apache.jasper.runtime.JspRuntimeLibrary.coerce(" + s + ", Byte.class)";
  666       } else {
  667           if (s == null || s.length() == 0) {
  668           return "new Byte((byte) 0)";
  669           } else {
  670           // Detect format error at translation time
  671           return "new Byte((byte)" + Byte.valueOf(s).toString() + ")";
  672           }
  673       }
  674       }
  675   
  676       public static String coerceToChar(String s, boolean isNamedAttribute) {
  677       if (isNamedAttribute) {
  678           return "org.apache.jasper.runtime.JspRuntimeLibrary.coerceToChar(" + s + ")";
  679       } else {
  680           if (s == null || s.length() == 0) {
  681           return "(char) 0";
  682           } else {
  683           char ch = s.charAt(0);
  684           // this trick avoids escaping issues
  685           return "((char) " + (int) ch + ")";
  686           }
  687       }
  688       }
  689   
  690       public static String coerceToCharacter(String s, boolean isNamedAttribute) {
  691       if (isNamedAttribute) {
  692           return "(Character) org.apache.jasper.runtime.JspRuntimeLibrary.coerce(" + s + ", Character.class)";
  693       } else {
  694           if (s == null || s.length() == 0) {
  695           return "new Character((char) 0)";
  696           } else {
  697           char ch = s.charAt(0);
  698           // this trick avoids escaping issues
  699           return "new Character((char) " + (int) ch + ")";
  700           }
  701       }
  702       }
  703   
  704       public static String coerceToPrimitiveDouble(String s,
  705                            boolean isNamedAttribute) {
  706       if (isNamedAttribute) {
  707           return "org.apache.jasper.runtime.JspRuntimeLibrary.coerceToDouble(" + s + ")";
  708       } else {
  709           if (s == null || s.length() == 0)
  710           return "(double) 0";
  711           else
  712           return Double.valueOf(s).toString();
  713       }
  714       }
  715   
  716       public static String coerceToDouble(String s, boolean isNamedAttribute) {
  717       if (isNamedAttribute) {
  718           return "(Double) org.apache.jasper.runtime.JspRuntimeLibrary.coerce(" + s + ", Double.class)";
  719       } else {
  720           if (s == null || s.length() == 0) {
  721           return "new Double(0)";
  722           } else {
  723           // Detect format error at translation time
  724           return "new Double(" + Double.valueOf(s).toString() + ")";
  725           }
  726       }
  727       }
  728   
  729       public static String coerceToPrimitiveFloat(String s,
  730                           boolean isNamedAttribute) {
  731       if (isNamedAttribute) {
  732           return "org.apache.jasper.runtime.JspRuntimeLibrary.coerceToFloat(" + s + ")";
  733       } else {
  734           if (s == null || s.length() == 0)
  735           return "(float) 0";
  736           else
  737           return Float.valueOf(s).toString() + "f";
  738       }
  739       }
  740   
  741       public static String coerceToFloat(String s, boolean isNamedAttribute) {
  742       if (isNamedAttribute) {
  743           return "(Float) org.apache.jasper.runtime.JspRuntimeLibrary.coerce(" + s + ", Float.class)";
  744       } else {
  745           if (s == null || s.length() == 0) {
  746           return "new Float(0)";
  747           } else {
  748           // Detect format error at translation time
  749           return "new Float(" + Float.valueOf(s).toString() + "f)";
  750           }
  751       }
  752       }
  753   
  754       public static String coerceToInt(String s, boolean isNamedAttribute) {
  755       if (isNamedAttribute) {
  756           return "org.apache.jasper.runtime.JspRuntimeLibrary.coerceToInt(" + s + ")";
  757       } else {
  758           if (s == null || s.length() == 0)
  759           return "0";
  760           else
  761           return Integer.valueOf(s).toString();
  762       }
  763       }
  764   
  765       public static String coerceToInteger(String s, boolean isNamedAttribute) {
  766       if (isNamedAttribute) {
  767           return "(Integer) org.apache.jasper.runtime.JspRuntimeLibrary.coerce(" + s + ", Integer.class)";
  768       } else {
  769           if (s == null || s.length() == 0) {
  770           return "new Integer(0)";
  771           } else {
  772           // Detect format error at translation time
  773           return "new Integer(" + Integer.valueOf(s).toString() + ")";
  774           }
  775       }
  776       }
  777   
  778       public static String coerceToPrimitiveShort(String s,
  779                           boolean isNamedAttribute) {
  780       if (isNamedAttribute) {
  781           return "org.apache.jasper.runtime.JspRuntimeLibrary.coerceToShort(" + s + ")";
  782       } else {
  783           if (s == null || s.length() == 0)
  784           return "(short) 0";
  785           else
  786           return "((short) " + Short.valueOf(s).toString() + ")";
  787       }
  788       }
  789       
  790       public static String coerceToShort(String s, boolean isNamedAttribute) {
  791       if (isNamedAttribute) {
  792           return "(Short) org.apache.jasper.runtime.JspRuntimeLibrary.coerce(" + s + ", Short.class)";
  793       } else {
  794           if (s == null || s.length() == 0) {
  795           return "new Short((short) 0)";
  796           } else {
  797           // Detect format error at translation time
  798           return "new Short(\"" + Short.valueOf(s).toString() + "\")";
  799           }
  800       }
  801       }
  802       
  803       public static String coerceToPrimitiveLong(String s,
  804                              boolean isNamedAttribute) {
  805       if (isNamedAttribute) {
  806           return "org.apache.jasper.runtime.JspRuntimeLibrary.coerceToLong(" + s + ")";
  807       } else {
  808           if (s == null || s.length() == 0)
  809           return "(long) 0";
  810           else
  811           return Long.valueOf(s).toString() + "l";
  812       }
  813       }
  814   
  815       public static String coerceToLong(String s, boolean isNamedAttribute) {
  816       if (isNamedAttribute) {
  817           return "(Long) org.apache.jasper.runtime.JspRuntimeLibrary.coerce(" + s + ", Long.class)";
  818       } else {
  819           if (s == null || s.length() == 0) {
  820           return "new Long(0)";
  821           } else {
  822           // Detect format error at translation time
  823           return "new Long(" + Long.valueOf(s).toString() + "l)";
  824           }
  825       }
  826       }
  827   
  828       public static InputStream getInputStream(String fname, JarFile jarFile,
  829                            JspCompilationContext ctxt,
  830                            ErrorDispatcher err)
  831           throws JasperException, IOException {
  832   
  833           InputStream in = null;
  834   
  835       if (jarFile != null) {
  836           String jarEntryName = fname.substring(1, fname.length());
  837           ZipEntry jarEntry = jarFile.getEntry(jarEntryName);
  838           if (jarEntry == null) {
  839           err.jspError("jsp.error.file.not.found", fname);
  840           }
  841           in = jarFile.getInputStream(jarEntry);
  842       } else {
  843           in = ctxt.getResourceAsStream(fname);
  844       }
  845   
  846       if (in == null) {
  847           err.jspError("jsp.error.file.not.found", fname);
  848       }
  849   
  850       return in;
  851       }
  852   
  853       /**
  854        * Gets the fully-qualified class name of the tag handler corresponding to
  855        * the given tag file path.
  856        *
  857        * @param path Tag file path
  858        * @param err Error dispatcher
  859        *
  860        * @return Fully-qualified class name of the tag handler corresponding to 
  861        * the given tag file path
  862        */
  863       public static String getTagHandlerClassName(String path,
  864                           ErrorDispatcher err)
  865                   throws JasperException {
  866   
  867           String className = null;
  868           int begin = 0;
  869           int index;
  870           
  871           index = path.lastIndexOf(".tag");
  872           if (index == -1) {
  873               err.jspError("jsp.error.tagfile.badSuffix", path);
  874           }
  875   
  876           //It's tempting to remove the ".tag" suffix here, but we can't.
  877           //If we remove it, the fully-qualified class name of this tag
  878           //could conflict with the package name of other tags.
  879           //For instance, the tag file
  880           //    /WEB-INF/tags/foo.tag
  881           //would have fully-qualified class name
  882           //    org.apache.jsp.tag.web.foo
  883           //which would conflict with the package name of the tag file
  884           //    /WEB-INF/tags/foo/bar.tag
  885   
  886           index = path.indexOf(WEB_INF_TAGS);
  887           if (index != -1) {
  888               className = "org.apache.jsp.tag.web.";
  889               begin = index + WEB_INF_TAGS.length();
  890           } else {
  891           index = path.indexOf(META_INF_TAGS);
  892           if (index != -1) {
  893           className = "org.apache.jsp.tag.meta.";
  894           begin = index + META_INF_TAGS.length();
  895           } else {
  896           err.jspError("jsp.error.tagfile.illegalPath", path);
  897           }
  898       }
  899   
  900           className += makeJavaPackage(path.substring(begin));
  901     
  902          return className;
  903       }
  904   
  905       /**
  906        * Converts the given path to a Java package or fully-qualified class name
  907        *
  908        * @param path Path to convert
  909        *
  910        * @return Java package corresponding to the given path
  911        */
  912       public static final String makeJavaPackage(String path) {
  913           String classNameComponents[] = split(path,"/");
  914           StringBuffer legalClassNames = new StringBuffer();
  915           for (int i = 0; i < classNameComponents.length; i++) {
  916               legalClassNames.append(makeJavaIdentifier(classNameComponents[i]));
  917               if (i < classNameComponents.length - 1) {
  918                   legalClassNames.append('.');
  919               }
  920           }
  921           return legalClassNames.toString();
  922       }
  923   
  924       /**
  925        * Splits a string into it's components.
  926        * @param path String to split
  927        * @param pat Pattern to split at
  928        * @return the components of the path
  929        */
  930       private static final String [] split(String path, String pat) {
  931           Vector comps = new Vector();
  932           int pos = path.indexOf(pat);
  933           int start = 0;
  934           while( pos >= 0 ) {
  935               if(pos > start ) {
  936                   String comp = path.substring(start,pos);
  937                   comps.add(comp);
  938               }
  939               start = pos + pat.length();
  940               pos = path.indexOf(pat,start);
  941           }
  942           if( start < path.length()) {
  943               comps.add(path.substring(start));
  944           }
  945           String [] result = new String[comps.size()];
  946           for(int i=0; i < comps.size(); i++) {
  947               result[i] = (String)comps.elementAt(i);
  948           }
  949           return result;
  950       }
  951               
  952       /**
  953        * Converts the given identifier to a legal Java identifier
  954        *
  955        * @param identifier Identifier to convert
  956        *
  957        * @return Legal Java identifier corresponding to the given identifier
  958        */
  959       public static final String makeJavaIdentifier(String identifier) {
  960           StringBuffer modifiedIdentifier = 
  961               new StringBuffer(identifier.length());
  962           if (!Character.isJavaIdentifierStart(identifier.charAt(0))) {
  963               modifiedIdentifier.append('_');
  964           }
  965           for (int i = 0; i < identifier.length(); i++) {
  966               char ch = identifier.charAt(i);
  967               if (Character.isJavaIdentifierPart(ch) && ch != '_') {
  968                   modifiedIdentifier.append(ch);
  969               } else if (ch == '.') {
  970                   modifiedIdentifier.append('_');
  971               } else {
  972                   modifiedIdentifier.append(mangleChar(ch));
  973               }
  974           }
  975           if (isJavaKeyword(modifiedIdentifier.toString())) {
  976               modifiedIdentifier.append('_');
  977           }
  978           return modifiedIdentifier.toString();
  979       }
  980       
  981       /**
  982        * Mangle the specified character to create a legal Java class name.
  983        */
  984       public static final String mangleChar(char ch) {
  985           char[] result = new char[5];
  986           result[0] = '_';
  987           result[1] = Character.forDigit((ch >> 12) & 0xf, 16);
  988           result[2] = Character.forDigit((ch >> 8) & 0xf, 16);
  989           result[3] = Character.forDigit((ch >> 4) & 0xf, 16);
  990           result[4] = Character.forDigit(ch & 0xf, 16);
  991           return new String(result);
  992       }
  993   
  994       /**
  995        * Test whether the argument is a Java keyword
  996        */
  997       public static boolean isJavaKeyword(String key) {
  998           int i = 0;
  999           int j = javaKeywords.length;
 1000           while (i < j) {
 1001               int k = (i+j)/2;
 1002               int result = javaKeywords[k].compareTo(key);
 1003               if (result == 0) {
 1004                   return true;
 1005               }
 1006               if (result < 0) {
 1007                   i = k+1;
 1008               } else {
 1009                   j = k;
 1010               }
 1011           }
 1012           return false;
 1013       }
 1014   
 1015       /**
 1016        * Converts the given Xml name to a legal Java identifier.  This is
 1017        * slightly more efficient than makeJavaIdentifier in that we only need
 1018        * to worry about '.', '-', and ':' in the string.  We also assume that
 1019        * the resultant string is further concatenated with some prefix string
 1020        * so that we don't have to worry about it being a Java key word.
 1021        *
 1022        * @param name Identifier to convert
 1023        *
 1024        * @return Legal Java identifier corresponding to the given identifier
 1025        */
 1026       public static final String makeXmlJavaIdentifier(String name) {
 1027           if (name.indexOf('-') >= 0)
 1028               name = replace(name, '-', "$1");
 1029           if (name.indexOf('.') >= 0)
 1030               name = replace(name, '.', "$2");
 1031           if (name.indexOf(':') >= 0)
 1032               name = replace(name, ':', "$3");
 1033           return name;
 1034       }
 1035   
 1036       static InputStreamReader getReader(String fname, String encoding,
 1037               JarFile jarFile,
 1038               JspCompilationContext ctxt,
 1039               ErrorDispatcher err)
 1040       throws JasperException, IOException {
 1041   
 1042           return getReader(fname, encoding, jarFile, ctxt, err, 0);
 1043       }
 1044   
 1045       static InputStreamReader getReader(String fname, String encoding,
 1046               JarFile jarFile,
 1047               JspCompilationContext ctxt,
 1048               ErrorDispatcher err, int skip)
 1049       throws JasperException, IOException {
 1050   
 1051           InputStreamReader reader = null;
 1052           InputStream in = getInputStream(fname, jarFile, ctxt, err);
 1053           for (int i = 0; i < skip; i++) {
 1054               in.read();
 1055           }
 1056           try {
 1057               reader = new InputStreamReader(in, encoding);
 1058           } catch (UnsupportedEncodingException ex) {
 1059               err.jspError("jsp.error.unsupported.encoding", encoding);
 1060           }
 1061   
 1062           return reader;
 1063       }
 1064       
 1065       /**
 1066        * Handles taking input from TLDs
 1067        * 'java.lang.Object' -> 'java.lang.Object.class'
 1068        * 'int' -> 'int.class'
 1069        * 'void' -> 'Void.TYPE'
 1070        * 'int[]' -> 'int[].class'
 1071        * 
 1072        * @param type
 1073        * @return
 1074        */
 1075       public static String toJavaSourceTypeFromTld(String type) {
 1076           if (type == null || "void".equals(type)) {
 1077               return "Void.TYPE";
 1078           }
 1079           return type + ".class";
 1080       }
 1081   
 1082       /**
 1083        * Class.getName() return arrays in the form "[[[<et>", where et,
 1084        * the element type can be one of ZBCDFIJS or L<classname>;
 1085        * It is converted into forms that can be understood by javac.
 1086        */
 1087       public static String toJavaSourceType(String type) {
 1088   
 1089       if (type.charAt(0) != '[') {
 1090           return type;
 1091       }
 1092   
 1093       int dims = 1;
 1094       String t = null;
 1095       for (int i = 1; i < type.length(); i++) {
 1096           if (type.charAt(i) == '[') {
 1097           dims++;
 1098           } else {
 1099           switch (type.charAt(i)) {
 1100           case 'Z': t = "boolean"; break;
 1101           case 'B': t = "byte"; break;
 1102           case 'C': t = "char"; break;
 1103           case 'D': t = "double"; break;
 1104           case 'F': t = "float"; break;
 1105           case 'I': t = "int"; break;
 1106           case 'J': t = "long"; break;
 1107           case 'S': t = "short"; break;
 1108           case 'L': t = type.substring(i+1, type.indexOf(';')); break;
 1109           }
 1110           break;
 1111           }
 1112       }
 1113       StringBuffer resultType = new StringBuffer(t);
 1114       for (; dims > 0; dims--) {
 1115           resultType.append("[]");
 1116       }
 1117       return resultType.toString();
 1118       }
 1119   
 1120       /**
 1121        * Compute the canonical name from a Class instance.  Note that a
 1122        * simple replacment of '$' with '.' of a binary name would not work,
 1123        * as '$' is a legal Java Identifier character.
 1124        * @param c A instance of java.lang.Class
 1125        * @return  The canonical name of c.
 1126        */
 1127       public static String getCanonicalName(Class c) {
 1128   
 1129           String binaryName = c.getName();
 1130           c = c.getDeclaringClass();
 1131   
 1132           if (c == null) {
 1133               return binaryName;
 1134           }
 1135   
 1136           StringBuffer buf = new StringBuffer(binaryName);
 1137           do {
 1138               buf.setCharAt(c.getName().length(), '.');
 1139               c = c.getDeclaringClass();
 1140           } while ( c != null);
 1141   
 1142           return buf.toString();
 1143       }
 1144   }

Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » jasper » compiler » [javadoc | source]