0001: /*
0002: GNUJSP - a free JSP implementation
0003: Copyright (C) 1998-1999, Vincent Partington <vinny@klomp.org>
0004:
0005: This program is free software; you can redistribute it and/or
0006: modify it under the terms of the GNU General Public License
0007: as published by the Free Software Foundation; either version 2
0008: of the License, or (at your option) any later version.
0009:
0010: This program is distributed in the hope that it will be useful,
0011: but WITHOUT ANY WARRANTY; without even the implied warranty of
0012: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0013: GNU General Public License for more details.
0014:
0015: You should have received a copy of the GNU General Public License
0016: along with this program; if not, write to the Free Software
0017: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
0018: */
0019:
0020: package org.gjt.jsp;
0021:
0022: import java.io.BufferedReader;
0023: import java.io.ByteArrayOutputStream;
0024: import java.io.File;
0025: import java.io.FileNotFoundException;
0026: import java.io.FileReader;
0027: import java.io.FileWriter;
0028: import java.io.IOException;
0029: import java.io.InputStreamReader;
0030: import java.io.LineNumberReader;
0031: import java.io.OutputStream;
0032: import java.io.PrintStream;
0033: import java.io.PrintWriter;
0034: import java.io.StringReader;
0035: import java.util.Enumeration;
0036: import java.util.Hashtable;
0037: import java.util.Properties;
0038: import java.util.StringTokenizer;
0039: import java.util.Vector;
0040:
0041: import javax.servlet.http.HttpServletRequest;
0042: import javax.servlet.http.HttpServletResponse;
0043:
0044: import Acme.Utils;
0045:
0046: /**
0047: * This JSP compiler class takes the quick&dirty approach to JSP parsing.
0048: * The whole JSP file is read into memory and an index is run through it
0049: * until a StringIndexOutOfBoundsException occurs. I was happily hacking
0050: * away at this until I discovered it had gotten more than 30K long. It
0051: * seems to work, but someday it might be a good idea to break this
0052: * all up into separate classes, like a JSPParser, JavaGenerator en
0053: * JavaCompiler class.
0054: *
0055: * A new JSPCompiler should be created every time a file is compiled.
0056: * The classfiles directory, the file and the classname are parameters
0057: * to the constructor. Call compile() to do the actual compiling.
0058: */
0059: public class JSPCompiler {
0060: public static final int COMPILER_VERSION_NR = 4;
0061:
0062: private static final int PARSE_NONE = 0, PARSE_HTML = 1,
0063: PARSE_DECLARATION = 2, PARSE_SCRIPTLET = 3,
0064: PARSE_EXPRESSION = 4;
0065:
0066: private static final String lineSeparator = System
0067: .getProperty("line.separator"),
0068: encodedLineSeparator = javaStringEncode(System
0069: .getProperty("line.separator"));
0070:
0071: private JSPServlet jspServlet;
0072: private File jspFile, javaFile, classFile;
0073: private String className;
0074: private HttpServletRequest servletRequest;
0075:
0076: private String src;
0077: private int srcPos, lineNr;
0078:
0079: private int parseState = PARSE_NONE;
0080: private boolean justWroteNewline = false;
0081:
0082: private Vector dependencies = new Vector();
0083: private boolean createSession = false;
0084: private String content_typeDirective = null;
0085: private StringBuffer extendsDirective = new StringBuffer(),
0086: implements Directive = new StringBuffer(),
0087: importDirective = new StringBuffer(),
0088: methodDirective = new StringBuffer(),
0089: declarationsCode = new StringBuffer(),
0090: beanCode = new StringBuffer(),
0091: scriptletsCode = new StringBuffer();
0092:
0093: /**
0094: * Create a JSPCompiler object.
0095: */
0096: public JSPCompiler(JSPServlet jspServlet, File jspFile,
0097: String className, HttpServletRequest servletRequest) {
0098: this .jspServlet = jspServlet;
0099: this .jspFile = jspFile;
0100: this .javaFile = getFileForClass(jspServlet.repository,
0101: className, ".java");
0102: this .classFile = getFileForClass(jspServlet.repository,
0103: className, ".class");
0104: this .className = className;
0105: this .servletRequest = servletRequest;
0106: }
0107:
0108: /**
0109: * Do the actual compilation. This is done in three phases:
0110: * <OL>
0111: * <LI>parse the JSP file
0112: * <LI>generate a <CODE>.java</CODE> file
0113: * <LI>compile the <CODE>.java</CODE> file into a <CODE>.class</CODE> file
0114: * </OL>
0115: *
0116: * @exception JSPException is thrown when a compilation error occurs
0117: */
0118: public void compile() throws JSPException {
0119: parseJspFile();
0120: generateJavaFile();
0121: compileJavaFile();
0122: }
0123:
0124: private void parseJspFile() throws JSPException {
0125: parseOneJspFile();
0126: changeParseState(PARSE_NONE);
0127:
0128: if (content_typeDirective == null) {
0129: content_typeDirective = jspServlet.defaultContentType;
0130: }
0131: if (extendsDirective.length() == 0) {
0132: extendsDirective.append("javax.servlet.http.HttpServlet");
0133: }
0134: if (methodDirective.length() == 0) {
0135: methodDirective.append("service");
0136: }
0137: }
0138:
0139: private void parseOneJspFile() throws JSPException {
0140: BufferedReader in;
0141: StringBuffer srcBuf;
0142: String s;
0143: int i;
0144: char c, d;
0145:
0146: // read jsp source
0147: dependencies.addElement(jspFile);
0148: dependencies.addElement(new Long(jspFile.lastModified()));
0149: try {
0150: in = new BufferedReader(new FileReader(jspFile));
0151: try {
0152: srcBuf = new StringBuffer((int) jspFile.length());
0153: while ((s = in.readLine()) != null) {
0154: srcBuf.append(s).append((char) '\n');
0155: }
0156: src = srcBuf.toString();
0157: srcBuf = null;
0158: } finally {
0159: in.close();
0160: }
0161: } catch (FileNotFoundException fnfexc) {
0162: throw new JSPException(HttpServletResponse.SC_NOT_FOUND,
0163: "File " + jspFile + " could not be found");
0164: } catch (IOException ioexc) {
0165: throw new JSPException(ioexc.toString());
0166: }
0167:
0168: // parse jsp source
0169: lineNr = 1;
0170: srcPos = 0;
0171: try {
0172: PARSING: for (;;) {
0173: c = src.charAt(srcPos);
0174:
0175: // check for possible state change
0176: if (c == '<') {
0177: if (parseState == PARSE_NONE
0178: || parseState == PARSE_HTML) {
0179: if (parseInNoneOrHtmlState()) {
0180: continue PARSING;
0181: }
0182: } else if (parseState == PARSE_DECLARATION) {
0183: if (parseInDeclarationState()) {
0184: continue PARSING;
0185: }
0186: }
0187: } else if (c == '%'
0188: && (parseState == PARSE_EXPRESSION || parseState == PARSE_SCRIPTLET)
0189: && (srcPos < src.length() - 1 && src
0190: .charAt(srcPos + 1) == '>')) {
0191: // end of expression or scriptlet
0192: changeParseState(PARSE_NONE);
0193: srcPos += 2;
0194: continue PARSING;
0195: }
0196:
0197: // output character
0198: switch (parseState) {
0199: case PARSE_NONE:
0200: changeParseState(PARSE_HTML);
0201: case PARSE_HTML:
0202: if (justWroteNewline && c != '\n') {
0203: justWroteNewline = false;
0204: scriptletsCode.append("\" +").append(
0205: lineSeparator).append("\t\t\t\"");
0206: }
0207:
0208: switch (c) {
0209: case '\b':
0210: scriptletsCode.append("\\b");
0211: break;
0212: case '\t':
0213: scriptletsCode.append("\\t");
0214: break;
0215: case '\n':
0216: scriptletsCode.append(encodedLineSeparator);
0217: justWroteNewline = true;
0218: lineNr++;
0219: break;
0220: case '\f':
0221: scriptletsCode.append("\\f");
0222: break;
0223: case '\'':
0224: scriptletsCode.append("\\\'");
0225: break;
0226: case '\"':
0227: scriptletsCode.append("\\\"");
0228: break;
0229: case '\\':
0230: scriptletsCode.append("\\\\");
0231: break;
0232: default:
0233: if (c > 0xFF) {
0234: s = "00" + Integer.toHexString(c);
0235: scriptletsCode.append("\\u").append(
0236: s.substring(s.length() - 4));
0237: } else if (c < ' ' || c >= 0x7F) {
0238: s = "00" + Integer.toOctalString(c);
0239: scriptletsCode.append((char) '\\').append(
0240: s.substring(s.length() - 3));
0241: } else {
0242: scriptletsCode.append((char) c);
0243: }
0244: break;
0245: }
0246: break;
0247: case PARSE_DECLARATION:
0248: if (c == '\n') {
0249: declarationsCode.append(lineSeparator);
0250: lineNr++;
0251: } else {
0252: declarationsCode.append((char) c);
0253: }
0254: break;
0255: default:
0256: if (c == '\n') {
0257: scriptletsCode.append(lineSeparator);
0258: lineNr++;
0259: } else {
0260: scriptletsCode.append((char) c);
0261: }
0262: break;
0263: }
0264: srcPos++;
0265: }
0266: } catch (StringIndexOutOfBoundsException sioobexc) {
0267: // instead of checking for the end of the string ourselves
0268: // we let java.lang.String find it. This makes the code
0269: // simpeler and more efficient.
0270: }
0271: }
0272:
0273: private boolean parseInNoneOrHtmlState()
0274: throws StringIndexOutOfBoundsException, JSPException {
0275: String[] keyAndValue;
0276: char d;
0277:
0278: if (srcPos < src.length() - 3 && src.charAt(srcPos + 1) == '%') {
0279: // directive or start of expression or scriptlet
0280: d = src.charAt(srcPos + 2);
0281: if (d == '=') {
0282: // start of expression
0283: changeParseState(PARSE_EXPRESSION);
0284: setSrcPos(srcPos + 3);
0285: return true;
0286: } else if (d == '@') {
0287: // directive
0288: parseDirective();
0289: return true;
0290: } else {
0291: // start of scriplet
0292: changeParseState(PARSE_SCRIPTLET);
0293: setSrcPos(srcPos + 2);
0294: return true;
0295: }
0296: } else if (srcPos < src.length() - 20
0297: && src.substring(srcPos + 1, srcPos + 12)
0298: .equalsIgnoreCase("!--#INCLUDE")
0299: && Character.isWhitespace(src.charAt(srcPos + 12))) {
0300: parseSSI();
0301: return true;
0302: } else if (srcPos < src.length() - 20
0303: && src.substring(srcPos + 1, srcPos + 7)
0304: .equalsIgnoreCase("SCRIPT")
0305: && Character.isWhitespace(src.charAt(srcPos + 7))) {
0306: // possible start of declaration
0307: boolean runatServer = false;
0308: int prevSrcPos = srcPos, prevLineNr = lineNr;
0309:
0310: srcPos += 7;
0311: skipWhitespace();
0312: for (;;) {
0313: // check for end of tag
0314: if (src.charAt(srcPos) == '>') {
0315: if (runatServer) {
0316: // start of declaration
0317: changeParseState(PARSE_DECLARATION);
0318: srcPos++;
0319: return true;
0320: } else {
0321: srcPos = prevSrcPos;
0322: lineNr = prevLineNr;
0323: return false;
0324: }
0325: }
0326: keyAndValue = parseKeyAndValue();
0327: if (keyAndValue[0].equalsIgnoreCase("RUNAT")
0328: && keyAndValue[1].equalsIgnoreCase("SERVER")) {
0329: runatServer = true;
0330: }
0331: }
0332: } else if (srcPos < src.length() - 10
0333: && src.substring(srcPos + 1, srcPos + 5)
0334: .equalsIgnoreCase("BEAN")
0335: && Character.isWhitespace(src.charAt(srcPos + 5))) {
0336: // bean
0337: parseBean();
0338: return true;
0339: }
0340:
0341: return false;
0342: }
0343:
0344: private boolean parseInDeclarationState()
0345: throws StringIndexOutOfBoundsException, JSPException {
0346: if (srcPos < src.length() - 8
0347: && src.substring(srcPos + 1, srcPos + 8)
0348: .equalsIgnoreCase("/SCRIPT")
0349: && (Character.isWhitespace(src.charAt(srcPos + 8)) || src
0350: .charAt(srcPos + 8) == '>')) {
0351: // end of declaration
0352: changeParseState(PARSE_NONE);
0353: setSrcPos(src.indexOf('>', srcPos));
0354: srcPos++;
0355: return true;
0356: }
0357: return false;
0358: }
0359:
0360: private void parseDirective()
0361: throws StringIndexOutOfBoundsException, JSPException {
0362: String[] keyAndValue;
0363: StringTokenizer toker;
0364: char c;
0365:
0366: srcPos += 3;
0367: skipWhitespace();
0368:
0369: for (;;) {
0370: // check for end of directive
0371: c = src.charAt(srcPos);
0372: if (c == '%') {
0373: if (src.charAt(srcPos + 1) == '>') {
0374: srcPos += 2;
0375: } else {
0376: srcPos++;
0377: }
0378: return;
0379: } else if (c == '>') {
0380: srcPos++;
0381: return;
0382: }
0383:
0384: keyAndValue = parseKeyAndValue();
0385:
0386: if (keyAndValue[0].equalsIgnoreCase("content_type")) {
0387: // content_type
0388: if (content_typeDirective == null) {
0389: content_typeDirective = keyAndValue[1];
0390: }
0391: } else if (keyAndValue[0].equalsIgnoreCase("extends")) {
0392: // extends
0393: if (extendsDirective.length() == 0) {
0394: extendsDirective.append(lineSeparator);
0395: recordFileAndLineNr(extendsDirective);
0396: extendsDirective.append(keyAndValue[1]);
0397: }
0398: } else if (keyAndValue[0].equalsIgnoreCase("implements")) {
0399: // implements
0400: toker = new StringTokenizer(keyAndValue[1], " ,");
0401: while (toker.hasMoreTokens()) {
0402: if (implements Directive.length() == 0) {
0403: implements Directive.append(" implements")
0404: .append(lineSeparator);
0405: } else {
0406: implements Directive.append(",").append(
0407: lineSeparator);
0408: }
0409: recordFileAndLineNr(implements Directive);
0410: implements Directive.append(toker.nextToken());
0411: }
0412: } else if (keyAndValue[0].equalsIgnoreCase("import")) {
0413: // import
0414: toker = new StringTokenizer(keyAndValue[1], " ,");
0415: while (toker.hasMoreTokens()) {
0416: recordFileAndLineNr(importDirective);
0417: importDirective.append("import ").append(
0418: toker.nextToken()).append((char) ';')
0419: .append(lineSeparator);
0420: }
0421: } else if (keyAndValue[0].equalsIgnoreCase("include")) {
0422: // include
0423: parseInclude(keyAndValue[1], false);
0424: } else if (keyAndValue[0].equalsIgnoreCase("language")) {
0425: // language
0426: if (!keyAndValue[1].equalsIgnoreCase("java")) {
0427: throw new JSPException("<B>" + jspFile.getPath()
0428: + ":" + lineNr
0429: + "</B>: Unknown jsp language "
0430: + keyAndValue[1]);
0431: }
0432: } else if (keyAndValue[0].equalsIgnoreCase("method")) {
0433: // method
0434: if (methodDirective.length() == 0) {
0435: methodDirective.append(lineSeparator);
0436: recordFileAndLineNr(methodDirective);
0437: methodDirective.append(keyAndValue[1]);
0438: }
0439: } else if (keyAndValue[0].equalsIgnoreCase("vinclude")) {
0440: // vinclude
0441: parseInclude(keyAndValue[1], true);
0442: } else {
0443: throw new JSPException("<B>" + jspFile.getPath() + ":"
0444: + lineNr + "</B>: Unknown jsp directive '<I>"
0445: + keyAndValue[0] + "</I>'");
0446: }
0447: }
0448: }
0449:
0450: private void parseSSI() throws StringIndexOutOfBoundsException,
0451: JSPException {
0452: String[] keyAndValue;
0453:
0454: srcPos += 12;
0455: skipWhitespace();
0456: keyAndValue = parseKeyAndValue();
0457:
0458: if (keyAndValue[0].equalsIgnoreCase("FILE")) {
0459: parseInclude(keyAndValue[1], false);
0460: } else if (keyAndValue[0].equalsIgnoreCase("VIRTUAL")) {
0461: parseInclude(keyAndValue[1], true);
0462: } else {
0463: throw new JSPException("<B>" + jspFile.getPath() + ":"
0464: + lineNr + "</B>: Unknown #INCLUDE parameter "
0465: + keyAndValue[0]);
0466: }
0467:
0468: setSrcPos(src.indexOf('>', srcPos));
0469: srcPos++;
0470: }
0471:
0472: private void parseInclude(String value, boolean virtual)
0473: throws StringIndexOutOfBoundsException, JSPException {
0474: File prevJspFile;
0475: String s, prevSrc;
0476: int prevSrcPos, prevLineNr;
0477:
0478: prevJspFile = jspFile;
0479: prevSrc = src;
0480: prevSrcPos = srcPos;
0481: prevLineNr = lineNr;
0482:
0483: try {
0484: if (virtual) {
0485: s = servletRequest.getRealPath(value);
0486: if (s == null)
0487: throw new JSPException("<B>" + jspFile.getPath()
0488: + ":" + lineNr + "</B>: Virtual file "
0489: + value
0490: + " could not be mapped to a real file");
0491: jspFile = new File(s);
0492: } else {
0493: jspFile = new File(jspFile.getParent(), value);
0494: }
0495: try {
0496: jspFile = new File(jspFile.getCanonicalPath());
0497: } catch (IOException ioexc) {
0498: jspFile = new File(jspFile.getAbsolutePath());
0499: }
0500: parseOneJspFile();
0501: } finally {
0502: jspFile = prevJspFile;
0503: src = prevSrc;
0504: srcPos = prevSrcPos;
0505: lineNr = prevLineNr;
0506: }
0507: }
0508:
0509: private void parseBean() throws StringIndexOutOfBoundsException,
0510: JSPException {
0511: Properties beanAttributes;
0512: Hashtable beanDefaultProperties;
0513: Enumeration e;
0514: String[] keyAndValue;
0515: String k, v, name, varName, type, introspect, create, scope, beanName, getFromScope;
0516: int startLineNr, endLineNr, i;
0517:
0518: startLineNr = lineNr;
0519: srcPos += 5;
0520: skipWhitespace();
0521:
0522: // gather <BEAN> tag parameters
0523: beanAttributes = new Properties();
0524: for (;;) {
0525: // check for end of tag
0526: if (src.charAt(srcPos) == '>') {
0527: break;
0528: }
0529: keyAndValue = parseKeyAndValue();
0530: beanAttributes.put(keyAndValue[0].toLowerCase(),
0531: keyAndValue[1]);
0532: }
0533:
0534: // gather <PARAM> tags
0535: beanDefaultProperties = new Hashtable();
0536: for (;;) {
0537: setSrcPos(src.indexOf('<', srcPos));
0538: if (src.substring(srcPos + 1, srcPos + 6).equalsIgnoreCase(
0539: "/BEAN")
0540: && (Character.isWhitespace(src.charAt(srcPos + 6)) || src
0541: .charAt(srcPos + 6) == '>')) {
0542: // </BEAN> tag
0543: setSrcPos(src.indexOf('>', srcPos));
0544: srcPos++;
0545: break;
0546: } else if (src.substring(srcPos + 1, srcPos + 6)
0547: .equalsIgnoreCase("PARAM")
0548: && Character.isWhitespace(src.charAt(srcPos + 6))) {
0549: // <PARAM> tag
0550: srcPos += 6;
0551: skipWhitespace();
0552:
0553: for (;;) {
0554: // check for end of tag
0555: if (src.charAt(srcPos) == '>') {
0556: break;
0557: }
0558: keyAndValue = parseKeyAndValue();
0559: beanDefaultProperties.put(keyAndValue[0],
0560: keyAndValue[1]);
0561: }
0562: } else {
0563: srcPos++;
0564: }
0565: }
0566:
0567: // check bean attributes
0568: name = beanAttributes.getProperty("name");
0569: if (name == null)
0570: throw new JSPException(
0571: "<B>"
0572: + jspFile.getPath()
0573: + ":"
0574: + lineNr
0575: + "</B>: <BEAN> tag does not have required name attribute");
0576: varName = beanAttributes.getProperty("varname", name);
0577: type = beanAttributes.getProperty("type", "Object");
0578: introspect = beanAttributes.getProperty("introspect", "yes");
0579: create = beanAttributes.getProperty("create", "yes");
0580: scope = beanAttributes.getProperty("scope", "request");
0581: beanName = beanAttributes.getProperty("beanname", type);
0582: if (scope.equals("request")) {
0583: getFromScope = "request.getAttribute(\"";
0584: } else if (scope.equals("session")) {
0585: createSession = true;
0586: getFromScope = "__session.getValue(\"";
0587: } else {
0588: throw new JSPException(
0589: "<B>"
0590: + jspFile.getPath()
0591: + ":"
0592: + lineNr
0593: + "</B>: <BEAN> tag has invalid scope attribute "
0594: + scope);
0595: }
0596:
0597: // generate bean code
0598: endLineNr = lineNr;
0599: try {
0600: // put back line number for start of <BEAN> tag
0601: lineNr = startLineNr;
0602:
0603: if (beanCode.length() == 0) {
0604: beanCode
0605: .append(
0606: "\t\tjava.beans.PropertyDescriptor[] __propertyDescriptors;")
0607: .append(lineSeparator);
0608: }
0609:
0610: // bean retrieval
0611: recordFileAndLineNr(beanCode);
0612: beanCode.append("\t\t").append(type).append((char) ' ')
0613: .append(varName).append(" = null;").append(
0614: lineSeparator);
0615:
0616: recordFileAndLineNr(beanCode);
0617: beanCode.append("\t\t").append("if(").append(getFromScope)
0618: .append(javaStringEncode(name)).append(
0619: "\") instanceof ").append(type).append(
0620: ") {").append(lineSeparator);
0621:
0622: recordFileAndLineNr(beanCode);
0623: beanCode.append("\t\t\t").append(varName).append(" = (")
0624: .append(type).append(") ").append(getFromScope)
0625: .append(javaStringEncode(name)).append("\");")
0626: .append(lineSeparator);
0627:
0628: beanCode.append("\t\t} else {").append(lineSeparator);
0629:
0630: if (create.equalsIgnoreCase("yes")) {
0631: // bean creation
0632: beanCode.append("\t\t\ttry {").append(lineSeparator);
0633:
0634: recordFileAndLineNr(beanCode);
0635: beanCode
0636: .append("\t\t\t\t")
0637: .append(varName)
0638: .append(" = (")
0639: .append(type)
0640: .append(") ")
0641: .append(
0642: "java.beans.Beans.instantiate(this.getClass().getClassLoader(), \"")
0643: .append(beanName).append("\");").append(
0644: lineSeparator);
0645: ;
0646:
0647: if (scope.equals("session")) {
0648: recordFileAndLineNr(beanCode);
0649: beanCode.append("\t\t\t\t__session.putValue(\"")
0650: .append(javaStringEncode(name)).append(
0651: "\", ").append(varName)
0652: .append(");").append(lineSeparator);
0653: }
0654:
0655: beanCode
0656: .append(
0657: "\t\t\t} catch(java.lang.ClassNotFoundException cnfexc) {")
0658: .append(lineSeparator);
0659:
0660: beanCode
0661: .append(
0662: "\t\t\t\t__beanError(response, \"Could not create bean ")
0663: .append(javaStringEncode(name)).append(
0664: " of type ").append(
0665: javaStringEncode(type)).append(
0666: " (class not found)\");").append(
0667: lineSeparator);
0668:
0669: beanCode.append("\t\t\t\treturn;")
0670: .append(lineSeparator);
0671:
0672: beanCode.append("\t\t\t}").append(lineSeparator);
0673: } else {
0674: recordFileAndLineNr(beanCode);
0675: beanCode.append("\t\t\t__beanError(response, \"Bean ")
0676: .append(javaStringEncode(name)).append(
0677: " does not exist or is not of type ")
0678: .append(javaStringEncode(type)).append("\");")
0679: .append(lineSeparator);
0680:
0681: beanCode.append("\t\t\treturn;");
0682: }
0683:
0684: beanCode.append("\t\t}").append(lineSeparator);
0685:
0686: if (beanDefaultProperties.size() > 0
0687: || introspect.equalsIgnoreCase("yes")) {
0688: beanCode.append("\t\ttry {").append(lineSeparator);
0689:
0690: recordFileAndLineNr(beanCode);
0691: beanCode
0692: .append(
0693: "\t\t\t__propertyDescriptors = java.beans.Introspector.getBeanInfo(")
0694: .append(varName)
0695: .append(
0696: ".getClass()).getPropertyDescriptors();")
0697: .append(lineSeparator);
0698:
0699: // set bean default properties
0700: e = beanDefaultProperties.keys();
0701: while (e.hasMoreElements()) {
0702: k = (String) e.nextElement();
0703: v = (String) beanDefaultProperties.get(k);
0704:
0705: recordFileAndLineNr(beanCode);
0706: beanCode.append("\t\t\tif(!__beanSetProperty(")
0707: .append(varName).append(
0708: ", __propertyDescriptors, \"")
0709: .append(javaStringEncode(k)).append(
0710: "\", \"").append(
0711: javaStringEncode(v)).append(
0712: "\")) {").append(lineSeparator);
0713:
0714: beanCode.append(
0715: "\t\t\t\t__beanError(response, \"Bean ")
0716: .append(javaStringEncode(name)).append(
0717: " of type").append(
0718: javaStringEncode(type)).append(
0719: " has no property named ").append(
0720: javaStringEncode(k)).append("\");")
0721: .append(lineSeparator);
0722:
0723: beanCode.append("\t\t\t\treturn;").append(
0724: lineSeparator);
0725:
0726: beanCode.append("\t\t\t}").append(lineSeparator);
0727: }
0728:
0729: // do bean introspection
0730: if (introspect.equalsIgnoreCase("yes")) {
0731: recordFileAndLineNr(beanCode);
0732: beanCode.append("\t\t\t__beanIntrospect(").append(
0733: varName).append(
0734: ", __propertyDescriptors, request);")
0735: .append(lineSeparator);
0736: }
0737:
0738: beanCode
0739: .append(
0740: "\t\t} catch(java.beans.IntrospectionException introexc) {")
0741: .append(lineSeparator);
0742:
0743: beanCode
0744: .append(
0745: "\t\t\t__beanError(response, \"Introspection failed for bean ")
0746: .append(javaStringEncode(name)).append(
0747: " of type ").append(
0748: javaStringEncode(type)).append("\");")
0749: .append(lineSeparator);
0750:
0751: beanCode.append("\t\t}").append(lineSeparator);
0752: }
0753: beanCode.append(lineSeparator);
0754: } finally {
0755: lineNr = endLineNr;
0756: }
0757: }
0758:
0759: private String[] parseKeyAndValue()
0760: throws StringIndexOutOfBoundsException {
0761: char c;
0762: int pos;
0763: String[] keyAndValue = new String[2];
0764:
0765: // gather key
0766: pos = srcPos;
0767: for (;;) {
0768: c = src.charAt(srcPos);
0769: if (c == '=' || Character.isWhitespace(c)) {
0770: break;
0771: }
0772: srcPos++;
0773: }
0774: keyAndValue[0] = src.substring(pos, srcPos);
0775: skipWhitespace();
0776:
0777: // quick work around page processing
0778: if ("page".equals(keyAndValue[0]))
0779: return parseKeyAndValue();
0780:
0781: // gather optional value
0782: if (src.charAt(srcPos) == '=') {
0783: srcPos++;
0784: skipWhitespace();
0785:
0786: c = src.charAt(srcPos);
0787: if (c == '\'' || c == '\"') {
0788: pos = src.indexOf(c, srcPos + 1);
0789: keyAndValue[1] = src.substring(srcPos + 1, pos);
0790: setSrcPos(pos + 1);
0791: } else {
0792: pos = srcPos;
0793: for (;;) {
0794: c = src.charAt(srcPos);
0795: if (c == '%' || c == '>'
0796: || Character.isWhitespace(c)) {
0797: break;
0798: }
0799: srcPos++;
0800: }
0801: keyAndValue[1] = src.substring(pos, srcPos);
0802: }
0803:
0804: skipWhitespace();
0805: } else {
0806: keyAndValue[1] = keyAndValue[0];
0807: }
0808:
0809: return keyAndValue;
0810: }
0811:
0812: private void changeParseState(int newState) {
0813: if (newState == parseState)
0814: return;
0815:
0816: switch (parseState) {
0817: case PARSE_HTML:
0818: scriptletsCode.append("\");").append(lineSeparator);
0819: break;
0820: case PARSE_EXPRESSION:
0821: scriptletsCode.append("));").append(lineSeparator);
0822: break;
0823: case PARSE_DECLARATION:
0824: declarationsCode.append(lineSeparator);
0825: break;
0826: case PARSE_SCRIPTLET:
0827: scriptletsCode.append(lineSeparator);
0828: break;
0829: }
0830:
0831: parseState = newState;
0832:
0833: switch (parseState) {
0834: case PARSE_HTML:
0835: recordFileAndLineNr(scriptletsCode);
0836: scriptletsCode.append("\t\t\tout.print(\"");
0837: break;
0838: case PARSE_EXPRESSION:
0839: recordFileAndLineNr(scriptletsCode);
0840: scriptletsCode.append("\t\t\tout.print(__valueOf(");
0841: break;
0842: case PARSE_DECLARATION:
0843: recordFileAndLineNr(declarationsCode);
0844: break;
0845: case PARSE_SCRIPTLET:
0846: recordFileAndLineNr(scriptletsCode);
0847: break;
0848: }
0849: }
0850:
0851: private void recordFileAndLineNr(StringBuffer code) {
0852: // FIXME: do nice encoding of backslashes in filename
0853: code.append(
0854: "//line " + jspFile.toString().replace('\\', '/') + ":"
0855: + lineNr).append(lineSeparator);
0856: }
0857:
0858: private void skipWhitespace() {
0859: char c;
0860:
0861: for (;;) {
0862: c = src.charAt(srcPos);
0863: if (!Character.isWhitespace(c)) {
0864: break;
0865: } else if (c == '\n') {
0866: lineNr++;
0867: }
0868: srcPos++;
0869: }
0870: }
0871:
0872: private void setSrcPos(int newSrcPos) {
0873: int from;
0874:
0875: if (newSrcPos < 0 || newSrcPos >= src.length())
0876: throw new StringIndexOutOfBoundsException(Integer
0877: .toString(newSrcPos));
0878:
0879: from = srcPos - 1;
0880: for (;;) {
0881: from = src.indexOf('\n', from + 1);
0882: if (from == -1 || from >= newSrcPos) {
0883: break;
0884: }
0885: lineNr++;
0886: }
0887: srcPos = newSrcPos;
0888: }
0889:
0890: private void generateJavaFile() throws JSPException {
0891: PrintWriter out;
0892: Enumeration e;
0893: File f;
0894: String pn, cn;
0895: Long l;
0896: int i;
0897:
0898: try {
0899: f = new File(javaFile.getParent());
0900: f.mkdirs();
0901: out = new PrintWriter(new FileWriter(javaFile));
0902: i = className.lastIndexOf('.');
0903: if (i > 0) {
0904: pn = className.substring(0, i);
0905: cn = className.substring(i + 1);
0906: } else {
0907: pn = null;
0908: cn = className;
0909: }
0910: try {
0911: // generate header and start of class
0912: out
0913: .println("/* Automatically generated by GNUJSP. Do not edit. */");
0914: if (pn != null) {
0915: out.println("package " + pn + ";");
0916: }
0917: out.println(importDirective);
0918: out.println("public final class " + cn + " extends "
0919: + extendsDirective + implements Directive);
0920: out.println("{");
0921:
0922: // generate declarations
0923: out.println(declarationsCode);
0924:
0925: // generate specified method
0926: out
0927: .println("\tpublic void "
0928: + methodDirective
0929: + "(javax.servlet.http.HttpServletRequest request, "
0930: + "javax.servlet.http.HttpServletResponse response) "
0931: + "throws javax.servlet.ServletException, java.io.IOException");
0932: out.println("\t{");
0933: if (createSession) {
0934: out
0935: .println("\t\tjavax.servlet.http.HttpSession __session = request.getSession(true);");
0936: }
0937: out.println(beanCode);
0938: out.println("\t\tresponse.setContentType(\""
0939: + javaStringEncode(content_typeDirective)
0940: + "\");");
0941: out
0942: .println("\t\tjava.io.PrintWriter out = response.getWriter();");
0943: out.println("\t\ttry {");
0944: out.println(scriptletsCode);
0945: out.println("\t\t} finally {");
0946: out.println("\t\t\tout.flush();");
0947: out.println("\t\t\tout.close();");
0948: out.println("\t\t}");
0949: out.println("\t}");
0950: out.println();
0951:
0952: // generate own version of String.valueOf()
0953: out
0954: .println("\tprivate static java.lang.String __valueOf(java.lang.Object obj) {");
0955: out.println("\t\tif(obj == null) {");
0956: out.println("\t\t\treturn \"\";");
0957: out.println("\t\t} else {");
0958: out.println("\t\t\treturn obj.toString();");
0959: out.println("\t\t}");
0960: out.println("\t}");
0961: out
0962: .println("\tprivate static java.lang.String __valueOf(boolean b) { return java.lang.String.valueOf(b); }");
0963: out
0964: .println("\tprivate static java.lang.String __valueOf(char c) { return java.lang.String.valueOf(c); }");
0965: out
0966: .println("\tprivate static java.lang.String __valueOf(int i) { return java.lang.String.valueOf(i); }");
0967: out
0968: .println("\tprivate static java.lang.String __valueOf(long l) { return java.lang.String.valueOf(l); }");
0969: out
0970: .println("\tprivate static java.lang.String __valueOf(float f) { return java.lang.String.valueOf(f); }");
0971: out
0972: .println("\tprivate static java.lang.String __valueOf(double d) { return java.lang.String.valueOf(d); }");
0973: out.println();
0974:
0975: // generate bean functions
0976: out
0977: .println("\tprivate void __beanError(javax.servlet.http.HttpServletResponse response, java.lang.String msg) throws java.io.IOException {");
0978: out
0979: .println("\t\tresponse.setStatus(javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR, \"JSP run-time error\");");
0980: out
0981: .println("\t\tresponse.setContentType(\"text/html\");");
0982: out
0983: .println("\t\tjava.io.PrintWriter errOut = response.getWriter();");
0984: out
0985: .println("\t\terrOut.println(\"<HTML><HEAD><TITLE>\" + javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR + \" JSP run-time error</TITLE></HEAD><BODY>\" +");
0986: out
0987: .println("\t\t\t\"<H2>\" + javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR + \" JSP run-time error</H2>\" +");
0988: out
0989: .println("\t\t\t\"The JSP page you requested could not be served because the following error(s) occured:<BR><PRE>\");");
0990: out.println("\t\terrOut.println(msg);");
0991: out
0992: .println("\t\terrOut.println(\"</PRE></BODY></HTML>\");");
0993: out.println("\t\terrOut.close();");
0994: out.println("\t}");
0995: out.println();
0996:
0997: out
0998: .println("\tprivate boolean __beanSetProperty(java.lang.Object bean, java.beans.PropertyDescriptor[] pds, java.lang.String key, java.lang.String value) {");
0999: out.println("\t\tjava.lang.reflect.Method meth;");
1000: out
1001: .println("\t\tfor(int i = 0; i < pds.length; i++) {");
1002: out
1003: .println("\t\t\tif(pds[i].getName().equals(key) && !pds[i].isHidden()) {");
1004: out.println("\t\t\t\tmeth = pds[i].getWriteMethod();");
1005: out.println("\t\t\t\tif(meth != null) {");
1006: out.println("\t\t\t\t\ttry {");
1007: out
1008: .println("\t\t\t\t\t\tmeth.invoke(bean, new Object[]{value});");
1009: out.println("\t\t\t\t\t\treturn true;");
1010: out
1011: .println("\t\t\t\t\t} catch(java.lang.IllegalAccessException iaccexc) {");
1012: out.println("\t\t\t\t\t\treturn false;");
1013: out
1014: .println("\t\t\t\t\t} catch(java.lang.IllegalArgumentException iargexc) {");
1015: out.println("\t\t\t\t\t\treturn false;");
1016: out
1017: .println("\t\t\t\t\t} catch(java.lang.reflect.InvocationTargetException itexc) {");
1018: out.println("\t\t\t\t\t\treturn false;");
1019: out.println("\t\t\t\t\t}");
1020: out.println("\t\t\t\t}");
1021: out.println("\t\t\t}");
1022: out.println("\t\t}");
1023: out.println("\t\treturn false;");
1024: out.println("\t}");
1025: out.println();
1026:
1027: out
1028: .println("\tprivate void __beanIntrospect(java.lang.Object bean, java.beans.PropertyDescriptor[] pds, javax.servlet.http.HttpServletRequest request) {");
1029: out.println("\t\tjava.lang.reflect.Method meth;");
1030: out.println("\t\tjava.lang.String value;");
1031: out
1032: .println("\t\tfor(int i = 0; i < pds.length; i++) {");
1033: out.println("\t\t\tif(!pds[i].isHidden()) {");
1034: out
1035: .println("\t\t\t\tvalue = request.getParameter(pds[i].getName());");
1036: out.println("\t\t\t\tif(value != null) {");
1037: out
1038: .println("\t\t\t\t\tmeth = pds[i].getWriteMethod();");
1039: out.println("\t\t\t\t\tif(meth != null) {");
1040: out.println("\t\t\t\t\t\ttry {");
1041: out
1042: .println("\t\t\t\t\t\t\tmeth.invoke(bean, new Object[]{value});");
1043: out
1044: .println("\t\t\t\t\t\t} catch(java.lang.IllegalAccessException iaccexc) {");
1045: out.println("\t\t\t\t\t\t\t//");
1046: out
1047: .println("\t\t\t\t\t\t} catch(java.lang.IllegalArgumentException iargexc) {");
1048: out.println("\t\t\t\t\t\t\t//");
1049: out
1050: .println("\t\t\t\t\t\t} catch(java.lang.reflect.InvocationTargetException itexc) {");
1051: out.println("\t\t\t\t\t\t\t//");
1052: out.println("\t\t\t\t\t\t}");
1053: out.println("\t\t\t\t\t}");
1054: out.println("\t\t\t\t}");
1055: out.println("\t\t\t}");
1056: out.println("\t\t}");
1057: out.println("\t}");
1058: out.println();
1059:
1060: // generate dependency check code
1061: out
1062: .println("\tpublic static final int __compilerVersionNr = "
1063: + COMPILER_VERSION_NR + ";");
1064: out.println();
1065:
1066: out
1067: .println("\tprivate static java.lang.Object[] __dependencies = new java.lang.Object[]{");
1068: e = dependencies.elements();
1069: for (;;) {
1070: f = (File) e.nextElement();
1071: l = (Long) e.nextElement();
1072: out.println("\t\tnew java.io.File(\""
1073: + javaStringEncode(f.toString()) + "\"),");
1074: out.print("\t\tnew java.lang.Long(" + l + "L)");
1075: if (e.hasMoreElements()) {
1076: out.println(",");
1077: } else {
1078: out.println();
1079: break;
1080: }
1081: }
1082: out.println("\t};");
1083: out.println();
1084:
1085: out
1086: .println("\tpublic static boolean __checkDependencies() {");
1087: out
1088: .println("\t\tfor(int i = 0; i < __dependencies.length; i += 2) {");
1089: out
1090: .println("\t\t\tif(!((java.io.File) __dependencies[i]).exists() ||");
1091: out
1092: .println("\t\t\t\t\t((java.io.File) __dependencies[i]).lastModified() > ((java.lang.Long) __dependencies[i+1]).longValue()) {");
1093: out.println("\t\t\t\treturn true;");
1094: out.println("\t\t\t}");
1095: out.println("\t\t}");
1096: out.println("\t\treturn false;");
1097: out.println("\t}");
1098:
1099: // generate end of class
1100: out.println("}");
1101: } finally {
1102: out.close();
1103: }
1104: } catch (IOException ioexc) {
1105: throw new JSPException("Could not write java file "
1106: + javaFile + ": " + ioexc.getMessage());
1107: }
1108: }
1109:
1110: private void compileJavaFile() throws JSPException {
1111: String[] compilerArgs;
1112: ByteArrayOutputStream compilerOut;
1113: PrintStream compilerOutStream;
1114: String s, t;
1115: StringBuffer buf;
1116: int i, j, k, l;
1117:
1118: compilerOut = new ByteArrayOutputStream();
1119: compilerOutStream = new PrintStream(compilerOut, true);
1120:
1121: // build compiler command line
1122: if (jspServlet.compiler[0].equals("builtin-javac")) {
1123: compilerArgs = new String[jspServlet.compiler.length - 1];
1124: j = 0;
1125: } else {
1126: compilerArgs = new String[jspServlet.compiler.length];
1127: compilerArgs[0] = jspServlet.compiler[0];
1128: j = 1;
1129: }
1130: compilerOutStream.print(jspServlet.compiler[0]);
1131:
1132: for (i = 1; i < jspServlet.compiler.length; i++) {
1133: s = jspServlet.compiler[i];
1134: buf = new StringBuffer(s.length() + 16);
1135: k = s.indexOf('%');
1136: l = -1;
1137: while (k != -1) {
1138: buf.append(s.substring(l + 1, k));
1139: l = s.indexOf('%', k + 1);
1140: if (l == -1) {
1141: l = k - 1;
1142: break;
1143: } else {
1144: t = s.substring(k + 1, l);
1145: if (t.length() == 0) {
1146: t = "%";
1147: } else if (t.equalsIgnoreCase("classpath")) {
1148: t = Utils.calculateClassPath(getClass()
1149: .getClassLoader());
1150: } else if (t.equalsIgnoreCase("repository")) {
1151: t = jspServlet.repository.toString();
1152: } else if (t.equalsIgnoreCase("source")) {
1153: t = javaFile.toString();
1154: } else {
1155: t = jspServlet.getServletConfig()
1156: .getInitParameter(t);
1157: }
1158:
1159: if (t != null) {
1160: buf.append(t);
1161: }
1162: k = s.indexOf('%', l + 1);
1163: }
1164: }
1165: buf.append(s.substring(l + 1));
1166: compilerArgs[j] = buf.toString();
1167: compilerOutStream.print((char) ' ');
1168: compilerOutStream.print(compilerArgs[j]);
1169: j++;
1170: }
1171: compilerOutStream.println();
1172:
1173: if (jspServlet.compiler[0].equals("builtin-javac")) {
1174: // use builtin compiler
1175: try {
1176: Object javaCompiler = Class.forName(
1177: "sun.tools.javac.Main")
1178: .getConstructor(
1179: new Class[] { OutputStream.class,
1180: String.class }).newInstance(
1181: new Object[] { compilerOutStream,
1182: "javac" });
1183: if (Boolean.FALSE.equals(javaCompiler.getClass()
1184: .getMethod("compile",
1185: new Class[] { String[].class }).invoke(
1186: javaCompiler,
1187: new Object[] { compilerArgs }))) {
1188: throw new JSPException(
1189: transcribeErrors(htmlEncode(compilerOut
1190: .toString())));
1191: }
1192: } catch (Exception e) {
1193: if (e instanceof JSPException)
1194: throw (JSPException) e;
1195: throw new JSPException(
1196: transcribeErrors(htmlEncode("Can't instantiate Java compiler, "
1197: + e + "/" + e.getCause())));
1198: }
1199: } else {
1200: // use external compiler
1201: Process p;
1202: BufferedReader stdout = null, stderr = null;
1203: String line;
1204: int exitValue = -1;
1205: long classLastModified;
1206:
1207: classLastModified = classFile.lastModified();
1208:
1209: try {
1210: p = Runtime.getRuntime().exec(compilerArgs);
1211: stdout = new BufferedReader(new InputStreamReader(p
1212: .getInputStream()));
1213: stderr = new BufferedReader(new InputStreamReader(p
1214: .getErrorStream()));
1215: // polling should be threaded
1216: while ((line = stdout.readLine()) != null) {
1217: compilerOutStream.println(line);
1218: }
1219:
1220: while ((line = stderr.readLine()) != null) {
1221: compilerOutStream.println(line);
1222: }
1223:
1224: try {
1225: p.waitFor();
1226: exitValue = p.exitValue();
1227: } catch (InterruptedException ix) {
1228: ;
1229: }
1230: } catch (IOException ioexc) {
1231: ioexc.printStackTrace(compilerOutStream);
1232: }
1233:
1234: if (classFile.lastModified() == classLastModified) {
1235: compilerOutStream
1236: .println("[no class file has been written]");
1237: exitValue = -1;
1238: }
1239:
1240: if (exitValue != 0) {
1241: throw new JSPException(
1242: transcribeErrors(htmlEncode(compilerOut
1243: .toString())));
1244: }
1245: }
1246: }
1247:
1248: private static String htmlEncode(String val) {
1249: StringBuffer buf = new StringBuffer(val.length() + 8);
1250: char c;
1251:
1252: for (int i = 0; i < val.length(); i++) {
1253: c = val.charAt(i);
1254: switch (c) {
1255: case '<':
1256: buf.append("<");
1257: break;
1258: case '>':
1259: buf.append(">");
1260: break;
1261: case '&':
1262: buf.append("&");
1263: break;
1264: default:
1265: buf.append(c);
1266: break;
1267: }
1268: }
1269: return buf.toString();
1270: }
1271:
1272: private static class MapEntry {
1273: int javaLineNr;
1274: String jspFile;
1275: int jspLineNr;
1276:
1277: MapEntry(int javaLineNr, String jspFile, int jspLineNr) {
1278: this .javaLineNr = javaLineNr;
1279: this .jspFile = jspFile;
1280: this .jspLineNr = jspLineNr;
1281: }
1282: }
1283:
1284: /**
1285: * Transcribe error messages
1286: */
1287: private String transcribeErrors(String errors) {
1288: LineNumberReader in;
1289: BufferedReader in2;
1290: Vector map;
1291: Enumeration e;
1292: MapEntry entry;
1293: StringBuffer errBuf;
1294: String s, jspFile;
1295: int i, j, k, l, javaLineNr, jspLineNr;
1296:
1297: try {
1298: /* Build mapping from java line numbers to jsp file/line# combinations.
1299: * We could have done this will writing the java file, but using
1300: * LineNumberReader is easier, and it would take extra time when
1301: * no errors occur.
1302: */
1303: in = new LineNumberReader(new FileReader(javaFile));
1304: in.setLineNumber(1);
1305: map = new Vector();
1306: try {
1307: while ((s = in.readLine()) != null) {
1308: if (s.startsWith("//line ")) {
1309: i = s.indexOf(':');
1310: if (i >= 0) {
1311: try {
1312: map.addElement(new MapEntry(in
1313: .getLineNumber(), s.substring(
1314: 7, i), Integer.parseInt(s
1315: .substring(i + 1))));
1316: } catch (NumberFormatException nfexc) {
1317: }
1318: }
1319: }
1320: }
1321: } finally {
1322: in.close();
1323: }
1324:
1325: /* Now we read every line of the error messages and translate any
1326: * file references there.
1327: */
1328: in2 = new BufferedReader(new StringReader(errors));
1329: errBuf = new StringBuffer();
1330: try {
1331: while ((s = in2.readLine()) != null) {
1332: i = s.indexOf(javaFile.getPath());
1333: if (i != -1) {
1334: j = i + javaFile.getPath().length();
1335: if (j < s.length() - 1 && s.charAt(j) == ':'
1336: && Character.isDigit(s.charAt(j + 1))) {
1337: j++;
1338: k = j;
1339: while (k < s.length()
1340: && Character.isDigit(s.charAt(k))) {
1341: k++;
1342: }
1343: l = k;
1344: while (l + 1 < s.length()
1345: && s.charAt(l) == ':'
1346: && Character.isDigit(s
1347: .charAt(l + 1))) {
1348: l += 2;
1349: while (l < s.length()
1350: && Character.isDigit(s
1351: .charAt(l))) {
1352: l++;
1353: }
1354: }
1355:
1356: try {
1357: javaLineNr = Integer.parseInt(s
1358: .substring(j, k));
1359: jspFile = null;
1360: jspLineNr = 0;
1361: for (e = map.elements(); e
1362: .hasMoreElements();) {
1363: entry = (MapEntry) e.nextElement();
1364: if (entry.javaLineNr > javaLineNr) {
1365: break;
1366: }
1367: jspFile = entry.jspFile;
1368: jspLineNr = entry.jspLineNr
1369: + (javaLineNr - entry.javaLineNr);
1370: }
1371: // valid translation found: use it
1372: if (jspFile != null) {
1373: errBuf.append(s.substring(0, i));
1374: errBuf.append("<B>")
1375: .append(jspFile).append(
1376: (char) ':').append(
1377: jspLineNr).append(
1378: "</B>");
1379: errBuf.append("<!-- ").append(
1380: s.substring(i, l)).append(
1381: " -->");
1382: errBuf.append(s.substring(l))
1383: .append(lineSeparator);
1384: continue;
1385: }
1386: } catch (NumberFormatException nfexc2) {
1387: }
1388: }
1389: }
1390: errBuf.append(s).append(lineSeparator);
1391: }
1392: return errBuf.toString();
1393: } finally {
1394: in2.close();
1395: }
1396: } catch (IOException ioexc) {
1397: return errors;
1398: }
1399: }
1400:
1401: private static String javaStringEncode(String val) {
1402: StringBuffer res;
1403: String s;
1404: int i;
1405: char c;
1406:
1407: res = new StringBuffer(val.length());
1408: for (i = 0; i < val.length(); i++) {
1409: c = val.charAt(i);
1410: switch (c) {
1411: case '\n':
1412: res.append("\\n");
1413: break;
1414: case '\r':
1415: res.append("\\r");
1416: break;
1417: case '\'':
1418: res.append("\\\'");
1419: break;
1420: case '\"':
1421: res.append("\\\"");
1422: break;
1423: case '\\':
1424: res.append("\\\\");
1425: break;
1426: default:
1427: if (c > 0xFF) {
1428: s = "00" + Integer.toHexString(c);
1429: res.append("\\u").append(
1430: s.substring(s.length() - 4));
1431: } else if (c < ' ' || c >= 0x7F) {
1432: s = "00" + Integer.toOctalString(c);
1433: res.append((char) '\\').append(
1434: s.substring(s.length() - 3));
1435: } else {
1436: res.append((char) c);
1437: }
1438: break;
1439: }
1440: }
1441: return res.toString();
1442: }
1443:
1444: public static String getClassNameForJspFile(File jspFile)
1445: throws JSPException {
1446: StringTokenizer toker;
1447: StringBuffer buf;
1448: String s = jspFile.toString();
1449: char c;
1450: int i;
1451:
1452: toker = new StringTokenizer(s, String
1453: .valueOf(File.separatorChar));
1454: buf = new StringBuffer(s.length() + 32);
1455: buf.append("_jsp");
1456: while (toker.hasMoreTokens()) {
1457: s = toker.nextToken();
1458: buf.append("._");
1459: for (i = 0; i < s.length(); i++) {
1460: c = s.charAt(i);
1461: if (Character.isJavaIdentifierPart(c)) {
1462: buf.append((char) c);
1463: } else {
1464: buf.append((char) '_').append(
1465: Integer.toHexString(c));
1466: }
1467: }
1468: }
1469:
1470: return buf.toString();
1471: }
1472:
1473: public static File getFileForClass(File repository,
1474: String className, String suffix) {
1475: return new File(repository, className.replace('.',
1476: File.separatorChar)
1477: + suffix);
1478: }
1479: }
|