| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.tomcat.util.net; |
| |
| import java.io.File; |
| import java.io.OutputStreamWriter; |
| import java.net.InetAddress; |
| import java.net.InetSocketAddress; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.StringTokenizer; |
| import java.util.concurrent.Executor; |
| import java.util.concurrent.TimeUnit; |
| |
| import javax.net.ssl.KeyManagerFactory; |
| |
| import org.apache.juli.logging.Log; |
| import org.apache.tomcat.util.IntrospectionUtils; |
| import org.apache.tomcat.util.res.StringManager; |
| import org.apache.tomcat.util.threads.CounterLatch; |
| import org.apache.tomcat.util.threads.ResizableExecutor; |
| import org.apache.tomcat.util.threads.TaskQueue; |
| import org.apache.tomcat.util.threads.TaskThreadFactory; |
| import org.apache.tomcat.util.threads.ThreadPoolExecutor; |
| /** |
| * |
| * @author fhanik |
| * @author Mladen Turk |
| * @author Remy Maucherat |
| */ |
| public abstract class AbstractEndpoint { |
| |
| // -------------------------------------------------------------- Constants |
| protected static final StringManager sm = StringManager.getManager("org.apache.tomcat.util.net.res"); |
| |
| public static interface Handler { |
| /** |
| * Different types of socket states to react upon. |
| */ |
| public enum SocketState { |
| OPEN, CLOSED, LONG, ASYNC_END |
| } |
| |
| |
| /** |
| * Obtain the GlobalRequestProcessor associated with the handler. |
| */ |
| public Object getGlobal(); |
| |
| |
| /** |
| * Recycle resources associated with the handler. |
| */ |
| public void recycle(); |
| } |
| |
| protected enum BindState { |
| UNBOUND, BOUND_ON_INIT, BOUND_ON_START |
| } |
| |
| private static final int INITIAL_ERROR_DELAY = 50; |
| private static final int MAX_ERROR_DELAY = 1600; |
| |
| // ----------------------------------------------------------------- Fields |
| |
| |
| /** |
| * Running state of the endpoint. |
| */ |
| protected volatile boolean running = false; |
| |
| |
| /** |
| * Will be set to true whenever the endpoint is paused. |
| */ |
| protected volatile boolean paused = false; |
| |
| /** |
| * Are we using an internal executor |
| */ |
| protected volatile boolean internalExecutor = false; |
| |
| /** |
| * counter for nr of connections handled by an endpoint |
| */ |
| private volatile CounterLatch connectionCounterLatch = null; |
| |
| /** |
| * Socket properties |
| */ |
| protected SocketProperties socketProperties = new SocketProperties(); |
| public SocketProperties getSocketProperties() { |
| return socketProperties; |
| } |
| |
| |
| // ----------------------------------------------------------------- Properties |
| |
| private int maxConnections = 10000; |
| public void setMaxConnections(int maxCon) { this.maxConnections = maxCon; } |
| public int getMaxConnections() { return this.maxConnections; } |
| /** |
| * External Executor based thread pool. |
| */ |
| private Executor executor = null; |
| public void setExecutor(Executor executor) { |
| this.executor = executor; |
| this.internalExecutor = (executor==null); |
| } |
| public Executor getExecutor() { return executor; } |
| |
| |
| /** |
| * Server socket port. |
| */ |
| private int port; |
| public int getPort() { return port; } |
| public void setPort(int port ) { this.port=port; } |
| |
| |
| /** |
| * Address for the server socket. |
| */ |
| private InetAddress address; |
| public InetAddress getAddress() { return address; } |
| public void setAddress(InetAddress address) { this.address = address; } |
| |
| /** |
| * Allows the server developer to specify the backlog that |
| * should be used for server sockets. By default, this value |
| * is 100. |
| */ |
| private int backlog = 100; |
| public void setBacklog(int backlog) { if (backlog > 0) this.backlog = backlog; } |
| public int getBacklog() { return backlog; } |
| |
| /** |
| * Controls when the Endpoint binds the port. <code>true</code>, the default |
| * binds the port on {@link #init()} and unbinds it on {@link #destroy()}. |
| * If set to <code>false</code> the port is bound on {@link #start()} and |
| * unbound on {@link #stop()}. |
| */ |
| private boolean bindOnInit = true; |
| public boolean getBindOnInit() { return bindOnInit; } |
| public void setBindOnInit(boolean b) { this.bindOnInit = b; } |
| private BindState bindState = BindState.UNBOUND; |
| |
| /** |
| * Keepalive timeout, if lesser or equal to 0 then soTimeout will be used. |
| */ |
| private int keepAliveTimeout = -1; |
| public int getKeepAliveTimeout() { return keepAliveTimeout;} |
| public void setKeepAliveTimeout(int keepAliveTimeout) { |
| this.keepAliveTimeout = keepAliveTimeout; |
| } |
| |
| |
| /** |
| * Socket TCP no delay. |
| */ |
| public boolean getTcpNoDelay() { return socketProperties.getTcpNoDelay();} |
| public void setTcpNoDelay(boolean tcpNoDelay) { socketProperties.setTcpNoDelay(tcpNoDelay); } |
| |
| |
| /** |
| * Socket linger. |
| */ |
| public int getSoLinger() { return socketProperties.getSoLingerTime(); } |
| public void setSoLinger(int soLinger) { |
| socketProperties.setSoLingerTime(soLinger); |
| socketProperties.setSoLingerOn(soLinger>=0); |
| } |
| |
| |
| /** |
| * Socket timeout. |
| */ |
| public int getSoTimeout() { return socketProperties.getSoTimeout(); } |
| public void setSoTimeout(int soTimeout) { socketProperties.setSoTimeout(soTimeout); } |
| |
| /** |
| * SSL engine. |
| */ |
| private boolean SSLEnabled = false; |
| public boolean isSSLEnabled() { return SSLEnabled; } |
| public void setSSLEnabled(boolean SSLEnabled) { this.SSLEnabled = SSLEnabled; } |
| |
| |
| private int minSpareThreads = 10; |
| public int getMinSpareThreads() { |
| return Math.min(minSpareThreads,getMaxThreads()); |
| } |
| public void setMinSpareThreads(int minSpareThreads) { |
| this.minSpareThreads = minSpareThreads; |
| if (running && executor!=null) { |
| if (executor instanceof java.util.concurrent.ThreadPoolExecutor) { |
| ((java.util.concurrent.ThreadPoolExecutor)executor).setCorePoolSize(minSpareThreads); |
| } else if (executor instanceof ResizableExecutor) { |
| ((ResizableExecutor)executor).resizePool(minSpareThreads, maxThreads); |
| } |
| } |
| } |
| |
| /** |
| * Maximum amount of worker threads. |
| */ |
| private int maxThreads = 200; |
| public void setMaxThreads(int maxThreads) { |
| this.maxThreads = maxThreads; |
| if (running && executor!=null) { |
| if (executor instanceof java.util.concurrent.ThreadPoolExecutor) { |
| ((java.util.concurrent.ThreadPoolExecutor)executor).setMaximumPoolSize(maxThreads); |
| } else if (executor instanceof ResizableExecutor) { |
| ((ResizableExecutor)executor).resizePool(minSpareThreads, maxThreads); |
| } |
| } |
| } |
| public int getMaxThreads() { |
| if (running && executor!=null) { |
| if (executor instanceof java.util.concurrent.ThreadPoolExecutor) { |
| return ((java.util.concurrent.ThreadPoolExecutor)executor).getMaximumPoolSize(); |
| } else if (executor instanceof ResizableExecutor) { |
| return ((ResizableExecutor)executor).getMaxThreads(); |
| } else { |
| return -1; |
| } |
| } else { |
| return maxThreads; |
| } |
| } |
| |
| /** |
| * Max keep alive requests |
| */ |
| private int maxKeepAliveRequests=100; // as in Apache HTTPD server |
| public int getMaxKeepAliveRequests() { |
| return maxKeepAliveRequests; |
| } |
| public void setMaxKeepAliveRequests(int maxKeepAliveRequests) { |
| this.maxKeepAliveRequests = maxKeepAliveRequests; |
| } |
| |
| /** |
| * Name of the thread pool, which will be used for naming child threads. |
| */ |
| private String name = "TP"; |
| public void setName(String name) { this.name = name; } |
| public String getName() { return name; } |
| |
| /** |
| * The default is true - the created threads will be |
| * in daemon mode. If set to false, the control thread |
| * will not be daemon - and will keep the process alive. |
| */ |
| private boolean daemon = true; |
| public void setDaemon(boolean b) { daemon = b; } |
| public boolean getDaemon() { return daemon; } |
| |
| |
| /** |
| * Priority of the worker threads. |
| */ |
| protected int threadPriority = Thread.NORM_PRIORITY; |
| public void setThreadPriority(int threadPriority) { this.threadPriority = threadPriority; } |
| public int getThreadPriority() { return threadPriority; } |
| |
| protected abstract boolean getDeferAccept(); |
| |
| |
| /** |
| * Attributes provide a way for configuration to be passed to sub-components |
| * without the {@link org.apache.coyote.ProtocolHandler} being aware of the |
| * properties available on those sub-components. One example of such a |
| * sub-component is the |
| * {@link org.apache.tomcat.util.net.ServerSocketFactory}. |
| */ |
| protected HashMap<String, Object> attributes = |
| new HashMap<String, Object>(); |
| /** |
| * Generic property setter called when a property for which a specific |
| * setter already exists within the |
| * {@link org.apache.coyote.ProtocolHandler} needs to be made available to |
| * sub-components. The specific setter will call this method to populate the |
| * attributes. |
| */ |
| public void setAttribute(String name, Object value) { |
| if (getLog().isTraceEnabled()) { |
| getLog().trace(sm.getString("abstractProtocolHandler.setAttribute", |
| name, value)); |
| } |
| attributes.put(name, value); |
| } |
| /** |
| * Used by sub-components to retrieve configuration information. |
| */ |
| public Object getAttribute(String key) { |
| Object value = attributes.get(key); |
| if (getLog().isTraceEnabled()) { |
| getLog().trace(sm.getString("abstractProtocolHandler.getAttribute", |
| key, value)); |
| } |
| return value; |
| } |
| |
| |
| |
| public boolean setProperty(String name, String value) { |
| setAttribute(name, value); |
| final String socketName = "socket."; |
| try { |
| if (name.startsWith(socketName)) { |
| return IntrospectionUtils.setProperty(socketProperties, name.substring(socketName.length()), value); |
| } else { |
| return IntrospectionUtils.setProperty(this,name,value,false); |
| } |
| }catch ( Exception x ) { |
| getLog().error("Unable to set attribute \""+name+"\" to \""+value+"\"",x); |
| return false; |
| } |
| } |
| public String getProperty(String name) { |
| return (String) getAttribute(name); |
| } |
| |
| /** |
| * Return the amount of threads that are managed by the pool. |
| * |
| * @return the amount of threads that are managed by the pool |
| */ |
| public int getCurrentThreadCount() { |
| if (executor!=null) { |
| if (executor instanceof ThreadPoolExecutor) { |
| return ((ThreadPoolExecutor)executor).getPoolSize(); |
| } else if (executor instanceof ResizableExecutor) { |
| return ((ResizableExecutor)executor).getPoolSize(); |
| } else { |
| return -1; |
| } |
| } else { |
| return -2; |
| } |
| } |
| |
| /** |
| * Return the amount of threads that are in use |
| * |
| * @return the amount of threads that are in use |
| */ |
| public int getCurrentThreadsBusy() { |
| if (executor!=null) { |
| if (executor instanceof ThreadPoolExecutor) { |
| return ((ThreadPoolExecutor)executor).getActiveCount(); |
| } else if (executor instanceof ResizableExecutor) { |
| return ((ResizableExecutor)executor).getActiveCount(); |
| } else { |
| return -1; |
| } |
| } else { |
| return -2; |
| } |
| } |
| |
| public boolean isRunning() { |
| return running; |
| } |
| |
| public boolean isPaused() { |
| return paused; |
| } |
| |
| |
| public void createExecutor() { |
| internalExecutor = true; |
| TaskQueue taskqueue = new TaskQueue(); |
| TaskThreadFactory tf = new TaskThreadFactory(getName() + "-exec-", daemon, getThreadPriority()); |
| executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), 60, TimeUnit.SECONDS,taskqueue, tf); |
| taskqueue.setParent( (ThreadPoolExecutor) executor); |
| } |
| |
| public void shutdownExecutor() { |
| if ( executor!=null && internalExecutor ) { |
| if ( executor instanceof ThreadPoolExecutor ) { |
| //this is our internal one, so we need to shut it down |
| ThreadPoolExecutor tpe = (ThreadPoolExecutor) executor; |
| tpe.shutdownNow(); |
| TaskQueue queue = (TaskQueue) tpe.getQueue(); |
| queue.setParent(null); |
| } |
| executor = null; |
| } |
| } |
| |
| /** |
| * Unlock the server socket accept using a bogus connection. |
| */ |
| protected void unlockAccept() { |
| java.net.Socket s = null; |
| InetSocketAddress saddr = null; |
| try { |
| // Need to create a connection to unlock the accept(); |
| if (address == null) { |
| saddr = new InetSocketAddress("localhost", getPort()); |
| } else { |
| saddr = new InetSocketAddress(address,getPort()); |
| } |
| s = new java.net.Socket(); |
| int stmo = 2 * 1000; |
| int utmo = 2 * 1000; |
| if (getSocketProperties().getSoTimeout() > stmo) |
| stmo = getSocketProperties().getSoTimeout(); |
| if (getSocketProperties().getUnlockTimeout() > utmo) |
| utmo = getSocketProperties().getUnlockTimeout(); |
| s.setSoTimeout(stmo); |
| // TODO Consider hard-coding to s.setSoLinger(true,0) |
| s.setSoLinger(getSocketProperties().getSoLingerOn(),getSocketProperties().getSoLingerTime()); |
| if (getLog().isDebugEnabled()) { |
| getLog().debug("About to unlock socket for:"+saddr); |
| } |
| s.connect(saddr,utmo); |
| if (getDeferAccept()) { |
| /* |
| * In the case of a deferred accept / accept filters we need to |
| * send data to wake up the accept. Send OPTIONS * to bypass |
| * even BSD accept filters. The Acceptor will discard it. |
| */ |
| OutputStreamWriter sw; |
| |
| sw = new OutputStreamWriter(s.getOutputStream(), "ISO-8859-1"); |
| sw.write("OPTIONS * HTTP/1.0\r\n" + |
| "User-Agent: Tomcat wakeup connection\r\n\r\n"); |
| sw.flush(); |
| } |
| if (getLog().isDebugEnabled()) { |
| getLog().debug("Socket unlock completed for:"+saddr); |
| } |
| } catch(Exception e) { |
| if (getLog().isDebugEnabled()) { |
| getLog().debug(sm.getString("endpoint.debug.unlock", "" + getPort()), e); |
| } |
| } finally { |
| if (s != null) { |
| try { |
| s.close(); |
| } catch (Exception e) { |
| // Ignore |
| } |
| } |
| } |
| } |
| |
| |
| // ------------------------------------------------------- Lifecycle methods |
| |
| /* |
| * NOTE: There is no maintenance of state or checking for valid transitions |
| * within this class other than ensuring that bind/unbind are called in the |
| * right place. It is expected that the calling code will maintain state and |
| * prevent invalid state transitions. |
| */ |
| |
| public abstract void bind() throws Exception; |
| public abstract void unbind() throws Exception; |
| public abstract void startInternal() throws Exception; |
| public abstract void stopInternal() throws Exception; |
| |
| public final void init() throws Exception { |
| if (bindOnInit) { |
| bind(); |
| bindState = BindState.BOUND_ON_INIT; |
| } |
| } |
| |
| public final void start() throws Exception { |
| if (bindState == BindState.UNBOUND) { |
| bind(); |
| bindState = BindState.BOUND_ON_START; |
| } |
| startInternal(); |
| } |
| |
| /** |
| * Pause the endpoint, which will stop it accepting new connections. |
| */ |
| public void pause() { |
| if (running && !paused) { |
| paused = true; |
| unlockAccept(); |
| // Heuristic: Sleep for a while to ensure pause of the endpoint |
| try { |
| Thread.sleep(1000); |
| } catch (InterruptedException e) { |
| // Ignore |
| } |
| } |
| } |
| |
| /** |
| * Resume the endpoint, which will make it start accepting new connections |
| * again. |
| */ |
| public void resume() { |
| if (running) { |
| paused = false; |
| } |
| } |
| |
| public final void stop() throws Exception { |
| stopInternal(); |
| if (bindState == BindState.BOUND_ON_START) { |
| unbind(); |
| bindState = BindState.UNBOUND; |
| } |
| } |
| |
| public final void destroy() throws Exception { |
| if (bindState == BindState.BOUND_ON_INIT) { |
| unbind(); |
| bindState = BindState.UNBOUND; |
| } |
| } |
| |
| |
| public String adjustRelativePath(String path, String relativeTo) { |
| String newPath = path; |
| File f = new File(newPath); |
| if ( !f.isAbsolute()) { |
| newPath = relativeTo + File.separator + newPath; |
| f = new File(newPath); |
| } |
| if (!f.exists()) { |
| getLog().warn("configured file:["+newPath+"] does not exist."); |
| } |
| return newPath; |
| } |
| |
| protected abstract Log getLog(); |
| public abstract boolean getUseSendfile(); |
| |
| protected CounterLatch initializeConnectionLatch() { |
| if (connectionCounterLatch==null) { |
| connectionCounterLatch = new CounterLatch(0,getMaxConnections()); |
| } |
| return connectionCounterLatch; |
| } |
| |
| protected void releaseConnectionLatch() { |
| CounterLatch latch = connectionCounterLatch; |
| if (latch!=null) latch.releaseAll(); |
| connectionCounterLatch = null; |
| } |
| |
| protected void awaitConnection() throws InterruptedException { |
| CounterLatch latch = connectionCounterLatch; |
| if (latch!=null) latch.await(); |
| } |
| |
| protected long countUpConnection() { |
| CounterLatch latch = connectionCounterLatch; |
| if (latch!=null) return latch.countUp(); |
| else return -1; |
| } |
| |
| protected long countDownConnection() { |
| CounterLatch latch = connectionCounterLatch; |
| if (latch!=null) { |
| long result = latch.countDown(); |
| if (result<0) { |
| getLog().warn("Incorrect connection count, multiple socket.close called on the same socket." ); |
| } |
| return result; |
| } else return -1; |
| } |
| |
| /** |
| * Provides a common approach for sub-classes to handle exceptions where a |
| * delay is required to prevent a Thread from entering a tight loop which |
| * will consume CPU and may also trigger large amounts of logging. For |
| * example, this can happen with the Acceptor thread if the ulimit for open |
| * files is reached. |
| * |
| * @param currentErrorDelay The current delay beign applied on failure |
| * @return The delay to apply on the next failure |
| */ |
| protected int handleExceptionWithDelay(int currentErrorDelay) { |
| // Don't delay on first exception |
| if (currentErrorDelay > 0) { |
| try { |
| Thread.sleep(currentErrorDelay); |
| } catch (InterruptedException e) { |
| // Ignore |
| } |
| } |
| |
| // On subsequent exceptions, start the delay at 50ms, doubling the delay |
| // on every subsequent exception until the delay reaches 1.6 seconds. |
| if (currentErrorDelay == 0) { |
| return INITIAL_ERROR_DELAY; |
| } else if (currentErrorDelay < MAX_ERROR_DELAY) { |
| return currentErrorDelay * 2; |
| } else { |
| return MAX_ERROR_DELAY; |
| } |
| |
| } |
| |
| // -------------------- SSL related properties -------------------- |
| |
| private String algorithm = KeyManagerFactory.getDefaultAlgorithm(); |
| public String getAlgorithm() { return algorithm;} |
| public void setAlgorithm(String s ) { this.algorithm = s;} |
| |
| private String clientAuth = "false"; |
| public String getClientAuth() { return clientAuth;} |
| public void setClientAuth(String s ) { this.clientAuth = s;} |
| |
| private String keystoreFile = System.getProperty("user.home")+"/.keystore"; |
| public String getKeystoreFile() { return keystoreFile;} |
| public void setKeystoreFile(String s ) { |
| String file = adjustRelativePath(s, |
| System.getProperty(Constants.CATALINA_BASE_PROP)); |
| this.keystoreFile = file; |
| } |
| |
| private String keystorePass = null; |
| public String getKeystorePass() { return keystorePass;} |
| public void setKeystorePass(String s ) { this.keystorePass = s;} |
| |
| private String keystoreType = "JKS"; |
| public String getKeystoreType() { return keystoreType;} |
| public void setKeystoreType(String s ) { this.keystoreType = s;} |
| |
| private String keystoreProvider = null; |
| public String getKeystoreProvider() { return keystoreProvider;} |
| public void setKeystoreProvider(String s ) { this.keystoreProvider = s;} |
| |
| private String sslProtocol = "TLS"; |
| public String getSslProtocol() { return sslProtocol;} |
| public void setSslProtocol(String s) { sslProtocol = s;} |
| |
| // Note: Some implementations use the comma separated string, some use |
| // the array |
| private String ciphers = null; |
| private String[] ciphersarr = new String[0]; |
| public String[] getCiphersArray() { return this.ciphersarr;} |
| public String getCiphers() { return ciphers;} |
| public void setCiphers(String s) { |
| ciphers = s; |
| if ( s == null ) ciphersarr = new String[0]; |
| else { |
| StringTokenizer t = new StringTokenizer(s,","); |
| ciphersarr = new String[t.countTokens()]; |
| for (int i=0; i<ciphersarr.length; i++ ) ciphersarr[i] = t.nextToken(); |
| } |
| } |
| |
| private String keyAlias = null; |
| public String getKeyAlias() { return keyAlias;} |
| public void setKeyAlias(String s ) { keyAlias = s;} |
| |
| private String keyPass = null; |
| public String getKeyPass() { return keyPass;} |
| public void setKeyPass(String s ) { this.keyPass = s;} |
| |
| private String truststoreFile = System.getProperty("javax.net.ssl.trustStore"); |
| public String getTruststoreFile() {return truststoreFile;} |
| public void setTruststoreFile(String s) { |
| if (s == null) { |
| this.truststoreFile = null; |
| } else { |
| String file = adjustRelativePath(s, |
| System.getProperty(Constants.CATALINA_BASE_PROP)); |
| this.truststoreFile = file; |
| } |
| } |
| |
| private String truststorePass = |
| System.getProperty("javax.net.ssl.trustStorePassword"); |
| public String getTruststorePass() {return truststorePass;} |
| public void setTruststorePass(String truststorePass) { |
| this.truststorePass = truststorePass; |
| } |
| |
| private String truststoreType = |
| System.getProperty("javax.net.ssl.trustStoreType"); |
| public String getTruststoreType() {return truststoreType;} |
| public void setTruststoreType(String truststoreType) { |
| this.truststoreType = truststoreType; |
| } |
| |
| private String truststoreProvider = null; |
| public String getTruststoreProvider() {return truststoreProvider;} |
| public void setTruststoreProvider(String truststoreProvider) { |
| this.truststoreProvider = truststoreProvider; |
| } |
| |
| private String truststoreAlgorithm = null; |
| public String getTruststoreAlgorithm() {return truststoreAlgorithm;} |
| public void setTruststoreAlgorithm(String truststoreAlgorithm) { |
| this.truststoreAlgorithm = truststoreAlgorithm; |
| } |
| |
| private String trustManagerClassName = null; |
| public String getTrustManagerClassName() {return trustManagerClassName;} |
| public void setTrustManagerClassName(String trustManagerClassName) { |
| this.trustManagerClassName = trustManagerClassName; |
| } |
| |
| private String crlFile = null; |
| public String getCrlFile() {return crlFile;} |
| public void setCrlFile(String crlFile) { |
| this.crlFile = crlFile; |
| } |
| |
| private String trustMaxCertLength = null; |
| public String getTrustMaxCertLength() {return trustMaxCertLength;} |
| public void setTrustMaxCertLength(String trustMaxCertLength) { |
| this.trustMaxCertLength = trustMaxCertLength; |
| } |
| |
| private String sessionCacheSize = null; |
| public String getSessionCacheSize() { return sessionCacheSize;} |
| public void setSessionCacheSize(String s) { sessionCacheSize = s;} |
| |
| private String sessionTimeout = "86400"; |
| public String getSessionTimeout() { return sessionTimeout;} |
| public void setSessionTimeout(String s) { sessionTimeout = s;} |
| |
| private String allowUnsafeLegacyRenegotiation = null; |
| public String getAllowUnsafeLegacyRenegotiation() { |
| return allowUnsafeLegacyRenegotiation; |
| } |
| public void setAllowUnsafeLegacyRenegotiation(String s) { |
| allowUnsafeLegacyRenegotiation = s; |
| } |
| |
| |
| private String[] sslEnabledProtocolsarr = new String[0]; |
| public String[] getSslEnabledProtocolsArray() { |
| return this.sslEnabledProtocolsarr; |
| } |
| public void setSslEnabledProtocols(String s) { |
| if (s == null) { |
| this.sslEnabledProtocolsarr = new String[0]; |
| } else { |
| ArrayList<String> sslEnabledProtocols = new ArrayList<String>(); |
| StringTokenizer t = new StringTokenizer(s,","); |
| while (t.hasMoreTokens()) { |
| String p = t.nextToken().trim(); |
| if (p.length() > 0) { |
| sslEnabledProtocols.add(p); |
| } |
| } |
| sslEnabledProtocolsarr = sslEnabledProtocols.toArray( |
| new String[sslEnabledProtocols.size()]); |
| } |
| } |
| |
| } |
| |