| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| |
| package org.apache.jasper.tagplugins.jstl; |
| |
| import java.io.ByteArrayOutputStream; |
| import java.io.IOException; |
| import java.io.PrintWriter; |
| import java.io.StringWriter; |
| import java.io.UnsupportedEncodingException; |
| import java.util.Locale; |
| |
| import javax.servlet.ServletOutputStream; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| import javax.servlet.http.HttpServletResponseWrapper; |
| import javax.servlet.jsp.JspException; |
| import javax.servlet.jsp.JspTagException; |
| import javax.servlet.jsp.PageContext; |
| |
| /** |
| * Util contains some often used consts, static methods and embedded class |
| * to support the JSTL tag plugin. |
| */ |
| |
| public class Util { |
| |
| public static final String VALID_SCHEME_CHAR = |
| "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+.-"; |
| |
| public static final String DEFAULT_ENCODING = |
| "ISO-8859-1"; |
| |
| public static final int HIGHEST_SPECIAL = '>'; |
| |
| public static char[][] specialCharactersRepresentation = new char[HIGHEST_SPECIAL + 1][]; |
| |
| static { |
| specialCharactersRepresentation['&'] = "&".toCharArray(); |
| specialCharactersRepresentation['<'] = "<".toCharArray(); |
| specialCharactersRepresentation['>'] = ">".toCharArray(); |
| specialCharactersRepresentation['"'] = """.toCharArray(); |
| specialCharactersRepresentation['\''] = "'".toCharArray(); |
| } |
| |
| /** |
| * Converts the given string description of a scope to the corresponding |
| * PageContext constant. |
| * |
| * The validity of the given scope has already been checked by the |
| * appropriate TLV. |
| * |
| * @param scope String description of scope |
| * |
| * @return PageContext constant corresponding to given scope description |
| * |
| * taken from org.apache.taglibs.standard.tag.common.core.Util |
| */ |
| public static int getScope(String scope){ |
| int ret = PageContext.PAGE_SCOPE; |
| |
| if("request".equalsIgnoreCase(scope)){ |
| ret = PageContext.REQUEST_SCOPE; |
| }else if("session".equalsIgnoreCase(scope)){ |
| ret = PageContext.SESSION_SCOPE; |
| }else if("application".equalsIgnoreCase(scope)){ |
| ret = PageContext.APPLICATION_SCOPE; |
| } |
| |
| return ret; |
| } |
| |
| /** |
| * Returns <tt>true</tt> if our current URL is absolute, |
| * <tt>false</tt> otherwise. |
| * taken from org.apache.taglibs.standard.tag.common.core.ImportSupport |
| */ |
| public static boolean isAbsoluteUrl(String url){ |
| if(url == null){ |
| return false; |
| } |
| |
| int colonPos = url.indexOf(":"); |
| if(colonPos == -1){ |
| return false; |
| } |
| |
| for(int i=0;i<colonPos;i++){ |
| if(VALID_SCHEME_CHAR.indexOf(url.charAt(i)) == -1){ |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| /** |
| * Get the value associated with a content-type attribute. |
| * Syntax defined in RFC 2045, section 5.1. |
| * taken from org.apache.taglibs.standard.tag.common.core.Util |
| */ |
| public static String getContentTypeAttribute(String input, String name) { |
| int begin; |
| int end; |
| int index = input.toUpperCase().indexOf(name.toUpperCase()); |
| if (index == -1) return null; |
| index = index + name.length(); // positioned after the attribute name |
| index = input.indexOf('=', index); // positioned at the '=' |
| if (index == -1) return null; |
| index += 1; // positioned after the '=' |
| input = input.substring(index).trim(); |
| |
| if (input.charAt(0) == '"') { |
| // attribute value is a quoted string |
| begin = 1; |
| end = input.indexOf('"', begin); |
| if (end == -1) return null; |
| } else { |
| begin = 0; |
| end = input.indexOf(';'); |
| if (end == -1) end = input.indexOf(' '); |
| if (end == -1) end = input.length(); |
| } |
| return input.substring(begin, end).trim(); |
| } |
| |
| /** |
| * Strips a servlet session ID from <tt>url</tt>. The session ID |
| * is encoded as a URL "path parameter" beginning with "jsessionid=". |
| * We thus remove anything we find between ";jsessionid=" (inclusive) |
| * and either EOS or a subsequent ';' (exclusive). |
| * |
| * taken from org.apache.taglibs.standard.tag.common.core.ImportSupport |
| */ |
| public static String stripSession(String url) { |
| StringBuffer u = new StringBuffer(url); |
| int sessionStart; |
| while ((sessionStart = u.toString().indexOf(";jsessionid=")) != -1) { |
| int sessionEnd = u.toString().indexOf(";", sessionStart + 1); |
| if (sessionEnd == -1) |
| sessionEnd = u.toString().indexOf("?", sessionStart + 1); |
| if (sessionEnd == -1) // still |
| sessionEnd = u.length(); |
| u.delete(sessionStart, sessionEnd); |
| } |
| return u.toString(); |
| } |
| |
| |
| /** |
| * Performs the following substring replacements |
| * (to facilitate output to XML/HTML pages): |
| * |
| * & -> & |
| * < -> < |
| * > -> > |
| * " -> " |
| * ' -> ' |
| * |
| * See also OutSupport.writeEscapedXml(). |
| * |
| * taken from org.apache.taglibs.standard.tag.common.core.Util |
| */ |
| public static String escapeXml(String buffer) { |
| int start = 0; |
| int length = buffer.length(); |
| char[] arrayBuffer = buffer.toCharArray(); |
| StringBuffer escapedBuffer = null; |
| |
| for (int i = 0; i < length; i++) { |
| char c = arrayBuffer[i]; |
| if (c <= HIGHEST_SPECIAL) { |
| char[] escaped = specialCharactersRepresentation[c]; |
| if (escaped != null) { |
| // create StringBuffer to hold escaped xml string |
| if (start == 0) { |
| escapedBuffer = new StringBuffer(length + 5); |
| } |
| // add unescaped portion |
| if (start < i) { |
| escapedBuffer.append(arrayBuffer,start,i-start); |
| } |
| start = i + 1; |
| // add escaped xml |
| escapedBuffer.append(escaped); |
| } |
| } |
| } |
| // no xml escaping was necessary |
| if (start == 0) { |
| return buffer; |
| } |
| // add rest of unescaped portion |
| if (start < length) { |
| escapedBuffer.append(arrayBuffer,start,length-start); |
| } |
| return escapedBuffer.toString(); |
| } |
| |
| /** Utility methods |
| * taken from org.apache.taglibs.standard.tag.common.core.UrlSupport |
| */ |
| public static String resolveUrl( |
| String url, String context, PageContext pageContext) |
| throws JspException { |
| // don't touch absolute URLs |
| if (isAbsoluteUrl(url)) |
| return url; |
| |
| // normalize relative URLs against a context root |
| HttpServletRequest request = |
| (HttpServletRequest) pageContext.getRequest(); |
| if (context == null) { |
| if (url.startsWith("/")) |
| return (request.getContextPath() + url); |
| else |
| return url; |
| } else { |
| if (!context.startsWith("/") || !url.startsWith("/")) { |
| throw new JspTagException( |
| "In URL tags, when the \"context\" attribute is specified, values of both \"context\" and \"url\" must start with \"/\"."); |
| } |
| if (context.equals("/")) { |
| // Don't produce string starting with '//', many |
| // browsers interpret this as host name, not as |
| // path on same host. |
| return url; |
| } else { |
| return (context + url); |
| } |
| } |
| } |
| |
| /** Wraps responses to allow us to retrieve results as Strings. |
| * mainly taken from org.apache.taglibs.standard.tag.common.core.importSupport |
| */ |
| public static class ImportResponseWrapper extends HttpServletResponseWrapper{ |
| |
| private StringWriter sw = new StringWriter(); |
| private ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
| private ServletOutputStream sos = new ServletOutputStream() { |
| public void write(int b) throws IOException { |
| bos.write(b); |
| } |
| }; |
| private boolean isWriterUsed; |
| private boolean isStreamUsed; |
| private int status = 200; |
| private String charEncoding; |
| |
| public ImportResponseWrapper(HttpServletResponse arg0) { |
| super(arg0); |
| // TODO Auto-generated constructor stub |
| } |
| |
| public PrintWriter getWriter() { |
| if (isStreamUsed) |
| throw new IllegalStateException("Unexpected internal error during <import>: " + |
| "Target servlet called getWriter(), then getOutputStream()"); |
| isWriterUsed = true; |
| return new PrintWriter(sw); |
| } |
| |
| public ServletOutputStream getOutputStream() { |
| if (isWriterUsed) |
| throw new IllegalStateException("Unexpected internal error during <import>: " + |
| "Target servlet called getOutputStream(), then getWriter()"); |
| isStreamUsed = true; |
| return sos; |
| } |
| |
| /** Has no effect. */ |
| public void setContentType(String x) { |
| // ignore |
| } |
| |
| /** Has no effect. */ |
| public void setLocale(Locale x) { |
| // ignore |
| } |
| |
| public void setStatus(int status) { |
| this.status = status; |
| } |
| |
| public int getStatus() { |
| return status; |
| } |
| |
| public String getCharEncoding(){ |
| return this.charEncoding; |
| } |
| |
| public void setCharEncoding(String ce){ |
| this.charEncoding = ce; |
| } |
| |
| public String getString() throws UnsupportedEncodingException { |
| if (isWriterUsed) |
| return sw.toString(); |
| else if (isStreamUsed) { |
| if (this.charEncoding != null && !this.charEncoding.equals("")) |
| return bos.toString(charEncoding); |
| else |
| return bos.toString("ISO-8859-1"); |
| } else |
| return ""; // target didn't write anything |
| } |
| } |
| |
| } |