package org.jrack;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.channels.Channels;
import java.util.Map;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jrack.logging.JRackLogger;
import org.jrack.logging.Slf4jLogger;
import org.jrack.utils.ClassUtilities;
public class RackServlet extends HttpServlet {
private JRackLogger logger = new Slf4jLogger(RackServlet.class.getName());
private JRack rack;
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
//todo jrack yaml config file
String rackClass = config.getInitParameter("rack");
//todo user logging
try {
setRack((JRack) ClassUtilities.loadClass(rackClass).newInstance());
} catch (Exception e) {
if (this.rack == null) {
throw new ServletException("Cannot load the 'rack' implementation: " + rackClass);
} else {
rackClass = this.rack.getClass().getCanonicalName();
logger.log(String.format("this 'rack' is using: %s", rackClass));
}
}
logger.log(String.format("%s; active ....", rackClass));
}
/**
* used by servlet container
*/
public RackServlet() {
}
public RackServlet(JRack rack) {
this.rack = rack;
}
private void processCall(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException {
try {
Context<String> resp = rack.call(rack.getEnvironment(httpRequest));
httpResponse.setStatus((Integer) resp.getObject(Rack.MESSAGE_STATUS));
for (Map.Entry<String, Object> entry : resp) {
if (entry.getKey().startsWith(Rack.HTTP_)) {
httpResponse.setHeader(entry.getKey().substring(Rack.HTTP_.length()),
(String) entry.getValue());
}
}
RackBody body = (RackBody) resp.getObject(Rack.MESSAGE_BODY);
//httpResponse.getWriter().print(rackResponse.getResponse());
if (body != null) {
if (body.getType() == RackBody.Type.file) {
// Copy.copy(new FileInputStream(body.getBodyAsFile()), httpResponse.getOutputStream());
// or use NIO?
final File file = body.getBodyAsFile();
if (file != null) {
try (FileInputStream inputStream = new FileInputStream(file)) {
inputStream.getChannel()
.transferTo(0, file.length(), Channels.newChannel(httpResponse.getOutputStream()));
}
}
} else {
httpResponse.setCharacterEncoding(RackResponse.DEFAULT_ENCODING);
httpResponse.getOutputStream().write(body.getBytes(RackResponse.DEFAULT_ENCODING));
}
} else {
httpResponse.setStatus(HttpServletResponse.SC_NO_CONTENT);
}
} catch (Exception e) {
RackServlet.throwAsError(e);
}
}
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
processCall((HttpServletRequest) req, (HttpServletResponse) res);
}
public JRack getRack() {
return rack;
}
public void setRack(JRack rack) {
this.rack = rack;
}
public static Error throwAsError(Throwable t) throws Error {
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else if (t instanceof Error) {
throw (Error) t;
} else {
throw new Error(t);
}
}
}