1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.bootstrap;
17
18 import io.netty.util.internal.SystemPropertyUtil;
19 import io.netty.util.internal.logging.InternalLogger;
20 import io.netty.util.internal.logging.InternalLoggerFactory;
21
22 import java.lang.ref.WeakReference;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.Comparator;
27 import java.util.List;
28 import java.util.ServiceLoader;
29
30
31
32
33 abstract class ChannelInitializerExtensions {
34 private static final InternalLogger logger = InternalLoggerFactory.getInstance(ChannelInitializerExtensions.class);
35 private static volatile ChannelInitializerExtensions implementation;
36
37 private ChannelInitializerExtensions() {
38 }
39
40
41
42
43
44
45 static ChannelInitializerExtensions getExtensions() {
46 ChannelInitializerExtensions impl = implementation;
47 if (impl == null) {
48 synchronized (ChannelInitializerExtensions.class) {
49 impl = implementation;
50 if (impl != null) {
51 return impl;
52 }
53 String extensionProp = SystemPropertyUtil.get(ChannelInitializerExtension.EXTENSIONS_SYSTEM_PROPERTY);
54 logger.debug("-Dio.netty.bootstrap.extensions: {}", extensionProp);
55 if ("serviceload".equalsIgnoreCase(extensionProp)) {
56 impl = new ServiceLoadingExtensions(true);
57 } else if ("log".equalsIgnoreCase(extensionProp)) {
58 impl = new ServiceLoadingExtensions(false);
59 } else {
60 impl = new EmptyExtensions();
61 }
62 implementation = impl;
63 }
64 }
65 return impl;
66 }
67
68
69
70
71 abstract Collection<ChannelInitializerExtension> extensions(ClassLoader cl);
72
73 private static final class EmptyExtensions extends ChannelInitializerExtensions {
74 @Override
75 Collection<ChannelInitializerExtension> extensions(ClassLoader cl) {
76 return Collections.emptyList();
77 }
78 }
79
80 private static final class ServiceLoadingExtensions extends ChannelInitializerExtensions {
81 private final boolean loadAndCache;
82
83 private WeakReference<ClassLoader> classLoader;
84 private Collection<ChannelInitializerExtension> extensions;
85
86 ServiceLoadingExtensions(boolean loadAndCache) {
87 this.loadAndCache = loadAndCache;
88 }
89
90 @SuppressWarnings("AssignmentOrReturnOfFieldWithMutableType")
91 @Override
92 synchronized Collection<ChannelInitializerExtension> extensions(ClassLoader cl) {
93 ClassLoader configured = classLoader == null ? null : classLoader.get();
94 if (configured == null || configured != cl) {
95 Collection<ChannelInitializerExtension> loaded = serviceLoadExtensions(loadAndCache, cl);
96 classLoader = new WeakReference<ClassLoader>(cl);
97 extensions = loadAndCache ? loaded : Collections.<ChannelInitializerExtension>emptyList();
98 }
99 return extensions;
100 }
101
102 private static Collection<ChannelInitializerExtension> serviceLoadExtensions(boolean load, ClassLoader cl) {
103 List<ChannelInitializerExtension> extensions = new ArrayList<ChannelInitializerExtension>();
104
105 ServiceLoader<ChannelInitializerExtension> loader = ServiceLoader.load(
106 ChannelInitializerExtension.class, cl);
107 for (ChannelInitializerExtension extension : loader) {
108 extensions.add(extension);
109 }
110
111 if (!extensions.isEmpty()) {
112 Collections.sort(extensions, new Comparator<ChannelInitializerExtension>() {
113 @Override
114 public int compare(ChannelInitializerExtension a, ChannelInitializerExtension b) {
115 return Double.compare(a.priority(), b.priority());
116 }
117 });
118 logger.info("ServiceLoader {}(s) {}: {}", ChannelInitializerExtension.class.getSimpleName(),
119 load ? "registered" : "detected", extensions);
120 return Collections.unmodifiableList(extensions);
121 }
122 logger.debug("ServiceLoader {}(s) {}: []", ChannelInitializerExtension.class.getSimpleName(),
123 load ? "registered" : "detected");
124 return Collections.emptyList();
125 }
126 }
127 }