package org.develnext.jphp.ext.httpserver.classes;
import org.develnext.jphp.ext.httpserver.HttpServerExtension;
import org.eclipse.jetty.server.*;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.handler.ResourceHandler;
import org.eclipse.jetty.server.session.DefaultSessionIdManager;
import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import php.runtime.Memory;
import php.runtime.annotation.Reflection.Name;
import php.runtime.annotation.Reflection.Namespace;
import php.runtime.annotation.Reflection.Signature;
import php.runtime.env.Environment;
import php.runtime.invoke.Invoker;
import php.runtime.lang.BaseObject;
import php.runtime.memory.ArrayMemory;
import php.runtime.reflection.ClassEntity;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.InetSocketAddress;
@Name("HttpServer")
@Namespace(HttpServerExtension.NS)
public class PHttpServer extends BaseObject {
private Server server;
private HandlerList handlers = new HandlerList();
private SessionIdManager idmanager;
public PHttpServer(Environment env, Server server) {
super(env);
this.server = server;
}
public PHttpServer(Environment env, ClassEntity clazz) {
super(env, clazz);
}
@Signature
public void __construct() {
server = new Server();
initSessionManager();
}
@Signature
public void __construct(int port) {
server = new Server(port);
initSessionManager();
}
private void initSessionManager() {
idmanager = new DefaultSessionIdManager(server);
server.setSessionIdManager(idmanager);
SessionHandler sessions = new SessionHandler();
sessions.setSessionIdManager(idmanager);
handlers.addHandler(sessions);
}
@Signature
public void __construct(int port, String host) {
server = new Server(new InetSocketAddress(host, port));
}
@Signature
public void addHandler(final Environment env, final Invoker invoker) {
handlers.addHandler(new AbstractHandler() {
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
invoker.callAny(new PHttpServerRequest(env, baseRequest), new PHttpServerResponse(env, response));
}
});
}
@Signature
public void addResourceHandler(ArrayMemory h) {
ResourceHandler handler = new ResourceHandler();
if (!h.containsKey("base")) {
throw new IllegalArgumentException("Resource handler must contain 'base' value");
}
handler.setResourceBase(h.valueOfIndex("base").toString());
if (h.containsKey("cacheControl")) {
handler.setCacheControl(h.valueOfIndex("cacheControl").toString());
}
if (h.containsKey("acceptRanges")) {
handler.setAcceptRanges(h.valueOfIndex("acceptRanges").toBoolean());
}
if (h.containsKey("dirAllowed")) {
handler.setDirAllowed(h.valueOfIndex("dirAllowed").toBoolean());
}
if (h.containsKey("dirsListed")) {
handler.setDirectoriesListed(h.valueOfIndex("dirsListed").toBoolean());
}
if (h.containsKey("etags")) {
handler.setEtags(h.valueOfIndex("etags").toBoolean());
}
if (h.containsKey("pathInfoOnly")) {
handler.setPathInfoOnly(h.valueOfIndex("pathInfoOnly").toBoolean());
}
if (h.containsKey("welcomeFile")) {
handler.setWelcomeFiles(new String[] { h.valueOfIndex("welcomeFile").toString() });
}
handlers.addHandler(handler);
}
@Signature
public void listen(Memory value) {
listen(value, null);
}
@Signature
public void listen(Memory value, ArrayMemory sslSettings) {
ServerConnector connector;
if (sslSettings != null) {
SslContextFactory contextFactory = new SslContextFactory();
// key store
if (sslSettings.containsKey("keyStorePath"))
contextFactory.setKeyStorePath(sslSettings.valueOfIndex("keyStorePath").toString());
if (sslSettings.containsKey("keyStorePassword"))
contextFactory.setKeyStoreType(sslSettings.valueOfIndex("keyStorePassword").toString());
if (sslSettings.containsKey("keyStoreType"))
contextFactory.setKeyStoreType(sslSettings.valueOfIndex("keyStoreType").toString());
if (sslSettings.containsKey("keyStoreProvider"))
contextFactory.setKeyStoreProvider(sslSettings.valueOfIndex("keyStoreProvider").toString());
// trust store
if (sslSettings.containsKey("trustStorePath"))
contextFactory.setTrustStorePath(sslSettings.valueOfIndex("trustStorePath").toString());
if (sslSettings.containsKey("trustStorePassword"))
contextFactory.setTrustStoreType(sslSettings.valueOfIndex("trustStorePassword").toString());
if (sslSettings.containsKey("trustStoreType"))
contextFactory.setTrustStoreType(sslSettings.valueOfIndex("trustStoreType").toString());
if (sslSettings.containsKey("trustStoreProvider"))
contextFactory.setTrustStoreProvider(sslSettings.valueOfIndex("trustStoreProvider").toString());
if (sslSettings.containsKey("trustAll"))
contextFactory.setTrustAll(sslSettings.valueOfIndex("trustAll").toBoolean());
if (sslSettings.containsKey("trustManagerFactoryAlgorithm"))
contextFactory.setTrustManagerFactoryAlgorithm(sslSettings.valueOfIndex("trustManagerFactoryAlgorithm").toString());
// key manager
if (sslSettings.containsKey("keyManagerFactoryAlgorithm"))
contextFactory.setKeyManagerFactoryAlgorithm(sslSettings.valueOfIndex("keyManagerFactoryAlgorithm").toString());
if (sslSettings.containsKey("keyManagerPassword"))
contextFactory.setKeyManagerPassword(sslSettings.valueOfIndex("keyManagerPassword").toString());
// other
if (sslSettings.containsKey("certAlias"))
contextFactory.setCertAlias(sslSettings.valueOfIndex("certAlias").toString());
if (sslSettings.containsKey("protocol"))
contextFactory.setProtocol(sslSettings.valueOfIndex("protocol").toString());
if (sslSettings.containsKey("provider"))
contextFactory.setProvider(sslSettings.valueOfIndex("provider").toString());
if (sslSettings.containsKey("validateCerts"))
contextFactory.setValidateCerts(sslSettings.valueOfIndex("validateCerts").toBoolean());
connector = new ServerConnector(server, contextFactory);
} else {
connector = new ServerConnector(server);
}
if (value.isNumber()) {
connector.setPort(value.toInteger());
} else {
String[] strings = value.toString().split("\\:");
if (strings.length < 2) {
throw new IllegalArgumentException("Invalid listen value: " + value);
}
connector.setHost(strings[0]);
connector.setPort(Integer.parseInt(strings[1]));
}
server.addConnector(connector);
}
@Signature
public void runInBackground() throws Exception {
server.setHandler(handlers);
server.start();
}
@Signature
public void run() throws Exception {
runInBackground();
server.join();
}
@Signature
public void shutdown() throws Exception {
server.stop();
}
}