Fail SSL Handshake if no supported Application Protocols

Motivation:
The ALPN API does not support the no_application_protocol alert as defined in http://tools.ietf.org/html/rfc7301#section-3.2.  This API also does not support the MAY clause defined in http://tools.ietf.org/html/rfc7301#section-3.1.

Modifications:
-Allow ALPN.ServerProvider.select to return null and throw SSLException.
-Allow ALPN.ClientProvider.selected to throw an SSLException
-Clarify usage example in comments
-Update ALPN map from synchronizedMap to ConcurrentHashMap

Result:
-API supports failure modes described in ALPN RFC http://tools.ietf.org/html/rfc7301.

Bug: 446063
Signed-off-by: Scott Mitchell <scott.k.mitch1@gmail.com>
diff --git a/src/main/java/org/eclipse/jetty/alpn/ALPN.java b/src/main/java/org/eclipse/jetty/alpn/ALPN.java
index 6a70617..1d85e5d 100644
--- a/src/main/java/org/eclipse/jetty/alpn/ALPN.java
+++ b/src/main/java/org/eclipse/jetty/alpn/ALPN.java
@@ -18,11 +18,12 @@
 
 package org.eclipse.jetty.alpn;
 
-import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
 import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLException;
 import javax.net.ssl.SSLSocket;
 
 /**
@@ -47,16 +48,10 @@
  * <p/>
  * Client side typical usage:
  * <pre>
- * SSLSocket sslSocket = ...;
+ * final SSLSocket sslSocket = ...;
  * ALPN.put(sslSocket, new ALPN.ClientProvider()
  * {
  *     &#64;Override
- *     public boolean supports()
- *     {
- *         return true;
- *     }
- *
- *     &#64;Override
  *     public List&lt;String&gt; protocols()
  *     {
  *         return Arrays.asList("spdy/3", "http/1.1");
@@ -65,28 +60,32 @@
  *     &#64;Override
  *     public void unsupported()
  *     {
+ *         ALPN.remove(sslSocket);
  *     }
  *
  *     &#64;Override
  *     public void selected(String protocol)
  *     {
  *         System.out.println("Selected protocol: " + protocol);
+ *         ALPN.remove(sslSocket);
  *     }
  *  });
  * </pre>
  * Server side typical usage:
  * <pre>
- * SSLSocket sslSocket = ...;
+ * final SSLSocket sslSocket = ...;
  * ALPN.put(sslSocket, new ALPN.ServerProvider()
  * {
  *     &#64;Override
  *     public void unsupported()
  *     {
+ *         ALPN.remove(sslSocket);
  *     }
  *
  *     &#64;Override
  *     public String select(List&lt;String&gt; protocols)
  *     {
+ *         ALPN.remove(sslSocket);
  *         return protocols.get(0);
  *     }
  *  });
@@ -106,7 +105,7 @@
      */
     public static boolean debug = false;
 
-    private static Map<Object, Provider> objects = Collections.synchronizedMap(new HashMap<Object, Provider>());
+    private static Map<Object, Provider> objects = new ConcurrentHashMap<Object, Provider>();
 
     private ALPN()
     {
@@ -192,14 +191,6 @@
     public interface ClientProvider extends Provider
     {
         /**
-         * Callback invoked to let the implementation know whether an
-         * ALPN extension should be added to a ClientHello TLS message.
-         *
-         * @return true to add the ALPN extension, false otherwise
-         */
-        public boolean supports();
-
-        /**
          * Callback invoked to let the implementation know the list
          * of protocols that should be added to the ALPN extension in
          * a ClientHello TLS message.
@@ -208,7 +199,7 @@
          * returned true.
          *
          * @return the list of protocols supported by the client;
-         * if null or empty, the ALPN extension is not sent
+         * if {@code null} or empty, the ALPN extension is not sent
          */
         public List<String> protocols();
 
@@ -222,7 +213,10 @@
          * Callback invoked to let the client application know
          * the protocol chosen by the server.
          *
-         * @param protocol the protocol selected by the server
+         * @param protocol the protocol selected by the server.
+         * @throws Throwable This may be thrown if the selected protocol
+         * is not acceptable and the desired behavior is to fail the handshake
+         * with an alert type of {@code no_application_protocol(120)}.
          */
         public void selected(String protocol);
     }
@@ -244,8 +238,14 @@
          * a protocol among the ones sent by the client.
          *
          * @param protocols the protocols sent by the client
-         * @return the protocol selected by the server application;
-         * must not be null
+         * @return the protocol selected by the server application.
+         * A {@code null} value will indicate the server will not
+         * include the {@code ALPN extension} message in the {@code ServerHello}
+         * message.  This means the server appears as though it doesn't support
+         * ALPN and lets the client decide how to handle the situation.
+         * @throws Throwable This may be thrown if no matching protocols
+         * are detected and the desired behavior is to fail the handshake
+         * with an alert type of {@code no_application_protocol(120)}.
          */
         public String select(List<String> protocols);
     }