001: /*
002: * The Apache Software License, Version 1.1
003: *
004: * Copyright (c) 1999 The Apache Software Foundation. All rights
005: * reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * 1. Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: *
014: * 2. Redistributions in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * 3. The end-user documentation included with the redistribution, if
020: * any, must include the following acknowlegement:
021: * "This product includes software developed by the
022: * Apache Software Foundation (http://www.apache.org/)."
023: * Alternately, this acknowlegement may appear in the software itself,
024: * if and wherever such third-party acknowlegements normally appear.
025: *
026: * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
027: * Foundation" must not be used to endorse or promote products derived
028: * from this software without prior written permission. For written
029: * permission, please contact apache@apache.org.
030: *
031: * 5. Products derived from this software may not be called "Apache"
032: * nor may "Apache" appear in their names without prior written
033: * permission of the Apache Group.
034: *
035: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: *
049: * This software consists of voluntary contributions made by many
050: * individuals on behalf of the Apache Software Foundation. For more
051: * information on the Apache Software Foundation, please see
052: * <http://www.apache.org/>.
053: *
054: */
055: package com.sun.portal.providers.jsp.jasper3.jasper.compiler;
056:
057: import java.net.URL;
058:
059: import java.io.CharArrayWriter;
060: import java.io.IOException;
061: import java.io.InputStream;
062: import java.io.FileInputStream;
063: import java.util.Hashtable;
064: import java.util.Enumeration;
065:
066: import com.sun.portal.providers.jsp.jasper3.jasper.Constants;
067: import com.sun.portal.providers.jsp.jasper3.jasper.JasperException;
068:
069: import org.w3c.dom.*;
070: import javax.xml.parsers.DocumentBuilder;
071: import javax.xml.parsers.DocumentBuilderFactory;
072: import javax.xml.parsers.ParserConfigurationException;
073: import org.xml.sax.EntityResolver;
074: import org.xml.sax.SAXException;
075: import org.xml.sax.InputSource;
076:
077: /**
078: * This class has all the utility method(s).
079: * Ideally should move all the bean containers here.
080: *
081: * @author Mandar Raje.
082: * @author Rajiv Mordani.
083: */
084: public class JspUtil {
085:
086: private static final String OPEN_EXPR = "<%=";
087: private static final String CLOSE_EXPR = "%>";
088:
089: public static char[] removeQuotes(char[] chars) {
090: CharArrayWriter caw = new CharArrayWriter();
091: for (int i = 0; i < chars.length; i++) {
092: if (chars[i] == '%' && chars[i + 1] == '\\'
093: && chars[i + 2] == '\\' && chars[i + 3] == '>') {
094: caw.write('%');
095: caw.write('>');
096: i = i + 3;
097: } else
098: caw.write(chars[i]);
099: }
100: return caw.toCharArray();
101: }
102:
103: // Checks if the token is a runtime expression.
104: public static boolean isExpression(String token) {
105:
106: if (token.startsWith(OPEN_EXPR) && token.endsWith(CLOSE_EXPR)) {
107: return true;
108: }
109:
110: return false;
111: }
112:
113: // Returns the "expression" part -- takin <%= and %> out.
114: public static String getExpr(String expression) {
115: String returnString;
116: int length = expression.length();
117:
118: if (expression.startsWith(OPEN_EXPR)
119: && expression.endsWith(CLOSE_EXPR)) {
120: returnString = expression.substring(OPEN_EXPR.length(),
121: length - CLOSE_EXPR.length());
122: } else {
123: returnString = "";
124: }
125:
126: return returnString;
127: }
128:
129: // Parses the XML document contained in the InputStream.
130: public static Document parseXMLDoc(InputStream in,
131: String dtdResource, String dtdId) throws JasperException {
132: return parseXMLDocJaxp(in, dtdResource, dtdId);
133: }
134:
135: // Parses the XML document contained in the InputStream.
136: public static Document parseXMLDocJaxp(InputStream in,
137: String dtdResource, String dtdId) throws JasperException {
138: try {
139: Document tld;
140: DocumentBuilderFactory docFactory = DocumentBuilderFactory
141: .newInstance();
142: docFactory.setValidating(true);
143: docFactory.setNamespaceAware(true);
144: DocumentBuilder builder = docFactory.newDocumentBuilder();
145:
146: /***
147: * These lines make sure that we have an internal catalog entry for
148: * the taglib.dtdfile; this is so that jasper can run standalone
149: * without running out to the net to pick up the taglib.dtd file.
150: */
151: MyEntityResolver resolver = new MyEntityResolver(dtdId,
152: dtdResource);
153: builder.setEntityResolver(resolver);
154: tld = builder.parse(in);
155: return tld;
156: } catch (ParserConfigurationException ex) {
157: throw new JasperException(Constants.getString(
158: "jsp.error.parse.error.in.TLD", new Object[] { ex
159: .getMessage() }));
160: } catch (SAXException sx) {
161: throw new JasperException(Constants.getString(
162: "jsp.error.parse.error.in.TLD", new Object[] { sx
163: .getMessage() }));
164: } catch (IOException io) {
165: throw new JasperException(Constants.getString(
166: "jsp.error.unable.to.open.TLD", new Object[] { io
167: .getMessage() }));
168: }
169: }
170:
171: public static void checkAttributes (String typeOfTag, Hashtable attrs,
172: ValidAttribute[] validAttributes, Mark start)
173: throws JasperException
174: {
175: boolean valid = true;
176: Hashtable temp = (Hashtable)attrs.clone ();
177:
178: /**
179: * First check to see if all the mandatory attributes are present.
180: * If so only then proceed to see if the other attributes are valid
181: * for the particular tag.
182: */
183: String missingAttribute = null;
184:
185: for (int i = 0; i < validAttributes.length; i++) {
186:
187: if (validAttributes[i].mandatory) {
188: if (temp.get (validAttributes[i].name) != null) {
189: temp.remove (validAttributes[i].name);
190: valid = true;
191: } else {
192: valid = false;
193: missingAttribute = validAttributes[i].name;
194: break;
195: }
196: }
197: }
198:
199: /**
200: * If mandatory attribute is missing then the exception is thrown.
201: */
202: if (!valid)
203: throw new ParseException(start, Constants.getString(
204: "jsp.error.mandatory.attribute",
205: new Object[] { typeOfTag, missingAttribute}));
206:
207: /**
208: * Check to see if there are any more attributes for the specified
209: * tag.
210: */
211: if (temp.size() == 0)
212: return;
213:
214: /**
215: * Now check to see if the rest of the attributes are valid too.
216: */
217: Enumeration enum = temp.keys ();
218: String attribute = null;
219:
220: while (enum.hasMoreElements ()) {
221: valid = false;
222: attribute = (String) enum.nextElement ();
223: for (int i = 0; i < validAttributes.length; i++) {
224: if (attribute.equals(validAttributes[i].name)) {
225: valid = true;
226: break;
227: }
228: }
229: if (!valid)
230: throw new ParseException(start, Constants.getString(
231: "jsp.error.invalid.attribute",
232: new Object[] { typeOfTag, attribute }));
233: }
234: }
235:
236: public static String escapeQueryString(String unescString) {
237: if (unescString == null)
238: return null;
239:
240: String escString = "";
241: String shellSpChars = "\\\"";
242:
243: for (int index = 0; index < unescString.length(); index++) {
244: char nextChar = unescString.charAt(index);
245:
246: if (shellSpChars.indexOf(nextChar) != -1)
247: escString += "\\";
248:
249: escString += nextChar;
250: }
251: return escString;
252: }
253:
254: /**
255: * Escape the 5 entities defined by XML.
256: */
257: public static String escapeXml(String s) {
258: if (s == null)
259: return null;
260: StringBuffer sb = new StringBuffer();
261: for (int i = 0; i < s.length(); i++) {
262: char c = s.charAt(i);
263: if (c == '<') {
264: sb.append("<");
265: } else if (c == '>') {
266: sb.append(">");
267: } else if (c == '\'') {
268: sb.append("'");
269: } else if (c == '&') {
270: sb.append("&");
271: } else if (c == '"') {
272: sb.append(""e;");
273: } else {
274: sb.append(c);
275: }
276: }
277: return sb.toString();
278: }
279:
280: public static class ValidAttribute {
281: String name;
282: boolean mandatory;
283:
284: public ValidAttribute(String name, boolean mandatory) {
285: this .name = name;
286: this .mandatory = mandatory;
287: }
288:
289: public ValidAttribute(String name) {
290: this (name, false);
291: }
292: }
293: }
294:
295: class MyEntityResolver implements EntityResolver {
296:
297: String dtdId;
298: String dtdResource;
299:
300: public MyEntityResolver(String id, String resource) {
301: this .dtdId = id;
302: this .dtdResource = resource;
303: }
304:
305: public InputSource resolveEntity(String publicId, String systemId)
306: throws SAXException, IOException {
307: //System.out.println ("publicId = " + publicId);
308: //System.out.println ("systemId is " + systemId);
309: //System.out.println ("resource is " + dtdResource);
310: if (publicId != null && publicId.equals(dtdId)) {
311: InputStream input = this .getClass().getResourceAsStream(
312: dtdResource);
313: InputSource isrc = new InputSource(input);
314: return isrc;
315: } else {
316: //System.out.println ("returning null though dtdURL is " + dtdURL);
317: return null;
318: }
319: }
320: }
|