Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » jasper » [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;
   19   
   20   import java.io.BufferedReader;
   21   import java.io.CharArrayWriter;
   22   import java.io.File;
   23   import java.io.FileInputStream;
   24   import java.io.FileNotFoundException;
   25   import java.io.FileOutputStream;
   26   import java.io.FileReader;
   27   import java.io.FileWriter;
   28   import java.io.IOException;
   29   import java.io.PrintWriter;
   30   import java.io.Writer;
   31   import java.net.MalformedURLException;
   32   import java.net.URL;
   33   import java.net.URLClassLoader;
   34   import java.util.ArrayList;
   35   import java.util.Iterator;
   36   import java.util.List;
   37   import java.util.Map;
   38   import java.util.HashMap;
   39   import java.util.Stack;
   40   import java.util.StringTokenizer;
   41   import java.util.Vector;
   42   
   43   import org.apache.jasper.compiler.Compiler;
   44   import org.apache.jasper.compiler.JspConfig;
   45   import org.apache.jasper.compiler.JspRuntimeContext;
   46   import org.apache.jasper.compiler.Localizer;
   47   import org.apache.jasper.compiler.TagPluginManager;
   48   import org.apache.jasper.compiler.TldLocationsCache;
   49   import org.apache.jasper.servlet.JspCServletContext;
   50   import org.apache.juli.logging.Log;
   51   import org.apache.juli.logging.LogFactory;
   52   
   53   import org.apache.tools.ant.AntClassLoader;
   54   import org.apache.tools.ant.Project;
   55   import org.apache.tools.ant.util.FileUtils;
   56   
   57   /**
   58    * Shell for the jspc compiler.  Handles all options associated with the
   59    * command line and creates compilation contexts which it then compiles
   60    * according to the specified options.
   61    *
   62    * This version can process files from a _single_ webapp at once, i.e.
   63    * a single docbase can be specified.
   64    *
   65    * It can be used as an Ant task using:
   66    * <pre>
   67    *   &lt;taskdef classname="org.apache.jasper.JspC" name="jasper2" &gt;
   68    *      &lt;classpath&gt;
   69    *          &lt;pathelement location="${java.home}/../lib/tools.jar"/&gt;
   70    *          &lt;fileset dir="${ENV.CATALINA_HOME}/server/lib"&gt;
   71    *              &lt;include name="*.jar"/&gt;
   72    *          &lt;/fileset&gt;
   73    *          &lt;fileset dir="${ENV.CATALINA_HOME}/common/lib"&gt;
   74    *              &lt;include name="*.jar"/&gt;
   75    *          &lt;/fileset&gt;
   76    *          &lt;path refid="myjars"/&gt;
   77    *       &lt;/classpath&gt;
   78    *  &lt;/taskdef&gt;
   79    *
   80    *  &lt;jasper2 verbose="0"
   81    *           package="my.package"
   82    *           uriroot="${webapps.dir}/${webapp.name}"
   83    *           webXmlFragment="${build.dir}/generated_web.xml"
   84    *           outputDir="${webapp.dir}/${webapp.name}/WEB-INF/src/my/package" /&gt;
   85    * </pre>
   86    *
   87    * @author Danno Ferrin
   88    * @author Pierre Delisle
   89    * @author Costin Manolache
   90    * @author Yoav Shapira
   91    */
   92   public class JspC implements Options {
   93   
   94       public static final String DEFAULT_IE_CLASS_ID =
   95               "clsid:8AD9C840-044E-11D1-B3E9-00805F499D93";
   96   
   97       // Logger
   98       protected static Log log = LogFactory.getLog(JspC.class);
   99   
  100       protected static final String SWITCH_VERBOSE = "-v";
  101       protected static final String SWITCH_HELP = "-help";
  102       protected static final String SWITCH_OUTPUT_DIR = "-d";
  103       protected static final String SWITCH_PACKAGE_NAME = "-p";
  104       protected static final String SWITCH_CACHE = "-cache";
  105       protected static final String SWITCH_CLASS_NAME = "-c";
  106       protected static final String SWITCH_FULL_STOP = "--";
  107       protected static final String SWITCH_COMPILE = "-compile";
  108       protected static final String SWITCH_SOURCE = "-source";
  109       protected static final String SWITCH_TARGET = "-target";
  110       protected static final String SWITCH_URI_BASE = "-uribase";
  111       protected static final String SWITCH_URI_ROOT = "-uriroot";
  112       protected static final String SWITCH_FILE_WEBAPP = "-webapp";
  113       protected static final String SWITCH_WEBAPP_INC = "-webinc";
  114       protected static final String SWITCH_WEBAPP_XML = "-webxml";
  115       protected static final String SWITCH_MAPPED = "-mapped";
  116       protected static final String SWITCH_XPOWERED_BY = "-xpoweredBy";
  117       protected static final String SWITCH_TRIM_SPACES = "-trimSpaces";
  118       protected static final String SWITCH_CLASSPATH = "-classpath";
  119       protected static final String SWITCH_DIE = "-die";
  120       protected static final String SWITCH_POOLING = "-poolingEnabled";
  121       protected static final String SWITCH_ENCODING = "-javaEncoding";
  122       protected static final String SWITCH_SMAP = "-smap";
  123       protected static final String SWITCH_DUMP_SMAP = "-dumpsmap";
  124   
  125       protected static final String SHOW_SUCCESS ="-s";
  126       protected static final String LIST_ERRORS = "-l";
  127       protected static final int INC_WEBXML = 10;
  128       protected static final int ALL_WEBXML = 20;
  129       protected static final int DEFAULT_DIE_LEVEL = 1;
  130       protected static final int NO_DIE_LEVEL = 0;
  131   
  132       protected static final String[] insertBefore =
  133       { "</web-app>", "<servlet-mapping>", "<session-config>",
  134         "<mime-mapping>", "<welcome-file-list>", "<error-page>", "<taglib>",
  135         "<resource-env-ref>", "<resource-ref>", "<security-constraint>",
  136         "<login-config>", "<security-role>", "<env-entry>", "<ejb-ref>",
  137         "<ejb-local-ref>" };
  138   
  139       protected static int die;
  140       protected String classPath = null;
  141       protected URLClassLoader loader = null;
  142       protected boolean trimSpaces = false;
  143       protected boolean genStringAsCharArray = false;
  144       protected boolean xpoweredBy;
  145       protected boolean mappedFile = false;
  146       protected boolean poolingEnabled = true;
  147       protected File scratchDir;
  148       protected String ieClassId = DEFAULT_IE_CLASS_ID;
  149       protected String targetPackage;
  150       protected String targetClassName;
  151       protected String uriBase;
  152       protected String uriRoot;
  153       protected Project project;
  154       protected int dieLevel;
  155       protected boolean helpNeeded = false;
  156       protected boolean compile = false;
  157       protected boolean smapSuppressed = true;
  158       protected boolean smapDumped = false;
  159       protected boolean caching = true;
  160       protected Map cache = new HashMap();
  161   
  162       protected String compiler = null;
  163   
  164       protected String compilerTargetVM = "1.4";
  165       protected String compilerSourceVM = "1.4";
  166   
  167       protected boolean classDebugInfo = true;
  168   
  169       /**
  170        * Throw an exception if there's a compilation error, or swallow it.
  171        * Default is true to preserve old behavior.
  172        */
  173       protected boolean failOnError = true;
  174   
  175       /**
  176        * The file extensions to be handled as JSP files.
  177        * Default list is .jsp and .jspx.
  178        */
  179       protected List extensions;
  180   
  181       /**
  182        * The pages.
  183        */
  184       protected List pages = new Vector();
  185   
  186       /**
  187        * Needs better documentation, this data member does.
  188        * True by default.
  189        */
  190       protected boolean errorOnUseBeanInvalidClassAttribute = true;
  191   
  192       /**
  193        * The java file encoding.  Default
  194        * is UTF-8.  Added per bugzilla 19622.
  195        */
  196       protected String javaEncoding = "UTF-8";
  197   
  198       // Generation of web.xml fragments
  199       protected String webxmlFile;
  200       protected int webxmlLevel;
  201       protected boolean addWebXmlMappings = false;
  202   
  203       protected Writer mapout;
  204       protected CharArrayWriter servletout;
  205       protected CharArrayWriter mappingout;
  206   
  207       /**
  208        * The servlet context.
  209        */
  210       protected JspCServletContext context;
  211   
  212       /**
  213        * The runtime context.
  214        * Maintain a dummy JspRuntimeContext for compiling tag files.
  215        */
  216       protected JspRuntimeContext rctxt;
  217   
  218       /**
  219        * Cache for the TLD locations
  220        */
  221       protected TldLocationsCache tldLocationsCache = null;
  222   
  223       protected JspConfig jspConfig = null;
  224       protected TagPluginManager tagPluginManager = null;
  225   
  226       protected boolean verbose = false;
  227       protected boolean listErrors = false;
  228       protected boolean showSuccess = false;
  229       protected int argPos;
  230       protected boolean fullstop = false;
  231       protected String args[];
  232   
  233       public static void main(String arg[]) {
  234           if (arg.length == 0) {
  235               System.out.println(Localizer.getMessage("jspc.usage"));
  236           } else {
  237               try {
  238                   JspC jspc = new JspC();
  239                   jspc.setArgs(arg);
  240                   if (jspc.helpNeeded) {
  241                       System.out.println(Localizer.getMessage("jspc.usage"));
  242                   } else {
  243                       jspc.execute();
  244                   }
  245               } catch (JasperException je) {
  246                   System.err.println(je);
  247                   if (die != NO_DIE_LEVEL) {
  248                       System.exit(die);
  249                   }
  250               }
  251           }
  252       }
  253   
  254       public void setArgs(String[] arg) throws JasperException {
  255           args = arg;
  256           String tok;
  257   
  258           dieLevel = NO_DIE_LEVEL;
  259           die = dieLevel;
  260   
  261           while ((tok = nextArg()) != null) {
  262               if (tok.equals(SWITCH_VERBOSE)) {
  263                   verbose = true;
  264                   showSuccess = true;
  265                   listErrors = true;
  266               } else if (tok.equals(SWITCH_OUTPUT_DIR)) {
  267                   tok = nextArg();
  268                   setOutputDir( tok );
  269               } else if (tok.equals(SWITCH_PACKAGE_NAME)) {
  270                   targetPackage = nextArg();
  271               } else if (tok.equals(SWITCH_COMPILE)) {
  272                   compile=true;
  273               } else if (tok.equals(SWITCH_CLASS_NAME)) {
  274                   targetClassName = nextArg();
  275               } else if (tok.equals(SWITCH_URI_BASE)) {
  276                   uriBase=nextArg();
  277               } else if (tok.equals(SWITCH_URI_ROOT)) {
  278                   setUriroot( nextArg());
  279               } else if (tok.equals(SWITCH_FILE_WEBAPP)) {
  280                   setUriroot( nextArg());
  281               } else if ( tok.equals( SHOW_SUCCESS ) ) {
  282                   showSuccess = true;
  283               } else if ( tok.equals( LIST_ERRORS ) ) {
  284                   listErrors = true;
  285               } else if (tok.equals(SWITCH_WEBAPP_INC)) {
  286                   webxmlFile = nextArg();
  287                   if (webxmlFile != null) {
  288                       webxmlLevel = INC_WEBXML;
  289                   }
  290               } else if (tok.equals(SWITCH_WEBAPP_XML)) {
  291                   webxmlFile = nextArg();
  292                   if (webxmlFile != null) {
  293                       webxmlLevel = ALL_WEBXML;
  294                   }
  295               } else if (tok.equals(SWITCH_MAPPED)) {
  296                   mappedFile = true;
  297               } else if (tok.equals(SWITCH_XPOWERED_BY)) {
  298                   xpoweredBy = true;
  299               } else if (tok.equals(SWITCH_TRIM_SPACES)) {
  300                   setTrimSpaces(true);
  301               } else if (tok.equals(SWITCH_CACHE)) {
  302                   tok = nextArg();
  303                   if ("false".equals(tok)) {
  304                       caching = false;
  305                   } else {
  306                       caching = true;
  307                   }            
  308               } else if (tok.equals(SWITCH_CLASSPATH)) {
  309                   setClassPath(nextArg());
  310               } else if (tok.startsWith(SWITCH_DIE)) {
  311                   try {
  312                       dieLevel = Integer.parseInt(
  313                           tok.substring(SWITCH_DIE.length()));
  314                   } catch (NumberFormatException nfe) {
  315                       dieLevel = DEFAULT_DIE_LEVEL;
  316                   }
  317                   die = dieLevel;
  318               } else if (tok.equals(SWITCH_HELP)) {
  319                   helpNeeded = true;
  320               } else if (tok.equals(SWITCH_POOLING)) {
  321                   tok = nextArg();
  322                   if ("false".equals(tok)) {
  323                       poolingEnabled = false;
  324                   } else {
  325                       poolingEnabled = true;
  326                   }
  327               } else if (tok.equals(SWITCH_ENCODING)) {
  328                   setJavaEncoding(nextArg());
  329               } else if (tok.equals(SWITCH_SOURCE)) {
  330                   setCompilerSourceVM(nextArg());
  331               } else if (tok.equals(SWITCH_TARGET)) {
  332                   setCompilerTargetVM(nextArg());
  333               } else if (tok.equals(SWITCH_SMAP)) {
  334                   smapSuppressed = false;
  335               } else if (tok.equals(SWITCH_DUMP_SMAP)) {
  336                   smapDumped = true;
  337               } else {
  338                   if (tok.startsWith("-")) {
  339                       throw new JasperException("Unrecognized option: " + tok +
  340                           ".  Use -help for help.");
  341                   }
  342                   if (!fullstop) {
  343                       argPos--;
  344                   }
  345                   // Start treating the rest as JSP Pages
  346                   break;
  347               }
  348           }
  349   
  350           // Add all extra arguments to the list of files
  351           while( true ) {
  352               String file = nextFile();
  353               if( file==null ) {
  354                   break;
  355               }
  356               pages.add( file );
  357           }
  358       }
  359   
  360       public boolean getKeepGenerated() {
  361           // isn't this why we are running jspc?
  362           return true;
  363       }
  364   
  365       public boolean getTrimSpaces() {
  366           return trimSpaces;
  367       }
  368   
  369       public void setTrimSpaces(boolean ts) {
  370           this.trimSpaces = ts;
  371       }
  372   
  373       public boolean isPoolingEnabled() {
  374           return poolingEnabled;
  375       }
  376   
  377       public void setPoolingEnabled(boolean poolingEnabled) {
  378           this.poolingEnabled = poolingEnabled;
  379       }
  380   
  381       public boolean isXpoweredBy() {
  382           return xpoweredBy;
  383       }
  384   
  385       public void setXpoweredBy(boolean xpoweredBy) {
  386           this.xpoweredBy = xpoweredBy;
  387       }
  388   
  389       public boolean getDisplaySourceFragment() {
  390           return true;
  391       }
  392       
  393       public boolean getErrorOnUseBeanInvalidClassAttribute() {
  394           return errorOnUseBeanInvalidClassAttribute;
  395       }
  396   
  397       public void setErrorOnUseBeanInvalidClassAttribute(boolean b) {
  398           errorOnUseBeanInvalidClassAttribute = b;
  399       }
  400   
  401       public int getTagPoolSize() {
  402           return Constants.MAX_POOL_SIZE;
  403       }
  404   
  405       /**
  406        * Are we supporting HTML mapped servlets?
  407        */
  408       public boolean getMappedFile() {
  409           return mappedFile;
  410       }
  411   
  412       // Off-line compiler, no need for security manager
  413       public Object getProtectionDomain() {
  414           return null;
  415       }
  416   
  417       /**
  418        * @deprecated
  419        */
  420       @Deprecated
  421       public boolean getSendErrorToClient() {
  422           return true;
  423       }
  424   
  425       public void setClassDebugInfo( boolean b ) {
  426           classDebugInfo=b;
  427       }
  428   
  429       public boolean getClassDebugInfo() {
  430           // compile with debug info
  431           return classDebugInfo;
  432       }
  433   
  434        /**
  435         * @see Options#isCaching()
  436        */
  437       public boolean isCaching() {
  438           return caching;
  439       }
  440   
  441       /**
  442        * @see Options#isCaching()
  443        */
  444       public void setCaching(boolean caching) {
  445           this.caching = caching;
  446       }
  447   
  448       /**
  449        * @see Options#getCache()
  450        */
  451       public Map getCache() {
  452           return cache;
  453       }
  454   
  455       /**
  456        * Background compilation check intervals in seconds
  457        */
  458       public int getCheckInterval() {
  459           return 0;
  460       }
  461   
  462       /**
  463        * Modification test interval.
  464        */
  465       public int getModificationTestInterval() {
  466           return 0;
  467       }
  468   
  469       /**
  470        * Is Jasper being used in development mode?
  471        */
  472       public boolean getDevelopment() {
  473           return false;
  474       }
  475   
  476       /**
  477        * Is the generation of SMAP info for JSR45 debuggin suppressed?
  478        */
  479       public boolean isSmapSuppressed() {
  480           return smapSuppressed;
  481       }
  482   
  483       /**
  484        * Set smapSuppressed flag.
  485        */
  486       public void setSmapSuppressed(boolean smapSuppressed) {
  487           this.smapSuppressed = smapSuppressed;
  488       }
  489   
  490       
  491       /**
  492        * Should SMAP info for JSR45 debugging be dumped to a file?
  493        */
  494       public boolean isSmapDumped() {
  495           return smapDumped;
  496       }
  497   
  498       /**
  499        * Set smapSuppressed flag.
  500        */
  501       public void setSmapDumped(boolean smapDumped) {
  502           this.smapDumped = smapDumped;
  503       }
  504   
  505       
  506       /**
  507        * Determines whether text strings are to be generated as char arrays,
  508        * which improves performance in some cases.
  509        *
  510        * @param genStringAsCharArray true if text strings are to be generated as
  511        * char arrays, false otherwise
  512        */
  513       public void setGenStringAsCharArray(boolean genStringAsCharArray) {
  514           this.genStringAsCharArray = genStringAsCharArray;
  515       }
  516   
  517       /**
  518        * Indicates whether text strings are to be generated as char arrays.
  519        *
  520        * @return true if text strings are to be generated as char arrays, false
  521        * otherwise
  522        */
  523       public boolean genStringAsCharArray() {
  524           return genStringAsCharArray;
  525       }
  526   
  527       /**
  528        * Sets the class-id value to be sent to Internet Explorer when using
  529        * <jsp:plugin> tags.
  530        *
  531        * @param ieClassId Class-id value
  532        */
  533       public void setIeClassId(String ieClassId) {
  534           this.ieClassId = ieClassId;
  535       }
  536   
  537       /**
  538        * Gets the class-id value that is sent to Internet Explorer when using
  539        * <jsp:plugin> tags.
  540        *
  541        * @return Class-id value
  542        */
  543       public String getIeClassId() {
  544           return ieClassId;
  545       }
  546   
  547       public File getScratchDir() {
  548           return scratchDir;
  549       }
  550   
  551       public Class getJspCompilerPlugin() {
  552          // we don't compile, so this is meanlingless
  553           return null;
  554       }
  555   
  556       public String getJspCompilerPath() {
  557          // we don't compile, so this is meanlingless
  558           return null;
  559       }
  560   
  561       /**
  562        * Compiler to use.
  563        */
  564       public String getCompiler() {
  565           return compiler;
  566       }
  567   
  568       public void setCompiler(String c) {
  569           compiler=c;
  570       }
  571   
  572       /**
  573        * Compiler class name to use.
  574        */
  575       public String getCompilerClassName() {
  576           return null;
  577       }
  578       
  579       /**
  580        * @see Options#getCompilerTargetVM
  581        */
  582       public String getCompilerTargetVM() {
  583           return compilerTargetVM;
  584       }
  585   
  586       public void setCompilerTargetVM(String vm) {
  587           compilerTargetVM = vm;
  588       }
  589   
  590       /**
  591        * @see Options#getCompilerSourceVM()
  592        */
  593        public String getCompilerSourceVM() {
  594            return compilerSourceVM;
  595        }
  596           
  597       /**
  598        * @see Options#getCompilerSourceVM()
  599        */
  600       public void setCompilerSourceVM(String vm) {
  601           compilerSourceVM = vm;
  602       }
  603   
  604       public TldLocationsCache getTldLocationsCache() {
  605           return tldLocationsCache;
  606       }
  607   
  608       /**
  609        * Returns the encoding to use for
  610        * java files.  The default is UTF-8.
  611        *
  612        * @return String The encoding
  613        */
  614       public String getJavaEncoding() {
  615           return javaEncoding;
  616       }
  617   
  618       /**
  619        * Sets the encoding to use for
  620        * java files.
  621        *
  622        * @param encodingName The name, e.g. "UTF-8"
  623        */
  624       public void setJavaEncoding(String encodingName) {
  625           javaEncoding = encodingName;
  626       }
  627   
  628       public boolean getFork() {
  629           return false;
  630       }
  631   
  632       public String getClassPath() {
  633           if( classPath != null )
  634               return classPath;
  635           return System.getProperty("java.class.path");
  636       }
  637   
  638       public void setClassPath(String s) {
  639           classPath=s;
  640       }
  641   
  642       /**
  643        * Returns the list of file extensions
  644        * that are treated as JSP files.
  645        *
  646        * @return The list of extensions
  647        */
  648       public List getExtensions() {
  649           return extensions;
  650       }
  651   
  652       /**
  653        * Adds the given file extension to the
  654        * list of extensions handled as JSP files.
  655        *
  656        * @param extension The extension to add, e.g. "myjsp"
  657        */
  658       protected void addExtension(final String extension) {
  659           if(extension != null) {
  660               if(extensions == null) {
  661                   extensions = new Vector();
  662               }
  663   
  664               extensions.add(extension);
  665           }
  666       }
  667   
  668       /**
  669        * Sets the project.
  670        *
  671        * @param theProject The project
  672        */
  673       public void setProject(final Project theProject) {
  674           project = theProject;
  675       }
  676   
  677       /**
  678        * Returns the project: may be null if not running
  679        * inside an Ant project.
  680        *
  681        * @return The project
  682        */
  683       public Project getProject() {
  684           return project;
  685       }
  686   
  687       /**
  688        * Base dir for the webapp. Used to generate class names and resolve
  689        * includes
  690        */
  691       public void setUriroot( String s ) {
  692           if( s==null ) {
  693               uriRoot = s;
  694               return;
  695           }
  696           try {
  697               uriRoot = resolveFile(s).getCanonicalPath();
  698           } catch( Exception ex ) {
  699               uriRoot = s;
  700           }
  701       }
  702   
  703       /**
  704        * Parses comma-separated list of JSP files to be processed.  If the argument
  705        * is null, nothing is done.
  706        *
  707        * <p>Each file is interpreted relative to uriroot, unless it is absolute,
  708        * in which case it must start with uriroot.</p>
  709        *
  710        * @param jspFiles Comma-separated list of JSP files to be processed
  711        */
  712       public void setJspFiles(final String jspFiles) {
  713           if(jspFiles == null) {
  714               return;
  715           }
  716   
  717           StringTokenizer tok = new StringTokenizer(jspFiles, ",");
  718           while (tok.hasMoreTokens()) {
  719               pages.add(tok.nextToken());
  720           }
  721       }
  722   
  723       /**
  724        * Sets the compile flag.
  725        *
  726        * @param b Flag value
  727        */
  728       public void setCompile( final boolean b ) {
  729           compile = b;
  730       }
  731   
  732       /**
  733        * Sets the verbosity level.  The actual number doesn't
  734        * matter: if it's greater than zero, the verbose flag will
  735        * be true.
  736        *
  737        * @param level Positive means verbose
  738        */
  739       public void setVerbose( final int level ) {
  740           if (level > 0) {
  741               verbose = true;
  742               showSuccess = true;
  743               listErrors = true;
  744           }
  745       }
  746   
  747       public void setValidateXml( boolean b ) {
  748           org.apache.jasper.xmlparser.ParserUtils.validating=b;
  749       }
  750   
  751       public void setListErrors( boolean b ) {
  752           listErrors = b;
  753       }
  754   
  755       public void setOutputDir( String s ) {
  756           if( s!= null ) {
  757               scratchDir = resolveFile(s).getAbsoluteFile();
  758           } else {
  759               scratchDir=null;
  760           }
  761       }
  762   
  763       public void setPackage( String p ) {
  764           targetPackage=p;
  765       }
  766   
  767       /**
  768        * Class name of the generated file ( without package ).
  769        * Can only be used if a single file is converted.
  770        * XXX Do we need this feature ?
  771        */
  772       public void setClassName( String p ) {
  773           targetClassName=p;
  774       }
  775   
  776       /**
  777        * File where we generate a web.xml fragment with the class definitions.
  778        */
  779       public void setWebXmlFragment( String s ) {
  780           webxmlFile=resolveFile(s).getAbsolutePath();
  781           webxmlLevel=INC_WEBXML;
  782       }
  783   
  784       /**
  785        * File where we generate a complete web.xml with the class definitions.
  786        */
  787       public void setWebXml( String s ) {
  788           webxmlFile=resolveFile(s).getAbsolutePath();
  789           webxmlLevel=ALL_WEBXML;
  790       }
  791   
  792       public void setAddWebXmlMappings(boolean b) {
  793           addWebXmlMappings = b;
  794       }
  795   
  796       /**
  797        * Set the option that throws an exception in case of a compilation error.
  798        */
  799       public void setFailOnError(final boolean b) {
  800           failOnError = b;
  801       }
  802   
  803       public boolean getFailOnError() {
  804           return failOnError;
  805       }
  806   
  807       /**
  808        * Obtain JSP configuration informantion specified in web.xml.
  809        */
  810       public JspConfig getJspConfig() {
  811           return jspConfig;
  812       }
  813   
  814       public TagPluginManager getTagPluginManager() {
  815           return tagPluginManager;
  816       }
  817   
  818       public void generateWebMapping( String file, JspCompilationContext clctxt )
  819           throws IOException
  820       {
  821           if (log.isDebugEnabled()) {
  822               log.debug("Generating web mapping for file " + file
  823                         + " using compilation context " + clctxt);
  824           }
  825   
  826           String className = clctxt.getServletClassName();
  827           String packageName = clctxt.getServletPackageName();
  828   
  829           String thisServletName;
  830           if  ("".equals(packageName)) {
  831               thisServletName = className;
  832           } else {
  833               thisServletName = packageName + '.' + className;
  834           }
  835   
  836           if (servletout != null) {
  837               servletout.write("\n    <servlet>\n        <servlet-name>");
  838               servletout.write(thisServletName);
  839               servletout.write("</servlet-name>\n        <servlet-class>");
  840               servletout.write(thisServletName);
  841               servletout.write("</servlet-class>\n    </servlet>\n");
  842           }
  843           if (mappingout != null) {
  844               mappingout.write("\n    <servlet-mapping>\n        <servlet-name>");
  845               mappingout.write(thisServletName);
  846               mappingout.write("</servlet-name>\n        <url-pattern>");
  847               mappingout.write(file.replace('\\', '/'));
  848               mappingout.write("</url-pattern>\n    </servlet-mapping>\n");
  849   
  850           }
  851       }
  852   
  853       /**
  854        * Include the generated web.xml inside the webapp's web.xml.
  855        */
  856       protected void mergeIntoWebXml() throws IOException {
  857   
  858           File webappBase = new File(uriRoot);
  859           File webXml = new File(webappBase, "WEB-INF/web.xml");
  860           File webXml2 = new File(webappBase, "WEB-INF/web2.xml");
  861           String insertStartMarker =
  862               Localizer.getMessage("jspc.webinc.insertStart");
  863           String insertEndMarker =
  864               Localizer.getMessage("jspc.webinc.insertEnd");
  865   
  866           BufferedReader reader = new BufferedReader(new FileReader(webXml));
  867           BufferedReader fragmentReader =
  868               new BufferedReader(new FileReader(webxmlFile));
  869           PrintWriter writer = new PrintWriter(new FileWriter(webXml2));
  870   
  871           // Insert the <servlet> and <servlet-mapping> declarations
  872           int pos = -1;
  873           String line = null;
  874           while (true) {
  875               line = reader.readLine();
  876               if (line == null) {
  877                   break;
  878               }
  879               // Skip anything previously generated by JSPC
  880               if (line.indexOf(insertStartMarker) >= 0) {
  881                   while (true) {
  882                       line = reader.readLine();
  883                       if (line == null) {
  884                           return;
  885                       }
  886                       if (line.indexOf(insertEndMarker) >= 0) {
  887                           line = reader.readLine();
  888                           line = reader.readLine();
  889                           if (line == null) {
  890                               return;
  891                           }
  892                           break;
  893                       }
  894                   }
  895               }
  896               for (int i = 0; i < insertBefore.length; i++) {
  897                   pos = line.indexOf(insertBefore[i]);
  898                   if (pos >= 0)
  899                       break;
  900               }
  901               if (pos >= 0) {
  902                   writer.print(line.substring(0, pos));
  903                   break;
  904               } else {
  905                   writer.println(line);
  906               }
  907           }
  908   
  909           writer.println(insertStartMarker);
  910           while (true) {
  911               String line2 = fragmentReader.readLine();
  912               if (line2 == null) {
  913                   writer.println();
  914                   break;
  915               }
  916               writer.println(line2);
  917           }
  918           writer.println(insertEndMarker);
  919           writer.println();
  920   
  921           for (int i = 0; i < pos; i++) {
  922               writer.print(" ");
  923           }
  924           writer.println(line.substring(pos));
  925   
  926           while (true) {
  927               line = reader.readLine();
  928               if (line == null) {
  929                   break;
  930               }
  931               writer.println(line);
  932           }
  933           writer.close();
  934   
  935           reader.close();
  936           fragmentReader.close();
  937   
  938           FileInputStream fis = new FileInputStream(webXml2);
  939           FileOutputStream fos = new FileOutputStream(webXml);
  940   
  941           byte buf[] = new byte[512];
  942           while (true) {
  943               int n = fis.read(buf);
  944               if (n < 0) {
  945                   break;
  946               }
  947               fos.write(buf, 0, n);
  948           }
  949   
  950           fis.close();
  951           fos.close();
  952   
  953           webXml2.delete();
  954           (new File(webxmlFile)).delete();
  955   
  956       }
  957   
  958       protected void processFile(String file)
  959           throws JasperException
  960       {
  961           if (log.isDebugEnabled()) {
  962               log.debug("Processing file: " + file);
  963           }
  964   
  965           ClassLoader originalClassLoader = null;
  966   
  967           try {
  968               // set up a scratch/output dir if none is provided
  969               if (scratchDir == null) {
  970                   String temp = System.getProperty("java.io.tmpdir");
  971                   if (temp == null) {
  972                       temp = "";
  973                   }
  974                   scratchDir = new File(new File(temp).getAbsolutePath());
  975               }
  976   
  977               String jspUri=file.replace('\\','/');
  978               JspCompilationContext clctxt = new JspCompilationContext
  979                   ( jspUri, false,  this, context, null, rctxt );
  980   
  981               /* Override the defaults */
  982               if ((targetClassName != null) && (targetClassName.length() > 0)) {
  983                   clctxt.setServletClassName(targetClassName);
  984                   targetClassName = null;
  985               }
  986               if (targetPackage != null) {
  987                   clctxt.setServletPackageName(targetPackage);
  988               }
  989   
  990               originalClassLoader = Thread.currentThread().getContextClassLoader();
  991               if( loader==null ) {
  992                   initClassLoader( clctxt );
  993               }
  994               Thread.currentThread().setContextClassLoader(loader);
  995   
  996               clctxt.setClassLoader(loader);
  997               clctxt.setClassPath(classPath);
  998   
  999               Compiler clc = clctxt.createCompiler();
 1000   
 1001               // If compile is set, generate both .java and .class, if
 1002               // .jsp file is newer than .class file;
 1003               // Otherwise only generate .java, if .jsp file is newer than
 1004               // the .java file
 1005               if( clc.isOutDated(compile) ) {
 1006                   if (log.isDebugEnabled()) {
 1007                       log.debug(jspUri + " is out dated, compiling...");
 1008                   }
 1009   
 1010                   clc.compile(compile, true);
 1011               }
 1012   
 1013               // Generate mapping
 1014               generateWebMapping( file, clctxt );
 1015               if ( showSuccess ) {
 1016                   log.info( "Built File: " + file );
 1017               }
 1018   
 1019           } catch (JasperException je) {
 1020               Throwable rootCause = je;
 1021               while (rootCause instanceof JasperException
 1022                       && ((JasperException) rootCause).getRootCause() != null) {
 1023                   rootCause = ((JasperException) rootCause).getRootCause();
 1024               }
 1025               if (rootCause != je) {
 1026                   log.error(Localizer.getMessage("jspc.error.generalException",
 1027                                                  file),
 1028                             rootCause);
 1029               }
 1030   
 1031               // Bugzilla 35114.
 1032               if(getFailOnError()) {
 1033                   throw je;
 1034               } else {
 1035                   log.error(je.getMessage());
 1036               }
 1037   
 1038           } catch (Exception e) {
 1039               if ((e instanceof FileNotFoundException) && log.isWarnEnabled()) {
 1040                   log.warn(Localizer.getMessage("jspc.error.fileDoesNotExist",
 1041                                                 e.getMessage()));
 1042               }
 1043               throw new JasperException(e);
 1044           } finally {
 1045               if(originalClassLoader != null) {
 1046                   Thread.currentThread().setContextClassLoader(originalClassLoader);
 1047               }
 1048           }
 1049       }
 1050   
 1051       /**
 1052        * Locate all jsp files in the webapp. Used if no explicit
 1053        * jsps are specified.
 1054        */
 1055       public void scanFiles( File base ) throws JasperException {
 1056           Stack<String> dirs = new Stack<String>();
 1057           dirs.push(base.toString());
 1058   
 1059           // Make sure default extensions are always included
 1060           if ((getExtensions() == null) || (getExtensions().size() < 2)) {
 1061               addExtension("jsp");
 1062               addExtension("jspx");
 1063           }
 1064   
 1065           while (!dirs.isEmpty()) {
 1066               String s = dirs.pop();
 1067               File f = new File(s);
 1068               if (f.exists() && f.isDirectory()) {
 1069                   String[] files = f.list();
 1070                   String ext;
 1071                   for (int i = 0; (files != null) && i < files.length; i++) {
 1072                       File f2 = new File(s, files[i]);
 1073                       if (f2.isDirectory()) {
 1074                           dirs.push(f2.getPath());
 1075                       } else {
 1076                           String path = f2.getPath();
 1077                           String uri = path.substring(uriRoot.length());
 1078                           ext = files[i].substring(files[i].lastIndexOf('.') +1);
 1079                           if (getExtensions().contains(ext) ||
 1080                               jspConfig.isJspPage(uri)) {
 1081                               pages.add(path);
 1082                           }
 1083                       }
 1084                   }
 1085               }
 1086           }
 1087       }
 1088   
 1089       /**
 1090        * Executes the compilation.
 1091        *
 1092        * @throws JasperException If an error occurs
 1093        */
 1094       public void execute() throws JasperException {
 1095           if(log.isDebugEnabled()) {
 1096               log.debug("execute() starting for " + pages.size() + " pages.");
 1097           }
 1098   
 1099           try {
 1100               if (uriRoot == null) {
 1101                   if( pages.size() == 0 ) {
 1102                       throw new JasperException(
 1103                           Localizer.getMessage("jsp.error.jspc.missingTarget"));
 1104                   }
 1105                   String firstJsp = (String) pages.get( 0 );
 1106                   File firstJspF = new File( firstJsp );
 1107                   if (!firstJspF.exists()) {
 1108                       throw new JasperException(
 1109                           Localizer.getMessage("jspc.error.fileDoesNotExist",
 1110                                                firstJsp));
 1111                   }
 1112                   locateUriRoot( firstJspF );
 1113               }
 1114   
 1115               if (uriRoot == null) {
 1116                   throw new JasperException(
 1117                       Localizer.getMessage("jsp.error.jspc.no_uriroot"));
 1118               }
 1119   
 1120               if( context==null ) {
 1121                   initServletContext();
 1122               }
 1123   
 1124               // No explicit pages, we'll process all .jsp in the webapp
 1125               if (pages.size() == 0) {
 1126                   scanFiles( new File( uriRoot ));
 1127               }
 1128   
 1129               File uriRootF = new File(uriRoot);
 1130               if (!uriRootF.exists() || !uriRootF.isDirectory()) {
 1131                   throw new JasperException(
 1132                       Localizer.getMessage("jsp.error.jspc.uriroot_not_dir"));
 1133               }
 1134   
 1135               initWebXml();
 1136   
 1137               Iterator iter = pages.iterator();
 1138               while (iter.hasNext()) {
 1139                   String nextjsp = iter.next().toString();
 1140                   File fjsp = new File(nextjsp);
 1141                   if (!fjsp.isAbsolute()) {
 1142                       fjsp = new File(uriRootF, nextjsp);
 1143                   }
 1144                   if (!fjsp.exists()) {
 1145                       if (log.isWarnEnabled()) {
 1146                           log.warn
 1147                               (Localizer.getMessage
 1148                                ("jspc.error.fileDoesNotExist", fjsp.toString()));
 1149                       }
 1150                       continue;
 1151                   }
 1152                   String s = fjsp.getAbsolutePath();
 1153                   if (s.startsWith(uriRoot)) {
 1154                       nextjsp = s.substring(uriRoot.length());
 1155                   }
 1156                   if (nextjsp.startsWith("." + File.separatorChar)) {
 1157                       nextjsp = nextjsp.substring(2);
 1158                   }
 1159                   processFile(nextjsp);
 1160               }
 1161   
 1162               completeWebXml();
 1163   
 1164               if (addWebXmlMappings) {
 1165                   mergeIntoWebXml();
 1166               }
 1167   
 1168           } catch (IOException ioe) {
 1169               throw new JasperException(ioe);
 1170   
 1171           } catch (JasperException je) {
 1172               Throwable rootCause = je;
 1173               while (rootCause instanceof JasperException
 1174                       && ((JasperException) rootCause).getRootCause() != null) {
 1175                   rootCause = ((JasperException) rootCause).getRootCause();
 1176               }
 1177               if (rootCause != je) {
 1178                   rootCause.printStackTrace();
 1179               }
 1180               throw je;
 1181           } finally {
 1182               if (loader != null) {
 1183                   LogFactory.release(loader);
 1184               }
 1185           }
 1186       }
 1187   
 1188       // ==================== protected utility methods ====================
 1189   
 1190       protected String nextArg() {
 1191           if ((argPos >= args.length)
 1192               || (fullstop = SWITCH_FULL_STOP.equals(args[argPos]))) {
 1193               return null;
 1194           } else {
 1195               return args[argPos++];
 1196           }
 1197       }
 1198   
 1199       protected String nextFile() {
 1200           if (fullstop) argPos++;
 1201           if (argPos >= args.length) {
 1202               return null;
 1203           } else {
 1204               return args[argPos++];
 1205           }
 1206       }
 1207   
 1208       protected void initWebXml() {
 1209           try {
 1210               if (webxmlLevel >= INC_WEBXML) {
 1211                   File fmapings = new File(webxmlFile);
 1212                   mapout = new FileWriter(fmapings);
 1213                   servletout = new CharArrayWriter();
 1214                   mappingout = new CharArrayWriter();
 1215               } else {
 1216                   mapout = null;
 1217                   servletout = null;
 1218                   mappingout = null;
 1219               }
 1220               if (webxmlLevel >= ALL_WEBXML) {
 1221                   mapout.write(Localizer.getMessage("jspc.webxml.header"));
 1222                   mapout.flush();
 1223               } else if ((webxmlLevel>= INC_WEBXML) && !addWebXmlMappings) {
 1224                   mapout.write(Localizer.getMessage("jspc.webinc.header"));
 1225                   mapout.flush();
 1226               }
 1227           } catch (IOException ioe) {
 1228               mapout = null;
 1229               servletout = null;
 1230               mappingout = null;
 1231           }
 1232       }
 1233   
 1234       protected void completeWebXml() {
 1235           if (mapout != null) {
 1236               try {
 1237                   servletout.writeTo(mapout);
 1238                   mappingout.writeTo(mapout);
 1239                   if (webxmlLevel >= ALL_WEBXML) {
 1240                       mapout.write(Localizer.getMessage("jspc.webxml.footer"));
 1241                   } else if ((webxmlLevel >= INC_WEBXML) && !addWebXmlMappings) {
 1242                       mapout.write(Localizer.getMessage("jspc.webinc.footer"));
 1243                   }
 1244                   mapout.close();
 1245               } catch (IOException ioe) {
 1246                   // noting to do if it fails since we are done with it
 1247               }
 1248           }
 1249       }
 1250   
 1251       protected void initServletContext() {
 1252           try {
 1253               context =new JspCServletContext
 1254                   (new PrintWriter(System.out),
 1255                    new URL("file:" + uriRoot.replace('\\','/') + '/'));
 1256               tldLocationsCache = new TldLocationsCache(context, true);
 1257           } catch (MalformedURLException me) {
 1258               System.out.println("**" + me);
 1259           }
 1260           rctxt = new JspRuntimeContext(context, this);
 1261           jspConfig = new JspConfig(context);
 1262           tagPluginManager = new TagPluginManager(context);
 1263       }
 1264   
 1265       /**
 1266        * Initializes the classloader as/if needed for the given
 1267        * compilation context.
 1268        *
 1269        * @param clctxt The compilation context
 1270        * @throws IOException If an error occurs
 1271        */
 1272       protected void initClassLoader(JspCompilationContext clctxt)
 1273           throws IOException {
 1274   
 1275           classPath = getClassPath();
 1276   
 1277           ClassLoader jspcLoader = getClass().getClassLoader();
 1278           if (jspcLoader instanceof AntClassLoader) {
 1279               classPath += File.pathSeparator
 1280                   + ((AntClassLoader) jspcLoader).getClasspath();
 1281           }
 1282   
 1283           // Turn the classPath into URLs
 1284           ArrayList<URL> urls = new ArrayList<URL>();
 1285           StringTokenizer tokenizer = new StringTokenizer(classPath,
 1286                                                           File.pathSeparator);
 1287           while (tokenizer.hasMoreTokens()) {
 1288               String path = tokenizer.nextToken();
 1289               try {
 1290                   File libFile = new File(path);
 1291                   urls.add(libFile.toURL());
 1292               } catch (IOException ioe) {
 1293                   // Failing a toCanonicalPath on a file that
 1294                   // exists() should be a JVM regression test,
 1295                   // therefore we have permission to freak uot
 1296                   throw new RuntimeException(ioe.toString());
 1297               }
 1298           }
 1299   
 1300           File webappBase = new File(uriRoot);
 1301           if (webappBase.exists()) {
 1302               File classes = new File(webappBase, "/WEB-INF/classes");
 1303               try {
 1304                   if (classes.exists()) {
 1305                       classPath = classPath + File.pathSeparator
 1306                           + classes.getCanonicalPath();
 1307                       urls.add(classes.getCanonicalFile().toURL());
 1308                   }
 1309               } catch (IOException ioe) {
 1310                   // failing a toCanonicalPath on a file that
 1311                   // exists() should be a JVM regression test,
 1312                   // therefore we have permission to freak out
 1313                   throw new RuntimeException(ioe.toString());
 1314               }
 1315               File lib = new File(webappBase, "/WEB-INF/lib");
 1316               if (lib.exists() && lib.isDirectory()) {
 1317                   String[] libs = lib.list();
 1318                   for (int i = 0; i < libs.length; i++) {
 1319                       if( libs[i].length() <5 ) continue;
 1320                       String ext=libs[i].substring( libs[i].length() - 4 );
 1321                       if (! ".jar".equalsIgnoreCase(ext)) {
 1322                           if (".tld".equalsIgnoreCase(ext)) {
 1323                               log.warn("TLD files should not be placed in "
 1324                                        + "/WEB-INF/lib");
 1325                           }
 1326                           continue;
 1327                       }
 1328                       try {
 1329                           File libFile = new File(lib, libs[i]);
 1330                           classPath = classPath + File.pathSeparator
 1331                               + libFile.getAbsolutePath();
 1332                           urls.add(libFile.getAbsoluteFile().toURL());
 1333                       } catch (IOException ioe) {
 1334                           // failing a toCanonicalPath on a file that
 1335                           // exists() should be a JVM regression test,
 1336                           // therefore we have permission to freak out
 1337                           throw new RuntimeException(ioe.toString());
 1338                       }
 1339                   }
 1340               }
 1341           }
 1342   
 1343           // What is this ??
 1344           urls.add(new File(clctxt.getRealPath("/")).getCanonicalFile().toURL());
 1345   
 1346           URL urlsA[]=new URL[urls.size()];
 1347           urls.toArray(urlsA);
 1348           loader = new URLClassLoader(urlsA, this.getClass().getClassLoader());
 1349   
 1350       }
 1351   
 1352       /**
 1353        * Find the WEB-INF dir by looking up in the directory tree.
 1354        * This is used if no explicit docbase is set, but only files.
 1355        * XXX Maybe we should require the docbase.
 1356        */
 1357       protected void locateUriRoot( File f ) {
 1358           String tUriBase = uriBase;
 1359           if (tUriBase == null) {
 1360               tUriBase = "/";
 1361           }
 1362           try {
 1363               if (f.exists()) {
 1364                   f = new File(f.getAbsolutePath());
 1365                   while (f != null) {
 1366                       File g = new File(f, "WEB-INF");
 1367                       if (g.exists() && g.isDirectory()) {
 1368                           uriRoot = f.getCanonicalPath();
 1369                           uriBase = tUriBase;
 1370                           if (log.isInfoEnabled()) {
 1371                               log.info(Localizer.getMessage(
 1372                                           "jspc.implicit.uriRoot",
 1373                                           uriRoot));
 1374                           }
 1375                           break;
 1376                       }
 1377                       if (f.exists() && f.isDirectory()) {
 1378                           tUriBase = "/" + f.getName() + "/" + tUriBase;
 1379                       }
 1380   
 1381                       String fParent = f.getParent();
 1382                       if (fParent == null) {
 1383                           break;
 1384                       } else {
 1385                           f = new File(fParent);
 1386                       }
 1387   
 1388                       // If there is no acceptible candidate, uriRoot will
 1389                       // remain null to indicate to the CompilerContext to
 1390                       // use the current working/user dir.
 1391                   }
 1392   
 1393                   if (uriRoot != null) {
 1394                       File froot = new File(uriRoot);
 1395                       uriRoot = froot.getCanonicalPath();
 1396                   }
 1397               }
 1398           } catch (IOException ioe) {
 1399               // since this is an optional default and a null value
 1400               // for uriRoot has a non-error meaning, we can just
 1401               // pass straight through
 1402           }
 1403       }
 1404   
 1405       /**
 1406        * Resolves the relative or absolute pathname correctly
 1407        * in both Ant and command-line situations.  If Ant launched
 1408        * us, we should use the basedir of the current project
 1409        * to resolve relative paths.
 1410        *
 1411        * See Bugzilla 35571.
 1412        *
 1413        * @param s The file
 1414        * @return The file resolved
 1415        */
 1416        protected File resolveFile(final String s) {
 1417            if(getProject() == null) {
 1418                // Note FileUtils.getFileUtils replaces FileUtils.newFileUtils in Ant 1.6.3
 1419                return FileUtils.newFileUtils().resolveFile(null, s);
 1420            } else {
 1421                return FileUtils.newFileUtils().resolveFile(getProject().getBaseDir(), s);
 1422            }
 1423        }
 1424   }

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