/*
* (C) Copyright 2006-2009 Nuxeo SAS (http://nuxeo.com/) and contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser General Public License
* (LGPL) version 2.1 which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl.html
*
* This library 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. See the GNU
* Lesser General Public License for more details.
*
* Contributors:
* bstefanescu
*
* $Id$
*/
package org.nuxeo.ecm.webengine.gwt.dev;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Enumeration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
*/
public class RedirectService extends HttpServlet implements Debug {
private static final long serialVersionUID = 1L;
protected static Pattern HTTP_RESP = Pattern.compile("HTTP/1\\..\\s+([0-9]+)\\s+(.*)");
protected String redirectPrefix = REDIRECT_PREFIX;
protected String redirectHost = REDIRECT_HOST;
protected int redirectPort = REDIRECT_PORT;
protected String redirectPattern = REDIRECT_PATTERN;
protected String redirectReplacement = REDIRECT_REPLACEMENT;
protected boolean trace = REDIRECT_TRACE;
protected boolean traceContent = REDIRECT_TRACE_CONTENT;
public RedirectService(String host, int port) {
this.redirectHost = host;
this.redirectPort = port;
// TODO: use logging instead
System.out.println("----------------------------------------------------------");
System.out.println("Redirect Service Enabled: ");
System.out.println("redirect.prefix: "+redirectPrefix);
System.out.println("redirect.host: "+redirectHost);
System.out.println("redirect.port: "+redirectPort);
System.out.println("redirect.pattern: "+redirectPattern);
System.out.println("redirect.replacement: "+redirectReplacement);
System.out.println("redirect.trace: "+trace);
System.out.println("----------------------------------------------------------");
}
public String getRedirectPrefix() {
return redirectPrefix;
}
public void setRedirectPrefix(String redirectPrefix) {
this.redirectPrefix = redirectPrefix;
}
public void setTrace(boolean trace) {
this.trace = trace;
}
public void setTraceContent(boolean traceContent) {
this.traceContent = traceContent;
}
@SuppressWarnings("unchecked")
public void redirect(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
StringBuilder buf = new StringBuilder(); // getRequestURL(req);
String urlPath = req.getRequestURI();
if (redirectPrefix.equals(urlPath)) {
urlPath = "/";
} else {
urlPath = urlPath.replaceAll(redirectPattern, redirectReplacement);
}
buf.append(req.getMethod()).append(" ").append(urlPath).append(" HTTP/1.0\r\n");
Enumeration<String> keys = req.getHeaderNames();
while (keys.hasMoreElements()) {
String key = keys.nextElement();
Enumeration<String> vals = req.getHeaders(key);
while (vals.hasMoreElements()) {
if (!"connection".equalsIgnoreCase(key)) { // skip Connection: Keep-Alive
buf.append(key).append(": ").append(vals.nextElement()).append("\r\n");
} else {
vals.nextElement();
}
}
}
buf.append("\r\n");
InputStream rin = null;
OutputStream rout =null;
InputStream in = null;
try {
Socket socket = new Socket(redirectHost, redirectPort);
rout = socket.getOutputStream();
rout.write(buf.toString().getBytes());
in = req.getInputStream();
if (trace) {
traceln("========== HTTP REQUEST ===========");
traceln(buf.toString());
traceln("");
copyDebug(in, rout);
traceln("===================================");
} else {
copy(in, rout);
}
rout.flush();
rin = new BufferedInputStream(socket.getInputStream());
if (trace) {
traceln("========= HTTP RESPONSE ===========");
}
transferResponse(rin, resp);
if (trace) {
traceln("===================================");
}
} finally {
if (rout != null) {
rout.close();
}
if (rin != null) {
rin.close();
}
if (in != null) {
in.close();
}
}
}
public void copy(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024*64];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
}
public void copyDebug(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024*64];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
if (traceContent) {
trace(new String(buffer, 0, read));
}
}
traceln("");
}
public int getStatusCode(String line) {
Matcher matcher = HTTP_RESP.matcher(line.trim());
if (matcher.matches()) {
return Integer.parseInt(matcher.group(1));
}
return -1;
}
public void transferResponse(InputStream in, HttpServletResponse resp) throws IOException {
int cnt = 0;
StringBuilder buf = new StringBuilder();
while (true) {
int c = in.read();
if (c == -1) {
break;
}
if (c == '\r') {
continue;
}
if (c == '\n') {
if (buf.length() > 0) {
if (cnt == 0) { // the first header
int status = getStatusCode(buf.toString().trim());
if (status == -1) {
throw new IOException("Bug in RedirectServlet?");
}
if (trace) {
traceln(buf.toString());
}
// if (status >= 400) {
// resp.sendError(status);
// return;
// }
resp.setStatus(status);
} else {
setHeader(buf.toString().trim(), resp);
}
buf.setLength(0);
cnt++;
} else {
break;
}
} else {
buf.append((char)c);
}
}
OutputStream out = resp.getOutputStream();
try {
if (trace) {
traceln("");
copyDebug(in, out);
} else {
copy(in, out);
}
} finally {
out.flush();
out.close();
}
}
protected void setHeader(String header, HttpServletResponse resp) {
if (trace) {
traceln(header);
}
int p = header.indexOf(':');
if (p > -1) {
resp.setHeader(header.substring(0, p), header.substring(p+1).trim());
}
}
public static void traceln(String str) {
System.out.println(str);
}
public static void trace(String str) {
System.out.print(str);
}
public static void main(String[] args) {
Matcher m = HTTP_RESP.matcher("HTTP/1.1 404 Not Found");
if (m.matches()) {
System.out.println(m.group(1));
System.out.println(m.group(2));
}
}
}