/*
* Copyright 2012 Future Systems
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.krakenapps.httpd.impl;
import java.io.File;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Set;
import javax.servlet.ServletContext;
import javax.servlet.ServletRegistration;
import org.krakenapps.api.Script;
import org.krakenapps.api.ScriptArgument;
import org.krakenapps.api.ScriptContext;
import org.krakenapps.api.ScriptUsage;
import org.krakenapps.httpd.FileResourceServlet;
import org.krakenapps.httpd.HttpConfiguration;
import org.krakenapps.httpd.HttpContext;
import org.krakenapps.httpd.HttpContextRegistry;
import org.krakenapps.httpd.HttpServer;
import org.krakenapps.httpd.HttpService;
import org.krakenapps.httpd.VirtualHost;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HttpdScript implements Script {
private final Logger logger = LoggerFactory.getLogger(HttpdScript.class.getName());
private ScriptContext context;
private HttpService httpd;
public HttpdScript(HttpService httpd) {
this.httpd = httpd;
}
@Override
public void setScriptContext(ScriptContext context) {
this.context = context;
}
@ScriptUsage(description = "print all http contexts")
public void contexts(String[] args) {
context.println("HTTP Contexts");
context.println("---------------");
HttpContextRegistry registry = httpd.getContextRegistry();
for (String name : registry.getContextNames()) {
HttpContext ctx = registry.findContext(name);
context.println(ctx);
context.println("");
}
}
@ScriptUsage(description = "remove http contexts", arguments = { @ScriptArgument(name = "context name", type = "string", description = "http context name") })
public void removeContext(String[] args) {
HttpContextRegistry registry = httpd.getContextRegistry();
registry.removeContext(args[0]);
}
@ScriptUsage(description = "get port bindings")
public void bindings(String[] args) {
context.println("Port Bindings");
context.println("---------------------");
for (InetSocketAddress binding : httpd.getListenAddresses()) {
HttpServer server = httpd.getServer(binding);
HttpConfiguration config = server.getConfiguration();
String ssl = config.isSsl() ? " (ssl: key " + config.getKeyAlias() + ", trust " + config.getTrustAlias() + ")" : "";
String virtualHosts = "";
if (config.getVirtualHosts().size() > 0) {
for (VirtualHost h : config.getVirtualHosts())
virtualHosts += "\n " + h;
}
String idleTime = "idle timeout: " + config.getIdleTimeout() + "seconds";
String defaultHttpContext = config.getDefaultHttpContext();
String additional = defaultHttpContext == null ? idleTime : "default context: " + config.getDefaultHttpContext()
+ ", " + idleTime;
String information = config.getListenAddress() + ssl + (server.isOpened() ? ", opened, " : ", closed, ") + additional;
context.println(information + virtualHosts);
}
}
@ScriptUsage(description = "open port", arguments = {
@ScriptArgument(name = "port", type = "int", description = "bind port"),
@ScriptArgument(name = "default context", type = "String", description = "default http context") })
public void open(String[] args) {
try {
int port = Integer.valueOf(args[0]);
String defaultContext = args[1];
HttpConfiguration config = new HttpConfiguration(new InetSocketAddress(port));
config.setDefaultHttpContext(defaultContext);
HttpServer server = httpd.createServer(config);
server.open();
context.println("opened http server");
} catch (Exception e) {
context.println(e.getMessage());
logger.error("kraken webconsole: cannot open port", e);
}
}
@ScriptUsage(description = "open https server", arguments = {
@ScriptArgument(name = "port", type = "int", description = "bind port"),
@ScriptArgument(name = "key alias", type = "string", description = "JKS keystore name"),
@ScriptArgument(name = "trust alias", type = "string", description = "JKS truststore name for client authentication", optional = true) })
public void openSsl(String[] args) {
try {
int port = Integer.valueOf(args[0]);
String keyAlias = args[1];
String trustAlias = null;
if (args.length > 2)
trustAlias = args[2];
InetSocketAddress listen = new InetSocketAddress(port);
HttpConfiguration config = new HttpConfiguration(listen, keyAlias, trustAlias);
HttpServer server = httpd.createServer(config);
server.open();
context.println("opened https server");
} catch (Exception e) {
context.println(e.getMessage());
logger.error("kraken webconsole: cannot open ssl port");
}
}
@ScriptUsage(description = "add virtual host", arguments = {
@ScriptArgument(name = "port", type = "int", description = "bind port"),
@ScriptArgument(name = "http context", type = "string", description = "http context name"),
@ScriptArgument(name = "host name pattern", type = "string", description = "host name pattern", optional = true) })
public void addVirtualHost(String[] args) {
int port = Integer.valueOf(args[0]);
InetSocketAddress listen = new InetSocketAddress(port);
HttpServer server = httpd.getServer(listen);
if (server == null) {
context.println("http server not found");
return;
}
String hostNamePattern = ".*";
if (args.length > 2)
hostNamePattern = args[2];
VirtualHost v = new VirtualHost();
v.setHttpContextName(args[1]);
v.setHostNames(Arrays.asList(hostNamePattern));
server.addVirtualHost(v);
context.println("added");
}
@ScriptUsage(description = "remove virtual host", arguments = {
@ScriptArgument(name = "port", type = "int", description = "bind port"),
@ScriptArgument(name = "http context", type = "string", description = "http context name") })
public void removeVirtualHost(String[] args) {
int port = Integer.valueOf(args[0]);
InetSocketAddress listen = new InetSocketAddress(port);
HttpServer server = httpd.getServer(listen);
if (server == null) {
context.println("http server not found");
return;
}
server.removeVirtualHost(args[1]);
context.println("removed");
}
@ScriptUsage(description = "close port", arguments = {
@ScriptArgument(name = "listen port", type = "int", description = "bind port"),
@ScriptArgument(name = "listen addr", type = "string", description = "bind address", optional = true) })
public void close(String[] args) {
try {
int port = Integer.valueOf(args[0]);
InetSocketAddress listen = null;
if (args.length >= 2)
listen = new InetSocketAddress(args[1], port);
else
listen = new InetSocketAddress(port);
httpd.removeServer(listen);
context.println("closed");
} catch (Exception e) {
context.println(e.getMessage());
logger.error("kraken webconsole: cannot close port", e);
}
}
@ScriptUsage(description = "attach filesystem path", arguments = {
@ScriptArgument(name = "context", type = "string", description = "http context name"),
@ScriptArgument(name = "servlet name", type = "string", description = "servlet name"),
@ScriptArgument(name = "prefix", type = "string", description = "path prefix without asterisk"),
@ScriptArgument(name = "filesystem path", type = "string", description = "filesystem path") })
public void attachDirectory(String[] args) {
String servletName = args[1];
String prefix = args[2];
String basePath = args[3];
if (prefix.contains("*")) {
context.println("prefix should not contain any asterisk");
return;
}
HttpContext ctx = httpd.ensureContext(args[0]);
try {
File target = new File(basePath);
if (!target.exists()) {
context.println("directory does not exists: " + target.getAbsolutePath());
return;
}
if (!target.isDirectory()) {
context.println("filesystem path is not a directory");
return;
}
ServletContext servletContext = ctx.getServletContext();
servletContext.addServlet(servletName, new FileResourceServlet(target));
ServletRegistration r = servletContext.getServletRegistration(servletName);
Set<String> failed = r.addMapping(buildUrlPattern(prefix));
if (failed != null && !failed.isEmpty()) {
context.println("cannot add following url patterns");
for (String fail : failed)
context.println(fail);
} else {
context.println("attached");
}
} catch (Throwable t) {
context.println("cannot attach filesystem path: " + t.getMessage());
logger.error("kraken httpd: cannot attach filesystem path", t);
}
}
private String buildUrlPattern(String prefix) {
if (prefix.isEmpty() || prefix.equals("/"))
return "/*";
return prefix + "/*";
}
@ScriptUsage(description = "remove servlet", arguments = {
@ScriptArgument(name = "context", type = "string", description = "context name"),
@ScriptArgument(name = "servlet", type = "string", description = "servlet name") })
public void removeServlet(String[] args) {
String contextName = args[0];
String servletName = args[1];
if (httpd != null) {
HttpContext ctx = httpd.ensureContext(contextName);
if (ctx == null) {
context.println("Context name" + contextName + "not Exist");
return;
}
ctx.removeServlet(servletName);
}
}
@ScriptUsage(description = "set idle timeout", arguments = {
@ScriptArgument(name = "listen address", type = "string", description = "listen ip address"),
@ScriptArgument(name = "listen port", type = "int", description = "listen port number (0-65535)"),
@ScriptArgument(name = "idle timeout", type = "int", description = "idle time out in seconds") })
public void setIdleTimeout(String[] args) {
try {
InetAddress addr = InetAddress.getByName(args[0]);
int port = Integer.valueOf(args[1]);
int idleTimeout = Integer.valueOf(args[2]);
InetSocketAddress listenAddr = new InetSocketAddress(addr, port);
HttpServer server = httpd.getServer(listenAddr);
if (server == null) {
context.println("http server not found");
return;
}
HttpConfiguration config = server.getConfiguration();
config.setIdleTimeout(idleTimeout);
context.println("set " + idleTimeout + " seconds");
} catch (UnknownHostException e) {
context.println("invalid listen ip format");
logger.error("kraken httpd: invalid listen ip format", e);
}
}
}