/*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.jasper.compiler;
import java.net.URL;
import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.FileInputStream;
import java.util.Hashtable;
import java.util.Enumeration;
import org.apache.jasper.Constants;
import org.apache.jasper.JasperException;
import org.w3c.dom.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.EntityResolver;
import org.xml.sax.SAXException;
import org.xml.sax.InputSource;
/**
* This class has all the utility method(s).
* Ideally should move all the bean containers here.
*
* @author Mandar Raje.
* @author Rajiv Mordani.
*/
public class JspUtil {
private static final String OPEN_EXPR = "<%=";
private static final String CLOSE_EXPR = "%>";
public static char[] removeQuotes(char []chars) {
CharArrayWriter caw = new CharArrayWriter();
for (int i = 0; i < chars.length; i++) {
if (chars[i] == '%' && chars[i+1] == '\\' &&
chars[i+2] == '\\' && chars[i+3] == '>') {
caw.write('%');
caw.write('>');
i = i + 3;
}
else caw.write(chars[i]);
}
return caw.toCharArray();
}
// Checks if the token is a runtime expression.
public static boolean isExpression (String token) {
if (token.startsWith(OPEN_EXPR) && token.endsWith(CLOSE_EXPR)) {
return true;
}
return false;
}
// Returns the "expression" part -- takin <%= and %> out.
public static String getExpr (String expression) {
String returnString;
int length = expression.length();
if (expression.startsWith(OPEN_EXPR) && expression.endsWith(CLOSE_EXPR)) {
returnString = expression.substring (OPEN_EXPR.length(), length - CLOSE_EXPR.length());
} else {
returnString = "";
}
return returnString;
}
// Parses the XML document contained in the InputStream.
public static Document parseXMLDoc(InputStream in, String dtdResource,
String dtdId) throws JasperException
{
return parseXMLDocJaxp(in, dtdResource, dtdId );
}
// Parses the XML document contained in the InputStream.
public static Document parseXMLDocJaxp(InputStream in, String dtdResource,
String dtdId)
throws JasperException
{
try {
Document tld;
DocumentBuilderFactory docFactory = DocumentBuilderFactory.
newInstance();
docFactory.setValidating(true);
docFactory.setNamespaceAware(true);
DocumentBuilder builder = docFactory.newDocumentBuilder();
/***
* These lines make sure that we have an internal catalog entry for
* the taglib.dtdfile; this is so that jasper can run standalone
* without running out to the net to pick up the taglib.dtd file.
*/
MyEntityResolver resolver =
new MyEntityResolver(dtdId, dtdResource);
builder.setEntityResolver(resolver);
tld = builder.parse(in);
return tld;
} catch( ParserConfigurationException ex ) {
throw new JasperException(Constants.
getString("jsp.error.parse.error.in.TLD",
new Object[] {
ex.getMessage()
}));
} catch ( SAXException sx ) {
throw new JasperException(Constants.
getString("jsp.error.parse.error.in.TLD",
new Object[] {
sx.getMessage()
}));
} catch (IOException io) {
throw new JasperException(Constants.
getString("jsp.error.unable.to.open.TLD",
new Object[] {
io.getMessage() }));
}
}
public static void checkAttributes (String typeOfTag, Hashtable attrs,
ValidAttribute[] validAttributes, Mark start)
throws JasperException
{
boolean valid = true;
Hashtable temp = (Hashtable)attrs.clone ();
/**
* First check to see if all the mandatory attributes are present.
* If so only then proceed to see if the other attributes are valid
* for the particular tag.
*/
String missingAttribute = null;
for (int i = 0; i < validAttributes.length; i++) {
if (validAttributes[i].mandatory) {
if (temp.get (validAttributes[i].name) != null) {
temp.remove (validAttributes[i].name);
valid = true;
} else {
valid = false;
missingAttribute = validAttributes[i].name;
break;
}
}
}
/**
* If mandatory attribute is missing then the exception is thrown.
*/
if (!valid)
throw new ParseException(start, Constants.getString(
"jsp.error.mandatory.attribute",
new Object[] { typeOfTag, missingAttribute}));
/**
* Check to see if there are any more attributes for the specified
* tag.
*/
if (temp.size() == 0)
return;
/**
* Now check to see if the rest of the attributes are valid too.
*/
Enumeration enum = temp.keys ();
String attribute = null;
while (enum.hasMoreElements ()) {
valid = false;
attribute = (String) enum.nextElement ();
for (int i = 0; i < validAttributes.length; i++) {
if (attribute.equals(validAttributes[i].name)) {
valid = true;
break;
}
}
if (!valid)
throw new ParseException(start, Constants.getString(
"jsp.error.invalid.attribute",
new Object[] { typeOfTag, attribute }));
}
}
public static String escapeQueryString(String unescString) {
if ( unescString == null )
return null;
String escString = "";
String shellSpChars = "\\\"";
for(int index=0; index<unescString.length(); index++) {
char nextChar = unescString.charAt(index);
if( shellSpChars.indexOf(nextChar) != -1 )
escString += "\\";
escString += nextChar;
}
return escString;
}
/**
* Escape the 5 entities defined by XML.
*/
public static String escapeXml(String s) {
if (s == null) return null;
StringBuffer sb = new StringBuffer();
for(int i=0; i<s.length(); i++) {
char c = s.charAt(i);
if (c == '<') {
sb.append("<");
} else if (c == '>') {
sb.append(">");
} else if (c == '\'') {
sb.append("'");
} else if (c == '&') {
sb.append("&");
} else if (c == '"') {
sb.append(""e;");
} else {
sb.append(c);
}
}
return sb.toString();
}
public static class ValidAttribute {
String name;
boolean mandatory;
public ValidAttribute (String name, boolean mandatory) {
this.name = name;
this.mandatory = mandatory;
}
public ValidAttribute (String name) {
this (name, false);
}
}
}
class MyEntityResolver implements EntityResolver {
String dtdId;
String dtdResource;
public MyEntityResolver(String id, String resource) {
this.dtdId = id;
this.dtdResource = resource;
}
public InputSource resolveEntity(String publicId, String systemId)
throws SAXException, IOException
{
//System.out.println ("publicId = " + publicId);
//System.out.println ("systemId is " + systemId);
//System.out.println ("resource is " + dtdResource);
if (publicId.equals(dtdId)) {
InputStream input =
this.getClass().getResourceAsStream(dtdResource);
InputSource isrc =
new InputSource(input);
return isrc;
}
else {
//System.out.println ("returning null though dtdURL is " + dtdURL);
return null;
}
}
}