View Javadoc

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.struts2.jasper;
19  
20  import com.opensymphony.xwork2.util.logging.Logger;
21  import com.opensymphony.xwork2.util.logging.LoggerFactory;
22  import org.apache.struts2.jasper.compiler.JspConfig;
23  import org.apache.struts2.jasper.compiler.Localizer;
24  import org.apache.struts2.jasper.compiler.TagPluginManager;
25  import org.apache.struts2.jasper.compiler.TldLocationsCache;
26  import org.apache.struts2.jasper.xmlparser.ParserUtils;
27  
28  import javax.servlet.ServletConfig;
29  import javax.servlet.ServletContext;
30  import java.io.File;
31  import java.util.Enumeration;
32  import java.util.Map;
33  import java.util.Properties;
34  
35  /***
36   * A class to hold all init parameters specific to the JSP engine.
37   *
38   * @author Anil K. Vijendran
39   * @author Hans Bergsten
40   * @author Pierre Delisle
41   */
42  public final class EmbeddedServletOptions implements Options {
43  
44      // Logger
45      private Logger log = LoggerFactory.getLogger(EmbeddedServletOptions.class);
46  
47      private Properties settings = new Properties();
48  
49      /***
50       * Is Jasper being used in development mode?
51       */
52      private boolean development = true;
53  
54      /***
55       * Should Ant fork its java compiles of JSP pages.
56       */
57      public boolean fork = true;
58  
59      /***
60       * Do you want to keep the generated Java files around?
61       */
62      private boolean keepGenerated = true;
63  
64      /***
65       * Should white spaces between directives or actions be trimmed?
66       */
67      private boolean trimSpaces = false;
68  
69      /***
70       * Determines whether tag handler pooling is enabled.
71       */
72      private boolean isPoolingEnabled = true;
73  
74      /***
75       * Do you want support for "mapped" files? This will generate
76       * servlet that has a print statement per line of the JSP file.
77       * This seems like a really nice feature to have for debugging.
78       */
79      private boolean mappedFile = true;
80  
81      /***
82       * Do you want stack traces and such displayed in the client's
83       * browser? If this is false, such messages go to the standard
84       * error or a log file if the standard error is redirected.
85       */
86      private boolean sendErrorToClient = false;
87  
88      /***
89       * Do we want to include debugging information in the class file?
90       */
91      private boolean classDebugInfo = true;
92  
93      /***
94       * Background compile thread check interval in seconds.
95       */
96      private int checkInterval = 0;
97  
98      /***
99       * Is the generation of SMAP info for JSR45 debuggin suppressed?
100      */
101     private boolean isSmapSuppressed = false;
102 
103     /***
104      * Should SMAP info for JSR45 debugging be dumped to a file?
105      */
106     private boolean isSmapDumped = false;
107 
108     /***
109      * Are Text strings to be generated as char arrays?
110      */
111     private boolean genStringAsCharArray = false;
112 
113     private boolean errorOnUseBeanInvalidClassAttribute = true;
114 
115     /***
116      * I want to see my generated servlets. Which directory are they
117      * in?
118      */
119     private File scratchDir;
120 
121     /***
122      * Need to have this as is for versions 4 and 5 of IE. Can be set from
123      * the initParams so if it changes in the future all that is needed is
124      * to have a jsp initParam of type ieClassId="<value>"
125      */
126     private String ieClassId = "clsid:8AD9C840-044E-11D1-B3E9-00805F499D93";
127 
128     /***
129      * What classpath should I use while compiling generated servlets?
130      */
131     private String classpath = null;
132 
133     /***
134      * Compiler to use.
135      */
136     private String compiler = null;
137 
138     /***
139      * Compiler target VM.
140      */
141     private String compilerTargetVM = "1.5";
142 
143     /***
144      * The compiler source VM.
145      */
146     private String compilerSourceVM = "1.5";
147 
148     /***
149      * Cache for the TLD locations
150      */
151     private TldLocationsCache tldLocationsCache = null;
152 
153     /***
154      * Jsp config information
155      */
156     private JspConfig jspConfig = null;
157 
158     /***
159      * TagPluginManager
160      */
161     private TagPluginManager tagPluginManager = null;
162 
163     /***
164      * Java platform encoding to generate the JSP
165      * page servlet.
166      */
167     private String javaEncoding = "UTF8";
168 
169     /***
170      * Modification test interval.
171      */
172     private int modificationTestInterval = 4;
173 
174     /***
175      * Is generation of X-Powered-By response header enabled/disabled?
176      */
177     private boolean xpoweredBy;
178 
179     public String getProperty(String name) {
180         return settings.getProperty(name);
181     }
182 
183     public void setProperty(String name, String value) {
184         if (name != null && value != null) {
185             settings.setProperty(name, value);
186         }
187     }
188 
189     /***
190      * Are we keeping generated code around?
191      */
192     public boolean getKeepGenerated() {
193         return keepGenerated;
194     }
195 
196     /***
197      * Should white spaces between directives or actions be trimmed?
198      */
199     public boolean getTrimSpaces() {
200         return trimSpaces;
201     }
202 
203     public boolean isPoolingEnabled() {
204         return isPoolingEnabled;
205     }
206 
207     /***
208      * Are we supporting HTML mapped servlets?
209      */
210     public boolean getMappedFile() {
211         return mappedFile;
212     }
213 
214     /***
215      * Should errors be sent to client or thrown into stderr?
216      */
217     public boolean getSendErrorToClient() {
218         return sendErrorToClient;
219     }
220 
221     /***
222      * Should class files be compiled with debug information?
223      */
224     public boolean getClassDebugInfo() {
225         return classDebugInfo;
226     }
227 
228     /***
229      * Background JSP compile thread check intervall
230      */
231     public int getCheckInterval() {
232         return checkInterval;
233     }
234 
235     /***
236      * Modification test interval.
237      */
238     public int getModificationTestInterval() {
239         return modificationTestInterval;
240     }
241 
242     /***
243      * Is Jasper being used in development mode?
244      */
245     public boolean getDevelopment() {
246         return development;
247     }
248 
249     /***
250      * Is the generation of SMAP info for JSR45 debuggin suppressed?
251      */
252     public boolean isSmapSuppressed() {
253         return isSmapSuppressed;
254     }
255 
256     /***
257      * Should SMAP info for JSR45 debugging be dumped to a file?
258      */
259     public boolean isSmapDumped() {
260         return isSmapDumped;
261     }
262 
263     /***
264      * Are Text strings to be generated as char arrays?
265      */
266     public boolean genStringAsCharArray() {
267         return this.genStringAsCharArray;
268     }
269 
270     /***
271      * Class ID for use in the plugin tag when the browser is IE.
272      */
273     public String getIeClassId() {
274         return ieClassId;
275     }
276 
277     /***
278      * What is my scratch dir?
279      */
280     public File getScratchDir() {
281         return scratchDir;
282     }
283 
284     /***
285      * What classpath should I use while compiling the servlets
286      * generated from JSP files?
287      */
288     public String getClassPath() {
289         return classpath;
290     }
291 
292     /***
293      * Is generation of X-Powered-By response header enabled/disabled?
294      */
295     public boolean isXpoweredBy() {
296         return xpoweredBy;
297     }
298 
299     /***
300      * Compiler to use.
301      */
302     public String getCompiler() {
303         return compiler;
304     }
305 
306     /***
307      * @see Options#getCompilerTargetVM
308      */
309     public String getCompilerTargetVM() {
310         return compilerTargetVM;
311     }
312 
313     /***
314      * @see Options#getCompilerSourceVM
315      */
316     public String getCompilerSourceVM() {
317         return compilerSourceVM;
318     }
319 
320     public boolean getErrorOnUseBeanInvalidClassAttribute() {
321         return errorOnUseBeanInvalidClassAttribute;
322     }
323 
324     public void setErrorOnUseBeanInvalidClassAttribute(boolean b) {
325         errorOnUseBeanInvalidClassAttribute = b;
326     }
327 
328     public TldLocationsCache getTldLocationsCache() {
329         return tldLocationsCache;
330     }
331 
332     public void setTldLocationsCache(TldLocationsCache tldC) {
333         tldLocationsCache = tldC;
334     }
335 
336     public String getJavaEncoding() {
337         return javaEncoding;
338     }
339 
340     public boolean getFork() {
341         return fork;
342     }
343 
344     public JspConfig getJspConfig() {
345         return jspConfig;
346     }
347 
348     public TagPluginManager getTagPluginManager() {
349         return tagPluginManager;
350     }
351 
352     public boolean isCaching() {
353         return false;
354     }
355 
356     public Map getCache() {
357         return null;
358     }
359 
360     /***
361      * Create an EmbeddedServletOptions object using data available from
362      * ServletConfig and ServletContext.
363      */
364     public EmbeddedServletOptions(ServletConfig config,
365                                   ServletContext context) {
366 
367         // JVM version numbers
368         try {
369             if (Float.parseFloat(System.getProperty("java.specification.version")) > 1.4) {
370                 compilerSourceVM = compilerTargetVM = "1.5";
371             } else {
372                 compilerSourceVM = compilerTargetVM = "1.4";
373             }
374         } catch (NumberFormatException e) {
375             // Ignore
376         }
377 
378         Enumeration enumeration = config.getInitParameterNames();
379         while (enumeration.hasMoreElements()) {
380             String k = (String) enumeration.nextElement();
381             String v = config.getInitParameter(k);
382             setProperty(k, v);
383         }
384 
385         // quick hack
386         String validating = config.getInitParameter("validating");
387         if ("false".equals(validating)) ParserUtils.validating = false;
388 
389         String keepgen = config.getInitParameter("keepgenerated");
390         if (keepgen != null) {
391             if (keepgen.equalsIgnoreCase("true")) {
392                 this.keepGenerated = true;
393             } else if (keepgen.equalsIgnoreCase("false")) {
394                 this.keepGenerated = false;
395             } else {
396                 if (log.isWarnEnabled()) {
397                     log.warn(Localizer.getMessage("jsp.warning.keepgen"));
398                 }
399             }
400         }
401 
402 
403         String trimsp = config.getInitParameter("trimSpaces");
404         if (trimsp != null) {
405             if (trimsp.equalsIgnoreCase("true")) {
406                 trimSpaces = true;
407             } else if (trimsp.equalsIgnoreCase("false")) {
408                 trimSpaces = false;
409             } else {
410                 if (log.isWarnEnabled()) {
411                     log.warn(Localizer.getMessage("jsp.warning.trimspaces"));
412                 }
413             }
414         }
415 
416         this.isPoolingEnabled = true;
417         String poolingEnabledParam
418                 = config.getInitParameter("enablePooling");
419         if (poolingEnabledParam != null
420                 && !poolingEnabledParam.equalsIgnoreCase("true")) {
421             if (poolingEnabledParam.equalsIgnoreCase("false")) {
422                 this.isPoolingEnabled = false;
423             } else {
424                 if (log.isWarnEnabled()) {
425                     log.warn(Localizer.getMessage("jsp.warning.enablePooling"));
426                 }
427             }
428         }
429 
430         String mapFile = config.getInitParameter("mappedfile");
431         if (mapFile != null) {
432             if (mapFile.equalsIgnoreCase("true")) {
433                 this.mappedFile = true;
434             } else if (mapFile.equalsIgnoreCase("false")) {
435                 this.mappedFile = false;
436             } else {
437                 if (log.isWarnEnabled()) {
438                     log.warn(Localizer.getMessage("jsp.warning.mappedFile"));
439                 }
440             }
441         }
442 
443         String senderr = config.getInitParameter("sendErrToClient");
444         if (senderr != null) {
445             if (senderr.equalsIgnoreCase("true")) {
446                 this.sendErrorToClient = true;
447             } else if (senderr.equalsIgnoreCase("false")) {
448                 this.sendErrorToClient = false;
449             } else {
450                 if (log.isWarnEnabled()) {
451                     log.warn(Localizer.getMessage("jsp.warning.sendErrToClient"));
452                 }
453             }
454         }
455 
456         String debugInfo = config.getInitParameter("classdebuginfo");
457         if (debugInfo != null) {
458             if (debugInfo.equalsIgnoreCase("true")) {
459                 this.classDebugInfo = true;
460             } else if (debugInfo.equalsIgnoreCase("false")) {
461                 this.classDebugInfo = false;
462             } else {
463                 if (log.isWarnEnabled()) {
464                     log.warn(Localizer.getMessage("jsp.warning.classDebugInfo"));
465                 }
466             }
467         }
468 
469         String checkInterval = config.getInitParameter("checkInterval");
470         if (checkInterval != null) {
471             try {
472                 this.checkInterval = Integer.parseInt(checkInterval);
473             } catch (NumberFormatException ex) {
474                 if (log.isWarnEnabled()) {
475                     log.warn(Localizer.getMessage("jsp.warning.checkInterval"));
476                 }
477             }
478         }
479 
480         String modificationTestInterval = config.getInitParameter("modificationTestInterval");
481         if (modificationTestInterval != null) {
482             try {
483                 this.modificationTestInterval = Integer.parseInt(modificationTestInterval);
484             } catch (NumberFormatException ex) {
485                 if (log.isWarnEnabled()) {
486                     log.warn(Localizer.getMessage("jsp.warning.modificationTestInterval"));
487                 }
488             }
489         }
490 
491         String development = config.getInitParameter("development");
492         if (development != null) {
493             if (development.equalsIgnoreCase("true")) {
494                 this.development = true;
495             } else if (development.equalsIgnoreCase("false")) {
496                 this.development = false;
497             } else {
498                 if (log.isWarnEnabled()) {
499                     log.warn(Localizer.getMessage("jsp.warning.development"));
500                 }
501             }
502         }
503 
504         String suppressSmap = config.getInitParameter("suppressSmap");
505         if (suppressSmap != null) {
506             if (suppressSmap.equalsIgnoreCase("true")) {
507                 isSmapSuppressed = true;
508             } else if (suppressSmap.equalsIgnoreCase("false")) {
509                 isSmapSuppressed = false;
510             } else {
511                 if (log.isWarnEnabled()) {
512                     log.warn(Localizer.getMessage("jsp.warning.suppressSmap"));
513                 }
514             }
515         }
516 
517         String dumpSmap = config.getInitParameter("dumpSmap");
518         if (dumpSmap != null) {
519             if (dumpSmap.equalsIgnoreCase("true")) {
520                 isSmapDumped = true;
521             } else if (dumpSmap.equalsIgnoreCase("false")) {
522                 isSmapDumped = false;
523             } else {
524                 if (log.isWarnEnabled()) {
525                     log.warn(Localizer.getMessage("jsp.warning.dumpSmap"));
526                 }
527             }
528         }
529 
530         String genCharArray = config.getInitParameter("genStrAsCharArray");
531         if (genCharArray != null) {
532             if (genCharArray.equalsIgnoreCase("true")) {
533                 genStringAsCharArray = true;
534             } else if (genCharArray.equalsIgnoreCase("false")) {
535                 genStringAsCharArray = false;
536             } else {
537                 if (log.isWarnEnabled()) {
538                     log.warn(Localizer.getMessage("jsp.warning.genchararray"));
539                 }
540             }
541         }
542 
543         String errBeanClass =
544                 config.getInitParameter("errorOnUseBeanInvalidClassAttribute");
545         if (errBeanClass != null) {
546             if (errBeanClass.equalsIgnoreCase("true")) {
547                 errorOnUseBeanInvalidClassAttribute = true;
548             } else if (errBeanClass.equalsIgnoreCase("false")) {
549                 errorOnUseBeanInvalidClassAttribute = false;
550             } else {
551                 if (log.isWarnEnabled()) {
552                     log.warn(Localizer.getMessage("jsp.warning.errBean"));
553                 }
554             }
555         }
556 
557         String ieClassId = config.getInitParameter("ieClassId");
558         if (ieClassId != null)
559             this.ieClassId = ieClassId;
560 
561         String classpath = config.getInitParameter("classpath");
562         if (classpath != null)
563             this.classpath = classpath;
564 
565         /*
566         * scratchdir
567         */
568         String dir = config.getInitParameter("scratchdir");
569         if (dir != null) {
570             scratchDir = new File(dir);
571         } else {
572             // First try the Servlet 2.2 javax.servlet.context.tempdir property
573             scratchDir = (File) context.getAttribute(Constants.TMP_DIR);
574             if (scratchDir == null) {
575                 // Not running in a Servlet 2.2 container.
576                 // Try to get the JDK 1.2 java.io.tmpdir property
577                 dir = System.getProperty("java.io.tmpdir");
578                 if (dir != null)
579                     scratchDir = new File(dir);
580             }
581         }
582         if (this.scratchDir == null) {
583             log.fatal(Localizer.getMessage("jsp.error.no.scratch.dir"));
584             return;
585         }
586 
587         if (!(scratchDir.exists() && scratchDir.canRead() &&
588                 scratchDir.canWrite() && scratchDir.isDirectory()))
589             log.fatal(Localizer.getMessage("jsp.error.bad.scratch.dir",
590                     scratchDir.getAbsolutePath()));
591 
592         this.compiler = config.getInitParameter("compiler");
593 
594         String compilerTargetVM = config.getInitParameter("compilerTargetVM");
595         if (compilerTargetVM != null) {
596             this.compilerTargetVM = compilerTargetVM;
597         }
598 
599         String compilerSourceVM = config.getInitParameter("compilerSourceVM");
600         if (compilerSourceVM != null) {
601             this.compilerSourceVM = compilerSourceVM;
602         }
603 
604         String javaEncoding = config.getInitParameter("javaEncoding");
605         if (javaEncoding != null) {
606             this.javaEncoding = javaEncoding;
607         }
608 
609         String fork = config.getInitParameter("fork");
610         if (fork != null) {
611             if (fork.equalsIgnoreCase("true")) {
612                 this.fork = true;
613             } else if (fork.equalsIgnoreCase("false")) {
614                 this.fork = false;
615             } else {
616                 if (log.isWarnEnabled()) {
617                     log.warn(Localizer.getMessage("jsp.warning.fork"));
618                 }
619             }
620         }
621 
622         String xpoweredBy = config.getInitParameter("xpoweredBy");
623         if (xpoweredBy != null) {
624             if (xpoweredBy.equalsIgnoreCase("true")) {
625                 this.xpoweredBy = true;
626             } else if (xpoweredBy.equalsIgnoreCase("false")) {
627                 this.xpoweredBy = false;
628             } else {
629                 if (log.isWarnEnabled()) {
630                     log.warn(Localizer.getMessage("jsp.warning.xpoweredBy"));
631                 }
632             }
633         }
634 
635         // Setup the global Tag Libraries location cache for this
636         // web-application.
637         tldLocationsCache = new TldLocationsCache(context);
638 
639         // Setup the jsp config info for this web app.
640         jspConfig = new JspConfig(context);
641 
642         // Create a Tag plugin instance
643         tagPluginManager = new TagPluginManager(context);
644     }
645 
646 }
647