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