1. /*
  2. * @(#)Socket.java 1.55 01/02/09
  3. *
  4. * Copyright 1995-2001 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package java.net;
  11. import java.io.InputStream;
  12. import java.io.OutputStream;
  13. import java.io.IOException;
  14. import java.io.InterruptedIOException;
  15. import java.security.AccessController;
  16. import java.security.PrivilegedExceptionAction;
  17. /**
  18. * This class implements client sockets (also called just
  19. * "sockets"). A socket is an endpoint for communication
  20. * between two machines.
  21. * <p>
  22. * The actual work of the socket is performed by an instance of the
  23. * <code>SocketImpl</code> class. An application, by changing
  24. * the socket factory that creates the socket implementation,
  25. * can configure itself to create sockets appropriate to the local
  26. * firewall.
  27. *
  28. * @author unascribed
  29. * @version 1.55, 02/09/01
  30. * @see java.net.Socket#setSocketImplFactory(java.net.SocketImplFactory)
  31. * @see java.net.SocketImpl
  32. * @since JDK1.0
  33. */
  34. public
  35. class Socket {
  36. /**
  37. * The implementation of this Socket.
  38. */
  39. SocketImpl impl;
  40. /**
  41. * Creates an unconnected socket, with the
  42. * system-default type of SocketImpl.
  43. *
  44. * @since JDK1.1
  45. */
  46. protected Socket() {
  47. impl = (factory != null) ? factory.createSocketImpl() :
  48. new PlainSocketImpl();
  49. }
  50. /**
  51. * Creates an unconnected Socket with a user-specified
  52. * SocketImpl.
  53. * <P>
  54. * @param impl an instance of a <B>SocketImpl</B>
  55. * the subclass wishes to use on the Socket.
  56. *
  57. * @exception SocketException if there is an error in the underlying protocol,
  58. * such as a TCP error.
  59. * @since JDK1.1
  60. */
  61. protected Socket(SocketImpl impl) throws SocketException {
  62. this.impl = impl;
  63. }
  64. /**
  65. * Creates a stream socket and connects it to the specified port
  66. * number on the named host.
  67. * <p>
  68. * If the application has specified a server socket factory, that
  69. * factory's <code>createSocketImpl</code> method is called to create
  70. * the actual socket implementation. Otherwise a "plain" socket is created.
  71. * <p>
  72. * If there is a security manager, its
  73. * <code>checkConnect</code> method is called
  74. * with the host address and <code>port</code>
  75. * as its arguments. This could result in a SecurityException.
  76. *
  77. * @param host the host name.
  78. * @param port the port number.
  79. *
  80. * @exception UnknownHostException if the IP address of
  81. * the host could not be determined.
  82. *
  83. * @exception IOException if an I/O error occurs when creating the socket.
  84. * @exception SecurityException if a security manager exists and its
  85. * <code>checkConnect</code> method doesn't allow the operation.
  86. * @see java.net.Socket#setSocketImplFactory(java.net.SocketImplFactory)
  87. * @see java.net.SocketImpl
  88. * @see java.net.SocketImplFactory#createSocketImpl()
  89. * @see SecurityManager#checkConnect
  90. */
  91. public Socket(String host, int port)
  92. throws UnknownHostException, IOException
  93. {
  94. this(InetAddress.getByName(host), port, null, 0, true);
  95. }
  96. /**
  97. * Creates a stream socket and connects it to the specified port
  98. * number at the specified IP address.
  99. * <p>
  100. * If the application has specified a socket factory, that factory's
  101. * <code>createSocketImpl</code> method is called to create the
  102. * actual socket implementation. Otherwise a "plain" socket is created.
  103. * <p>
  104. * If there is a security manager, its
  105. * <code>checkConnect</code> method is called
  106. * with the host address and <code>port</code>
  107. * as its arguments. This could result in a SecurityException.
  108. *
  109. * @param address the IP address.
  110. * @param port the port number.
  111. * @exception IOException if an I/O error occurs when creating the socket.
  112. * @exception SecurityException if a security manager exists and its
  113. * <code>checkConnect</code> method doesn't allow the operation.
  114. * @see java.net.Socket#setSocketImplFactory(java.net.SocketImplFactory)
  115. * @see java.net.SocketImpl
  116. * @see java.net.SocketImplFactory#createSocketImpl()
  117. * @see SecurityManager#checkConnect
  118. */
  119. public Socket(InetAddress address, int port) throws IOException {
  120. this(address, port, null, 0, true);
  121. }
  122. /**
  123. * Creates a socket and connects it to the specified remote host on
  124. * the specified remote port. The Socket will also bind() to the local
  125. * address and port supplied.
  126. * <p>
  127. * If there is a security manager, its
  128. * <code>checkConnect</code> method is called
  129. * with the host address and <code>port</code>
  130. * as its arguments. This could result in a SecurityException.
  131. *
  132. * @param host the name of the remote host
  133. * @param port the remote port
  134. * @param localAddr the local address the socket is bound to
  135. * @param localPort the local port the socket is bound to
  136. * @exception IOException if an I/O error occurs when creating the socket.
  137. * @exception SecurityException if a security manager exists and its
  138. * <code>checkConnect</code> method doesn't allow the operation.
  139. * @see SecurityManager#checkConnect
  140. * @since JDK1.1
  141. */
  142. public Socket(String host, int port, InetAddress localAddr,
  143. int localPort) throws IOException {
  144. this(InetAddress.getByName(host), port, localAddr, localPort, true);
  145. }
  146. /**
  147. * Creates a socket and connects it to the specified remote address on
  148. * the specified remote port. The Socket will also bind() to the local
  149. * address and port supplied.
  150. * <p>
  151. * If there is a security manager, its
  152. * <code>checkConnect</code> method is called
  153. * with the host address and <code>port</code>
  154. * as its arguments. This could result in a SecurityException.
  155. *
  156. * @param address the remote address
  157. * @param port the remote port
  158. * @param localAddr the local address the socket is bound to
  159. * @param localPort the local port the socket is bound to
  160. * @exception IOException if an I/O error occurs when creating the socket.
  161. * @exception SecurityException if a security manager exists and its
  162. * <code>checkConnect</code> method doesn't allow the operation.
  163. * @see SecurityManager#checkConnect
  164. * @since JDK1.1
  165. */
  166. public Socket(InetAddress address, int port, InetAddress localAddr,
  167. int localPort) throws IOException {
  168. this(address, port, localAddr, localPort, true);
  169. }
  170. /**
  171. * Creates a stream socket and connects it to the specified port
  172. * number on the named host.
  173. * <p>
  174. * If the stream argument is <code>true</code>, this creates a
  175. * stream socket. If the stream argument is <code>false</code>, it
  176. * creates a datagram socket.
  177. * <p>
  178. * If the application has specified a server socket factory, that
  179. * factory's <code>createSocketImpl</code> method is called to create
  180. * the actual socket implementation. Otherwise a "plain" socket is created.
  181. * <p>
  182. * If there is a security manager, its
  183. * <code>checkConnect</code> method is called
  184. * with the host address and <code>port</code>
  185. * as its arguments. This could result in a SecurityException.
  186. *
  187. * @param host the host name.
  188. * @param port the port number.
  189. * @param stream a <code>boolean</code> indicating whether this is
  190. * a stream socket or a datagram socket.
  191. * @exception IOException if an I/O error occurs when creating the socket.
  192. * @exception SecurityException if a security manager exists and its
  193. * <code>checkConnect</code> method doesn't allow the operation.
  194. * @see java.net.Socket#setSocketImplFactory(java.net.SocketImplFactory)
  195. * @see java.net.SocketImpl
  196. * @see java.net.SocketImplFactory#createSocketImpl()
  197. * @see SecurityManager#checkConnect
  198. * @deprecated Use DatagramSocket instead for UDP transport.
  199. */
  200. public Socket(String host, int port, boolean stream) throws IOException {
  201. this(InetAddress.getByName(host), port, null, 0, stream);
  202. }
  203. /**
  204. * Creates a socket and connects it to the specified port number at
  205. * the specified IP address.
  206. * <p>
  207. * If the stream argument is <code>true</code>, this creates a
  208. * stream socket. If the stream argument is <code>false</code>, it
  209. * creates a datagram socket.
  210. * <p>
  211. * If the application has specified a server socket factory, that
  212. * factory's <code>createSocketImpl</code> method is called to create
  213. * the actual socket implementation. Otherwise a "plain" socket is created.
  214. *
  215. * <p>If there is a security manager, its
  216. * <code>checkConnect</code> method is called
  217. * with <code>host.getHostAddress()</code> and <code>port</code>
  218. * as its arguments. This could result in a SecurityException.
  219. *
  220. * @param host the IP address.
  221. * @param port the port number.
  222. * @param stream if <code>true</code>, create a stream socket;
  223. * otherwise, create a datagram socket.
  224. * @exception IOException if an I/O error occurs when creating the socket.
  225. * @exception SecurityException if a security manager exists and its
  226. * <code>checkConnect</code> method doesn't allow the operation.
  227. * @see java.net.Socket#setSocketImplFactory(java.net.SocketImplFactory)
  228. * @see java.net.SocketImpl
  229. * @see java.net.SocketImplFactory#createSocketImpl()
  230. * @see SecurityManager#checkConnect
  231. * @deprecated Use DatagramSocket instead for UDP transport.
  232. */
  233. public Socket(InetAddress host, int port, boolean stream) throws IOException {
  234. this(host, port, null, 0, stream);
  235. }
  236. private Socket(InetAddress address, int port, InetAddress localAddr,
  237. int localPort, boolean stream) throws IOException {
  238. this();
  239. if (port < 0 || port > 0xFFFF) {
  240. throw new IllegalArgumentException("port out range:"+port);
  241. }
  242. if (localPort < 0 || localPort > 0xFFFF) {
  243. throw new IllegalArgumentException("port out range:"+localPort);
  244. }
  245. SecurityManager security = System.getSecurityManager();
  246. if (security != null) {
  247. security.checkConnect(address.getHostAddress(), port);
  248. }
  249. try {
  250. impl.create(stream);
  251. if (localAddr != null || localPort > 0) {
  252. if (localAddr == null) {
  253. localAddr = InetAddress.anyLocalAddress;
  254. }
  255. impl.bind(localAddr, localPort);
  256. }
  257. impl.connect(address, port);
  258. } catch (SocketException e) {
  259. impl.close();
  260. throw e;
  261. }
  262. }
  263. /**
  264. * Returns the address to which the socket is connected.
  265. *
  266. * @return the remote IP address to which this socket is connected.
  267. */
  268. public InetAddress getInetAddress() {
  269. return impl.getInetAddress();
  270. }
  271. /**
  272. * Gets the local address to which the socket is bound.
  273. *
  274. * @return the local address to which the socket is bound.
  275. * @since JDK1.1
  276. */
  277. public InetAddress getLocalAddress() {
  278. InetAddress in = null;
  279. try {
  280. in = (InetAddress) impl.getOption(SocketOptions.SO_BINDADDR);
  281. } catch (Exception e) {
  282. in = InetAddress.anyLocalAddress; // "0.0.0.0"
  283. }
  284. return in;
  285. }
  286. /**
  287. * Returns the remote port to which this socket is connected.
  288. *
  289. * @return the remote port number to which this socket is connected.
  290. */
  291. public int getPort() {
  292. return impl.getPort();
  293. }
  294. /**
  295. * Returns the local port to which this socket is bound.
  296. *
  297. * @return the local port number to which this socket is connected.
  298. */
  299. public int getLocalPort() {
  300. return impl.getLocalPort();
  301. }
  302. /**
  303. * Returns an input stream for this socket.
  304. *
  305. * @return an input stream for reading bytes from this socket.
  306. * @exception IOException if an I/O error occurs when creating the
  307. * input stream.
  308. */
  309. public InputStream getInputStream() throws IOException {
  310. try {
  311. return (InputStream)
  312. AccessController.doPrivileged(new PrivilegedExceptionAction() {
  313. public Object run() throws IOException {
  314. return impl.getInputStream();
  315. }
  316. });
  317. } catch (java.security.PrivilegedActionException e) {
  318. throw (IOException) e.getException();
  319. }
  320. }
  321. /**
  322. * Returns an output stream for this socket.
  323. *
  324. * @return an output stream for writing bytes to this socket.
  325. * @exception IOException if an I/O error occurs when creating the
  326. * output stream.
  327. */
  328. public OutputStream getOutputStream() throws IOException {
  329. try {
  330. return (OutputStream)
  331. AccessController.doPrivileged(new PrivilegedExceptionAction() {
  332. public Object run() throws IOException {
  333. return impl.getOutputStream();
  334. }
  335. });
  336. } catch (java.security.PrivilegedActionException e) {
  337. throw (IOException) e.getException();
  338. }
  339. }
  340. /**
  341. * Enable/disable TCP_NODELAY (disable/enable Nagle's algorithm).
  342. *
  343. * @param on <code>true</code> to enable TCP_NODELAY,
  344. * <code>false</coder> to disable.
  345. *
  346. * @exception SocketException if there is an error
  347. * in the underlying protocol, such as a TCP error.
  348. *
  349. * @since JDK1.1
  350. *
  351. * @see #getTcpNoDelay()
  352. */
  353. public void setTcpNoDelay(boolean on) throws SocketException {
  354. impl.setOption(SocketOptions.TCP_NODELAY, new Boolean(on));
  355. }
  356. /**
  357. * Tests if TCP_NODELAY is enabled.
  358. *
  359. * @return a <code>boolean</code> indicating whether or not TCP_NODELAY is enabled.
  360. * @exception SocketException if there is an error
  361. * in the underlying protocol, such as a TCP error.
  362. * @since JDK1.1
  363. * @see #setTcpNoDelay(boolean)
  364. */
  365. public boolean getTcpNoDelay() throws SocketException {
  366. return ((Boolean) impl.getOption(SocketOptions.TCP_NODELAY)).booleanValue();
  367. }
  368. /**
  369. * Enable/disable SO_LINGER with the specified linger time in seconds.
  370. * The maximum timeout value is platform specific.
  371. *
  372. * The setting only affects socket close.
  373. *
  374. * @param on whether or not to linger on.
  375. * @param linger how to linger for, if on is true.
  376. * @exception SocketException if there is an error
  377. * in the underlying protocol, such as a TCP error.
  378. * @exception IllegalArgumentException if the linger value is negative.
  379. * @since JDK1.1
  380. * @see #getSoLinger()
  381. */
  382. public void setSoLinger(boolean on, int linger) throws SocketException {
  383. if (!on) {
  384. impl.setOption(SocketOptions.SO_LINGER, new Boolean(on));
  385. } else {
  386. if (linger < 0) {
  387. throw new IllegalArgumentException("invalid value for SO_LINGER");
  388. }
  389. if (linger > 65535)
  390. linger = 65535;
  391. impl.setOption(SocketOptions.SO_LINGER, new Integer(linger));
  392. }
  393. }
  394. /**
  395. * Returns setting for SO_LINGER. -1 returns implies that the
  396. * option is disabled.
  397. *
  398. * The setting only affects socket close.
  399. *
  400. * @return the setting for SO_LINGER.
  401. * @exception SocketException if there is an error
  402. * in the underlying protocol, such as a TCP error.
  403. * @since JDK1.1
  404. * @see #setSoLinger(boolean, int)
  405. */
  406. public int getSoLinger() throws SocketException {
  407. Object o = impl.getOption(SocketOptions.SO_LINGER);
  408. if (o instanceof Integer) {
  409. return ((Integer) o).intValue();
  410. } else {
  411. return -1;
  412. }
  413. }
  414. /**
  415. * Enable/disable SO_TIMEOUT with the specified timeout, in
  416. * milliseconds. With this option set to a non-zero timeout,
  417. * a read() call on the InputStream associated with this Socket
  418. * will block for only this amount of time. If the timeout expires,
  419. * a <B>java.io.InterruptedIOException</B> is raised, though the
  420. * Socket is still valid. The option <B>must</B> be enabled
  421. * prior to entering the blocking operation to have effect. The
  422. * timeout must be > 0.
  423. * A timeout of zero is interpreted as an infinite timeout.
  424. * @param timeout the specified timeout, in milliseconds.
  425. * @exception SocketException if there is an error
  426. * in the underlying protocol, such as a TCP error.
  427. * @since JDK 1.1
  428. * @see #getSoTimeout()
  429. */
  430. public synchronized void setSoTimeout(int timeout) throws SocketException {
  431. impl.setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
  432. }
  433. /**
  434. * Returns setting for SO_TIMEOUT. 0 returns implies that the
  435. * option is disabled (i.e., timeout of infinity).
  436. * @return the setting for SO_TIMEOUT
  437. * @exception SocketException if there is an error
  438. * in the underlying protocol, such as a TCP error.
  439. * @since JDK1.1
  440. * @see #setSoTimeout(int)
  441. */
  442. public synchronized int getSoTimeout() throws SocketException {
  443. Object o = impl.getOption(SocketOptions.SO_TIMEOUT);
  444. /* extra type safety */
  445. if (o instanceof Integer) {
  446. return ((Integer) o).intValue();
  447. } else {
  448. return 0;
  449. }
  450. }
  451. /**
  452. * Sets the SO_SNDBUF option to the specified value for this
  453. * <tt>Socket</tt>. The SO_SNDBUF option is used by the platform's
  454. * networking code as a hint for the size to set
  455. * the underlying network I/O buffers.
  456. *
  457. * <p>Increasing buffer size can increase the performance of
  458. * network I/O for high-volume connection, while decreasing it can
  459. * help reduce the backlog of incoming data. For UDP, this sets
  460. * the maximum size of a packet that may be sent on this <tt>Socket</tt>.
  461. *
  462. * <p>Because SO_SNDBUF is a hint, applications that want to
  463. * verify what size the buffers were set to should call
  464. * {@link #getSendBufferSize()}.
  465. *
  466. * @exception SocketException if there is an error
  467. * in the underlying protocol, such as a TCP error.
  468. *
  469. * @param size the size to which to set the send buffer
  470. * size. This value must be greater than 0.
  471. *
  472. * @exception IllegalArgumentException if the
  473. * value is 0 or is negative.
  474. *
  475. * @see #getSendBufferSize()
  476. */
  477. public synchronized void setSendBufferSize(int size)
  478. throws SocketException{
  479. if (!(size > 0)) {
  480. throw new IllegalArgumentException("negative send size");
  481. }
  482. impl.setOption(SocketOptions.SO_SNDBUF, new Integer(size));
  483. }
  484. /**
  485. * Get value of the SO_SNDBUF option for this <tt>Socket</tt>,
  486. * that is the buffer size used by the platform
  487. * for output on this <tt>Socket</tt>.
  488. * @return the value of the SO_SNDBUF option for this <tt>Socket</tt>.
  489. *
  490. * @exception SocketException if there is an error
  491. * in the underlying protocol, such as a TCP error.
  492. *
  493. * @see #setSendBufferSize(int)
  494. */
  495. public synchronized int getSendBufferSize() throws SocketException {
  496. int result = 0;
  497. Object o = impl.getOption(SocketOptions.SO_SNDBUF);
  498. if (o instanceof Integer) {
  499. result = ((Integer)o).intValue();
  500. }
  501. return result;
  502. }
  503. /**
  504. * Sets the SO_RCVBUF option to the specified value for this
  505. * <tt>Socket</tt>. The SO_RCVBUF option is used by the platform's
  506. * networking code as a hint for the size to set
  507. * the underlying network I/O buffers.
  508. *
  509. * <p>Increasing buffer size can increase the performance of
  510. * network I/O for high-volume connection, while decreasing it can
  511. * help reduce the backlog of incoming data. For UDP, this sets
  512. * the maximum size of a packet that may be sent on this <tt>Socket</tt>.
  513. *
  514. * <p>Because SO_RCVBUF is a hint, applications that want to
  515. * verify what size the buffers were set to should call
  516. * {@link #getReceiveBufferSize()}.
  517. *
  518. * @param size the size to which to set the receive buffer
  519. * size. This value must be greater than 0.
  520. *
  521. * @exception IllegalArgumentException if the value is 0 or is
  522. * negative.
  523. *
  524. * @exception SocketException if there is an error
  525. * in the underlying protocol, such as a TCP error.
  526. *
  527. * @see #getReceiveBufferSize()
  528. */
  529. public synchronized void setReceiveBufferSize(int size)
  530. throws SocketException{
  531. if (size <= 0) {
  532. throw new IllegalArgumentException("invalid receive size");
  533. }
  534. impl.setOption(SocketOptions.SO_RCVBUF, new Integer(size));
  535. }
  536. /**
  537. * Gets the value of the SO_RCVBUF option for this <tt>Socket</tt>,
  538. * that is the buffer size used by the platform for
  539. * input on this <tt>Socket</tt>.
  540. *
  541. * @return the value of the SO_RCVBUF option for this <tt>Socket</tt>.
  542. * @exception SocketException if there is an error
  543. * in the underlying protocol, such as a TCP error.
  544. * @see #setReceiveBufferSize(int)
  545. */
  546. public synchronized int getReceiveBufferSize()
  547. throws SocketException{
  548. int result = 0;
  549. Object o = impl.getOption(SocketOptions.SO_RCVBUF);
  550. if (o instanceof Integer) {
  551. result = ((Integer)o).intValue();
  552. }
  553. return result;
  554. }
  555. /**
  556. * Enable/disable SO_KEEPALIVE.
  557. *
  558. * @param on whether or not to have socket keep alive turned on.
  559. * @exception SocketException if there is an error
  560. * in the underlying protocol, such as a TCP error.
  561. * @since 1.3
  562. * @see #getKeepAlive()
  563. */
  564. public void setKeepAlive(boolean on) throws SocketException {
  565. impl.setOption(SocketOptions.SO_KEEPALIVE, new Boolean(on));
  566. }
  567. /**
  568. * Tests if SO_KEEPALIVE is enabled.
  569. *
  570. * @return a <code>boolean</code> indicating whether or not SO_KEEPALIVE is enabled.
  571. * @exception SocketException if there is an error
  572. * in the underlying protocol, such as a TCP error.
  573. * @since 1.3
  574. * @see #setKeepAlive(boolean)
  575. */
  576. public boolean getKeepAlive() throws SocketException {
  577. return ((Boolean) impl.getOption(SocketOptions.SO_KEEPALIVE)).booleanValue();
  578. }
  579. /**
  580. * Closes this socket.
  581. *
  582. * @exception IOException if an I/O error occurs when closing this socket.
  583. */
  584. public synchronized void close() throws IOException {
  585. impl.close();
  586. }
  587. /**
  588. * Places the input stream for this socket at "end of stream".
  589. * Any data sent to the input stream side of the socket is acknowledged
  590. * and then silently discarded.
  591. *
  592. * If you read from a socket input stream after invoking
  593. * shutdownInput() on the socket, the stream will return EOF.
  594. *
  595. * @exception IOException if an I/O error occurs when shutting down this
  596. * socket.
  597. * @see java.net.Socket#shutdownOutput()
  598. * @see java.net.Socket#close()
  599. * @see java.net.Socket#setSoLinger(boolean, int)
  600. */
  601. public void shutdownInput() throws IOException
  602. {
  603. impl.shutdownInput();
  604. }
  605. /**
  606. * Disables the output stream for this socket.
  607. * For a TCP socket, any previously written data will be sent
  608. * followed by TCP's normal connection termination sequence.
  609. *
  610. * If you write to a socket output stream after invoking
  611. * shutdownOutput() on the socket, the stream will throw
  612. * an IOException.
  613. *
  614. * @exception IOException if an I/O error occurs when shutting down this
  615. * socket.
  616. * @see java.net.Socket#shutdownInput()
  617. * @see java.net.Socket#close()
  618. * @see java.net.Socket#setSoLinger(boolean, int)
  619. */
  620. public void shutdownOutput() throws IOException
  621. {
  622. impl.shutdownOutput();
  623. }
  624. /**
  625. * Converts this socket to a <code>String</code>.
  626. *
  627. * @return a string representation of this socket.
  628. */
  629. public String toString() {
  630. return "Socket[addr=" + impl.getInetAddress() +
  631. ",port=" + impl.getPort() +
  632. ",localport=" + impl.getLocalPort() + "]";
  633. }
  634. /**
  635. * The factory for all client sockets.
  636. */
  637. private static SocketImplFactory factory;
  638. /**
  639. * Sets the client socket implementation factory for the
  640. * application. The factory can be specified only once.
  641. * <p>
  642. * When an application creates a new client socket, the socket
  643. * implementation factory's <code>createSocketImpl</code> method is
  644. * called to create the actual socket implementation.
  645. *
  646. * <p>If there is a security manager, this method first calls
  647. * the security manager's <code>checkSetFactory</code> method
  648. * to ensure the operation is allowed.
  649. * This could result in a SecurityException.
  650. *
  651. * @param fac the desired factory.
  652. * @exception IOException if an I/O error occurs when setting the
  653. * socket factory.
  654. * @exception SocketException if the factory is already defined.
  655. * @exception SecurityException if a security manager exists and its
  656. * <code>checkSetFactory</code> method doesn't allow the operation.
  657. * @see java.net.SocketImplFactory#createSocketImpl()
  658. * @see SecurityManager#checkSetFactory
  659. */
  660. public static synchronized void setSocketImplFactory(SocketImplFactory fac)
  661. throws IOException
  662. {
  663. if (factory != null) {
  664. throw new SocketException("factory already defined");
  665. }
  666. SecurityManager security = System.getSecurityManager();
  667. if (security != null) {
  668. security.checkSetFactory();
  669. }
  670. factory = fac;
  671. }
  672. }