diff --git a/htroot/ConfigAccounts_p.java b/htroot/ConfigAccounts_p.java index f1c502616..cd5562999 100644 --- a/htroot/ConfigAccounts_p.java +++ b/htroot/ConfigAccounts_p.java @@ -39,7 +39,7 @@ import net.yacy.cora.util.ConcurrentLog; import net.yacy.data.TransactionManager; import net.yacy.data.UserDB; import net.yacy.data.UserDB.AccessRight; -import net.yacy.http.Jetty9HttpServerImpl; +import net.yacy.http.YaCyHttpServer; import net.yacy.search.Switchboard; import net.yacy.search.SwitchboardConstants; import net.yacy.server.serverObjects; @@ -80,7 +80,7 @@ public class ConfigAccounts_p { env.setConfig(SwitchboardConstants.ADMIN_ACCOUNT_B64MD5, sb.encodeDigestAuth(user, pw1)); env.setConfig(SwitchboardConstants.ADMIN_ACCOUNT_USER_NAME,user); // make sure server accepts new credentials - Jetty9HttpServerImpl jhttpserver = (Jetty9HttpServerImpl)sb.getHttpServer(); + YaCyHttpServer jhttpserver = (YaCyHttpServer)sb.getHttpServer(); if (!user.equals(oldusername)) jhttpserver.removeUser(oldusername); jhttpserver.resetUser(user); } else { diff --git a/htroot/ConfigUser_p.java b/htroot/ConfigUser_p.java index 35d96a78c..a3c4a950b 100644 --- a/htroot/ConfigUser_p.java +++ b/htroot/ConfigUser_p.java @@ -25,7 +25,7 @@ import net.yacy.cora.protocol.RequestHeader; import net.yacy.cora.util.ConcurrentLog; import net.yacy.data.UserDB; import net.yacy.data.UserDB.AccessRight; -import net.yacy.http.Jetty9HttpServerImpl; +import net.yacy.http.YaCyHttpServer; import net.yacy.search.Switchboard; import net.yacy.search.SwitchboardConstants; import net.yacy.server.serverObjects; @@ -151,7 +151,7 @@ public class ConfigUser_p { } catch (final Exception e) { ConcurrentLog.logException(e); } - Jetty9HttpServerImpl jhttpserver = (Jetty9HttpServerImpl) sb.getHttpServer(); + YaCyHttpServer jhttpserver = (YaCyHttpServer) sb.getHttpServer(); jhttpserver.resetUser(entry.getUserName()); } else { prop.put("error", "1"); @@ -162,7 +162,7 @@ public class ConfigUser_p { prop.putHTML("username", username); } else if (post.containsKey("delete")) { sb.userDB.removeEntry(post.get("username")); - Jetty9HttpServerImpl jhttpserver = (Jetty9HttpServerImpl) sb.getHttpServer(); + YaCyHttpServer jhttpserver = (YaCyHttpServer) sb.getHttpServer(); jhttpserver.removeUser(post.get("username")); prop.put(serverObjects.ACTION_LOCATION, "ConfigAccountList_p.html"); // jump back to user list } diff --git a/source/net/yacy/http/Jetty9HttpServerImpl.java b/source/net/yacy/http/Jetty9HttpServerImpl.java deleted file mode 100644 index 84082f027..000000000 --- a/source/net/yacy/http/Jetty9HttpServerImpl.java +++ /dev/null @@ -1,534 +0,0 @@ -// -// Jetty9HttpServerImpl -// Copyright 2011 by Florian Richter -// First released 13.04.2011 at http://yacy.net -// -// $LastChangedDate$ -// $LastChangedRevision$ -// $LastChangedBy$ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library 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 -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with this program in the file lgpl21.txt -// If not, see . -// - -package net.yacy.http; - -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.net.InetAddress; -import java.security.KeyStore; -import java.util.StringTokenizer; - -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; - -import org.eclipse.jetty.http.HttpMethod; -import org.eclipse.jetty.http.HttpVersion; -import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.Handler; -import org.eclipse.jetty.server.HttpConfiguration; -import org.eclipse.jetty.server.HttpConnectionFactory; -import org.eclipse.jetty.server.SecureRequestCustomizer; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.server.SslConnectionFactory; -import org.eclipse.jetty.server.handler.ContextHandler; -import org.eclipse.jetty.server.handler.ContextHandlerCollection; -import org.eclipse.jetty.server.handler.DefaultHandler; -import org.eclipse.jetty.server.handler.HandlerList; -import org.eclipse.jetty.server.handler.InetAccessHandler; -import org.eclipse.jetty.server.handler.gzip.GzipHandler; -import org.eclipse.jetty.servlet.ServletHolder; -import org.eclipse.jetty.util.ProcessorUtils; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.resource.Resource; -import org.eclipse.jetty.util.ssl.SslContextFactory; -import org.eclipse.jetty.webapp.WebAppContext; - -import net.yacy.cora.util.ConcurrentLog; -import net.yacy.http.servlets.YaCyDefaultServlet; -import net.yacy.search.Switchboard; -import net.yacy.search.SwitchboardConstants; -import net.yacy.utils.PKCS12Tool; - -/** - * class to embedded Jetty 9 http server into YaCy - */ -public class Jetty9HttpServerImpl implements YaCyHttpServer { - - private final Server server; - - /** - * @param port TCP Port to listen for http requests - */ - public Jetty9HttpServerImpl(int port) { - Switchboard sb = Switchboard.getSwitchboard(); - - this.server = new Server(); - - int cores = ProcessorUtils.availableProcessors(); - int acceptors = Math.max(1, Math.min(4, cores/2)); // original: Math.max(1, Math.min(4,cores/8)); - HttpConnectionFactory hcf = new HttpConnectionFactory(); - ServerConnector connector = new ServerConnector(this.server, null, null, null, acceptors, -1, hcf); - connector.setPort(port); - connector.setName("httpd:"+Integer.toString(port)); - connector.setIdleTimeout(9000); // timout in ms when no bytes send / received - connector.setAcceptQueueSize(128); - - this.server.addConnector(connector); - - - // add ssl/https connector - boolean useSSL = sb.getConfigBool("server.https", false); - - if (useSSL) { - final SslContextFactory sslContextFactory = new SslContextFactory.Server(); - final SSLContext sslContext = initSslContext(sb); - if (sslContext != null) { - - int sslport = sb.getConfigInt(SwitchboardConstants.SERVER_SSLPORT, 8443); - sslContextFactory.setSslContext(sslContext); - - // SSL HTTP Configuration - HttpConfiguration https_config = new HttpConfiguration(); - https_config.addCustomizer(new SecureRequestCustomizer()); - - // SSL Connector - ServerConnector sslConnector = new ServerConnector(this.server, - new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()), - new HttpConnectionFactory(https_config)); - sslConnector.setPort(sslport); - sslConnector.setName("ssld:" + Integer.toString(sslport)); // name must start with ssl (for withSSL() to work correctly) - sslConnector.setIdleTimeout(9000); // timout in ms when no bytes send / received - - this.server.addConnector(sslConnector); - ConcurrentLog.info("SERVER", "SSL support initialized successfully on port " + sslport); - } - } - - YacyDomainHandler domainHandler = new YacyDomainHandler(); - domainHandler.setAlternativeResolver(sb.peers); - - // configure root context - WebAppContext htrootContext = new WebAppContext(); - htrootContext.setContextPath("/"); - String htrootpath = sb.appPath + "/" + sb.getConfig(SwitchboardConstants.HTROOT_PATH, SwitchboardConstants.HTROOT_PATH_DEFAULT); - ConcurrentLog.info("Jetty9HttpServerImpl", "htrootpath = " + htrootpath); - htrootContext.setErrorHandler(new YaCyErrorHandler()); // handler for custom error page - try { - htrootContext.setBaseResource(Resource.newResource(htrootpath)); - - // set web.xml to use - // make use of Jetty feature to define web.xml other as default WEB-INF/web.xml - // and to use a DefaultsDescriptor merged with a individual web.xml - // use defaults/web.xml as default and look in DATA/SETTINGS for local addition/changes - htrootContext.setDefaultsDescriptor(sb.appPath + "/defaults/web.xml"); - Resource webxml = Resource.newResource(sb.dataPath + "/DATA/SETTINGS/web.xml"); - if (webxml.exists()) { - htrootContext.setDescriptor(webxml.getName()); - } - - } catch (IOException ex) { - if (htrootContext.getBaseResource() == null) { - ConcurrentLog.severe("SERVER", "could not find directory: htroot "); - } else { - ConcurrentLog.warn("SERVER", "could not find: defaults/web.xml or DATA/SETTINGS/web.xml"); - } - } - - // as fundamental component leave this hardcoded, other servlets may be defined in web.xml only - ServletHolder sholder = new ServletHolder(YaCyDefaultServlet.class); - sholder.setInitParameter("resourceBase", htrootpath); - sholder.setAsyncSupported(true); // needed for YaCyQoSFilter - //sholder.setInitParameter("welcomeFile", "index.html"); // default is index.html, welcome.html - htrootContext.addServlet(sholder, "/*"); - - final GzipHandler gzipHandler = new GzipHandler(); - /* - * Decompression of incoming requests body is required for index distribution - * APIs /yacy/transferRWI.html and /yacy/transferURL.html This was previously - * handled by a GZIPRequestWrapper in the YaCyDefaultServlet. - */ - gzipHandler.setInflateBufferSize(4096); - - if (!sb.getConfigBool(SwitchboardConstants.SERVER_RESPONSE_COMPRESS_GZIP, - SwitchboardConstants.SERVER_RESPONSE_COMPRESS_GZIP_DEFAULT)) { - /* Gzip compression of responses can be disabled by user configuration */ - gzipHandler.setExcludedMethods(HttpMethod.GET.asString(), HttpMethod.POST.asString()); - } - htrootContext.setGzipHandler(gzipHandler); - - // ----------------------------------------------------------------------------- - // here we set and map the mandatory servlets, needed for typical YaCy operation - // to make sure they are available even if removed in individual web.xml - // additional, optional or individual servlets or servlet mappings can be set in web.xml - - // in Jetty 9 servlet should be set only once - // therefore only the settings in web.xml is used - //add SolrSelectServlet - //htrootContext.addServlet(SolrSelectServlet.class, "/solr/select"); // uses the default core, collection1 - //htrootContext.addServlet(SolrSelectServlet.class, "/solr/collection1/select"); // the same servlet, identifies the collection1 core using the path - //htrootContext.addServlet(SolrSelectServlet.class, "/solr/webgraph/select"); // the same servlet, identifies the webgraph core using the path - - //htrootContext.addServlet(SolrServlet.class, "/solr/collection1/admin/luke"); - //htrootContext.addServlet(SolrServlet.class, "/solr/webgraph/admin/luke"); - - // add proxy?url= servlet - //htrootContext.addServlet(YaCyProxyServlet.class,"/proxy.html"); - - // add GSA servlet - //htrootContext.addServlet(GSAsearchServlet.class,"/gsa/search"); - // --- eof default servlet mappings -------------------------------------------- - - // define list of YaCy specific general handlers - HandlerList handlers = new HandlerList(); - if (sb.getConfigBool(SwitchboardConstants.PROXY_TRANSPARENT_PROXY, false)) { - // Proxyhandlers are only needed if feature activated (save resources if not used) - ConcurrentLog.info("SERVER", "load Jetty handler for transparent proxy"); - handlers.setHandlers(new Handler[]{new MonitorHandler(), domainHandler, new ProxyCacheHandler(), new ProxyHandler()}); - } else { - handlers.setHandlers(new Handler[]{new MonitorHandler(), domainHandler}); - } - // context handler for dispatcher and security (hint: dispatcher requires a context) - ContextHandler context = new ContextHandler(); - context.setServer(this.server); - context.setContextPath("/"); - context.setHandler(handlers); - context.setMaxFormContentSize(1024 * 1024 * 10); // allow 10MB, large forms may be required during crawl starts with long lists - org.eclipse.jetty.util.log.Logger log = Log.getRootLogger(); - context.setLogger(log); - // make YaCy handlers (in context) and servlet context handlers available (both contain root context "/") - // logic: 1. YaCy handlers are called if request not handled (e.g. proxy) then servlets handle it - ContextHandlerCollection allrequesthandlers = new ContextHandlerCollection(); - allrequesthandlers.setServer(this.server); - allrequesthandlers.addHandler(context); - allrequesthandlers.addHandler(htrootContext); - allrequesthandlers.addHandler(new DefaultHandler()); // if not handled by other handler - - YaCyLoginService loginService = new YaCyLoginService(); - // this is very important (as it is part of the user password hash) - // changes will ivalidate all current existing user-password-hashes (from userDB) - loginService.setName(sb.getConfig(SwitchboardConstants.ADMIN_REALM,"YaCy")); - - Jetty9YaCySecurityHandler securityHandler = new Jetty9YaCySecurityHandler(); - securityHandler.setLoginService(loginService); - - htrootContext.setSecurityHandler(securityHandler); - - // wrap all handlers - Handler crashHandler = new CrashProtectionHandler(this.server, allrequesthandlers); - // check server access restriction and add InetAccessHandler if restrictions are needed - // otherwise don't (to save performance) - final String white = sb.getConfig("serverClient", "*"); - if (!white.equals("*")) { // full ip (allowed ranges 0-255 or prefix 10.0-255,0,0-100 or CIDR notation 192.168.1.0/24) - final StringTokenizer st = new StringTokenizer(white, ","); - final InetAccessHandler whiteListHandler; - if (white.contains("|")) { - /* - * At least one pattern includes a path definition : we must use the - * InetPathAccessHandler as InetAccessHandler doesn't support path patterns - */ - whiteListHandler = new InetPathAccessHandler(); - } else { - whiteListHandler = new InetAccessHandler(); - } - int i = 0; - while (st.hasMoreTokens()) { - final String pattern = st.nextToken(); - try { - whiteListHandler.include(pattern); - } catch (final IllegalArgumentException nex) { // catch format exception on wrong ip address pattern - ConcurrentLog.severe("SERVER", "Server Access Settings - IP filter: " + nex.getMessage()); - continue; - } - i++; - } - if (i > 0) { - final String loopbackAddress = InetAddress.getLoopbackAddress().getHostAddress(); - whiteListHandler.include(loopbackAddress); - whiteListHandler.setHandler(crashHandler); - this.server.setHandler(whiteListHandler); - - ConcurrentLog.info("SERVER","activated IP access restriction to: [" + loopbackAddress + "," + white +"]"); - } else { - this.server.setHandler(crashHandler); // InetAccessHandler not needed - } - } else { - this.server.setHandler(crashHandler); // InetAccessHandler not needed - } - } - - /** - * start http server - */ - @Override - public void startupServer() throws Exception { - // option to finish running requests on shutdown -// server.setGracefulShutdown(3000); - this.server.setStopAtShutdown(true); - this.server.start(); - } - - /** - * stop http server and wait for it - */ - @Override - public void stop() throws Exception { - this.server.stop(); - this.server.join(); - } - - /** - * @return true if ssl/https connector is available - */ - @Override - public boolean withSSL() { - Connector[] clist = this.server.getConnectors(); - for (Connector c:clist) { - if (c.getName().startsWith("ssl")) return true; - } - return false; - } - - /** - * The port of actual running ssl connector - * @return the ssl/https port or -1 if not active - */ - @Override - public int getSslPort() { - Connector[] clist = this.server.getConnectors(); - for (Connector c:clist) { - if (c.getName().startsWith("ssl")) { - int port =((ServerConnector)c).getLocalPort(); - return port; - } - } - return -1; - } - - /** - * reconnect with new port settings (after waiting milsec) - routine returns - * immediately - * checks http and ssl connector for new port settings - * @param milsec wait time - */ - @Override - public void reconnect(final int milsec) { - - new Thread("Jetty8HttpServer.reconnect") { - - @Override - public void run() { - if (milsec > 0) try { - Thread.sleep(milsec); - } catch (final InterruptedException e) { - ConcurrentLog.logException(e); - } catch (final Exception e) { - ConcurrentLog.logException(e); - } - try { - if (!Jetty9HttpServerImpl.this.server.isRunning() || Jetty9HttpServerImpl.this.server.isStopped()) { - Jetty9HttpServerImpl.this.server.start(); - } - - // reconnect with new settings (instead to stop/start server, just manipulate connectors - final Connector[] cons = Jetty9HttpServerImpl.this.server.getConnectors(); - final int port = Switchboard.getSwitchboard().getLocalPort(); - final int sslport = Switchboard.getSwitchboard().getConfigInt(SwitchboardConstants.SERVER_SSLPORT, 8443); - for (Connector con : cons) { - // check http connector - if (con.getName().startsWith("httpd") && ((ServerConnector)con).getPort() != port) { - ((ServerConnector)con).close(); - con.stop(); - if (!con.isStopped()) { - ConcurrentLog.warn("SERVER", "Reconnect: Jetty Connector failed to stop"); - } - ((ServerConnector)con).setPort(port); - con.start(); - ConcurrentLog.info("SERVER", "set new port for Jetty connector " + con.getName()); - continue; - } - // check https connector - if (con.getName().startsWith("ssl") && ((ServerConnector)con).getPort() != sslport) { - ((ServerConnector)con).close(); - con.stop(); - if (!con.isStopped()) { - ConcurrentLog.warn("SERVER", "Reconnect: Jetty Connector failed to stop"); - } - ((ServerConnector)con).setPort(sslport); - con.start(); - ConcurrentLog.info("SERVER", "set new port for Jetty connector " + con.getName()); - } - } - } catch (Exception ex) { - ConcurrentLog.logException(ex); - } - } - }.start(); - } - - /** - * forces loginservice to reload user credentials - * (used after setting new pwd in cfg file/db) - * @param username - */ - public void resetUser(String username) { - Jetty9YaCySecurityHandler hx = this.server.getChildHandlerByClass(Jetty9YaCySecurityHandler.class); - if (hx != null) { - YaCyLoginService loginservice = (YaCyLoginService) hx.getLoginService(); - if (loginservice.removeUser(username)) { // remove old credential from cache - loginservice.loadUserInfo(username); - } - } - } - - /** - * removes user from knowuser cache of loginservice - * @param username - */ - public void removeUser(String username) { - Jetty9YaCySecurityHandler hx = this.server.getChildHandlerByClass(Jetty9YaCySecurityHandler.class); - if (hx != null) { - YaCyLoginService loginservice = (YaCyLoginService) hx.getLoginService(); - loginservice.removeUser(username); - } - } - - /** - * get Jetty version - * @return version_string - */ - @Override - public String getVersion() { - return "Jetty " + Server.getVersion(); - } - - /** - * Init SSL Context from config settings - * @param sb Switchboard - * @return default or sslcontext according to config - */ - private SSLContext initSslContext(Switchboard sb) { - - // getting the keystore file name - String keyStoreFileName = sb.getConfig("keyStore", "").trim(); - - // getting the keystore pwd - String keyStorePwd = sb.getConfig("keyStorePassword", "").trim(); - - // take a look if we have something to import - final String pkcs12ImportFile = sb.getConfig("pkcs12ImportFile", "").trim(); - - // if no keyStore and no import is defined, then set the default key - if (keyStoreFileName.isEmpty() && keyStorePwd.isEmpty() && pkcs12ImportFile.isEmpty()) { - keyStoreFileName = "defaults/freeworldKeystore"; - keyStorePwd = "freeworld"; - sb.setConfig("keyStore", keyStoreFileName); - sb.setConfig("keyStorePassword", keyStorePwd); - } - - if (pkcs12ImportFile.length() > 0) { - ConcurrentLog.info("SERVER", "Import certificates from import file '" + pkcs12ImportFile + "'."); - - try { - // getting the password - final String pkcs12ImportPwd = sb.getConfig("pkcs12ImportPwd", "").trim(); - - // creating tool to import cert - final PKCS12Tool pkcsTool = new PKCS12Tool(pkcs12ImportFile,pkcs12ImportPwd); - - // creating a new keystore file - if (keyStoreFileName.isEmpty()) { - // using the default keystore name - keyStoreFileName = "DATA/SETTINGS/myPeerKeystore"; - - // creating an empty java keystore - final KeyStore ks = KeyStore.getInstance("JKS"); - ks.load(null,keyStorePwd.toCharArray()); - try ( - /* Automatically closed by this try-with-resources statement */ - final FileOutputStream ksOut = new FileOutputStream(keyStoreFileName); - ) { - ks.store(ksOut, keyStorePwd.toCharArray()); - } - - // storing path to keystore into config file - sb.setConfig("keyStore", keyStoreFileName); - } - - // importing certificate - pkcsTool.importToJKS(keyStoreFileName, keyStorePwd); - - // removing entries from config file - sb.setConfig("pkcs12ImportFile", ""); - sb.setConfig("pkcs12ImportPwd", ""); - - // deleting original import file - // TODO: should we do this - } catch (final Exception e) { - ConcurrentLog.severe("SERVER", "Unable to import certificate from import file '" + pkcs12ImportFile + "'.",e); - } - } else if (keyStoreFileName.isEmpty()) return null; - - // get the ssl context - try { - ConcurrentLog.info("SERVER","Initializing SSL support ..."); - - // creating a new keystore instance of type (java key store) - if (ConcurrentLog.isFine("SERVER")) ConcurrentLog.fine("SERVER", "Initializing keystore ..."); - final KeyStore ks = KeyStore.getInstance("JKS"); - - // loading keystore data from file - if (ConcurrentLog.isFine("SERVER")) ConcurrentLog.fine("SERVER","Loading keystore file " + keyStoreFileName); - final FileInputStream stream = new FileInputStream(keyStoreFileName); - try { - ks.load(stream, keyStorePwd.toCharArray()); - } finally { - try { - stream.close(); - } catch(IOException ioe) { - ConcurrentLog.warn("SERVER", "Could not close input stream on file " + keyStoreFileName); - } - } - - // creating a keystore factory - if (ConcurrentLog.isFine("SERVER")) ConcurrentLog.fine("SERVER","Initializing key manager factory ..."); - final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - kmf.init(ks,keyStorePwd.toCharArray()); - - // initializing the ssl context - if (ConcurrentLog.isFine("SERVER")) ConcurrentLog.fine("SERVER","Initializing SSL context ..."); - final SSLContext sslcontext = SSLContext.getInstance("TLS"); - sslcontext.init(kmf.getKeyManagers(), null, null); - - return sslcontext; - } catch (final Exception e) { - final String errorMsg = "FATAL ERROR: Unable to initialize the SSL Socket factory. " + e.getMessage(); - ConcurrentLog.severe("SERVER",errorMsg); - System.out.println(errorMsg); - return null; - } - } - - @Override - public int getServerThreads() { - return this.server == null ? 0 : this.server.getThreadPool().getThreads() - this.server.getThreadPool().getIdleThreads(); - } - - @Override - public String toString() { - return this.server.dump() + "\n\n" + this.server.getState(); - } -} diff --git a/source/net/yacy/http/YaCyHttpServer.java b/source/net/yacy/http/YaCyHttpServer.java index c25bd2caa..cf155cd37 100644 --- a/source/net/yacy/http/YaCyHttpServer.java +++ b/source/net/yacy/http/YaCyHttpServer.java @@ -1,22 +1,523 @@ - -package net.yacy.http; - -/** - * Isolation of HttpServer - * - * Development Goal: allow for individual implementation of a HttpServer - * to provide the routines and entry points required by the - * YaCy servlets - * - * Implementation Jetty9HttpServerImpl.java - */ -public interface YaCyHttpServer { - - abstract void startupServer() throws Exception; - abstract void stop() throws Exception; - abstract int getSslPort(); - abstract boolean withSSL(); - abstract void reconnect(int milsec); - abstract String getVersion(); - abstract int getServerThreads(); -} +// +// YaCyHttpServer +// Copyright 2011 by Florian Richter +// First released 13.04.2011 at http://yacy.net +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program in the file lgpl21.txt +// If not, see . +// + +package net.yacy.http; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.InetAddress; +import java.security.KeyStore; +import java.util.StringTokenizer; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; + +import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.jetty.http.HttpVersion; +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.HttpConfiguration; +import org.eclipse.jetty.server.HttpConnectionFactory; +import org.eclipse.jetty.server.SecureRequestCustomizer; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.SslConnectionFactory; +import org.eclipse.jetty.server.handler.ContextHandler; +import org.eclipse.jetty.server.handler.ContextHandlerCollection; +import org.eclipse.jetty.server.handler.DefaultHandler; +import org.eclipse.jetty.server.handler.HandlerList; +import org.eclipse.jetty.server.handler.InetAccessHandler; +import org.eclipse.jetty.server.handler.gzip.GzipHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.util.ProcessorUtils; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.resource.Resource; +import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.eclipse.jetty.webapp.WebAppContext; + +import net.yacy.cora.util.ConcurrentLog; +import net.yacy.http.servlets.YaCyDefaultServlet; +import net.yacy.search.Switchboard; +import net.yacy.search.SwitchboardConstants; +import net.yacy.utils.PKCS12Tool; + +/** + * class to embedded Jetty 9 http server into YaCy + */ +public class YaCyHttpServer { + + private final Server server; + + /** + * @param port TCP Port to listen for http requests + */ + public YaCyHttpServer(final int port) { + final Switchboard sb = Switchboard.getSwitchboard(); + + this.server = new Server(); + + final int cores = ProcessorUtils.availableProcessors(); + final int acceptors = Math.max(1, Math.min(4, cores/2)); // original: Math.max(1, Math.min(4,cores/8)); + final HttpConnectionFactory hcf = new HttpConnectionFactory(); + final ServerConnector connector = new ServerConnector(this.server, null, null, null, acceptors, -1, hcf); + connector.setPort(port); + connector.setName("httpd:"+Integer.toString(port)); + connector.setIdleTimeout(9000); // timout in ms when no bytes send / received + connector.setAcceptQueueSize(128); + + this.server.addConnector(connector); + + + // add ssl/https connector + final boolean useSSL = sb.getConfigBool("server.https", false); + + if (useSSL) { + final SslContextFactory sslContextFactory = new SslContextFactory.Server(); + final SSLContext sslContext = initSslContext(sb); + if (sslContext != null) { + + final int sslport = sb.getConfigInt(SwitchboardConstants.SERVER_SSLPORT, 8443); + sslContextFactory.setSslContext(sslContext); + + // SSL HTTP Configuration + final HttpConfiguration https_config = new HttpConfiguration(); + https_config.addCustomizer(new SecureRequestCustomizer()); + + // SSL Connector + final ServerConnector sslConnector = new ServerConnector(this.server, + new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()), + new HttpConnectionFactory(https_config)); + sslConnector.setPort(sslport); + sslConnector.setName("ssld:" + Integer.toString(sslport)); // name must start with ssl (for withSSL() to work correctly) + sslConnector.setIdleTimeout(9000); // timout in ms when no bytes send / received + + this.server.addConnector(sslConnector); + ConcurrentLog.info("SERVER", "SSL support initialized successfully on port " + sslport); + } + } + + final YacyDomainHandler domainHandler = new YacyDomainHandler(); + domainHandler.setAlternativeResolver(sb.peers); + + // configure root context + final WebAppContext htrootContext = new WebAppContext(); + htrootContext.setContextPath("/"); + final String htrootpath = sb.appPath + "/" + sb.getConfig(SwitchboardConstants.HTROOT_PATH, SwitchboardConstants.HTROOT_PATH_DEFAULT); + ConcurrentLog.info("Jetty9HttpServerImpl", "htrootpath = " + htrootpath); + htrootContext.setErrorHandler(new YaCyErrorHandler()); // handler for custom error page + try { + htrootContext.setBaseResource(Resource.newResource(htrootpath)); + + // set web.xml to use + // make use of Jetty feature to define web.xml other as default WEB-INF/web.xml + // and to use a DefaultsDescriptor merged with a individual web.xml + // use defaults/web.xml as default and look in DATA/SETTINGS for local addition/changes + htrootContext.setDefaultsDescriptor(sb.appPath + "/defaults/web.xml"); + final Resource webxml = Resource.newResource(sb.dataPath + "/DATA/SETTINGS/web.xml"); + if (webxml.exists()) { + htrootContext.setDescriptor(webxml.getName()); + } + + } catch (final IOException ex) { + if (htrootContext.getBaseResource() == null) { + ConcurrentLog.severe("SERVER", "could not find directory: htroot "); + } else { + ConcurrentLog.warn("SERVER", "could not find: defaults/web.xml or DATA/SETTINGS/web.xml"); + } + } + + // as fundamental component leave this hardcoded, other servlets may be defined in web.xml only + final ServletHolder sholder = new ServletHolder(YaCyDefaultServlet.class); + sholder.setInitParameter("resourceBase", htrootpath); + sholder.setAsyncSupported(true); // needed for YaCyQoSFilter + //sholder.setInitParameter("welcomeFile", "index.html"); // default is index.html, welcome.html + htrootContext.addServlet(sholder, "/*"); + + final GzipHandler gzipHandler = new GzipHandler(); + /* + * Decompression of incoming requests body is required for index distribution + * APIs /yacy/transferRWI.html and /yacy/transferURL.html This was previously + * handled by a GZIPRequestWrapper in the YaCyDefaultServlet. + */ + gzipHandler.setInflateBufferSize(4096); + + if (!sb.getConfigBool(SwitchboardConstants.SERVER_RESPONSE_COMPRESS_GZIP, + SwitchboardConstants.SERVER_RESPONSE_COMPRESS_GZIP_DEFAULT)) { + /* Gzip compression of responses can be disabled by user configuration */ + gzipHandler.setExcludedMethods(HttpMethod.GET.asString(), HttpMethod.POST.asString()); + } + htrootContext.setGzipHandler(gzipHandler); + + // ----------------------------------------------------------------------------- + // here we set and map the mandatory servlets, needed for typical YaCy operation + // to make sure they are available even if removed in individual web.xml + // additional, optional or individual servlets or servlet mappings can be set in web.xml + + // in Jetty 9 servlet should be set only once + // therefore only the settings in web.xml is used + //add SolrSelectServlet + //htrootContext.addServlet(SolrSelectServlet.class, "/solr/select"); // uses the default core, collection1 + //htrootContext.addServlet(SolrSelectServlet.class, "/solr/collection1/select"); // the same servlet, identifies the collection1 core using the path + //htrootContext.addServlet(SolrSelectServlet.class, "/solr/webgraph/select"); // the same servlet, identifies the webgraph core using the path + + //htrootContext.addServlet(SolrServlet.class, "/solr/collection1/admin/luke"); + //htrootContext.addServlet(SolrServlet.class, "/solr/webgraph/admin/luke"); + + // add proxy?url= servlet + //htrootContext.addServlet(YaCyProxyServlet.class,"/proxy.html"); + + // add GSA servlet + //htrootContext.addServlet(GSAsearchServlet.class,"/gsa/search"); + // --- eof default servlet mappings -------------------------------------------- + + // define list of YaCy specific general handlers + final HandlerList handlers = new HandlerList(); + if (sb.getConfigBool(SwitchboardConstants.PROXY_TRANSPARENT_PROXY, false)) { + // Proxyhandlers are only needed if feature activated (save resources if not used) + ConcurrentLog.info("SERVER", "load Jetty handler for transparent proxy"); + handlers.setHandlers(new Handler[]{new MonitorHandler(), domainHandler, new ProxyCacheHandler(), new ProxyHandler()}); + } else { + handlers.setHandlers(new Handler[]{new MonitorHandler(), domainHandler}); + } + // context handler for dispatcher and security (hint: dispatcher requires a context) + final ContextHandler context = new ContextHandler(); + context.setServer(this.server); + context.setContextPath("/"); + context.setHandler(handlers); + context.setMaxFormContentSize(1024 * 1024 * 10); // allow 10MB, large forms may be required during crawl starts with long lists + final org.eclipse.jetty.util.log.Logger log = Log.getRootLogger(); + context.setLogger(log); + // make YaCy handlers (in context) and servlet context handlers available (both contain root context "/") + // logic: 1. YaCy handlers are called if request not handled (e.g. proxy) then servlets handle it + final ContextHandlerCollection allrequesthandlers = new ContextHandlerCollection(); + allrequesthandlers.setServer(this.server); + allrequesthandlers.addHandler(context); + allrequesthandlers.addHandler(htrootContext); + allrequesthandlers.addHandler(new DefaultHandler()); // if not handled by other handler + + final YaCyLoginService loginService = new YaCyLoginService(); + // this is very important (as it is part of the user password hash) + // changes will ivalidate all current existing user-password-hashes (from userDB) + loginService.setName(sb.getConfig(SwitchboardConstants.ADMIN_REALM,"YaCy")); + + final YaCySecurityHandler securityHandler = new YaCySecurityHandler(); + securityHandler.setLoginService(loginService); + + htrootContext.setSecurityHandler(securityHandler); + + // wrap all handlers + final Handler crashHandler = new CrashProtectionHandler(this.server, allrequesthandlers); + // check server access restriction and add InetAccessHandler if restrictions are needed + // otherwise don't (to save performance) + final String white = sb.getConfig("serverClient", "*"); + if (!white.equals("*")) { // full ip (allowed ranges 0-255 or prefix 10.0-255,0,0-100 or CIDR notation 192.168.1.0/24) + final StringTokenizer st = new StringTokenizer(white, ","); + final InetAccessHandler whiteListHandler; + if (white.contains("|")) { + /* + * At least one pattern includes a path definition : we must use the + * InetPathAccessHandler as InetAccessHandler doesn't support path patterns + */ + whiteListHandler = new InetPathAccessHandler(); + } else { + whiteListHandler = new InetAccessHandler(); + } + int i = 0; + while (st.hasMoreTokens()) { + final String pattern = st.nextToken(); + try { + whiteListHandler.include(pattern); + } catch (final IllegalArgumentException nex) { // catch format exception on wrong ip address pattern + ConcurrentLog.severe("SERVER", "Server Access Settings - IP filter: " + nex.getMessage()); + continue; + } + i++; + } + if (i > 0) { + final String loopbackAddress = InetAddress.getLoopbackAddress().getHostAddress(); + whiteListHandler.include(loopbackAddress); + whiteListHandler.setHandler(crashHandler); + this.server.setHandler(whiteListHandler); + + ConcurrentLog.info("SERVER","activated IP access restriction to: [" + loopbackAddress + "," + white +"]"); + } else { + this.server.setHandler(crashHandler); // InetAccessHandler not needed + } + } else { + this.server.setHandler(crashHandler); // InetAccessHandler not needed + } + } + + /** + * start http server + */ + public void startupServer() throws Exception { + // option to finish running requests on shutdown +// server.setGracefulShutdown(3000); + this.server.setStopAtShutdown(true); + this.server.start(); + } + + /** + * stop http server and wait for it + */ + public void stop() throws Exception { + this.server.stop(); + this.server.join(); + } + + /** + * @return true if ssl/https connector is available + */ + public boolean withSSL() { + final Connector[] clist = this.server.getConnectors(); + for (final Connector c:clist) { + if (c.getName().startsWith("ssl")) return true; + } + return false; + } + + /** + * The port of actual running ssl connector + * @return the ssl/https port or -1 if not active + */ + public int getSslPort() { + final Connector[] clist = this.server.getConnectors(); + for (final Connector c:clist) { + if (c.getName().startsWith("ssl")) { + final int port =((ServerConnector)c).getLocalPort(); + return port; + } + } + return -1; + } + + /** + * reconnect with new port settings (after waiting milsec) - routine returns + * immediately + * checks http and ssl connector for new port settings + * @param milsec wait time + */ + public void reconnect(final int milsec) { + + new Thread("Jetty8HttpServer.reconnect") { + + @Override + public void run() { + if (milsec > 0) try { + Thread.sleep(milsec); + } catch (final InterruptedException e) { + ConcurrentLog.logException(e); + } catch (final Exception e) { + ConcurrentLog.logException(e); + } + try { + if (!YaCyHttpServer.this.server.isRunning() || YaCyHttpServer.this.server.isStopped()) { + YaCyHttpServer.this.server.start(); + } + + // reconnect with new settings (instead to stop/start server, just manipulate connectors + final Connector[] cons = YaCyHttpServer.this.server.getConnectors(); + final int port = Switchboard.getSwitchboard().getLocalPort(); + final int sslport = Switchboard.getSwitchboard().getConfigInt(SwitchboardConstants.SERVER_SSLPORT, 8443); + for (final Connector con : cons) { + // check http connector + if (con.getName().startsWith("httpd") && ((ServerConnector)con).getPort() != port) { + ((ServerConnector)con).close(); + con.stop(); + if (!con.isStopped()) { + ConcurrentLog.warn("SERVER", "Reconnect: Jetty Connector failed to stop"); + } + ((ServerConnector)con).setPort(port); + con.start(); + ConcurrentLog.info("SERVER", "set new port for Jetty connector " + con.getName()); + continue; + } + // check https connector + if (con.getName().startsWith("ssl") && ((ServerConnector)con).getPort() != sslport) { + ((ServerConnector)con).close(); + con.stop(); + if (!con.isStopped()) { + ConcurrentLog.warn("SERVER", "Reconnect: Jetty Connector failed to stop"); + } + ((ServerConnector)con).setPort(sslport); + con.start(); + ConcurrentLog.info("SERVER", "set new port for Jetty connector " + con.getName()); + } + } + } catch (final Exception ex) { + ConcurrentLog.logException(ex); + } + } + }.start(); + } + + /** + * forces loginservice to reload user credentials + * (used after setting new pwd in cfg file/db) + * @param username + */ + public void resetUser(final String username) { + final YaCySecurityHandler hx = this.server.getChildHandlerByClass(YaCySecurityHandler.class); + if (hx != null) { + final YaCyLoginService loginservice = (YaCyLoginService) hx.getLoginService(); + if (loginservice.removeUser(username)) { // remove old credential from cache + loginservice.loadUserInfo(username); + } + } + } + + /** + * removes user from knowuser cache of loginservice + * @param username + */ + public void removeUser(final String username) { + final YaCySecurityHandler hx = this.server.getChildHandlerByClass(YaCySecurityHandler.class); + if (hx != null) { + final YaCyLoginService loginservice = (YaCyLoginService) hx.getLoginService(); + loginservice.removeUser(username); + } + } + + /** + * get Jetty version + * @return version_string + */ + public String getVersion() { + return "Jetty " + Server.getVersion(); + } + + /** + * Init SSL Context from config settings + * @param sb Switchboard + * @return default or sslcontext according to config + */ + private SSLContext initSslContext(final Switchboard sb) { + + // getting the keystore file name + String keyStoreFileName = sb.getConfig("keyStore", "").trim(); + + // getting the keystore pwd + String keyStorePwd = sb.getConfig("keyStorePassword", "").trim(); + + // take a look if we have something to import + final String pkcs12ImportFile = sb.getConfig("pkcs12ImportFile", "").trim(); + + // if no keyStore and no import is defined, then set the default key + if (keyStoreFileName.isEmpty() && keyStorePwd.isEmpty() && pkcs12ImportFile.isEmpty()) { + keyStoreFileName = "defaults/freeworldKeystore"; + keyStorePwd = "freeworld"; + sb.setConfig("keyStore", keyStoreFileName); + sb.setConfig("keyStorePassword", keyStorePwd); + } + + if (pkcs12ImportFile.length() > 0) { + ConcurrentLog.info("SERVER", "Import certificates from import file '" + pkcs12ImportFile + "'."); + + try { + // getting the password + final String pkcs12ImportPwd = sb.getConfig("pkcs12ImportPwd", "").trim(); + + // creating tool to import cert + final PKCS12Tool pkcsTool = new PKCS12Tool(pkcs12ImportFile,pkcs12ImportPwd); + + // creating a new keystore file + if (keyStoreFileName.isEmpty()) { + // using the default keystore name + keyStoreFileName = "DATA/SETTINGS/myPeerKeystore"; + + // creating an empty java keystore + final KeyStore ks = KeyStore.getInstance("JKS"); + ks.load(null,keyStorePwd.toCharArray()); + try ( + /* Automatically closed by this try-with-resources statement */ + final FileOutputStream ksOut = new FileOutputStream(keyStoreFileName); + ) { + ks.store(ksOut, keyStorePwd.toCharArray()); + } + + // storing path to keystore into config file + sb.setConfig("keyStore", keyStoreFileName); + } + + // importing certificate + pkcsTool.importToJKS(keyStoreFileName, keyStorePwd); + + // removing entries from config file + sb.setConfig("pkcs12ImportFile", ""); + sb.setConfig("pkcs12ImportPwd", ""); + + // deleting original import file + // TODO: should we do this + } catch (final Exception e) { + ConcurrentLog.severe("SERVER", "Unable to import certificate from import file '" + pkcs12ImportFile + "'.",e); + } + } else if (keyStoreFileName.isEmpty()) return null; + + // get the ssl context + try { + ConcurrentLog.info("SERVER","Initializing SSL support ..."); + + // creating a new keystore instance of type (java key store) + if (ConcurrentLog.isFine("SERVER")) ConcurrentLog.fine("SERVER", "Initializing keystore ..."); + final KeyStore ks = KeyStore.getInstance("JKS"); + + // loading keystore data from file + if (ConcurrentLog.isFine("SERVER")) ConcurrentLog.fine("SERVER","Loading keystore file " + keyStoreFileName); + final FileInputStream stream = new FileInputStream(keyStoreFileName); + try { + ks.load(stream, keyStorePwd.toCharArray()); + } finally { + try { + stream.close(); + } catch(final IOException ioe) { + ConcurrentLog.warn("SERVER", "Could not close input stream on file " + keyStoreFileName); + } + } + + // creating a keystore factory + if (ConcurrentLog.isFine("SERVER")) ConcurrentLog.fine("SERVER","Initializing key manager factory ..."); + final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(ks,keyStorePwd.toCharArray()); + + // initializing the ssl context + if (ConcurrentLog.isFine("SERVER")) ConcurrentLog.fine("SERVER","Initializing SSL context ..."); + final SSLContext sslcontext = SSLContext.getInstance("TLS"); + sslcontext.init(kmf.getKeyManagers(), null, null); + + return sslcontext; + } catch (final Exception e) { + final String errorMsg = "FATAL ERROR: Unable to initialize the SSL Socket factory. " + e.getMessage(); + ConcurrentLog.severe("SERVER",errorMsg); + System.out.println(errorMsg); + return null; + } + } + + public int getServerThreads() { + return this.server == null ? 0 : this.server.getThreadPool().getThreads() - this.server.getThreadPool().getIdleThreads(); + } + + @Override + public String toString() { + return this.server.dump() + "\n\n" + this.server.getState(); + } +} diff --git a/source/net/yacy/http/Jetty9YaCySecurityHandler.java b/source/net/yacy/http/YaCySecurityHandler.java similarity index 98% rename from source/net/yacy/http/Jetty9YaCySecurityHandler.java rename to source/net/yacy/http/YaCySecurityHandler.java index 3196a618d..1014a1edd 100644 --- a/source/net/yacy/http/Jetty9YaCySecurityHandler.java +++ b/source/net/yacy/http/YaCySecurityHandler.java @@ -44,7 +44,7 @@ import org.eclipse.jetty.server.Request; * demands authentication for pages with _p. inside * and updates AccessTracker */ -public class Jetty9YaCySecurityHandler extends ConstraintSecurityHandler { +public class YaCySecurityHandler extends ConstraintSecurityHandler { /** * create the constraint for the given path diff --git a/source/net/yacy/server/serverSwitch.java b/source/net/yacy/server/serverSwitch.java index 10e2a3eb5..7a9e48cfb 100644 --- a/source/net/yacy/server/serverSwitch.java +++ b/source/net/yacy/server/serverSwitch.java @@ -71,7 +71,7 @@ public class serverSwitch { private final ConcurrentMap configRemoved; private final NavigableMap workerThreads; private YaCyHttpServer httpserver; // implemented HttpServer - private ConcurrentMap upnpPortMap = new ConcurrentHashMap<>(); + private final ConcurrentMap upnpPortMap = new ConcurrentHashMap<>(); private boolean isConnectedViaUpnp; public serverSwitch(final File dataPath, final File appPath, final String initPath, final String configPath) { @@ -105,9 +105,9 @@ public class serverSwitch { } // overwrite configs with values from environment variables that start with "yacy_" - Properties sysprops = System.getProperties(); + final Properties sysprops = System.getProperties(); sysprops.forEach((key, value) -> { - String k = (String) key; + final String k = (String) key; if (k.startsWith("yacy.")) { this.configProps.put(k.substring(5), (String) value); } @@ -115,7 +115,7 @@ public class serverSwitch { // remove all values from config that do not appear in init this.configRemoved = new ConcurrentHashMap(); - Iterator i = this.configProps.keySet().iterator(); + final Iterator i = this.configProps.keySet().iterator(); String key; while (i.hasNext()) { key = i.next(); @@ -133,15 +133,15 @@ public class serverSwitch { // Read system properties and set all variables that have a prefix "yacy.". // This will make it possible that settings can be overwritten with environment variables. // Do this i.e. with "export YACY_PORT=8091 && ./startYACY.sh" - for (Map.Entry entry: System.getProperties().entrySet()) { - String yacykey = (String) entry.getKey(); + for (final Map.Entry entry: System.getProperties().entrySet()) { + final String yacykey = (String) entry.getKey(); if (yacykey.startsWith("YACY_")) { key = yacykey.substring(5).toLowerCase().replace('_', '.'); if (this.configProps.containsKey(key)) this.configProps.put(key, (String) entry.getValue()); } } - for (Map.Entry entry: System.getenv().entrySet()) { - String yacykey = entry.getKey(); + for (final Map.Entry entry: System.getenv().entrySet()) { + final String yacykey = entry.getKey(); if (yacykey.startsWith("YACY_")) { key = yacykey.substring(5).toLowerCase().replace('_', '.'); if (this.configProps.containsKey(key)) this.configProps.put(key, entry.getValue()); @@ -169,7 +169,7 @@ public class serverSwitch { * get my public IP, either set statically or figure out dynamic This method * is deprecated because there may be more than one public IPs of this peer, * i.e. one IPv4 and one IPv6. Please use myPublicIPs() instead - * + * * @return the public IP of this peer, if known */ public String myPublicIP() { @@ -188,26 +188,26 @@ public class serverSwitch { /** * Get all my public IPs. If there was a static IP assignment, only one, * that IP is returned. - * + * * @return a set of IPs which are supposed to be my own public IPs */ public Set myPublicIPs() { // if a static IP was configured, we have to return it here ... final String staticIP = getConfig(SwitchboardConstants.SERVER_STATICIP, ""); if (staticIP.length() > 0) { - HashSet h = new HashSet<>(); + final HashSet h = new HashSet<>(); h.add(staticIP); return h; } - Set h = new LinkedHashSet<>(); - for (InetAddress i : Domains.myPublicIPv6()) { - String s = i.getHostAddress(); + final Set h = new LinkedHashSet<>(); + for (final InetAddress i : Domains.myPublicIPv6()) { + final String s = i.getHostAddress(); if (Seed.isProperIP(s)) h.add(Domains.chopZoneID(s)); } - for (InetAddress i : Domains.myPublicIPv4()) { - String s = i.getHostAddress(); + for (final InetAddress i : Domains.myPublicIPv4()) { + final String s = i.getHostAddress(); if (Seed.isProperIP(s)) h.add(Domains.chopZoneID(s)); } @@ -218,19 +218,19 @@ public class serverSwitch { * Gets public port. May differ from local port due to NATting. This method * will eventually removed once nobody used IPv4 anymore, but until then we * have to live with it. - * + * * @param key * original key from config (for example "port" or "port.ssl") * @param dflt * default value which will be used if no value is found * @return the public port of this system on its IPv4 address - * + * * @see #getLocalPort() */ public int getPublicPort(final String key, final int dflt) { - if (isConnectedViaUpnp && upnpPortMap.containsKey(key)) { - return upnpPortMap.get(key).intValue(); + if (this.isConnectedViaUpnp && this.upnpPortMap.containsKey(key)) { + return this.upnpPortMap.get(key).intValue(); } // TODO: add way of setting and retrieving port for manual NAT @@ -241,9 +241,9 @@ public class serverSwitch { /** * Wrapper for {@link #getConfigInt(String, int)} to have a more consistent * API. - * + * * Default value 8090 will be used if no value is found in configuration. - * + * * @return the local http port of this system * @see #getPublicPort(String, int) */ @@ -262,7 +262,7 @@ public class serverSwitch { /** * add whole map of key-value pairs to config - * + * * @param otherConfigs */ public void setConfig(final Map otherConfigs) { @@ -300,25 +300,25 @@ public class serverSwitch { } public void setConfig(final String key, final String[] value) { - StringBuilder sb = new StringBuilder(); - if (value != null) for (String s: value) sb.append(',').append(s); + final StringBuilder sb = new StringBuilder(); + if (value != null) for (final String s: value) sb.append(',').append(s); setConfig(key, sb.length() > 0 ? sb.substring(1) : ""); } - public void setConfig(final String key, Set value) { - String[] a = new String[value.size()]; + public void setConfig(final String key, final Set value) { + final String[] a = new String[value.size()]; int c = 0; - for (String s: value) a[c++] = s; + for (final String s: value) a[c++] = s; setConfig(key, a); } - + public void removeConfig(final String key) { this.configProps.remove(key); } /** * Gets a configuration parameter from the properties. - * + * * @param key * name of the configuration parameter * @param dflt @@ -339,7 +339,7 @@ public class serverSwitch { /** * Gets a configuration parameter from the properties. - * + * * @param key * name of the configuration parameter * @param dflt @@ -357,7 +357,7 @@ public class serverSwitch { /** * Gets a configuration parameter from the properties. - * + * * @param key * name of the configuration parameter * @param dflt @@ -375,7 +375,7 @@ public class serverSwitch { public boolean isConnectedViaUpnp() { - return isConnectedViaUpnp; + return this.isConnectedViaUpnp; } public void setConnectedViaUpnp(final boolean isConnectedViaUpnp) { @@ -383,22 +383,22 @@ public class serverSwitch { this.isConnectedViaUpnp = isConnectedViaUpnp; if (!isConnectedViaUpnp) { - upnpPortMap.clear(); + this.upnpPortMap.clear(); } } public void setUpnpPorts(final String key, final int port) { - upnpPortMap.put(key, Integer.valueOf(port)); + this.upnpPortMap.put(key, Integer.valueOf(port)); } public void removeUpnpPort(final String key) { - upnpPortMap.remove(key); + this.upnpPortMap.remove(key); } /** * Gets a configuration parameter from the properties. - * + * * @param key * name of the configuration parameter * @param dflt @@ -418,7 +418,7 @@ public class serverSwitch { /** * Gets a configuration parameter from the properties. - * + * * @param key * name of the configuration parameter * @param dflt @@ -438,7 +438,7 @@ public class serverSwitch { */ public String[] getConfigArray(final String key, final String dflt) { return CommonPattern.COMMA.split(this.getConfig(key, dflt)); - } + } /** * get a configuration parameter set @@ -446,14 +446,14 @@ public class serverSwitch { * @return a set of strings which had been separated by comma in the setting */ public Set getConfigSet(final String key) { - Set h = new LinkedHashSet<>(); + final Set h = new LinkedHashSet<>(); for (String s: getConfigArray(key, "")) {s = s.trim(); if (s.length() > 0) h.add(s.trim());} return h; } - + /** * Create a File instance for a configuration setting specifying a path. - * + * * @param key * config key * @param dflt @@ -470,7 +470,7 @@ public class serverSwitch { /** * return file at path from config entry "key", or fallback to default dflt - * + * * @param key * @param dflt * @return @@ -479,7 +479,7 @@ public class serverSwitch { return getFileByPath(key, dflt, this.appPath); } - private File getFileByPath(String key, String dflt, File prefix) { + private File getFileByPath(final String key, final String dflt, final File prefix) { final String path = getConfig(key, dflt).replace('\\', '/'); final File f = new File(path); return (f.isAbsolute() ? new File(f.getAbsolutePath()) : new File( @@ -494,7 +494,7 @@ public class serverSwitch { * write the changes to permanent storage (File) */ private void saveConfig() { - ConcurrentMap configPropsCopy = new ConcurrentHashMap(); + final ConcurrentMap configPropsCopy = new ConcurrentHashMap(); configPropsCopy.putAll(this.configProps); // avoid concurrency problems FileUtils.saveMap(this.configFile, configPropsCopy, this.configComment); } @@ -502,13 +502,13 @@ public class serverSwitch { /** * Gets configuration parameters which have been removed during * initialization. - * + * * @return contains parameter name as key and parameter value as value */ public ConcurrentMap getRemoved() { return this.configRemoved; } - + /** * @return the default configuration properties loaded form the * defaults/yacy.init file. The properties are empty when the file can @@ -519,9 +519,9 @@ public class serverSwitch { try (final FileInputStream fis = new FileInputStream(new File(this.appPath, "defaults/yacy.init"))) { config.load(fis); } catch (final FileNotFoundException e) { - log.severe("Could not find default configuration file defaults/yacy.init."); + this.log.severe("Could not find default configuration file defaults/yacy.init."); } catch (final IOException | IllegalArgumentException e) { - log.severe("Could not read configuration file."); + this.log.severe("Could not read configuration file."); } return config; } @@ -671,7 +671,7 @@ public class serverSwitch { /** * Retrieve text data (e. g. config file) from file file may be an url or a * filename with path relative to rootPath parameter - * + * * @param file * url or filename * @param rootPath @@ -690,7 +690,7 @@ public class serverSwitch { final RequestHeader reqHeader = new RequestHeader(); reqHeader.put(HeaderFramework.USER_AGENT, ClientIdentification.yacyInternetCrawlerAgent.userAgent); client.setHeader(reqHeader.entrySet()); - byte[] data = client.GETbytes(uri, + final byte[] data = client.GETbytes(uri, getConfig(SwitchboardConstants.ADMIN_ACCOUNT_USER_NAME, "admin"), getConfig(SwitchboardConstants.ADMIN_ACCOUNT_B64MD5, ""), false); if (data == null || data.length == 0) { @@ -724,10 +724,10 @@ public class serverSwitch { /** * set/remember jetty server - * + * * @param jettyserver */ - public void setHttpServer(YaCyHttpServer jettyserver) { + public void setHttpServer(final YaCyHttpServer jettyserver) { this.httpserver = jettyserver; } diff --git a/source/net/yacy/yacy.java b/source/net/yacy/yacy.java index db8091972..6f524bbc3 100644 --- a/source/net/yacy/yacy.java +++ b/source/net/yacy/yacy.java @@ -69,7 +69,6 @@ import net.yacy.data.TransactionManager; import net.yacy.data.Translator; import net.yacy.gui.YaCyApp; import net.yacy.gui.framework.Browser; -import net.yacy.http.Jetty9HttpServerImpl; import net.yacy.http.YaCyHttpServer; import net.yacy.kelondro.util.FileUtils; import net.yacy.kelondro.util.Formatter; @@ -293,7 +292,7 @@ public final class yacy { try { // start http server YaCyHttpServer httpServer; - httpServer = new Jetty9HttpServerImpl(port); + httpServer = new YaCyHttpServer(port); httpServer.startupServer(); sb.setHttpServer(httpServer); // TODO: this has no effect on Jetty (but needed to reflect configured value and limit is still used) @@ -628,7 +627,7 @@ public final class yacy { * * @param dataHome data directory */ - static private void preReadSavedConfigandInit(File dataHome) { + static private void preReadSavedConfigandInit(final File dataHome) { final File lockFile = new File(dataHome, "DATA/yacy.running"); final String conf = "DATA/SETTINGS/yacy.conf"; @@ -688,7 +687,7 @@ public final class yacy { * @param args * Given arguments from the command line. */ - public static void main(String args[]) { + public static void main(final String args[]) { try { // check assertion status