1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.forgerock.opendj.examples;
19
20 import static org.forgerock.opendj.ldap.LDAPConnectionFactory.*;
21 import static org.forgerock.opendj.ldap.LDAPListener.*;
22 import static org.forgerock.opendj.ldap.requests.Requests.newSimpleBindRequest;
23
24 import java.io.IOException;
25 import java.util.Collection;
26 import java.util.LinkedList;
27 import java.util.List;
28
29 import org.forgerock.opendj.ldap.ConnectionFactory;
30 import org.forgerock.opendj.ldap.Connections;
31 import org.forgerock.opendj.ldap.ConsistentHashMap;
32 import org.forgerock.opendj.ldap.DN;
33 import org.forgerock.opendj.ldap.LDAPClientContext;
34 import org.forgerock.opendj.ldap.LDAPConnectionFactory;
35 import org.forgerock.opendj.ldap.LDAPListener;
36 import org.forgerock.opendj.ldap.LdapException;
37 import org.forgerock.opendj.ldap.RequestContext;
38 import org.forgerock.opendj.ldap.RequestHandlerFactory;
39 import org.forgerock.opendj.ldap.ServerConnectionFactory;
40 import org.forgerock.opendj.ldap.requests.BindRequest;
41 import org.forgerock.util.Options;
42
43 import com.forgerock.reactive.ServerConnectionFactoryAdapter;
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 public final class Proxy {
66
67
68
69
70
71
72
73
74 public static void main(final String[] args) {
75 if (args.length < 6 || args.length % 2 != 0) {
76 System.err.println("Usage: [--load-balancer <mode>] listenAddress listenPort "
77 + "proxyDN proxyPassword remoteAddress1 remotePort1 remoteAddress2 remotePort2 ...");
78 System.exit(1);
79 }
80
81
82 int i = 0;
83
84 final LoadBalancingAlgorithm algorithm;
85 if ("--load-balancer".equals(args[i])) {
86 algorithm = getLoadBalancingAlgorithm(args[i + 1]);
87 i += 2;
88 } else {
89 algorithm = LoadBalancingAlgorithm.LEAST_REQUESTS;
90 }
91
92 final String localAddress = args[i++];
93 final int localPort = Integer.parseInt(args[i++]);
94
95 final String proxyDN = args[i++];
96 final String proxyPassword = args[i++];
97
98
99
100 final List<ConnectionFactory> factories = new LinkedList<>();
101 final BindRequest bindRequest = newSimpleBindRequest(proxyDN, proxyPassword.toCharArray());
102 final Options factoryOptions = Options.defaultOptions()
103 .set(HEARTBEAT_ENABLED, true)
104 .set(AUTHN_BIND_REQUEST, bindRequest);
105
106 final List<ConnectionFactory> bindFactories = new LinkedList<>();
107 final Options bindFactoryOptions = Options.defaultOptions().set(HEARTBEAT_ENABLED, true);
108
109 for (; i < args.length; i += 2) {
110 final String remoteAddress = args[i];
111 final int remotePort = Integer.parseInt(args[i + 1]);
112
113 factories.add(Connections.newCachedConnectionPool(new LDAPConnectionFactory(remoteAddress,
114 remotePort,
115 factoryOptions)));
116
117 bindFactories.add(Connections.newCachedConnectionPool(new LDAPConnectionFactory(remoteAddress,
118 remotePort,
119 bindFactoryOptions)));
120 }
121
122
123 final ConnectionFactory factory = algorithm.newLoadBalancer(factories, factoryOptions);
124 final ConnectionFactory bindFactory = algorithm.newLoadBalancer(bindFactories, bindFactoryOptions);
125
126
127
128
129
130
131
132 final RequestHandlerFactory<LDAPClientContext, RequestContext> proxyFactory =
133 new RequestHandlerFactory<LDAPClientContext, RequestContext>() {
134 @Override
135 public ProxyBackend handleAccept(LDAPClientContext clientContext)
136 throws LdapException {
137 return new ProxyBackend(factory, bindFactory);
138 }
139 };
140 final ServerConnectionFactory<LDAPClientContext, Integer> connectionHandler =
141 Connections.newServerConnectionFactory(proxyFactory);
142
143
144
145
146 final Options options = Options.defaultOptions().set(CONNECT_MAX_BACKLOG, 4096);
147 LDAPListener listener = null;
148 try {
149 listener = new LDAPListener(localAddress, localPort, new ServerConnectionFactoryAdapter(
150 options.get(LDAP_DECODE_OPTIONS), connectionHandler), options);
151 System.out.println("Press any key to stop the server...");
152 System.in.read();
153 } catch (final IOException e) {
154 System.out.println("Error listening on " + localAddress + ":" + localPort);
155 e.printStackTrace();
156 } finally {
157 if (listener != null) {
158 listener.close();
159 }
160 }
161
162 }
163
164 private static LoadBalancingAlgorithm getLoadBalancingAlgorithm(final String algorithmName) {
165 switch (algorithmName) {
166 case "least-requests":
167 return LoadBalancingAlgorithm.LEAST_REQUESTS;
168 case "fail-over":
169 return LoadBalancingAlgorithm.FAIL_OVER;
170 case "affinity":
171 return LoadBalancingAlgorithm.AFFINITY;
172 case "distribution":
173 return LoadBalancingAlgorithm.DISTRIBUTION;
174 default:
175 System.err.println("Unrecognized load-balancing algorithm '" + algorithmName + "'. Should be one of "
176 + "'least-requests', 'fail-over', 'affinity', or 'distribution'.");
177 System.exit(1);
178 }
179 return LoadBalancingAlgorithm.LEAST_REQUESTS;
180 }
181
182 private enum LoadBalancingAlgorithm {
183 LEAST_REQUESTS {
184 @Override
185 ConnectionFactory newLoadBalancer(final Collection<ConnectionFactory> factories, final Options options) {
186
187 return Connections.newLeastRequestsLoadBalancer(factories, options);
188
189 }
190 },
191 FAIL_OVER {
192 @Override
193 ConnectionFactory newLoadBalancer(final Collection<ConnectionFactory> factories, final Options options) {
194 return Connections.newFailoverLoadBalancer(factories, options);
195 }
196 },
197 AFFINITY {
198 @Override
199 ConnectionFactory newLoadBalancer(final Collection<ConnectionFactory> factories, final Options options) {
200 return Connections.newAffinityRequestLoadBalancer(factories, options);
201 }
202 },
203 DISTRIBUTION {
204 @Override
205 ConnectionFactory newLoadBalancer(final Collection<ConnectionFactory> factories, final Options options) {
206 final ConsistentHashMap<ConnectionFactory> partitions = new ConsistentHashMap<>();
207 int i = 0;
208 for (final ConnectionFactory factory : factories) {
209 partitions.put("partition-" + i++, factory);
210 }
211 return Connections.newFixedSizeDistributionLoadBalancer(DN.valueOf("ou=people,dc=example,dc=com"),
212 partitions,
213 options);
214 }
215 };
216
217 abstract ConnectionFactory newLoadBalancer(Collection<ConnectionFactory> factories, Options options);
218 }
219
220 private Proxy() {
221
222 }
223 }