/*
* Copyright (c) 1998-2011 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
* Free SoftwareFoundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package com.caucho.jstl.el;
import com.caucho.el.Expr;
import com.caucho.jsp.BodyContentImpl;
import com.caucho.jsp.PageContextImpl;
import com.caucho.jstl.NameValueTag;
import com.caucho.server.http.CauchoResponse;
import com.caucho.util.CharBuffer;
import com.caucho.util.L10N;
import com.caucho.vfs.FlushBuffer;
import com.caucho.vfs.ReadStream;
import com.caucho.vfs.Vfs;
import javax.el.ELContext;
import javax.el.ELException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
public class ImportTag extends BodyTagSupport implements NameValueTag {
private static L10N L = new L10N(ImportTag.class);
private Expr _urlExpr;
private Expr _contextExpr;
private CharBuffer _query = new CharBuffer();
private Expr _charEncodingExpr;
private String _var;
private String _scope;
private String _varReader;
private Reader _reader;
/**
* Sets the URL to be imported.
*/
public void setURL(Expr url)
{
_urlExpr = url;
}
/**
* Sets the external context for the import.
*/
public void setContext(Expr context)
{
_contextExpr = context;
}
/**
* Adds a parameter.
*/
public void addParam(String name, String value)
{
if (name == null)
return;
if (value == null)
value = "";
if (_query.length() != 0)
_query.append('&');
_query.append(name);
_query.append('=');
int len = value.length();
for (int i = 0; i < len; i++) {
char ch = value.charAt(i);
switch (ch) {
case '&':
_query.append("%26");
break;
case '%':
_query.append("%25");
break;
case '+':
_query.append("%2b");
break;
case '=':
_query.append("%3d");
break;
default:
_query.append(ch);
break;
}
}
}
/**
* Sets the external character encoding for the import.
*/
public void setCharEncoding(Expr charEncoding)
{
_charEncodingExpr = charEncoding;
}
/**
* Sets the variable for the import.
*/
public void setVar(String var)
{
_var = var;
}
/**
* Sets the scope for the result variable for the output.
*/
public void setScope(String scope)
{
_scope = scope;
}
/**
* Sets the variable for the import.
*/
public void setVarReader(String varReader)
{
_varReader = varReader;
}
/**
* Process the tag.
*/
public int doStartTag()
throws JspException
{
JspWriter jspWriter = null;
_query.clear();
PageContextImpl pageContext = (PageContextImpl) this.pageContext;
try {
if (_varReader != null) {
jspWriter = pageContext.pushBody();
handleBody();
BodyContentImpl body = (BodyContentImpl) pageContext.getOut();
_reader = body.getReader();
pageContext.setAttribute(_varReader, _reader);
return EVAL_BODY_INCLUDE;
}
else
return EVAL_BODY_BUFFERED;
} catch (JspException e) {
throw e;
} catch (Exception e) {
throw new JspException(e);
} finally {
if (jspWriter != null)
pageContext.popBody();
}
}
/**
* Process the end tag
*/
public int doEndTag()
throws JspException
{
if (_varReader == null) {
try {
JspWriter jspWriter = pageContext.pushBody();
handleBody();
BodyContentImpl body = (BodyContentImpl) pageContext.getOut();
if (_var != null) {
String value = body.getString();
pageContext.popBody();
CoreSetTag.setValue(pageContext, _var, _scope, value);
}
else {
body.writeOut(body.getEnclosingWriter());
pageContext.popBody();
}
} catch (JspException e) {
throw e;
} catch (Exception e) {
throw new JspException(e);
}
}
return EVAL_PAGE;
}
private void handleBody()
throws JspException, ServletException, IOException, ELException
{
PageContextImpl pageContext = (PageContextImpl) this.pageContext;
ELContext env = pageContext.getELContext();
String url = _urlExpr.evalString(env);
if (url == null || url.equals(""))
throw new JspTagException(L.l("URL may not be null for `{0}'",
_urlExpr));
if (_query == null || _query.getLength() == 0) {
}
else if (url.indexOf('?') > 0)
url = url + '&' + _query;
else
url = url + '?' + _query;
JspWriter out = pageContext.getOut();
if (out instanceof FlushBuffer)
((FlushBuffer) out).flushBuffer();
else
out.flush();
if (_contextExpr != null) {
String context = _contextExpr.evalString(env);
if (! url.startsWith("/"))
throw new JspException(L.l("URL `{0}' must start with `/' with context `{0}'", url, context));
if (context != null && context.startsWith("/")) {
ServletContext app = pageContext.getServletContext().getContext(context);
try {
RequestDispatcher disp = app.getRequestDispatcher(url);
if (disp == null)
throw new JspException(L.l("URL `{0}' does not map to any servlet",
url));
CauchoResponse response = (CauchoResponse) pageContext.getResponse();
response.getResponseStream().setEncoding(null);
disp.include(pageContext.getRequest(), response);
} catch (FileNotFoundException e) {
throw new JspException(L.l("`{0}' is an unknown file or servlet.",
url));
}
}
else
handleExternalBody(context + url);
return;
}
int colon = url.indexOf(':');
int slash = url.indexOf('/');
if (slash == 0 || colon < 0 || slash < 0 || slash < colon) {
ServletRequest request = pageContext.getRequest();
try {
RequestDispatcher disp = request.getRequestDispatcher(url);
if (disp == null)
throw new JspException(L.l("URL `{0}' does not map to any servlet",
url));
CauchoResponse response = (CauchoResponse) pageContext.getResponse();
response.getResponseStream().setEncoding(null);
disp.include(pageContext.getRequest(), response);
} catch (FileNotFoundException e) {
throw new JspException(L.l("URL `{0}' is an unknown file or servlet.",
url));
}
}
else
handleExternalBody(url);
}
private void handleExternalBody(String url)
throws JspException, ServletException, IOException, ELException
{
PageContextImpl pageContext = (PageContextImpl) this.pageContext;
ELContext env = pageContext.getELContext();
URL netURL = new URL(url);
URLConnection conn = netURL.openConnection();
if (conn instanceof HttpURLConnection)
((HttpURLConnection) conn).setFollowRedirects(true);
InputStream is = conn.getInputStream();
try {
ReadStream in = Vfs.openRead(is);
String encoding = conn.getContentEncoding();
String contentType = conn.getContentType();
if (_charEncodingExpr != null) {
encoding = _charEncodingExpr.evalString(env);
if (encoding != null && ! encoding.equals(""))
in.setEncoding(encoding);
}
else if (encoding != null)
in.setEncoding(encoding);
else if (contentType != null) {
int p = contentType.indexOf("charset=");
if (p > 0) {
CharBuffer cb = new CharBuffer();
for (int i = p + 8; i < contentType.length(); i++) {
int ch = contentType.charAt(i);
if (ch == '"' || ch == '\'') {
}
else if (ch >= 'a' && ch <= 'z')
cb.append((char) ch);
else if (ch >= 'A' && ch <= 'Z')
cb.append((char) ch);
else if (ch >= '0' && ch <= '9')
cb.append((char) ch);
else if (ch == '-' || ch == '_')
cb.append((char) ch);
else
break;
}
encoding = cb.toString();
in.setEncoding(encoding);
}
}
JspWriter out = pageContext.getOut();
int ch;
while ((ch = in.readChar()) >= 0)
out.print((char) ch);
} finally {
is.close();
}
}
}