/*
* COMSAT
* Copyright (c) 2013-2016, Parallel Universe Software Co. All rights reserved.
*
* This program and the accompanying materials are dual-licensed under
* either the terms of the Eclipse Public License v1.0 as published by
* the Eclipse Foundation
*
* or (per the licensee's choosing)
*
* under the terms of the GNU Lesser General Public License version 3.0
* as published by the Free Software Foundation.
*/
package co.paralleluniverse.fibers.servlet;
import java.io.IOException;
import javax.servlet.AsyncContext;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
/**
*
* @author eitan
*/
class FiberRequestDispatcher implements RequestDispatcher {
public static final String SLASH = "/";
private final String path;
private final AsyncContext ac;
public FiberRequestDispatcher(String path, AsyncContext ac) {
this.path = path;
this.ac = ac;
}
@Override
public void forward(ServletRequest request, final ServletResponse response) throws ServletException, IOException {
if (ac == null)
throw new UnsupportedOperationException("Sync forward emulation is disabled");
final ServletRequest baseReq = ((FiberServletRequest) request).getReq();
if (baseReq != ac.getRequest() || response != ac.getResponse())
throw new UnsupportedOperationException("Changing the request or the response in forward is not yet supported from fiber servlet");
response.reset();
if (ac.getRequest() instanceof HttpServletRequest)
ac.dispatch(relToAbs((HttpServletRequest) ac.getRequest(), path));
else
ac.dispatch(path); // TODO: think about relative forward in GenericServlet
}
@Override
public void include(ServletRequest request, final ServletResponse response) throws ServletException {
throw new UnsupportedOperationException("Include calls are not yet supported by fiber servlet");
}
public static String relToAbs(HttpServletRequest req, String rel) {
if (!rel.startsWith("/")) {
String relTo = addPaths(req.getServletPath(), req.getPathInfo());
int slash = relTo.lastIndexOf("/");
if (slash > 1)
relTo = relTo.substring(0, slash + 1);
else
relTo = "/";
rel = addPaths(relTo, rel);
}
return rel;
}
public static String addPaths(String p1, String p2) {
if (p1 == null || p1.length() == 0) {
if (p1 != null && p2 == null)
return p1;
return p2;
}
if (p2 == null || p2.length() == 0)
return p1;
int split = p1.indexOf(';');
if (split < 0)
split = p1.indexOf('?');
if (split == 0)
return p2 + p1;
if (split < 0)
split = p1.length();
StringBuilder buf = new StringBuilder(p1.length() + p2.length() + 2);
buf.append(p1);
if (buf.charAt(split - 1) == '/') {
if (p2.startsWith(SLASH)) {
buf.deleteCharAt(split - 1);
buf.insert(split - 1, p2);
} else
buf.insert(split, p2);
} else {
if (p2.startsWith(SLASH))
buf.insert(split, p2);
else {
buf.insert(split, SLASH);
buf.insert(split + 1, p2);
}
}
return buf.toString();
}
}