/** * diqube: Distributed Query Base. * * Copyright (C) 2015 Bastian Gloeckle * * This file is part of diqube. * * diqube is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.diqube.ui; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.servlet.ServletContext; import org.diqube.context.AutoInstatiate; import org.diqube.context.InjectOptional; import org.diqube.thrift.base.thrift.RNodeAddress; import org.diqube.thrift.base.thrift.RNodeHttpAddress; import org.diqube.thrift.base.thrift.Ticket; import org.diqube.ui.db.UiDatabase; import org.diqube.util.Pair; import com.google.common.collect.Sets; /** * Configuration for the diqube UI. * * Loads the config from servlet context init params or chooses defaults if it finds none. The init params can be * overwritten in the container somewhere, see container specific documentation. * * @author Bastian Gloeckle */ @AutoInstatiate public class DiqubeServletConfig { // For a description of what these configuration keys mean, see the #get.. methods below. public static final String INIT_PARAM_CLUSTER = "diqube.cluster"; public static final String INIT_PARAM_CLUSTER_RESPONSE = "diqube.clusterresponse"; public static final String INIT_PARAM_TICKET_PUBLIC_KEY_PEM = "diqube.ticketPublicKeyPem"; public static final String INIT_PARAM_TICKET_PUBLIC_KEY_PEM_ALT1 = "diqube.ticketPublicKeyPemAlt1"; public static final String INIT_PARAM_TICKET_PUBLIC_KEY_PEM_ALT2 = "diqube.ticketPublicKeyPemAlt2"; public static final String INIT_PARAM_LOGOUT_TICKET_FETCH_SEC = "diqube.logoutTicketFetchSec"; public static final String INIT_PARAM_UI_DB_TYPE = "diqube.uiDbType"; public static final String INIT_PARAM_UI_DB_LOCATION = "diqube.uiDbLocation"; public static final String INIT_PARAM_UI_DB_USER = "diqube.uiDbUser"; public static final String INIT_PARAM_UI_DB_PASSWORD = "diqube.uiDbPassword"; public static final String UI_DB_TYPE_HSQLDB = "hsqldb"; public static final String DEFAULT_CLUSTER = "localhost:5101"; public static final String DEFAULT_CLUSTER_RESPONSE = "http://localhost:8080"; public static final String DEFAULT_LOGOUT_TICKET_FETCH_SEC = "120"; public static final String DEFAULT_UI_DB_TYPE = UI_DB_TYPE_HSQLDB; public static final String DEFAULT_UI_DB_LOCATION = "diqube-ui.db"; @InjectOptional private List<ServletConfigListener> servletConfigListeners; private List<Pair<String, Short>> clusterServers; private String clusterResponseAddr; private String ticketPublicKeyPem; private String ticketPublicKeyPemAlt1; private String ticketPublicKeyPemAlt2; private long logoutTicketFetchSec; private String uiDbType; private String uiDbLocation; private String uiDbUser; private String uiDbPassword; /* package */ void initialize(ServletContext ctx) { String clusterLocation = ctx.getInitParameter(INIT_PARAM_CLUSTER); if (clusterLocation == null) clusterLocation = DEFAULT_CLUSTER; clusterServers = new ArrayList<>(); for (String hostPortStr : clusterLocation.split(",")) { String[] split = hostPortStr.split(":"); clusterServers.add(new Pair<>(split[0], Short.valueOf(split[1]))); } clusterServers = Collections.unmodifiableList(clusterServers); String clusterResponse = ctx.getInitParameter(INIT_PARAM_CLUSTER_RESPONSE); if (clusterResponse == null) clusterResponse = DEFAULT_CLUSTER_RESPONSE; clusterResponseAddr = clusterResponse + ctx.getContextPath(); ticketPublicKeyPem = ctx.getInitParameter(INIT_PARAM_TICKET_PUBLIC_KEY_PEM); if (ticketPublicKeyPem == null) throw new RuntimeException("Value for paramater '" + INIT_PARAM_TICKET_PUBLIC_KEY_PEM + "' needed."); ticketPublicKeyPemAlt1 = ctx.getInitParameter(INIT_PARAM_TICKET_PUBLIC_KEY_PEM_ALT1); ticketPublicKeyPemAlt2 = ctx.getInitParameter(INIT_PARAM_TICKET_PUBLIC_KEY_PEM_ALT2); String logoutTicketFetchSecString = ctx.getInitParameter(INIT_PARAM_LOGOUT_TICKET_FETCH_SEC); if (logoutTicketFetchSecString == null) logoutTicketFetchSecString = DEFAULT_LOGOUT_TICKET_FETCH_SEC; logoutTicketFetchSec = Long.parseLong(logoutTicketFetchSecString); uiDbType = ctx.getInitParameter(INIT_PARAM_UI_DB_TYPE); if (uiDbType == null) uiDbType = DEFAULT_UI_DB_TYPE; if (!Sets.newHashSet(UI_DB_TYPE_HSQLDB).contains(uiDbType)) throw new RuntimeException("Unknown " + INIT_PARAM_UI_DB_TYPE + ": " + uiDbType); uiDbLocation = ctx.getInitParameter(INIT_PARAM_UI_DB_LOCATION); if (uiDbLocation == null) uiDbLocation = DEFAULT_UI_DB_LOCATION; uiDbUser = ctx.getInitParameter(INIT_PARAM_UI_DB_USER); uiDbPassword = ctx.getInitParameter(INIT_PARAM_UI_DB_PASSWORD); if (servletConfigListeners != null) servletConfigListeners.forEach(l -> l.servletConfigurationAvailable()); } /** * @return List of Pair of hostname, port of the seed cluster nodes. */ public List<Pair<String, Short>> getClusterServers() { return clusterServers; } /** * @return The address of this UI that cluster nodes can use to send responses to after we issued a query for example. * Example value: http://localhost:8080/diqube-ui. It does not contain a trailing / and contains the whole URL * up until the root of this web application (no servlet-specific part!). */ public String getClusterResponseAddr() { return clusterResponseAddr; } /** * @return A new instance of {@link RNodeAddress} that contains {@link #getClusterResponseAddr()}. */ public RNodeAddress createClusterResponseAddr() { RNodeAddress res = new RNodeAddress(); res.setHttpAddr(new RNodeHttpAddress()); res.getHttpAddr().setUrl(getClusterResponseAddr() + ThriftServlet.URL_PATTERN); return res; } /** * @return File name of the .pem file containing a RSA public key which can be used to validate {@link Ticket}s. */ public String getTicketPublicKeyPem() { return ticketPublicKeyPem; } /** * @return File name of the .pem file containing a RSA public key which can be used to validate {@link Ticket}s. This * can be <code>null</code>. */ public String getTicketPublicKeyPemAlt1() { return ticketPublicKeyPemAlt1; } /** * @return File name of the .pem file containing a RSA public key which can be used to validate {@link Ticket}s. This * can be <code>null</code>. */ public String getTicketPublicKeyPemAlt2() { return ticketPublicKeyPemAlt2; } /** * @return Duration in seconds after which a current list of logged out {@link Ticket}s should be fetched from a * diqube-server. If logged out tickets cannot be fetched, the UI will not accept any {@link Ticket} anymore * until connection is re-established! Note that the longer this time is, the longer the UI might accept * tickets which actually have logged out already! */ public long getLogoutTicketFetchSec() { return logoutTicketFetchSec; } /** * @return Type of the database the UI should use. */ public String getUiDbType() { return uiDbType; } /** * @return DB-type dependent information on where the db is. Used in connection string. For more details, see JavaDoc * of implementation class of {@link UiDatabase}. */ public String getUiDbLocation() { return uiDbLocation; } /** * @return Username to use to connect to UI DB. Optional, if needed by DB implementation. */ public String getUiDbUser() { return uiDbUser; } /** * @return Password to use to connect to UI DB. Optional, if needed by DB implementation. */ public String getUiDbPassword() { return uiDbPassword; } /** * Simple listener interface that gets called as soon as the {@link DiqubeServletConfig} is initialized. */ public static interface ServletConfigListener { public void servletConfigurationAvailable(); } }