package org.dcache.services.httpd; import com.google.common.base.Joiner; import jersey.repackaged.com.google.common.base.Throwables; import org.eclipse.jetty.server.Handler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Required; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import java.io.File; import java.io.FileNotFoundException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.Map; import java.util.NoSuchElementException; import dmg.cells.nucleus.CellCommandListener; import dmg.util.HttpResponseEngine; import org.dcache.services.httpd.handlers.BadConfigHandler; import org.dcache.services.httpd.handlers.ContextHandler; import org.dcache.services.httpd.handlers.HandlerDelegator; import org.dcache.services.httpd.handlers.PathHandler; import org.dcache.services.httpd.handlers.RedirectHandler; import org.dcache.services.httpd.handlers.ResponseEngineHandler; import org.dcache.services.httpd.handlers.WebAppHandler; import org.dcache.services.httpd.util.AliasEntry; import org.dcache.util.Args; import static org.dcache.services.httpd.util.AliasEntry.AliasType; public class HttpdCommandLineInterface implements CellCommandListener { private static final Logger logger = LoggerFactory.getLogger(HttpdCommandLineInterface.class); @Autowired private AutowireCapableBeanFactory beanFactory; private HandlerDelegator delegator; @Required public void setDelegator(HandlerDelegator delegator) { this.delegator = delegator; } public static final String hh_ls_alias = "[<alias>]"; public String ac_ls_alias_$_0_1(Args args) throws NoSuchElementException { if (args.argc() == 0) { StringBuilder sb = new StringBuilder(); for (Map.Entry<String, AliasEntry> aliasEntry : delegator.getAliases().entrySet()) { sb.append(aliasEntry.getKey()).append(" -> ").append( aliasEntry.getValue()).append("\n"); } return sb.toString(); } else { AliasEntry entry = delegator.getAlias(args.argv(0)); if (entry == null) { throw new NoSuchElementException("Alias not found : " + args.argv(0)); } return args.argv(0) + " -> " + entry; } } public static final String hh_set_alias = "<aliasName> directory|class|context <specification>"; public static final String fh_set_alias = "set alias <alias> <type> [<typeSpecific> <...>]\n" + " <type> <specific> \n" + " directory <fullDirectoryPath>\n" + " file <fullFilePath> <arguments> <...>\n" + " class <fullClassName> <...>\n" + " context [options] <context> or <contextNameStart>*\n" + " options : -overwrite=<alias> -onError=<alias>\n" + " webapp <warPath> <...> \n" + " redirect <forward-to-context>\n" + " predefined alias : <home> = default for http://host:port/ \n" + " <default> = default for any type or error \n"; public String ac_set_alias_$_3_16(Args args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, FileNotFoundException, InvocationTargetException, ClassNotFoundException, IllegalArgumentException { String alias = args.argv(0); String type = args.argv(1); args.shift(2); AliasEntry entry = createEntry(alias, type, args); logger.debug("Creating alias {}: {}", entry.getName(), entry); delegator.addAlias(entry.getName(), entry); return entry.getStatusMessage(); } public static final String hh_unset_alias = "<aliasName>"; public String ac_unset_alias_$_1(Args args) throws InvocationTargetException { delegator.removeAlias(args.argv(0)); return "Done"; } private AliasEntry createEntry(String alias, String type, Args args) throws FileNotFoundException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { String specific = args.argv(0); args.shift(); AliasType aliasType = AliasType.fromType(type); AliasEntry entry; Handler handler; switch (aliasType) { case FILE: case DIR: File dir = new File(specific); if ((!dir.isDirectory()) && (!dir.isFile())) { throw new FileNotFoundException(specific); } handler = new PathHandler(dir); entry = new AliasEntry(alias, aliasType, handler, specific); entry.setStatusMessage(alias + " -> " + aliasType.getType() + "(" + specific + ")"); break; case CONTEXT: handler = (Handler) beanFactory.initializeBean(new ContextHandler(specific), alias); entry = new AliasEntry(alias, aliasType, handler, specific); entry.setOnError(args.getOpt("onError")); entry.setOverwrite(args.getOpt("overwrite")); entry.setStatusMessage(alias + " -> " + aliasType.getType() + "(" + specific + ")"); break; case REDIRECT: handler = new RedirectHandler(alias, specific); entry = new AliasEntry(alias, aliasType, handler, specific); entry.setStatusMessage(alias + " -> " + aliasType.getType() + "(" + specific + ")"); break; case ENGINE: StringBuilder sb = new StringBuilder(); sb.append("class=").append(specific); Joiner.on(";").appendTo(sb, args.getArguments()); String failure = null; Class<? extends HttpResponseEngine> c = Class.forName(specific).asSubclass(HttpResponseEngine.class); Constructor<? extends HttpResponseEngine> constr = c.getConstructor(String[].class); try { HttpResponseEngine engine = constr.newInstance(new Object[] { args.getArguments().toArray(new String[args.argc()]) }); handler = new ResponseEngineHandler((HttpResponseEngine) beanFactory.initializeBean(engine, alias)); } catch (InvocationTargetException e) { Throwables.propagateIfPossible(e.getCause()); throw e; } entry = new AliasEntry(alias, aliasType, handler, sb.toString()); entry.setIntFailureMsg(failure); entry.setStatusMessage(alias + " -> " + aliasType.getType() + "(" + entry.getSpecificString() + ")"); break; case WEBAPP: WebAppHandler webappContext = (WebAppHandler) beanFactory.getBean("webapp-handler"); webappContext.setWar(new File(specific).getAbsolutePath()); webappContext.setContextPath("/" + alias); handler = webappContext; entry = new AliasEntry(alias, aliasType, handler, specific); entry.setStatusMessage(alias + " -> " + aliasType.getType() + "(" + args + ")"); break; default: handler = new BadConfigHandler(); entry = new AliasEntry(alias, aliasType, handler, specific); entry.setStatusMessage(alias + " -> " + aliasType.getType() + "(" + specific + ")"); break; } if (handler instanceof BadConfigHandler) { ((BadConfigHandler) handler).setFailureMessage(entry.getIntFailureMsg()); } return entry; } }