1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.server;
20
21 import java.util.ArrayList;
22 import java.util.Iterator;
23 import java.util.List;
24
25 import javax.net.ssl.SSLEngine;
26
27 import org.eclipse.jetty.io.AbstractConnection;
28 import org.eclipse.jetty.io.Connection;
29 import org.eclipse.jetty.io.EndPoint;
30 import org.eclipse.jetty.io.ssl.SslConnection;
31
32 public abstract class NegotiatingServerConnectionFactory extends AbstractConnectionFactory
33 {
34 public static void checkProtocolNegotiationAvailable()
35 {
36 if (!isAvailableInBootClassPath("org.eclipse.jetty.alpn.ALPN"))
37 throw new IllegalStateException("No ALPN classes available");
38 }
39
40 private static boolean isAvailableInBootClassPath(String className)
41 {
42 try
43 {
44 Class<?> klass = ClassLoader.getSystemClassLoader().loadClass(className);
45 if (klass.getClassLoader() != null)
46 throw new IllegalStateException(className + " must be on JVM boot classpath");
47 return true;
48 }
49 catch (ClassNotFoundException x)
50 {
51 return false;
52 }
53 }
54
55 private final List<String> negotiatedProtocols;
56 private String defaultProtocol;
57
58 public NegotiatingServerConnectionFactory(String protocol, String... negotiatedProtocols)
59 {
60 super(protocol);
61 this.negotiatedProtocols = new ArrayList<>();
62 if (negotiatedProtocols != null)
63 {
64
65 for (String p : negotiatedProtocols)
66 {
67 p = p.trim();
68 if (!p.isEmpty())
69 this.negotiatedProtocols.add(p.trim());
70 }
71 }
72 }
73
74 public String getDefaultProtocol()
75 {
76 return defaultProtocol;
77 }
78
79 public void setDefaultProtocol(String defaultProtocol)
80 {
81
82 String dft = defaultProtocol == null ? "" : defaultProtocol.trim();
83 this.defaultProtocol = dft.isEmpty() ? null : dft;
84 }
85
86 public List<String> getNegotiatedProtocols()
87 {
88 return negotiatedProtocols;
89 }
90
91 @Override
92 public Connection newConnection(Connector connector, EndPoint endPoint)
93 {
94 List<String> negotiated = this.negotiatedProtocols;
95 if (negotiated.isEmpty())
96 {
97
98 negotiated = new ArrayList<>(connector.getProtocols());
99 for (Iterator<String> i = negotiated.iterator();i.hasNext();)
100 {
101 String protocol = i.next();
102
103 ConnectionFactory f = connector.getConnectionFactory(protocol);
104
105 if ((f instanceof SslConnectionFactory) ||
106 (f instanceof NegotiatingServerConnectionFactory))
107 {
108 i.remove();
109 }
110 }
111 }
112
113
114 String dft = defaultProtocol;
115 if (dft == null && !negotiated.isEmpty())
116 dft = negotiated.get(0);
117
118 SSLEngine engine = null;
119 EndPoint ep = endPoint;
120 while (engine == null && ep != null)
121 {
122
123 if (ep instanceof SslConnection.DecryptedEndPoint)
124 engine = ((SslConnection.DecryptedEndPoint)ep).getSslConnection().getSSLEngine();
125 else
126 ep = null;
127 }
128
129 return configure(newServerConnection(connector, endPoint, engine, negotiated, dft), connector, endPoint);
130 }
131
132 protected abstract AbstractConnection newServerConnection(Connector connector, EndPoint endPoint, SSLEngine engine, List<String> protocols, String defaultProtocol);
133
134 @Override
135 public String toString()
136 {
137 return String.format("%s@%x{%s,%s,%s}", getClass().getSimpleName(), hashCode(), getProtocols(), getDefaultProtocol(), getNegotiatedProtocols());
138 }
139 }