Skip to content

Commit a425a85

Browse files
committed
[netty#5174] Expose Bootstrap getter methods and add some additional ones
Motivation: The Bootstrap class (applies also to AbstractBootstrap and ServerBootstrap) has a few package private getter methods and some things such as #attr() and #options() aren't exposed at all. Modifications: Expose "getters" for configured things in a safe-manner via the config() method. Result: Easier for the user to check what is configured for a Bootstrap/ServerBootstrap.
1 parent da46928 commit a425a85

6 files changed

Lines changed: 383 additions & 115 deletions

File tree

transport/src/main/java/io/netty/bootstrap/AbstractBootstrap.java

Lines changed: 40 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import java.net.InetAddress;
3636
import java.net.InetSocketAddress;
3737
import java.net.SocketAddress;
38+
import java.util.Collections;
3839
import java.util.LinkedHashMap;
3940
import java.util.Map;
4041

@@ -314,7 +315,7 @@ public void operationComplete(ChannelFuture future) throws Exception {
314315
}
315316

316317
final ChannelFuture initAndRegister() {
317-
final Channel channel = channelFactory().newChannel();
318+
final Channel channel = channelFactory.newChannel();
318319
try {
319320
init(channel);
320321
} catch (Throwable t) {
@@ -376,6 +377,41 @@ public B handler(ChannelHandler handler) {
376377
return (B) this;
377378
}
378379

380+
/**
381+
* Returns the configured {@link EventLoopGroup} or {@code null} if non is configured yet.
382+
*
383+
* @deprecated Use {@link #config()} instead.
384+
*/
385+
@Deprecated
386+
public final EventLoopGroup group() {
387+
return group;
388+
}
389+
390+
/**
391+
* Returns the {@link AbstractBootstrapConfig} object that can be used to obtain the current config
392+
* of the bootstrap.
393+
*/
394+
public abstract AbstractBootstrapConfig<B, C> config();
395+
396+
static <K, V> Map<K, V> copiedMap(Map<K, V> map) {
397+
final Map<K, V> copied;
398+
synchronized (map) {
399+
if (map.isEmpty()) {
400+
return Collections.emptyMap();
401+
}
402+
copied = new LinkedHashMap<K, V>(map);
403+
}
404+
return Collections.unmodifiableMap(copied);
405+
}
406+
407+
final Map<ChannelOption<?>, Object> options0() {
408+
return options;
409+
}
410+
411+
final Map<AttributeKey<?>, Object> attrs0() {
412+
return attrs;
413+
}
414+
379415
final SocketAddress localAddress() {
380416
return localAddress;
381417
}
@@ -389,66 +425,19 @@ final ChannelHandler handler() {
389425
return handler;
390426
}
391427

392-
/**
393-
* Return the configured {@link EventLoopGroup} or {@code null} if non is configured yet.
394-
*/
395-
public EventLoopGroup group() {
396-
return group;
397-
}
398-
399428
final Map<ChannelOption<?>, Object> options() {
400-
return options;
429+
return copiedMap(options);
401430
}
402431

403432
final Map<AttributeKey<?>, Object> attrs() {
404-
return attrs;
433+
return copiedMap(attrs);
405434
}
406435

407436
@Override
408437
public String toString() {
409438
StringBuilder buf = new StringBuilder()
410439
.append(StringUtil.simpleClassName(this))
411-
.append('(');
412-
if (group != null) {
413-
buf.append("group: ")
414-
.append(StringUtil.simpleClassName(group))
415-
.append(", ");
416-
}
417-
if (channelFactory != null) {
418-
buf.append("channelFactory: ")
419-
.append(channelFactory)
420-
.append(", ");
421-
}
422-
if (localAddress != null) {
423-
buf.append("localAddress: ")
424-
.append(localAddress)
425-
.append(", ");
426-
}
427-
synchronized (options) {
428-
if (!options.isEmpty()) {
429-
buf.append("options: ")
430-
.append(options)
431-
.append(", ");
432-
}
433-
}
434-
synchronized (attrs) {
435-
if (!attrs.isEmpty()) {
436-
buf.append("attrs: ")
437-
.append(attrs)
438-
.append(", ");
439-
}
440-
}
441-
if (handler != null) {
442-
buf.append("handler: ")
443-
.append(handler)
444-
.append(", ");
445-
}
446-
if (buf.charAt(buf.length() - 1) == '(') {
447-
buf.append(')');
448-
} else {
449-
buf.setCharAt(buf.length() - 2, ')');
450-
buf.setLength(buf.length() - 1);
451-
}
440+
.append('(').append(config()).append(')');
452441
return buf.toString();
453442
}
454443

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*
2+
* Copyright 2016 The Netty Project
3+
*
4+
* The Netty Project licenses this file to you under the Apache License,
5+
* version 2.0 (the "License"); you may not use this file except in compliance
6+
* with the License. You may obtain a copy of the License at:
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations
14+
* under the License.
15+
*/
16+
package io.netty.bootstrap;
17+
18+
import io.netty.channel.Channel;
19+
import io.netty.channel.ChannelHandler;
20+
import io.netty.channel.ChannelOption;
21+
import io.netty.channel.EventLoopGroup;
22+
import io.netty.util.AttributeKey;
23+
import io.netty.util.internal.ObjectUtil;
24+
import io.netty.util.internal.StringUtil;
25+
26+
import java.net.SocketAddress;
27+
import java.util.Map;
28+
29+
/**
30+
* Exposes the configuration of an {@link AbstractBootstrap}.
31+
*/
32+
public abstract class AbstractBootstrapConfig<B extends AbstractBootstrap<B, C>, C extends Channel> {
33+
34+
protected final B bootstrap;
35+
36+
protected AbstractBootstrapConfig(B bootstrap) {
37+
this.bootstrap = ObjectUtil.checkNotNull(bootstrap, "bootstrap");
38+
}
39+
40+
/**
41+
* Returns the configured local address or {@code null} if non is configured yet.
42+
*/
43+
public final SocketAddress localAddress() {
44+
return bootstrap.localAddress();
45+
}
46+
47+
/**
48+
* Returns the configured {@link ChannelFactory} or {@code null} if non is configured yet.
49+
*/
50+
@SuppressWarnings("deprecation")
51+
public final ChannelFactory<? extends C> channelFactory() {
52+
return bootstrap.channelFactory();
53+
}
54+
55+
/**
56+
* Returns the configured {@link ChannelHandler} or {@code null} if non is configured yet.
57+
*/
58+
public final ChannelHandler handler() {
59+
return bootstrap.handler();
60+
}
61+
62+
/**
63+
* Returns a copy of the configured options.
64+
*/
65+
public final Map<ChannelOption<?>, Object> options() {
66+
return bootstrap.options();
67+
}
68+
69+
/**
70+
* Returns a copy of the configured attributes.
71+
*/
72+
public final Map<AttributeKey<?>, Object> attrs() {
73+
return bootstrap.attrs();
74+
}
75+
76+
/**
77+
* Returns the configured {@link EventLoopGroup} or {@code null} if non is configured yet.
78+
*/
79+
@SuppressWarnings("deprecation")
80+
public final EventLoopGroup group() {
81+
return bootstrap.group();
82+
}
83+
84+
@Override
85+
public String toString() {
86+
StringBuilder buf = new StringBuilder()
87+
.append(StringUtil.simpleClassName(this))
88+
.append('(');
89+
EventLoopGroup group = group();
90+
if (group != null) {
91+
buf.append("group: ")
92+
.append(StringUtil.simpleClassName(group))
93+
.append(", ");
94+
}
95+
@SuppressWarnings("deprecation")
96+
ChannelFactory<? extends C> factory = channelFactory();
97+
if (factory != null) {
98+
buf.append("channelFactory: ")
99+
.append(factory)
100+
.append(", ");
101+
}
102+
SocketAddress localAddress = localAddress();
103+
if (localAddress != null) {
104+
buf.append("localAddress: ")
105+
.append(localAddress)
106+
.append(", ");
107+
}
108+
109+
Map<ChannelOption<?>, Object> options = options();
110+
if (!options.isEmpty()) {
111+
buf.append("options: ")
112+
.append(options)
113+
.append(", ");
114+
}
115+
Map<AttributeKey<?>, Object> attrs = attrs();
116+
if (!attrs.isEmpty()) {
117+
buf.append("attrs: ")
118+
.append(attrs)
119+
.append(", ");
120+
}
121+
ChannelHandler handler = handler();
122+
if (handler != null) {
123+
buf.append("handler: ")
124+
.append(handler)
125+
.append(", ");
126+
}
127+
if (buf.charAt(buf.length() - 1) == '(') {
128+
buf.append(')');
129+
} else {
130+
buf.setCharAt(buf.length() - 2, ')');
131+
buf.setLength(buf.length() - 1);
132+
}
133+
return buf.toString();
134+
}
135+
}

transport/src/main/java/io/netty/bootstrap/Bootstrap.java

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ public class Bootstrap extends AbstractBootstrap<Bootstrap, Channel> {
5353

5454
private static final AddressResolverGroup<?> DEFAULT_RESOLVER = DefaultAddressResolverGroup.INSTANCE;
5555

56+
private final BootstrapConfig config = new BootstrapConfig(this);
57+
5658
@SuppressWarnings("unchecked")
5759
private volatile AddressResolverGroup<SocketAddress> resolver =
5860
(AddressResolverGroup<SocketAddress>) DEFAULT_RESOLVER;
@@ -113,7 +115,7 @@ public ChannelFuture connect() {
113115
throw new IllegalStateException("remoteAddress not set");
114116
}
115117

116-
return doResolveAndConnect(remoteAddress, localAddress());
118+
return doResolveAndConnect(remoteAddress, config.localAddress());
117119
}
118120

119121
/**
@@ -139,7 +141,7 @@ public ChannelFuture connect(SocketAddress remoteAddress) {
139141
}
140142

141143
validate();
142-
return doResolveAndConnect(remoteAddress, localAddress());
144+
return doResolveAndConnect(remoteAddress, config.localAddress());
143145
}
144146

145147
/**
@@ -256,9 +258,9 @@ public void run() {
256258
@SuppressWarnings("unchecked")
257259
void init(Channel channel) throws Exception {
258260
ChannelPipeline p = channel.pipeline();
259-
p.addLast(handler());
261+
p.addLast(config.handler());
260262

261-
final Map<ChannelOption<?>, Object> options = options();
263+
final Map<ChannelOption<?>, Object> options = options0();
262264
synchronized (options) {
263265
for (Entry<ChannelOption<?>, Object> e: options.entrySet()) {
264266
try {
@@ -271,7 +273,7 @@ void init(Channel channel) throws Exception {
271273
}
272274
}
273275

274-
final Map<AttributeKey<?>, Object> attrs = attrs();
276+
final Map<AttributeKey<?>, Object> attrs = attrs0();
275277
synchronized (attrs) {
276278
for (Entry<AttributeKey<?>, Object> e: attrs.entrySet()) {
277279
channel.attr((AttributeKey<Object>) e.getKey()).set(e.getValue());
@@ -282,7 +284,7 @@ void init(Channel channel) throws Exception {
282284
@Override
283285
public Bootstrap validate() {
284286
super.validate();
285-
if (handler() == null) {
287+
if (config.handler() == null) {
286288
throw new IllegalStateException("handler not set");
287289
}
288290
return this;
@@ -306,17 +308,15 @@ public Bootstrap clone(EventLoopGroup group) {
306308
}
307309

308310
@Override
309-
public String toString() {
310-
if (remoteAddress == null) {
311-
return super.toString();
312-
}
311+
public final BootstrapConfig config() {
312+
return config;
313+
}
313314

314-
StringBuilder buf = new StringBuilder(super.toString());
315-
buf.setLength(buf.length() - 1);
315+
final SocketAddress remoteAddress() {
316+
return remoteAddress;
317+
}
316318

317-
return buf.append(", remoteAddress: ")
318-
.append(remoteAddress)
319-
.append(')')
320-
.toString();
319+
final AddressResolverGroup<?> resolver() {
320+
return resolver;
321321
}
322322
}

0 commit comments

Comments
 (0)