001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.vfs;
031:
032: import com.caucho.util.L10N;
033: import com.caucho.util.Log;
034:
035: import java.io.IOException;
036: import java.lang.reflect.InvocationTargetException;
037: import java.lang.reflect.Method;
038: import java.net.BindException;
039: import java.net.InetAddress;
040: import java.net.ServerSocket;
041: import java.util.logging.Level;
042: import java.util.logging.Logger;
043:
044: /**
045: * Abstract socket to handle both normal sockets and bin/resin sockets.
046: */
047: public class QJniServerSocket {
048: private static final L10N L = new L10N(QJniServerSocket.class);
049: private static final Logger log = Log.open(QJniServerSocket.class);
050:
051: private QJniServerSocket() {
052: }
053:
054: /**
055: * Creates the SSL ServerSocket.
056: */
057: public static QServerSocket create(int port, int listenBacklog)
058: throws IOException {
059: return create(null, port, listenBacklog);
060: }
061:
062: /**
063: * Creates the SSL ServerSocket.
064: */
065: public static QServerSocket create(InetAddress host, int port,
066: int listenBacklog) throws IOException {
067: try {
068: // JNI doesn't listen immediately
069: QServerSocket ss = createJNI(host, port);
070:
071: if (ss != null)
072: return ss;
073: } catch (IOException e) {
074: log.log(Level.FINE, e.toString(), e);
075: } catch (Throwable e) {
076: log.log(Level.FINE, e.toString(), e);
077: }
078:
079: for (int i = 0; i < 10; i++) {
080: try {
081: ServerSocket ss = new ServerSocket(port, listenBacklog,
082: host);
083:
084: return new QServerSocketWrapper(ss);
085: } catch (BindException e) {
086: }
087:
088: try {
089: Thread.currentThread().sleep(1);
090: } catch (Throwable e) {
091: }
092: }
093:
094: try {
095: ServerSocket ss = new ServerSocket(port, listenBacklog,
096: host);
097:
098: return new QServerSocketWrapper(ss);
099: } catch (BindException e) {
100: if (host != null)
101: throw new BindException(
102: L
103: .l(
104: "{0}\nCan't bind to {1}:{2}.\nCheck for another server listening to that port.",
105: e.getMessage(), host, String
106: .valueOf(port)));
107: else
108: throw new BindException(
109: L
110: .l(
111: "{0}\nCan't bind to *:{1}.\nCheck for another server listening to that port.",
112: e.getMessage(), String
113: .valueOf(port)));
114: }
115:
116: }
117:
118: /**
119: * Creates the SSL ServerSocket.
120: */
121: public static QServerSocket createJNI(InetAddress host, int port)
122: throws IOException {
123: try {
124: Thread thread = Thread.currentThread();
125: ClassLoader loader = thread.getContextClassLoader();
126:
127: Class cl = Class
128: .forName("com.caucho.vfs.JniServerSocketImpl",
129: false, loader);
130:
131: Method method = cl.getMethod("create", new Class[] {
132: String.class, int.class });
133:
134: String hostAddress;
135:
136: if (host != null)
137: hostAddress = host.getHostAddress();
138: else
139: hostAddress = "0.0.0.0";
140:
141: try {
142: return (QServerSocket) method.invoke(null, hostAddress,
143: port);
144: } catch (InvocationTargetException e) {
145: throw e.getTargetException();
146: }
147: } catch (IOException e) {
148: throw e;
149: } catch (ClassNotFoundException e) {
150: log.fine(e.toString());
151:
152: throw new IOException(
153: L
154: .l("JNI Socket support requires Resin Professional."));
155: } catch (Throwable e) {
156: log.log(Level.FINE, e.toString(), e);
157:
158: throw new IOException(
159: L
160: .l("JNI Socket support requires Resin Professional."));
161: }
162: }
163:
164: /**
165: * Creates the SSL ServerSocket.
166: */
167: public static QServerSocket openJNI(int fd, int port)
168: throws IOException {
169: try {
170: Class cl = Class
171: .forName("com.caucho.vfs.JniServerSocketImpl");
172:
173: Method method = cl.getMethod("open", new Class[] {
174: int.class, int.class });
175:
176: try {
177: return (QServerSocket) method.invoke(null, fd, port);
178: } catch (InvocationTargetException e) {
179: throw e.getTargetException();
180: }
181: } catch (IOException e) {
182: throw e;
183: } catch (ClassNotFoundException e) {
184: log.fine(e.toString());
185:
186: throw new IOException(
187: L
188: .l("JNI Socket support requires Resin Professional."));
189: } catch (Throwable e) {
190: log.log(Level.FINE, e.toString(), e);
191:
192: throw new IOException(
193: L
194: .l("JNI Socket support requires Resin Professional."));
195: }
196: }
197: }
|