8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package jdk.net;
27
28 import java.net.SocketOption;
29
30 /**
31 * Defines extended socket options, beyond those defined in
32 * {@link java.net.StandardSocketOptions}. These options may be platform
33 * specific.
34 *
35 * @since 1.8
36 */
37 public final class ExtendedSocketOptions {
38
39 private static class ExtSocketOption<T> implements SocketOption<T> {
40 private final String name;
41 private final Class<T> type;
42 ExtSocketOption(String name, Class<T> type) {
43 this.name = name;
44 this.type = type;
45 }
46 @Override public String name() { return name; }
47 @Override public Class<T> type() { return type; }
48 @Override public String toString() { return name; }
49 }
50
51 private ExtendedSocketOptions() {}
52
53 /**
54 * Service level properties. When a security manager is installed,
55 * setting or getting this option requires a {@link NetworkPermission}
56 * {@code ("setOption.SO_FLOW_SLA")} or {@code "getOption.SO_FLOW_SLA"}
57 * respectively.
58 */
59 public static final SocketOption<SocketFlow> SO_FLOW_SLA = new
60 ExtSocketOption<SocketFlow>("SO_FLOW_SLA", SocketFlow.class);
61 }
|
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package jdk.net;
27
28 import java.io.FileDescriptor;
29 import java.net.SocketException;
30 import java.net.SocketOption;
31 import java.security.AccessController;
32 import java.security.PrivilegedAction;
33 import java.util.Collections;
34 import java.util.Set;
35 import jdk.internal.misc.JavaIOFileDescriptorAccess;
36 import jdk.internal.misc.SharedSecrets;
37
38 /**
39 * Defines extended socket options, beyond those defined in
40 * {@link java.net.StandardSocketOptions}. These options may be platform
41 * specific.
42 *
43 * @since 1.8
44 */
45 public final class ExtendedSocketOptions {
46
47 private static class ExtSocketOption<T> implements SocketOption<T> {
48 private final String name;
49 private final Class<T> type;
50 ExtSocketOption(String name, Class<T> type) {
51 this.name = name;
52 this.type = type;
53 }
54 @Override public String name() { return name; }
55 @Override public Class<T> type() { return type; }
56 @Override public String toString() { return name; }
57 }
58
59 private ExtendedSocketOptions() { }
60
61 /**
62 * Service level properties. When a security manager is installed,
63 * setting or getting this option requires a {@link NetworkPermission}
64 * {@code ("setOption.SO_FLOW_SLA")} or {@code "getOption.SO_FLOW_SLA"}
65 * respectively.
66 */
67 public static final SocketOption<SocketFlow> SO_FLOW_SLA = new
68 ExtSocketOption<SocketFlow>("SO_FLOW_SLA", SocketFlow.class);
69
70
71 private static final PlatformSocketOptions platformSocketOptions =
72 PlatformSocketOptions.get();
73
74 private static final boolean flowSupported =
75 platformSocketOptions.flowSupported();
76
77 private static final Set<SocketOption<?>> extendedOptions = options();
78
79 static Set<SocketOption<?>> options() {
80 if (flowSupported)
81 return Set.of(SO_FLOW_SLA);
82 else
83 return Collections.unmodifiableSet(Collections.<SocketOption<?>>emptySet());
84 }
85
86 static {
87 // Registers the extended socket options with the base module.
88 sun.net.ext.ExtendedSocketOptions.register(
89 new sun.net.ext.ExtendedSocketOptions(extendedOptions) {
90
91 @Override
92 public void setOption(FileDescriptor fd,
93 SocketOption<?> option,
94 Object value)
95 throws SocketException
96 {
97 SecurityManager sm = System.getSecurityManager();
98 if (sm != null)
99 sm.checkPermission(new NetworkPermission("setOption." + option.name()));
100
101 if (fd == null || !fd.valid())
102 throw new SocketException("socket closed");
103
104 if (option == SO_FLOW_SLA) {
105 assert flowSupported;
106 SocketFlow flow = checkValueType(value, option.type());
107 setFlowOption(fd, flow);
108 } else {
109 throw new InternalError("Unexpected option " + option);
110 }
111 }
112
113 @Override
114 public Object getOption(FileDescriptor fd,
115 SocketOption<?> option)
116 throws SocketException
117 {
118 SecurityManager sm = System.getSecurityManager();
119 if (sm != null)
120 sm.checkPermission(new NetworkPermission("getOption." + option.name()));
121
122 if (fd == null || !fd.valid())
123 throw new SocketException("socket closed");
124
125 if (option == SO_FLOW_SLA) {
126 assert flowSupported;
127 SocketFlow flow = SocketFlow.create();
128 getFlowOption(fd, flow);
129 return flow;
130 } else {
131 throw new InternalError("Unexpected option " + option);
132 }
133 }
134 });
135 }
136
137 @SuppressWarnings("unchecked")
138 private static <T> T checkValueType(Object value, Class<?> type) {
139 if (!type.isAssignableFrom(value.getClass())) {
140 String s = "Found: " + value.getClass() + ", Expected: " + type;
141 throw new IllegalArgumentException(s);
142 }
143 return (T) value;
144 }
145
146 private static final JavaIOFileDescriptorAccess fdAccess =
147 SharedSecrets.getJavaIOFileDescriptorAccess();
148
149 private static void setFlowOption(FileDescriptor fd, SocketFlow f)
150 throws SocketException
151 {
152 int status = platformSocketOptions.setFlowOption(fdAccess.get(fd),
153 f.priority(),
154 f.bandwidth());
155 f.status(status); // augment the given flow with the status
156 }
157
158 private static void getFlowOption(FileDescriptor fd, SocketFlow f)
159 throws SocketException
160 {
161 int status = platformSocketOptions.getFlowOption(fdAccess.get(fd), f);
162 f.status(status); // augment the given flow with the status
163 }
164
165 static class PlatformSocketOptions {
166
167 protected PlatformSocketOptions() {}
168
169 @SuppressWarnings("unchecked")
170 private static PlatformSocketOptions newInstance(String cn) {
171 Class<PlatformSocketOptions> c;
172 try {
173 c = (Class<PlatformSocketOptions>)Class.forName(cn);
174 return c.getConstructor(new Class<?>[] { }).newInstance();
175 } catch (ReflectiveOperationException x) {
176 throw new AssertionError(x);
177 }
178 }
179
180 private static PlatformSocketOptions create() {
181 String osname = AccessController.doPrivileged(
182 new PrivilegedAction<String>() {
183 public String run() {
184 return System.getProperty("os.name");
185 }
186 });
187 if ("SunOS".equals(osname))
188 return newInstance("jdk.net.SolarisSocketOptions");
189 return new PlatformSocketOptions();
190 }
191
192 private static final PlatformSocketOptions instance = create();
193
194 static PlatformSocketOptions get() {
195 return instance;
196 }
197
198 int setFlowOption(int fd, int priority, long bandwidth)
199 throws SocketException
200 {
201 throw new UnsupportedOperationException("unsupported socket option");
202 }
203
204 int getFlowOption(int fd, SocketFlow f) throws SocketException {
205 throw new UnsupportedOperationException("unsupported socket option");
206 }
207
208 boolean flowSupported() {
209 return false;
210 }
211 }
212 }
|