test/jdk/com/sun/jndi/ldap/lib/BaseLdapServer.java
author xyin
Mon, 06 May 2019 14:23:32 +0800
branchJDK-8210696-branch
changeset 57351 b9e5f8090688
parent 57346 3efc6cb7ffdb
permissions -rw-r--r--
JDK-8210696-branch: fix loadCaptureFile exception swallowing
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
57345
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
     1
/*
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
     2
 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
     4
 *
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
     7
 * published by the Free Software Foundation.
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
     8
 *
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    13
 * accompanied this code).
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    14
 *
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    18
 *
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    20
 * or visit www.oracle.com if you need additional information or have any
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    21
 * questions.
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    22
 */
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    23
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    24
import java.io.ByteArrayOutputStream;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    25
import java.io.Closeable;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    26
import java.io.IOException;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    27
import java.io.InputStream;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    28
import java.io.OutputStream;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    29
import java.net.InetAddress;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    30
import java.net.ServerSocket;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    31
import java.net.Socket;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    32
import java.util.ArrayList;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    33
import java.util.Arrays;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    34
import java.util.HashSet;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    35
import java.util.List;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    36
import java.util.Objects;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    37
import java.util.Set;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    38
import java.util.concurrent.ExecutorService;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    39
import java.util.concurrent.Executors;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    40
import java.util.concurrent.RejectedExecutionException;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    41
import java.util.concurrent.ThreadFactory;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    42
import java.util.concurrent.TimeUnit;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    43
import java.util.stream.Stream;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    44
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    45
import static java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    46
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    47
/**
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    48
 * A base dummy ldap server.
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    49
 *
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    50
 * For any ldap tests which required a simple dummy server to support the
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    51
 * test, may use this server directly with specifying ConnectionHandler,
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    52
 * SessionHandler/RequestHandler, or extends to build more complex server logic.
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    53
 *
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    54
 * This server already extends Thread and implements AutoCloseable, so it can
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    55
 * be started in thread and integrated with try-with-resources
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    56
 *
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    57
 * To initiate a instance of this server, valid ServerSocket could be supplied,
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    58
 * it will allow the flexibility for listening address/port customization
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    59
 * and SSL usage, for default no parameter constructor, a ServerSocket which
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    60
 * listen on loopback address will be created.
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    61
 *
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    62
 * To use this dummy server in test, user could customize the processing logic
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    63
 * in three level with below handler interface.
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    64
 *   -ConnectionHandler provide connection level handling, server will hand
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    65
 *                      over accepted socket and processing thread to handler.
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    66
 *                      By default, DefaultConnectionHandler will be used if no
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    67
 *                      specified, it reads full ldap request message then
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    68
 *                      pass it to RequestHandler instance which returned by
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    69
 *                      SessionHandler per session.
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    70
 *
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    71
 *   -SessionHandler    provide session level handling when DefaultConnectionHandler
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    72
 *                      been used, it's to retrieve RequestHandler instance of
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    73
 *                      current session.
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    74
 *                      For most of tests, only one session need to be handled
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    75
 *                      on server or all ldap request could be handled by same
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    76
 *                      logic whatever current session is, user can use
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    77
 *                      setCommonRequestHandler to setup one single session
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    78
 *                      handler which will always return given RequestHandler
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    79
 *                      instance.
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    80
 *
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    81
 *   -RequestHandler    provide ldap message request handling when
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    82
 *                      DefaultConnectionHandler been used.
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    83
 *
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    84
 * @see ConnectionHandler
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    85
 * @see SessionHandler
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    86
 * @see RequestHandler
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    87
 */
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    88
public class BaseLdapServer extends Thread implements AutoCloseable {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    89
    private volatile boolean isRunning;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    90
    private final List<Socket> socketList = new ArrayList<>();
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    91
    private ServerSocket serverSocket;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    92
    private ExecutorService workingPool;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    93
    private ConnectionHandler connectionHandler;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    94
    private SessionHandler sessionHandler;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    95
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    96
    enum DebugLevel {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    97
        FULL,      // all debug message will be printed
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    98
        NONE,      // none of debug message will be printed
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
    99
        CUSTOMIZE  // only specified class debug message will be printed
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   100
    }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   101
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   102
    private StackWalker stackWalker = null;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   103
    private DebugLevel debugLevel = DebugLevel.NONE;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   104
    private Set<Class<?>> debugOptions = new HashSet<>();
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   105
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   106
    /**
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   107
     * BaseLdapServer overload default constructor.
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   108
     *
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   109
     * @throws IOException if an I/O error occurs when opening the socket.
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   110
     */
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   111
    public BaseLdapServer() throws IOException {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   112
        this(new ServerSocket(0, 0, InetAddress.getLoopbackAddress()));
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   113
    }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   114
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   115
    /**
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   116
     * BaseLdapServer constructor with given server socket and specify whether
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   117
     * use daemon for each accept connection handling thread.
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   118
     *
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   119
     * @param serverSocket    given server socket
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   120
     */
57346
3efc6cb7ffdb Removed the daemon-threads-based ExecutorService
prappo
parents: 57345
diff changeset
   121
    public BaseLdapServer(ServerSocket serverSocket) {
57345
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   122
        this.serverSocket = Objects.requireNonNull(serverSocket);
57346
3efc6cb7ffdb Removed the daemon-threads-based ExecutorService
prappo
parents: 57345
diff changeset
   123
        workingPool = Executors.newCachedThreadPool();
57345
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   124
        try {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   125
            stackWalker = StackWalker.getInstance(RETAIN_CLASS_REFERENCE);
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   126
        } catch (SecurityException se) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   127
            // just ignore
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   128
        }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   129
    }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   130
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   131
    @Override
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   132
    public void run() {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   133
        if (getConnectionHandler() == null) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   134
            debug("INFO: No connection handler been specified, try default.");
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   135
            connectionHandler = new DefaultConnectionHandler();
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   136
        }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   137
        debug("INFO: Using connection handler : " + getConnectionHandler()
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   138
                .getClass().getName());
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   139
        debug("INFO: LdapServer running and listening on port " + getPort());
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   140
        try {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   141
            while (isRunning) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   142
                Socket socket = serverSocket.accept();
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   143
                debug("INFO: Accept new connection " + socket);
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   144
                synchronized (socketList) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   145
                    socketList.add(socket);
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   146
                }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   147
                workingPool.submit(() -> getConnectionHandler()
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   148
                        .handleConnection(socket));
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   149
            }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   150
        } catch (IOException | RejectedExecutionException e) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   151
            if (isRunning) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   152
                throw new RuntimeException(e);
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   153
            } else {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   154
                debug("INFO: Server exit.");
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   155
            }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   156
        }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   157
    }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   158
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   159
    /*
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   160
     * Override Thread.start()
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   161
     */
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   162
    @Override
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   163
    public synchronized void start() {
57351
b9e5f8090688 JDK-8210696-branch: fix loadCaptureFile exception swallowing
xyin
parents: 57346
diff changeset
   164
        isRunning = true;
57345
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   165
        super.start();
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   166
    }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   167
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   168
    /**
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   169
     * Start Server thread and return itself for method chaining
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   170
     *
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   171
     * @return current server instance
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   172
     */
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   173
    @SuppressWarnings("unchecked")
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   174
    public <T extends BaseLdapServer> T startServer() {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   175
        start();
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   176
        return (T) this;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   177
    }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   178
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   179
    /**
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   180
     * Stop server.
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   181
     */
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   182
    public void stopServer() {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   183
        debug("INFO: Stopping Server.");
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   184
        isRunning = false;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   185
        workingPool.shutdown();
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   186
        cleanupClosableRes(serverSocket);
57346
3efc6cb7ffdb Removed the daemon-threads-based ExecutorService
prappo
parents: 57345
diff changeset
   187
        // let's cleanup thread pool
3efc6cb7ffdb Removed the daemon-threads-based ExecutorService
prappo
parents: 57345
diff changeset
   188
        synchronized (socketList) {
3efc6cb7ffdb Removed the daemon-threads-based ExecutorService
prappo
parents: 57345
diff changeset
   189
            socketList.forEach(BaseLdapServer::cleanupClosableRes);
3efc6cb7ffdb Removed the daemon-threads-based ExecutorService
prappo
parents: 57345
diff changeset
   190
        }
3efc6cb7ffdb Removed the daemon-threads-based ExecutorService
prappo
parents: 57345
diff changeset
   191
        try {
3efc6cb7ffdb Removed the daemon-threads-based ExecutorService
prappo
parents: 57345
diff changeset
   192
            if (!workingPool.awaitTermination(10, TimeUnit.SECONDS)) {
3efc6cb7ffdb Removed the daemon-threads-based ExecutorService
prappo
parents: 57345
diff changeset
   193
                workingPool.shutdownNow();
57345
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   194
            }
57346
3efc6cb7ffdb Removed the daemon-threads-based ExecutorService
prappo
parents: 57345
diff changeset
   195
        } catch (InterruptedException e) {
3efc6cb7ffdb Removed the daemon-threads-based ExecutorService
prappo
parents: 57345
diff changeset
   196
            workingPool.shutdownNow();
3efc6cb7ffdb Removed the daemon-threads-based ExecutorService
prappo
parents: 57345
diff changeset
   197
            Thread.currentThread().interrupt();
57345
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   198
        }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   199
    }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   200
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   201
    /**
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   202
     * Return local port which server is listening.
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   203
     *
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   204
     * @return port which server is listening
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   205
     */
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   206
    public int getPort() {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   207
        if (serverSocket != null) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   208
            return serverSocket.getLocalPort();
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   209
        } else {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   210
            return -1;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   211
        }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   212
    }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   213
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   214
    /**
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   215
     * Return flag to indicate whether current server is running.
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   216
     *
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   217
     * @return <tt>true</tt> if current server is running.
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   218
     */
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   219
    public boolean isRunning() {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   220
        return isRunning;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   221
    }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   222
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   223
    /**
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   224
     * Return ConnectionHandler instance
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   225
     *
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   226
     * @return ConnectionHandler instance
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   227
     * @see ConnectionHandler
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   228
     */
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   229
    ConnectionHandler getConnectionHandler() {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   230
        return connectionHandler;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   231
    }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   232
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   233
    /**
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   234
     * Set ConnectionHandler when server is not running.
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   235
     *
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   236
     * @param connHandler ConnectionHandler instance
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   237
     * @return current server instance for method chaining
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   238
     */
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   239
    @SuppressWarnings("unchecked")
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   240
    public <T extends BaseLdapServer> T setConnectionHandler(
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   241
            ConnectionHandler connHandler) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   242
        if (!isRunning) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   243
            connectionHandler = connHandler;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   244
        }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   245
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   246
        return (T) this;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   247
    }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   248
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   249
    /**
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   250
     * Return SessionHandler instance
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   251
     *
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   252
     * @return SessionHandler instance
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   253
     * @see SessionHandler
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   254
     */
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   255
    SessionHandler getSessionHandler() {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   256
        return sessionHandler;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   257
    }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   258
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   259
    /**
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   260
     * Set SessionHandler when server is not running.
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   261
     *
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   262
     * @param sessionHandler given SessionHandler
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   263
     * @return current server instance for method chaining
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   264
     */
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   265
    @SuppressWarnings("unchecked")
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   266
    public <T extends BaseLdapServer> T setSessionHandler(
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   267
            SessionHandler sessionHandler) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   268
        if (!isRunning) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   269
            this.sessionHandler = sessionHandler;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   270
        }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   271
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   272
        return (T) this;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   273
    }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   274
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   275
    /**
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   276
     * Set one common RequestHandler, it will be used to handle all requests
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   277
     * whatever current session is.
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   278
     *
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   279
     * For most of tests, server only need to handle one session, use this
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   280
     * method will create stateless session handler with given request handler.
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   281
     *
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   282
     * @param requestHandler RequestHandler instance
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   283
     * @return current server instance for method chaining
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   284
     */
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   285
    @SuppressWarnings("unchecked")
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   286
    public <T extends BaseLdapServer> T setCommonRequestHandler(
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   287
            RequestHandler requestHandler) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   288
        if (!isRunning) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   289
            // ignore any session, always return fixed request handler
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   290
            setSessionHandler(socket -> requestHandler);
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   291
        }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   292
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   293
        return (T) this;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   294
    }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   295
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   296
    @Override
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   297
    public void close() {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   298
        stopServer();
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   299
    }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   300
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   301
    /**
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   302
     * Cleanup any given closable resource
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   303
     *
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   304
     * @param res given closable resource
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   305
     */
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   306
    static void cleanupClosableRes(Closeable res) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   307
        if (res != null) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   308
            try {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   309
                res.close();
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   310
            } catch (IOException e) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   311
                // ignore
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   312
            }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   313
        }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   314
    }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   315
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   316
    /**
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   317
     * Set debug level to specify which kinds of debug message will be printed.
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   318
     *
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   319
     * @param debugLevel given debug level
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   320
     * @param opts       given opts if debug level is DebugLevel.CUSTOMIZE
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   321
     * @return current server instance for method chaining
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   322
     */
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   323
    @SuppressWarnings("unchecked")
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   324
    public <T extends BaseLdapServer> T setDebugLevel(DebugLevel debugLevel,
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   325
            Class<?>... opts) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   326
        Objects.requireNonNull(debugLevel);
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   327
        if (!isRunning) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   328
            this.debugLevel = debugLevel;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   329
            if (debugLevel == DebugLevel.CUSTOMIZE) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   330
                debugOptions.clear();
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   331
                Stream.of(opts).filter(Objects::nonNull)
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   332
                        .forEach(debugOptions::add);
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   333
            }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   334
        }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   335
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   336
        return (T) this;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   337
    }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   338
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   339
    /**
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   340
     * Print given message if debug enabled.
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   341
     *
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   342
     * @param message given message to print
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   343
     */
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   344
    void debug(String message) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   345
        switch (debugLevel) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   346
            case FULL:
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   347
                System.out.println((stackWalker != null ?
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   348
                        stackWalker.getCallerClass().getName() :
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   349
                        "") + ": " + message);
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   350
                break;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   351
            case CUSTOMIZE:
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   352
                if (stackWalker != null) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   353
                    if (debugOptions.contains(stackWalker.getCallerClass())) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   354
                        System.out.println(
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   355
                                stackWalker.getCallerClass().getName() + ": "
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   356
                                        + message);
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   357
                    }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   358
                }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   359
                break;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   360
            case NONE:
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   361
            default:
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   362
                break;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   363
        }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   364
    }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   365
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   366
    /**
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   367
     * Default connection handler implementation.
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   368
     */
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   369
    class DefaultConnectionHandler implements ConnectionHandler {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   370
        @Override
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   371
        public void handleConnection(Socket socket) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   372
            try (socket;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   373
                    OutputStream out = socket.getOutputStream();
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   374
                    InputStream in = socket.getInputStream()) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   375
                byte[] inBuffer = new byte[1024];
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   376
                int count;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   377
                byte[] request;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   378
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   379
                ByteArrayOutputStream buffer = new ByteArrayOutputStream();
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   380
                int msgLen = -1;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   381
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   382
                while ((count = in.read(inBuffer)) > 0) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   383
                    buffer.write(inBuffer, 0, count);
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   384
                    if (msgLen <= 0) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   385
                        msgLen = getMessageLength(buffer.toByteArray());
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   386
                    }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   387
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   388
                    if (msgLen > 0 && buffer.size() >= msgLen) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   389
                        if (buffer.size() > msgLen) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   390
                            byte[] tmpBuffer = buffer.toByteArray();
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   391
                            request = Arrays.copyOf(tmpBuffer, msgLen);
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   392
                            buffer.reset();
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   393
                            buffer.write(tmpBuffer, msgLen,
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   394
                                    tmpBuffer.length - msgLen);
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   395
                        } else {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   396
                            request = buffer.toByteArray();
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   397
                            buffer.reset();
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   398
                        }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   399
                        msgLen = -1;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   400
                    } else {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   401
                        debug("INFO: request msg not complete, received "
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   402
                                + buffer.size() + ", expected " + msgLen);
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   403
                        continue;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   404
                    }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   405
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   406
                    if (getSessionHandler() != null) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   407
                        var handler = getSessionHandler()
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   408
                                .getRequestHandler(socket);
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   409
                        if (handler != null) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   410
                            debug("INFO: Process request. Session handler : "
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   411
                                    + getSessionHandler()
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   412
                                    + ", Request handler : " + handler);
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   413
                            handler.handleRequest(new LdapMessage(request),
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   414
                                    out);
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   415
                        } else {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   416
                            debug("WARNING: no valid request handler returned from "
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   417
                                    + getSessionHandler() + ", " + socket);
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   418
                        }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   419
                    } else {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   420
                        debug("WARNING: no valid session handler been specified, discard request.");
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   421
                    }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   422
                }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   423
                debug("INFO: Connection Handler exit.");
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   424
            } catch (IOException e) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   425
                if (!isRunning()) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   426
                    debug("INFO: Connection Handler exit : " + e.getMessage());
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   427
                } else {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   428
                    e.printStackTrace();
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   429
                }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   430
            }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   431
        }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   432
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   433
        private int getMessageLength(byte[] encoding) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   434
            if (encoding.length < 2) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   435
                // no enough data to extract msg len, just return -1
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   436
                return -1;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   437
            }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   438
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   439
            if (encoding[0] != 0x30) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   440
                throw new RuntimeException("Error: bad LDAP encoding message: "
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   441
                        + "expected ASN.1 SEQUENCE tag (0x30), encountered "
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   442
                        + encoding[0]);
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   443
            }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   444
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   445
            int len;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   446
            int index = 1;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   447
            int payloadLen = 0;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   448
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   449
            if ((encoding[1] & 0x80) == 0x80) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   450
                len = (encoding[1] & 0x0F);
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   451
                index++;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   452
            } else {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   453
                len = 1;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   454
            }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   455
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   456
            if (len > 4) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   457
                throw new RuntimeException(
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   458
                        "Error: LDAP encoding message payload too large");
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   459
            }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   460
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   461
            if (encoding.length < index + len) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   462
                // additional data required to extract payload len, return -1
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   463
                return -1;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   464
            }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   465
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   466
            for (byte b : Arrays.copyOfRange(encoding, index, index + len)) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   467
                payloadLen = payloadLen << 8 | (b & 0xFF);
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   468
            }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   469
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   470
            if (payloadLen <= 0) {
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   471
                throw new RuntimeException(
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   472
                        "Error: invalid LDAP encoding message length or payload too large");
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   473
            }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   474
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   475
            return index + len + payloadLen;
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   476
        }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   477
    }
ff884a2f247b JDK-8210696-branch: push initial fix change
xyin
parents:
diff changeset
   478
}