1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
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
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
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
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
567
568 String dir = config.getInitParameter("scratchdir");
569 if (dir != null) {
570 scratchDir = new File(dir);
571 } else {
572
573 scratchDir = (File) context.getAttribute(Constants.TMP_DIR);
574 if (scratchDir == null) {
575
576
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
636
637 tldLocationsCache = new TldLocationsCache(context);
638
639
640 jspConfig = new JspConfig(context);
641
642
643 tagPluginManager = new TagPluginManager(context);
644 }
645
646 }
647