📄 importsupport.java
字号:
package org.apache.velocity.tools.view;
/*
* 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.
*/
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Locale;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* <p>Provides methods to import arbitrary local or remote resources as strings.</p>
* <p>Based on ImportSupport from the JSTL taglib by Shawn Bayern</p>
*
* @author <a href="mailto:marinoj@centrum.is">Marino A. Jonsson</a>
* @since VelocityTools 1.1
* @version $Revision: 477914 $ $Date: 2006-11-21 13:52:11 -0800 (Tue, 21 Nov 2006) $
*/
public abstract class ImportSupport {
protected static final Log LOG = LogFactory.getLog(ImportSupport.class);
protected ServletContext application;
protected HttpServletRequest request;
protected HttpServletResponse response;
protected static final String VALID_SCHEME_CHARS =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+.-";
/** Default character encoding for response. */
protected static final String DEFAULT_ENCODING = "ISO-8859-1";
//*********************************************************************
// URL importation logic
/*
* Overall strategy: we have two entry points, acquireString() and
* acquireReader(). The latter passes data through unbuffered if
* possible (but note that it is not always possible -- specifically
* for cases where we must use the RequestDispatcher. The remaining
* methods handle the common.core logic of loading either a URL or a local
* resource.
*
* We consider the 'natural' form of absolute URLs to be Readers and
* relative URLs to be Strings. Thus, to avoid doing extra work,
* acquireString() and acquireReader() delegate to one another as
* appropriate. (Perhaps I could have spelled things out more clearly,
* but I thought this implementation was instructive, not to mention
* somewhat cute...)
*/
/**
*
* @param url the URL resource to return as string
* @return the URL resource as string
* @throws IOException
* @throws java.lang.Exception
*/
protected String acquireString(String url) throws IOException, Exception {
// Record whether our URL is absolute or relative
if (isAbsoluteUrl(url))
{
// for absolute URLs, delegate to our peer
BufferedReader r = null;
try
{
r = new BufferedReader(acquireReader(url));
StringBuffer sb = new StringBuffer();
int i;
// under JIT, testing seems to show this simple loop is as fast
// as any of the alternatives
while ((i = r.read()) != -1)
{
sb.append((char)i);
}
return sb.toString();
}
finally
{
if(r != null)
{
try
{
r.close();
}
catch (IOException ioe)
{
LOG.error("Could not close reader.", ioe);
}
}
}
}
else // handle relative URLs ourselves
{
// URL is relative, so we must be an HTTP request
if (!(request instanceof HttpServletRequest
&& response instanceof HttpServletResponse))
{
throw new Exception("Relative import from non-HTTP request not allowed");
}
// retrieve an appropriate ServletContext
// normalize the URL if we have an HttpServletRequest
if (!url.startsWith("/"))
{
String sp = ((HttpServletRequest)request).getServletPath();
url = sp.substring(0, sp.lastIndexOf('/')) + '/' + url;
}
// strip the session id from the url
url = stripSession(url);
// from this context, get a dispatcher
RequestDispatcher rd = application.getRequestDispatcher(url);
if (rd == null)
{
throw new Exception("Couldn't get a RequestDispatcher for \""
+ url + "\"");
}
// include the resource, using our custom wrapper
ImportResponseWrapper irw =
new ImportResponseWrapper((HttpServletResponse)response);
try
{
rd.include(request, irw);
}
catch (IOException ex)
{
throw new Exception("Problem importing the relative URL \""
+ url + "\". " + ex);
}
catch (RuntimeException ex)
{
throw new Exception("Problem importing the relative URL \""
+ url + "\". " + ex);
}
// disallow inappropriate response codes per JSTL spec
if (irw.getStatus() < 200 || irw.getStatus() > 299)
{
throw new Exception("Invalid response code '" + irw.getStatus()
+ "' for \"" + url + "\"");
}
// recover the response String from our wrapper
return irw.getString();
}
}
/**
*
* @param url the URL to read
* @return a Reader for the InputStream created from the supplied URL
* @throws IOException
* @throws java.lang.Exception
*/
protected Reader acquireReader(String url) throws IOException, Exception
{
if (!isAbsoluteUrl(url))
{
// for relative URLs, delegate to our peer
return new StringReader(acquireString(url));
}
else
{
// absolute URL
URLConnection uc = null;
HttpURLConnection huc = null;
InputStream i = null;
try
{
// handle absolute URLs ourselves, using java.net.URL
URL u = new URL(url);
// URL u = new URL("http", "proxy.hi.is", 8080, target);
uc = u.openConnection();
i = uc.getInputStream();
// check response code for HTTP URLs, per spec,
if (uc instanceof HttpURLConnection)
{
huc = (HttpURLConnection)uc;
int status = huc.getResponseCode();
if (status < 200 || status > 299)
{
throw new Exception(status + " " + url);
}
}
// okay, we've got a stream; encode it appropriately
Reader r = null;
String charSet;
// charSet extracted according to RFC 2045, section 5.1
String contentType = uc.getContentType();
if (contentType != null)
{
charSet = ImportSupport.getContentTypeAttribute(contentType, "charset");
if (charSet == null)
{
charSet = DEFAULT_ENCODING;
}
}
else
{
charSet = DEFAULT_ENCODING;
}
try
{
r = new InputStreamReader(i, charSet);
}
catch (UnsupportedEncodingException ueex)
{
r = new InputStreamReader(i, DEFAULT_ENCODING);
}
if (huc == null)
{
return r;
}
else
{
return new SafeClosingHttpURLConnectionReader(r, huc);
}
}
catch (IOException ex)
{
if (i != null)
{
try
{
i.close();
}
catch (IOException ioe)
{
LOG.error("Could not close InputStream", ioe);
}
}
if (huc != null)
{
huc.disconnect();
}
throw new Exception("Problem accessing the absolute URL \""
+ url + "\". " + ex);
}
catch (RuntimeException ex)
{
if (i != null)
{
try
{
i.close();
}
catch (IOException ioe)
{
LOG.error("Could not close InputStream", ioe);
}
}
if (huc != null)
{
huc.disconnect();
}
// because the spec makes us
throw new Exception("Problem accessing the absolute URL \""
+ url + "\". " + ex);
}
}
}
protected static class SafeClosingHttpURLConnectionReader extends Reader
{
private HttpURLConnection huc;
private Reader wrappedReader;
SafeClosingHttpURLConnectionReader(Reader r, HttpURLConnection huc)
{
this.wrappedReader = r;
this.huc = huc;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -