001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.jasper;
019:
020: import java.io.File;
021: import java.util.*;
022:
023: import javax.servlet.ServletConfig;
024: import javax.servlet.ServletContext;
025:
026: import org.apache.jasper.compiler.TldLocationsCache;
027: import org.apache.jasper.compiler.JspConfig;
028: import org.apache.jasper.compiler.TagPluginManager;
029: import org.apache.jasper.compiler.Localizer;
030: import org.apache.jasper.xmlparser.ParserUtils;
031: import org.apache.juli.logging.Log;
032: import org.apache.juli.logging.LogFactory;
033:
034: /**
035: * A class to hold all init parameters specific to the JSP engine.
036: *
037: * @author Anil K. Vijendran
038: * @author Hans Bergsten
039: * @author Pierre Delisle
040: */
041: public final class EmbeddedServletOptions implements Options {
042:
043: // Logger
044: private Log log = LogFactory.getLog(EmbeddedServletOptions.class);
045:
046: private Properties settings = new Properties();
047:
048: /**
049: * Is Jasper being used in development mode?
050: */
051: private boolean development = true;
052:
053: /**
054: * Should Ant fork its java compiles of JSP pages.
055: */
056: public boolean fork = true;
057:
058: /**
059: * Do you want to keep the generated Java files around?
060: */
061: private boolean keepGenerated = true;
062:
063: /**
064: * Should white spaces between directives or actions be trimmed?
065: */
066: private boolean trimSpaces = false;
067:
068: /**
069: * Determines whether tag handler pooling is enabled.
070: */
071: private boolean isPoolingEnabled = true;
072:
073: /**
074: * Do you want support for "mapped" files? This will generate
075: * servlet that has a print statement per line of the JSP file.
076: * This seems like a really nice feature to have for debugging.
077: */
078: private boolean mappedFile = true;
079:
080: /**
081: * Do you want stack traces and such displayed in the client's
082: * browser? If this is false, such messages go to the standard
083: * error or a log file if the standard error is redirected.
084: */
085: private boolean sendErrorToClient = false;
086:
087: /**
088: * Do we want to include debugging information in the class file?
089: */
090: private boolean classDebugInfo = true;
091:
092: /**
093: * Background compile thread check interval in seconds.
094: */
095: private int checkInterval = 0;
096:
097: /**
098: * Is the generation of SMAP info for JSR45 debuggin suppressed?
099: */
100: private boolean isSmapSuppressed = false;
101:
102: /**
103: * Should SMAP info for JSR45 debugging be dumped to a file?
104: */
105: private boolean isSmapDumped = false;
106:
107: /**
108: * Are Text strings to be generated as char arrays?
109: */
110: private boolean genStringAsCharArray = false;
111:
112: private boolean errorOnUseBeanInvalidClassAttribute = true;
113:
114: /**
115: * I want to see my generated servlets. Which directory are they
116: * in?
117: */
118: private File scratchDir;
119:
120: /**
121: * Need to have this as is for versions 4 and 5 of IE. Can be set from
122: * the initParams so if it changes in the future all that is needed is
123: * to have a jsp initParam of type ieClassId="<value>"
124: */
125: private String ieClassId = "clsid:8AD9C840-044E-11D1-B3E9-00805F499D93";
126:
127: /**
128: * What classpath should I use while compiling generated servlets?
129: */
130: private String classpath = null;
131:
132: /**
133: * Compiler to use.
134: */
135: private String compiler = null;
136:
137: /**
138: * Compiler target VM.
139: */
140: private String compilerTargetVM = "1.5";
141:
142: /**
143: * The compiler source VM.
144: */
145: private String compilerSourceVM = "1.5";
146:
147: /**
148: * The compiler class name.
149: */
150: private String compilerClassName = null;
151:
152: /**
153: * Cache for the TLD locations
154: */
155: private TldLocationsCache tldLocationsCache = null;
156:
157: /**
158: * Jsp config information
159: */
160: private JspConfig jspConfig = null;
161:
162: /**
163: * TagPluginManager
164: */
165: private TagPluginManager tagPluginManager = null;
166:
167: /**
168: * Java platform encoding to generate the JSP
169: * page servlet.
170: */
171: private String javaEncoding = "UTF8";
172:
173: /**
174: * Modification test interval.
175: */
176: private int modificationTestInterval = 4;
177:
178: /**
179: * Is generation of X-Powered-By response header enabled/disabled?
180: */
181: private boolean xpoweredBy;
182:
183: /**
184: * Should we include a source fragment in exception messages, which could be displayed
185: * to the developer ?
186: */
187: private boolean displaySourceFragment = true;
188:
189: public String getProperty(String name) {
190: return settings.getProperty(name);
191: }
192:
193: public void setProperty(String name, String value) {
194: if (name != null && value != null) {
195: settings.setProperty(name, value);
196: }
197: }
198:
199: /**
200: * Are we keeping generated code around?
201: */
202: public boolean getKeepGenerated() {
203: return keepGenerated;
204: }
205:
206: /**
207: * Should white spaces between directives or actions be trimmed?
208: */
209: public boolean getTrimSpaces() {
210: return trimSpaces;
211: }
212:
213: public boolean isPoolingEnabled() {
214: return isPoolingEnabled;
215: }
216:
217: /**
218: * Are we supporting HTML mapped servlets?
219: */
220: public boolean getMappedFile() {
221: return mappedFile;
222: }
223:
224: /**
225: * Should errors be sent to client or thrown into stderr?
226: */
227: public boolean getSendErrorToClient() {
228: return sendErrorToClient;
229: }
230:
231: /**
232: * Should class files be compiled with debug information?
233: */
234: public boolean getClassDebugInfo() {
235: return classDebugInfo;
236: }
237:
238: /**
239: * Background JSP compile thread check intervall
240: */
241: public int getCheckInterval() {
242: return checkInterval;
243: }
244:
245: /**
246: * Modification test interval.
247: */
248: public int getModificationTestInterval() {
249: return modificationTestInterval;
250: }
251:
252: /**
253: * Is Jasper being used in development mode?
254: */
255: public boolean getDevelopment() {
256: return development;
257: }
258:
259: /**
260: * Is the generation of SMAP info for JSR45 debuggin suppressed?
261: */
262: public boolean isSmapSuppressed() {
263: return isSmapSuppressed;
264: }
265:
266: /**
267: * Should SMAP info for JSR45 debugging be dumped to a file?
268: */
269: public boolean isSmapDumped() {
270: return isSmapDumped;
271: }
272:
273: /**
274: * Are Text strings to be generated as char arrays?
275: */
276: public boolean genStringAsCharArray() {
277: return this .genStringAsCharArray;
278: }
279:
280: /**
281: * Class ID for use in the plugin tag when the browser is IE.
282: */
283: public String getIeClassId() {
284: return ieClassId;
285: }
286:
287: /**
288: * What is my scratch dir?
289: */
290: public File getScratchDir() {
291: return scratchDir;
292: }
293:
294: /**
295: * What classpath should I use while compiling the servlets
296: * generated from JSP files?
297: */
298: public String getClassPath() {
299: return classpath;
300: }
301:
302: /**
303: * Is generation of X-Powered-By response header enabled/disabled?
304: */
305: public boolean isXpoweredBy() {
306: return xpoweredBy;
307: }
308:
309: /**
310: * Compiler to use.
311: */
312: public String getCompiler() {
313: return compiler;
314: }
315:
316: /**
317: * @see Options#getCompilerTargetVM
318: */
319: public String getCompilerTargetVM() {
320: return compilerTargetVM;
321: }
322:
323: /**
324: * @see Options#getCompilerSourceVM
325: */
326: public String getCompilerSourceVM() {
327: return compilerSourceVM;
328: }
329:
330: /**
331: * Java compiler class to use.
332: */
333: public String getCompilerClassName() {
334: return compilerClassName;
335: }
336:
337: public boolean getErrorOnUseBeanInvalidClassAttribute() {
338: return errorOnUseBeanInvalidClassAttribute;
339: }
340:
341: public void setErrorOnUseBeanInvalidClassAttribute(boolean b) {
342: errorOnUseBeanInvalidClassAttribute = b;
343: }
344:
345: public TldLocationsCache getTldLocationsCache() {
346: return tldLocationsCache;
347: }
348:
349: public void setTldLocationsCache(TldLocationsCache tldC) {
350: tldLocationsCache = tldC;
351: }
352:
353: public String getJavaEncoding() {
354: return javaEncoding;
355: }
356:
357: public boolean getFork() {
358: return fork;
359: }
360:
361: public JspConfig getJspConfig() {
362: return jspConfig;
363: }
364:
365: public TagPluginManager getTagPluginManager() {
366: return tagPluginManager;
367: }
368:
369: public boolean isCaching() {
370: return false;
371: }
372:
373: public Map getCache() {
374: return null;
375: }
376:
377: /**
378: * Should we include a source fragment in exception messages, which could be displayed
379: * to the developer ?
380: */
381: public boolean getDisplaySourceFragment() {
382: return displaySourceFragment;
383: }
384:
385: /**
386: * Create an EmbeddedServletOptions object using data available from
387: * ServletConfig and ServletContext.
388: */
389: public EmbeddedServletOptions(ServletConfig config,
390: ServletContext context) {
391:
392: // JVM version numbers
393: try {
394: if (Float.parseFloat(System
395: .getProperty("java.specification.version")) > 1.4) {
396: compilerSourceVM = compilerTargetVM = "1.5";
397: } else {
398: compilerSourceVM = compilerTargetVM = "1.4";
399: }
400: } catch (NumberFormatException e) {
401: // Ignore
402: }
403:
404: Enumeration enumeration = config.getInitParameterNames();
405: while (enumeration.hasMoreElements()) {
406: String k = (String) enumeration.nextElement();
407: String v = config.getInitParameter(k);
408: setProperty(k, v);
409: }
410:
411: // quick hack
412: String validating = config.getInitParameter("validating");
413: if ("false".equals(validating))
414: ParserUtils.validating = false;
415:
416: String keepgen = config.getInitParameter("keepgenerated");
417: if (keepgen != null) {
418: if (keepgen.equalsIgnoreCase("true")) {
419: this .keepGenerated = true;
420: } else if (keepgen.equalsIgnoreCase("false")) {
421: this .keepGenerated = false;
422: } else {
423: if (log.isWarnEnabled()) {
424: log.warn(Localizer
425: .getMessage("jsp.warning.keepgen"));
426: }
427: }
428: }
429:
430: String trimsp = config.getInitParameter("trimSpaces");
431: if (trimsp != null) {
432: if (trimsp.equalsIgnoreCase("true")) {
433: trimSpaces = true;
434: } else if (trimsp.equalsIgnoreCase("false")) {
435: trimSpaces = false;
436: } else {
437: if (log.isWarnEnabled()) {
438: log.warn(Localizer
439: .getMessage("jsp.warning.trimspaces"));
440: }
441: }
442: }
443:
444: this .isPoolingEnabled = true;
445: String poolingEnabledParam = config
446: .getInitParameter("enablePooling");
447: if (poolingEnabledParam != null
448: && !poolingEnabledParam.equalsIgnoreCase("true")) {
449: if (poolingEnabledParam.equalsIgnoreCase("false")) {
450: this .isPoolingEnabled = false;
451: } else {
452: if (log.isWarnEnabled()) {
453: log.warn(Localizer
454: .getMessage("jsp.warning.enablePooling"));
455: }
456: }
457: }
458:
459: String mapFile = config.getInitParameter("mappedfile");
460: if (mapFile != null) {
461: if (mapFile.equalsIgnoreCase("true")) {
462: this .mappedFile = true;
463: } else if (mapFile.equalsIgnoreCase("false")) {
464: this .mappedFile = false;
465: } else {
466: if (log.isWarnEnabled()) {
467: log.warn(Localizer
468: .getMessage("jsp.warning.mappedFile"));
469: }
470: }
471: }
472:
473: String senderr = config.getInitParameter("sendErrToClient");
474: if (senderr != null) {
475: if (senderr.equalsIgnoreCase("true")) {
476: this .sendErrorToClient = true;
477: } else if (senderr.equalsIgnoreCase("false")) {
478: this .sendErrorToClient = false;
479: } else {
480: if (log.isWarnEnabled()) {
481: log.warn(Localizer
482: .getMessage("jsp.warning.sendErrToClient"));
483: }
484: }
485: }
486:
487: String debugInfo = config.getInitParameter("classdebuginfo");
488: if (debugInfo != null) {
489: if (debugInfo.equalsIgnoreCase("true")) {
490: this .classDebugInfo = true;
491: } else if (debugInfo.equalsIgnoreCase("false")) {
492: this .classDebugInfo = false;
493: } else {
494: if (log.isWarnEnabled()) {
495: log.warn(Localizer
496: .getMessage("jsp.warning.classDebugInfo"));
497: }
498: }
499: }
500:
501: String checkInterval = config.getInitParameter("checkInterval");
502: if (checkInterval != null) {
503: try {
504: this .checkInterval = Integer.parseInt(checkInterval);
505: } catch (NumberFormatException ex) {
506: if (log.isWarnEnabled()) {
507: log.warn(Localizer
508: .getMessage("jsp.warning.checkInterval"));
509: }
510: }
511: }
512:
513: String modificationTestInterval = config
514: .getInitParameter("modificationTestInterval");
515: if (modificationTestInterval != null) {
516: try {
517: this .modificationTestInterval = Integer
518: .parseInt(modificationTestInterval);
519: } catch (NumberFormatException ex) {
520: if (log.isWarnEnabled()) {
521: log
522: .warn(Localizer
523: .getMessage("jsp.warning.modificationTestInterval"));
524: }
525: }
526: }
527:
528: String development = config.getInitParameter("development");
529: if (development != null) {
530: if (development.equalsIgnoreCase("true")) {
531: this .development = true;
532: } else if (development.equalsIgnoreCase("false")) {
533: this .development = false;
534: } else {
535: if (log.isWarnEnabled()) {
536: log.warn(Localizer
537: .getMessage("jsp.warning.development"));
538: }
539: }
540: }
541:
542: String suppressSmap = config.getInitParameter("suppressSmap");
543: if (suppressSmap != null) {
544: if (suppressSmap.equalsIgnoreCase("true")) {
545: isSmapSuppressed = true;
546: } else if (suppressSmap.equalsIgnoreCase("false")) {
547: isSmapSuppressed = false;
548: } else {
549: if (log.isWarnEnabled()) {
550: log.warn(Localizer
551: .getMessage("jsp.warning.suppressSmap"));
552: }
553: }
554: }
555:
556: String dumpSmap = config.getInitParameter("dumpSmap");
557: if (dumpSmap != null) {
558: if (dumpSmap.equalsIgnoreCase("true")) {
559: isSmapDumped = true;
560: } else if (dumpSmap.equalsIgnoreCase("false")) {
561: isSmapDumped = false;
562: } else {
563: if (log.isWarnEnabled()) {
564: log.warn(Localizer
565: .getMessage("jsp.warning.dumpSmap"));
566: }
567: }
568: }
569:
570: String genCharArray = config
571: .getInitParameter("genStrAsCharArray");
572: if (genCharArray != null) {
573: if (genCharArray.equalsIgnoreCase("true")) {
574: genStringAsCharArray = true;
575: } else if (genCharArray.equalsIgnoreCase("false")) {
576: genStringAsCharArray = false;
577: } else {
578: if (log.isWarnEnabled()) {
579: log.warn(Localizer
580: .getMessage("jsp.warning.genchararray"));
581: }
582: }
583: }
584:
585: String errBeanClass = config
586: .getInitParameter("errorOnUseBeanInvalidClassAttribute");
587: if (errBeanClass != null) {
588: if (errBeanClass.equalsIgnoreCase("true")) {
589: errorOnUseBeanInvalidClassAttribute = true;
590: } else if (errBeanClass.equalsIgnoreCase("false")) {
591: errorOnUseBeanInvalidClassAttribute = false;
592: } else {
593: if (log.isWarnEnabled()) {
594: log.warn(Localizer
595: .getMessage("jsp.warning.errBean"));
596: }
597: }
598: }
599:
600: String ieClassId = config.getInitParameter("ieClassId");
601: if (ieClassId != null)
602: this .ieClassId = ieClassId;
603:
604: String classpath = config.getInitParameter("classpath");
605: if (classpath != null)
606: this .classpath = classpath;
607:
608: /*
609: * scratchdir
610: */
611: String dir = config.getInitParameter("scratchdir");
612: if (dir != null) {
613: scratchDir = new File(dir);
614: } else {
615: // First try the Servlet 2.2 javax.servlet.context.tempdir property
616: scratchDir = (File) context.getAttribute(Constants.TMP_DIR);
617: if (scratchDir == null) {
618: // Not running in a Servlet 2.2 container.
619: // Try to get the JDK 1.2 java.io.tmpdir property
620: dir = System.getProperty("java.io.tmpdir");
621: if (dir != null)
622: scratchDir = new File(dir);
623: }
624: }
625: if (this .scratchDir == null) {
626: log.fatal(Localizer.getMessage("jsp.error.no.scratch.dir"));
627: return;
628: }
629:
630: if (!(scratchDir.exists() && scratchDir.canRead()
631: && scratchDir.canWrite() && scratchDir.isDirectory()))
632: log.fatal(Localizer.getMessage("jsp.error.bad.scratch.dir",
633: scratchDir.getAbsolutePath()));
634:
635: this .compiler = config.getInitParameter("compiler");
636:
637: String compilerTargetVM = config
638: .getInitParameter("compilerTargetVM");
639: if (compilerTargetVM != null) {
640: this .compilerTargetVM = compilerTargetVM;
641: }
642:
643: String compilerSourceVM = config
644: .getInitParameter("compilerSourceVM");
645: if (compilerSourceVM != null) {
646: this .compilerSourceVM = compilerSourceVM;
647: }
648:
649: String javaEncoding = config.getInitParameter("javaEncoding");
650: if (javaEncoding != null) {
651: this .javaEncoding = javaEncoding;
652: }
653:
654: String compilerClassName = config
655: .getInitParameter("compilerClassName");
656: if (compilerClassName != null) {
657: this .compilerClassName = compilerClassName;
658: }
659:
660: String fork = config.getInitParameter("fork");
661: if (fork != null) {
662: if (fork.equalsIgnoreCase("true")) {
663: this .fork = true;
664: } else if (fork.equalsIgnoreCase("false")) {
665: this .fork = false;
666: } else {
667: if (log.isWarnEnabled()) {
668: log.warn(Localizer.getMessage("jsp.warning.fork"));
669: }
670: }
671: }
672:
673: String xpoweredBy = config.getInitParameter("xpoweredBy");
674: if (xpoweredBy != null) {
675: if (xpoweredBy.equalsIgnoreCase("true")) {
676: this .xpoweredBy = true;
677: } else if (xpoweredBy.equalsIgnoreCase("false")) {
678: this .xpoweredBy = false;
679: } else {
680: if (log.isWarnEnabled()) {
681: log.warn(Localizer
682: .getMessage("jsp.warning.xpoweredBy"));
683: }
684: }
685: }
686:
687: String displaySourceFragment = config
688: .getInitParameter("displaySourceFragment");
689: if (displaySourceFragment != null) {
690: if (displaySourceFragment.equalsIgnoreCase("true")) {
691: this .displaySourceFragment = true;
692: } else if (displaySourceFragment.equalsIgnoreCase("false")) {
693: this .displaySourceFragment = false;
694: } else {
695: if (log.isWarnEnabled()) {
696: log
697: .warn(Localizer
698: .getMessage("jsp.warning.displaySourceFragment"));
699: }
700: }
701: }
702:
703: // Setup the global Tag Libraries location cache for this
704: // web-application.
705: tldLocationsCache = new TldLocationsCache(context);
706:
707: // Setup the jsp config info for this web app.
708: jspConfig = new JspConfig(context);
709:
710: // Create a Tag plugin instance
711: tagPluginManager = new TagPluginManager(context);
712: }
713:
714: }
|