diff options
| author | Michael Peter Christen <mc@yacy.net> | 2026-07-11 12:08:35 +0200 |
|---|---|---|
| committer | Michael Peter Christen <mc@yacy.net> | 2026-07-11 12:08:35 +0200 |
| commit | b32b659023fa65a4141e64bbcfb82183bb6994de (patch) | |
| tree | 37cad21a1212d2cb4fbc1b572c8358c9ba3363d0 /source | |
| parent | e42386b3fbed3f94f733433a66495c453bfe7a51 (diff) | |
Added a server interface which is now implemeted by jetty 9
This will enable a better transition once we migrate to jetty 10
Diffstat (limited to 'source')
| -rw-r--r-- | source/net/yacy/http/Jetty9HttpServerImpl.java | 526 | ||||
| -rw-r--r-- | source/net/yacy/http/YaCyHttpServer.java | 494 | ||||
| -rw-r--r-- | source/net/yacy/yacy.java | 137 |
3 files changed, 618 insertions, 539 deletions
diff --git a/source/net/yacy/http/Jetty9HttpServerImpl.java b/source/net/yacy/http/Jetty9HttpServerImpl.java new file mode 100644 index 000000000..fea7e30a8 --- /dev/null +++ b/source/net/yacy/http/Jetty9HttpServerImpl.java @@ -0,0 +1,526 @@ +// +// Jetty9HttpServerImpl +// Copyright 2011 by Florian Richter +// First released 13.04.2011 at https://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 <http://www.gnu.org/licenses/>. +// + +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.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 + * @param host The network interface this connector binds to as an IP address or a hostname. + */ + public Jetty9HttpServerImpl(final int port, final String host) { + final Switchboard sb = Switchboard.getSwitchboard(); + + this.server = new Server(); + + final int cores = Runtime.getRuntime().availableProcessors(); + final int acceptors = Math.max(1, Math.min(4, cores/2)); // original: Math.max(1, Math.min(4,cores/8)); + + final HttpConfiguration httpConfig = new HttpConfiguration(); + httpConfig.setRequestHeaderSize(16384); + final HttpConnectionFactory hcf = new HttpConnectionFactory(httpConfig); + final ServerConnector connector = new ServerConnector(this.server, null, null, null, acceptors, -1, hcf); + connector.setPort(port); + connector.setHost(host); + connector.setName("httpd-" + host + ":" + 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 = this.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(-1); + 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 part of the built-in administrator's DIGEST password hash. + // Changing it invalidates the configured administrator password hash. + 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 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 (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 the login service to reload the built-in administrator credentials + * after they were changed in the configuration. + * @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 the built-in administrator from the login service cache. + * @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/YaCyHttpServer.java b/source/net/yacy/http/YaCyHttpServer.java index b4844eb78..a4bff7bbd 100644 --- a/source/net/yacy/http/YaCyHttpServer.java +++ b/source/net/yacy/http/YaCyHttpServer.java @@ -20,507 +20,59 @@ 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.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 + * Servlet-container neutral interface to YaCy's embedded http server. + * This is the only view the rest of the code base has on the server; + * all container specific code (currently Jetty 9, see {@link Jetty9HttpServerImpl}) + * stays behind this interface to ease migration to newer container versions. */ -public class YaCyHttpServer { - - private final Server server; +public interface YaCyHttpServer { /** - * @param port TCP Port to listen for http requests - * @param host The network interface this connector binds to as an IP address or a hostname. + * start the http server */ - public YaCyHttpServer(final int port, final String host) { - final Switchboard sb = Switchboard.getSwitchboard(); - - this.server = new Server(); - - final int cores = Runtime.getRuntime().availableProcessors(); - final int acceptors = Math.max(1, Math.min(4, cores/2)); // original: Math.max(1, Math.min(4,cores/8)); - - final HttpConfiguration httpConfig = new HttpConfiguration(); - httpConfig.setRequestHeaderSize(16384); - final HttpConnectionFactory hcf = new HttpConnectionFactory(httpConfig); - final ServerConnector connector = new ServerConnector(this.server, null, null, null, acceptors, -1, hcf); - connector.setPort(port); - connector.setHost(host); - connector.setName("httpd-" + host + ":" + 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 = this.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(-1); - 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 part of the built-in administrator's DIGEST password hash. - // Changing it invalidates the configured administrator password hash. - 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 - } - } + void startupServer() throws Exception; /** - * start http server + * stop the http server */ - public void startupServer() throws Exception { - // option to finish running requests on shutdown -// server.setGracefulShutdown(3000); - this.server.setStopAtShutdown(true); - this.server.start(); - } + void stop() throws Exception; /** - * stop http server and wait for it + * reconnect with new port settings (after waiting milsec) - routine returns immediately + * @param milsec wait time */ - public void stop() throws Exception { - this.server.stop(); - this.server.join(); - } + void reconnect(int milsec); /** - * @return true if ssl/https connector is available + * @return true if the server runs a ssl/https connector */ - public boolean withSSL() { - final Connector[] clist = this.server.getConnectors(); - for (final Connector c:clist) { - if (c.getName().startsWith("ssl")) return true; - } - return false; - } + boolean withSSL(); /** - * 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 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(); - } + int getSslPort(); /** - * Forces the login service to reload the built-in administrator credentials - * after they were changed in the configuration. + * forces loginservice to reload user credentials * @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); - } - } - } + void resetUser(String username); /** - * Removes the built-in administrator from the login service cache. + * removes user from the 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); - } - } + void removeUser(String username); /** - * get Jetty version - * @return version_string + * @return version string of the servlet container */ - public String getVersion() { - return "Jetty " + Server.getVersion(); - } + String getVersion(); /** - * Init SSL Context from config settings - * @param sb Switchboard - * @return default or sslcontext according to config + * @return the number of currently active (busy) server threads */ - 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(); - } + int getServerThreads(); } diff --git a/source/net/yacy/yacy.java b/source/net/yacy/yacy.java index 1a5babbc4..251df47c5 100644 --- a/source/net/yacy/yacy.java +++ b/source/net/yacy/yacy.java @@ -42,10 +42,10 @@ import java.util.LinkedHashMap; import java.util.List;
import java.util.Locale;
import java.util.Map;
-import java.util.Properties; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.Semaphore; -import java.util.concurrent.TimeUnit; +import java.util.Properties;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
import org.apache.http.Header;
import org.apache.http.HttpStatus;
@@ -61,13 +61,14 @@ import net.yacy.cora.protocol.ClientIdentification; import net.yacy.cora.protocol.ConnectionInfo;
import net.yacy.cora.protocol.HeaderFramework;
import net.yacy.cora.protocol.TimeoutRequest;
-import net.yacy.cora.protocol.http.HTTPClient; -import net.yacy.cora.util.ConcurrentLog; -import net.yacy.ai.LogReportService; -import net.yacy.data.TransactionManager; +import net.yacy.cora.protocol.http.HTTPClient;
+import net.yacy.cora.util.ConcurrentLog;
+import net.yacy.ai.LogReportService;
+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;
@@ -292,14 +293,14 @@ public final class yacy { final int deleteOldDownloadsAfterDays = (int) sb.getConfigLong("update.deleteOld", 30);
yacyRelease.deleteOldDownloads(sb.releasePath, deleteOldDownloadsAfterDays );
- // start main threads - final int port = sb.getLocalPort(); - final String host = sb.getLocalHost(); - ScheduledExecutorService logReportScheduler = null; - try { - // start http server - YaCyHttpServer httpServer; - httpServer = new YaCyHttpServer(port, host); + // start main threads
+ final int port = sb.getLocalPort();
+ final String host = sb.getLocalHost();
+ ScheduledExecutorService logReportScheduler = null;
+ try {
+ // start http server
+ YaCyHttpServer httpServer;
+ httpServer = new Jetty9HttpServerImpl(port, host);
httpServer.startupServer();
sb.setHttpServer(httpServer);
// TODO: this has no effect on Jetty (but needed to reflect configured value and limit is still used)
@@ -375,13 +376,13 @@ public final class yacy { }
}
// initialize number formatter with this locale
- if (!lang.equals("browser")) // "default" is handled by .setLocale() - Formatter.setLocale(lang); - - logReportScheduler = LogReportService.startScheduler(sb); - - // registering shutdown hook - ConcurrentLog.config("STARTUP", "Registering Shutdown Hook"); + if (!lang.equals("browser")) // "default" is handled by .setLocale()
+ Formatter.setLocale(lang);
+
+ logReportScheduler = LogReportService.startScheduler(sb);
+
+ // registering shutdown hook
+ ConcurrentLog.config("STARTUP", "Registering Shutdown Hook");
final Runtime run = Runtime.getRuntime();
run.addShutdownHook(new shutdownHookThread(sb, shutdownSemaphore));
@@ -400,18 +401,18 @@ public final class yacy { } catch (final Exception e) {
ConcurrentLog.severe("MAIN CONTROL LOOP", "PANIC: " + e.getMessage(),e);
}
- // shut down - ConcurrentLog.config("SHUTDOWN", "caught termination signal"); - LogReportService.stopScheduler(logReportScheduler); - httpServer.stop(); -
- ConcurrentLog.config("SHUTDOWN", "server has terminated"); - sb.close(); - } catch (final Exception e) { - LogReportService.stopScheduler(logReportScheduler); - ConcurrentLog.severe("STARTUP", "Unexpected Error: " + e.getClass().getName(),e); - //System.exit(1); - } + // shut down
+ ConcurrentLog.config("SHUTDOWN", "caught termination signal");
+ LogReportService.stopScheduler(logReportScheduler);
+ httpServer.stop();
+
+ ConcurrentLog.config("SHUTDOWN", "server has terminated");
+ sb.close();
+ } catch (final Exception e) {
+ LogReportService.stopScheduler(logReportScheduler);
+ ConcurrentLog.severe("STARTUP", "Unexpected Error: " + e.getClass().getName(),e);
+ //System.exit(1);
+ }
if (lock != null && lock.isValid()) lock.release();
if (channel != null && channel.isOpen()) channel.close();
} catch (final Exception ee) {
@@ -726,21 +727,21 @@ public final class yacy { final StringBuilder s = new StringBuilder(); for (final String a: args) s.append(a).append(" ");
yacyRelease.startParameter = s.toString().trim();
- // case for the application path if started normally with a jre command - File applicationRoot = new File(System.getProperty("user.dir").replace('\\', '/')); - File dataRoot = applicationRoot; - final String dataRootOverrideProp = System.getProperty("yacy.data"); - final String dataRootOverrideEnv = System.getenv("YACY_DATA"); - final String dataRootOverride = (dataRootOverrideProp != null && !dataRootOverrideProp.isEmpty()) - ? dataRootOverrideProp - : dataRootOverrideEnv; - if (dataRootOverride != null && !dataRootOverride.isEmpty()) { - dataRoot = new File(dataRootOverride); - if(!dataRoot.isAbsolute()) { - /* data root folder provided as a path relative to the user home folder */ - dataRoot = new File(System.getProperty("user.home").replace('\\', '/'), dataRootOverride); - } - } + // case for the application path if started normally with a jre command
+ File applicationRoot = new File(System.getProperty("user.dir").replace('\\', '/'));
+ File dataRoot = applicationRoot;
+ final String dataRootOverrideProp = System.getProperty("yacy.data");
+ final String dataRootOverrideEnv = System.getenv("YACY_DATA");
+ final String dataRootOverride = (dataRootOverrideProp != null && !dataRootOverrideProp.isEmpty())
+ ? dataRootOverrideProp
+ : dataRootOverrideEnv;
+ if (dataRootOverride != null && !dataRootOverride.isEmpty()) {
+ dataRoot = new File(dataRootOverride);
+ if(!dataRoot.isAbsolute()) {
+ /* data root folder provided as a path relative to the user home folder */
+ dataRoot = new File(System.getProperty("user.home").replace('\\', '/'), dataRootOverride);
+ }
+ }
//System.out.println("args.length=" + args.length);
//System.out.print("args=["); for (int i = 0; i < args.length; i++) System.out.print(args[i] + ", "); System.out.println("]");
if ((args.length >= 1) && (args[0].toLowerCase(Locale.ROOT).equals("-startup") || args[0].equals("-start"))) {
@@ -765,24 +766,24 @@ public final class yacy { }
preReadSavedConfigandInit(dataRoot);
startup(dataRoot, applicationRoot, startupMemFree, startupMemTotal, true);
- } else if ((args.length >= 1) && ((args[0].toLowerCase(Locale.ROOT).equals("-shutdown")) || (args[0].equals("-stop")))) { - // normal shutdown of yacy - if (args.length == 2) { - dataRoot = new File(args[1]); - if(!dataRoot.isAbsolute()) { - dataRoot = new File(System.getProperty("user.home").replace('\\', '/'), args[1]); - } - } - shutdown(dataRoot); - } else if ((args.length >= 1) && (args[0].toLowerCase(Locale.ROOT).equals("-update"))) { - // aut-update yacy - if (args.length == 2) { - dataRoot = new File(args[1]); - if(!dataRoot.isAbsolute()) { - dataRoot = new File(System.getProperty("user.home").replace('\\', '/'), args[1]); - } - } - update(dataRoot); + } else if ((args.length >= 1) && ((args[0].toLowerCase(Locale.ROOT).equals("-shutdown")) || (args[0].equals("-stop")))) {
+ // normal shutdown of yacy
+ if (args.length == 2) {
+ dataRoot = new File(args[1]);
+ if(!dataRoot.isAbsolute()) {
+ dataRoot = new File(System.getProperty("user.home").replace('\\', '/'), args[1]);
+ }
+ }
+ shutdown(dataRoot);
+ } else if ((args.length >= 1) && (args[0].toLowerCase(Locale.ROOT).equals("-update"))) {
+ // aut-update yacy
+ if (args.length == 2) {
+ dataRoot = new File(args[1]);
+ if(!dataRoot.isAbsolute()) {
+ dataRoot = new File(System.getProperty("user.home").replace('\\', '/'), args[1]);
+ }
+ }
+ update(dataRoot);
} else if ((args.length >= 1) && (args[0].toLowerCase(Locale.ROOT).equals("-version"))) {
// show yacy version
System.out.println(copyright);
|
