| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.yoko.orb.OCI.IIOP; |
| |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| |
| import org.apache.yoko.orb.CORBA.OutputStream; |
| import org.apache.yoko.orb.OB.Assert; |
| import org.apache.yoko.orb.OCI.IIOP.PLUGIN_ID; |
| import org.omg.IOP.Codec; |
| |
| final class Acceptor_impl extends org.omg.CORBA.LocalObject implements |
| org.apache.yoko.orb.OCI.Acceptor { |
| // the real logger backing instance. We use the interface class as the locator |
| static final Logger logger = Logger.getLogger(org.apache.yoko.orb.OCI.Acceptor.class.getName()); |
| |
| // Some data members must not be private because the info object |
| // must be able to access them |
| public String[] hosts_; // The hosts |
| |
| public java.net.ServerSocket socket_; // The socket |
| |
| private boolean multiProfile_; // Use multiple profiles? |
| |
| private int port_; // The port |
| |
| private boolean keepAlive_; // The keepalive flag |
| |
| private java.net.InetAddress localAddress_; // The local address |
| |
| private final AcceptorInfo_impl info_; // Acceptor information |
| |
| private ListenerMap listenMap_; |
| |
| private final ConnectionHelper connectionHelper_; // plugin for managing connection config/creation |
| |
| private final ExtendedConnectionHelper extendedConnectionHelper_; |
| |
| private final Codec codec_; |
| |
| // ------------------------------------------------------------------ |
| // Standard IDL to Java Mapping |
| // ------------------------------------------------------------------ |
| |
| public String id() { |
| return PLUGIN_ID.value; |
| } |
| |
| public int tag() { |
| return org.omg.IOP.TAG_INTERNET_IOP.value; |
| } |
| |
| public int handle() { |
| throw new org.omg.CORBA.NO_IMPLEMENT(); |
| } |
| |
| public void close() { |
| logger.log(Level.FINE, "Closing server socket with host=" + localAddress_ + ", port=" + port_, new Exception("Stack trace")); |
| // |
| // Destroy the info object |
| // |
| info_._OB_destroy(); |
| |
| // |
| // Close the socket |
| // |
| try { |
| socket_.close(); |
| socket_ = null; |
| logger.log(Level.FINE, "Closed server socket with host=" + localAddress_ + ", port=" + port_); |
| } catch (java.io.IOException ex) { |
| logger.log(Level.FINE, "Exception closing server socket with host=" + localAddress_ + ", port=" + port_, ex); |
| } |
| } |
| |
| public void shutdown() { |
| // |
| // This operation does nothing in the java implementation |
| // |
| } |
| |
| public void listen() { |
| // |
| // This operation does nothing in the java implementation |
| // |
| } |
| |
| public org.apache.yoko.orb.OCI.Transport accept(boolean block) { |
| // |
| // Accept |
| // |
| java.net.Socket socket; |
| try { |
| // |
| // If non-blocking, use a timeout of 1ms |
| // |
| if (!block) |
| socket_.setSoTimeout(1); |
| else |
| socket_.setSoTimeout(0); |
| |
| logger.fine("Accepting connection for host=" + localAddress_ + ", port=" + port_); |
| socket = socket_.accept(); |
| logger.fine("Received inbound connection on socket " + socket); |
| } catch (java.io.InterruptedIOException ex) { |
| if (!block) |
| return null; // Timeout |
| else { |
| logger.log(Level.FINE, "Failure accepting connection for host=" + localAddress_ + ", port=" + port_, ex); |
| |
| throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE( |
| org.apache.yoko.orb.OB.MinorCodes |
| .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorAccept) |
| + ": " + ex.getMessage(), |
| org.apache.yoko.orb.OB.MinorCodes.MinorAccept, |
| org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex); |
| } |
| } catch (java.io.IOException ex) { |
| logger.log(Level.FINE, "Failure accepting connection for host=" + localAddress_ + ", port=" + port_, ex); |
| throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE( |
| org.apache.yoko.orb.OB.MinorCodes |
| .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorAccept) |
| + ": " + ex.getMessage(), |
| org.apache.yoko.orb.OB.MinorCodes.MinorAccept, |
| org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex); |
| } |
| |
| // |
| // Set TCP_NODELAY and SO_KEEPALIVE options |
| // |
| try { |
| socket.setTcpNoDelay(true); |
| if (keepAlive_) |
| socket.setKeepAlive(true); |
| } catch (java.net.SocketException ex) { |
| logger.log(Level.FINE, "Failure configuring server connection for host=" + localAddress_ + ", port=" + port_, ex); |
| throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE( |
| org.apache.yoko.orb.OB.MinorCodes |
| .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorSetsockopt) |
| + ": " + ex.getMessage(), |
| org.apache.yoko.orb.OB.MinorCodes.MinorSetsockopt, |
| org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex); |
| } |
| |
| // |
| // Create new transport |
| // |
| org.apache.yoko.orb.OCI.Transport tr = null; |
| try { |
| tr = new Transport_impl(this, socket, listenMap_); |
| logger.fine("Inbound connection received from " + socket.getInetAddress()); |
| } catch (org.omg.CORBA.SystemException ex) { |
| try { |
| socket.close(); |
| } catch (java.io.IOException e) { |
| } |
| logger.log(Level.FINE, "error creating inbound connection", ex); |
| throw ex; |
| } |
| |
| // |
| // Call callbacks |
| // |
| org.apache.yoko.orb.OCI.TransportInfo trInfo = tr.get_info(); |
| try { |
| info_._OB_callAcceptCB(trInfo); |
| } catch (org.omg.CORBA.SystemException ex) { |
| tr.close(); |
| logger.log(Level.FINE, "error calling connection callbacks", ex); |
| throw ex; |
| } |
| |
| // |
| // Return new transport |
| // |
| return tr; |
| } |
| |
| public org.apache.yoko.orb.OCI.Transport connect_self() { |
| // |
| // Create socket and connect to local address |
| // |
| java.net.Socket socket = null; |
| try { |
| if (connectionHelper_ != null) { |
| socket = connectionHelper_.createSelfConnection(localAddress_, port_); |
| } else { |
| socket = extendedConnectionHelper_.createSelfConnection(localAddress_, port_); |
| } |
| } catch (java.net.ConnectException ex) { |
| logger.log(Level.FINE, "Failure making self connection for host=" + localAddress_ + ", port=" + port_, ex); |
| throw new org.omg.CORBA.TRANSIENT( |
| org.apache.yoko.orb.OB.MinorCodes |
| .describeTransient(org.apache.yoko.orb.OB.MinorCodes.MinorConnectFailed) |
| + ": " + ex.getMessage(), |
| org.apache.yoko.orb.OB.MinorCodes.MinorConnectFailed, |
| org.omg.CORBA.CompletionStatus.COMPLETED_NO); |
| } catch (java.io.IOException ex) { |
| logger.log(Level.FINE, "Failure making self connection for host=" + localAddress_ + ", port=" + port_, ex); |
| throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE( |
| org.apache.yoko.orb.OB.MinorCodes |
| .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorSocket) |
| + ": " + ex.getMessage(), |
| org.apache.yoko.orb.OB.MinorCodes.MinorSocket, |
| org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex); |
| } |
| |
| // |
| // Set TCP_NODELAY option |
| // |
| try { |
| socket.setTcpNoDelay(true); |
| } catch (java.net.SocketException ex) { |
| logger.log(Level.FINE, "Failure configuring self connection for host=" + localAddress_ + ", port=" + port_, ex); |
| try { |
| socket.close(); |
| } catch (java.io.IOException e) { |
| } |
| throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE( |
| org.apache.yoko.orb.OB.MinorCodes |
| .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorSetsockopt) |
| + ": " + ex.getMessage(), |
| org.apache.yoko.orb.OB.MinorCodes.MinorSetsockopt, |
| org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex); |
| } |
| |
| // |
| // Create and return new transport |
| // |
| org.apache.yoko.orb.OCI.Transport tr = null; |
| try { |
| tr = new Transport_impl(this, socket, listenMap_); |
| } catch (org.omg.CORBA.SystemException ex) { |
| try { |
| socket.close(); |
| } catch (java.io.IOException e) { |
| } |
| throw ex; |
| } |
| return tr; |
| } |
| |
| public void add_profiles(org.apache.yoko.orb.OCI.ProfileInfo profileInfo, |
| org.apache.yoko.orb.OBPortableServer.POAPolicies policies, |
| org.omg.IOP.IORHolder ior) { |
| if (port_ == 0) |
| throw new RuntimeException(); |
| |
| // |
| // Filter components according to IIOP version |
| // |
| java.util.Vector components = new java.util.Vector(); |
| if (profileInfo.major == 1 && profileInfo.minor == 0) { |
| // |
| // No components for IIOP 1.0 |
| // |
| } else { |
| for (int i = 0; i < profileInfo.components.length; i++) |
| components.addElement(profileInfo.components[i]); |
| } |
| |
| if (profileInfo.major == 1 && profileInfo.minor == 0) { |
| // |
| // For IIOP 1.0, we always add one profile for each host, |
| // since IIOP 1.0 doesn't support tagged components in a |
| // profile |
| // |
| for (int i = 0; i < hosts_.length; i++) { |
| org.omg.IIOP.ProfileBody_1_0 body = new org.omg.IIOP.ProfileBody_1_0(); |
| body.iiop_version = new org.omg.IIOP.Version(profileInfo.major, |
| profileInfo.minor); |
| body.host = hosts_[i]; |
| // the CSIv2 policy may require zeroing the port in the IOR. |
| if (policies.zeroPortPolicy()) { |
| body.port = 0; |
| } |
| else { |
| if (port_ >= 0x8000) |
| body.port = (short) (port_ - 0xffff - 1); |
| else |
| body.port = (short) port_; |
| } |
| body.object_key = profileInfo.key; |
| |
| int len = ior.value.profiles.length + 1; |
| org.omg.IOP.TaggedProfile[] profiles = new org.omg.IOP.TaggedProfile[len]; |
| System.arraycopy(ior.value.profiles, 0, profiles, 0, |
| ior.value.profiles.length); |
| ior.value.profiles = profiles; |
| ior.value.profiles[len - 1] = new org.omg.IOP.TaggedProfile(); |
| ior.value.profiles[len - 1].tag = org.omg.IOP.TAG_INTERNET_IOP.value; |
| org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(); |
| OutputStream out = new OutputStream(buf); |
| out._OB_writeEndian(); |
| org.omg.IIOP.ProfileBody_1_0Helper.write(out, body); |
| ior.value.profiles[len - 1].profile_data = new byte[buf |
| .length()]; |
| System.arraycopy(buf.data(), 0, |
| ior.value.profiles[len - 1].profile_data, 0, buf |
| .length()); |
| } |
| } else { |
| if (multiProfile_) { |
| // |
| // Add one profile for each host |
| // |
| |
| for (int i = 0; i < hosts_.length; i++) { |
| org.omg.IIOP.ProfileBody_1_1 body = new org.omg.IIOP.ProfileBody_1_1(); |
| body.iiop_version = new org.omg.IIOP.Version( |
| profileInfo.major, profileInfo.minor); |
| body.host = hosts_[i]; |
| // the CSIv2 policy may require zeroing the port in the IOR. |
| if (policies.zeroPortPolicy()) { |
| body.port = 0; |
| } |
| else { |
| if (port_ >= 0x8000) |
| body.port = (short) (port_ - 0xffff - 1); |
| else |
| body.port = (short) port_; |
| } |
| body.object_key = profileInfo.key; |
| body.components = new org.omg.IOP.TaggedComponent[components |
| .size()]; |
| components.copyInto(body.components); |
| |
| int len = ior.value.profiles.length + 1; |
| org.omg.IOP.TaggedProfile[] profiles = new org.omg.IOP.TaggedProfile[len]; |
| System.arraycopy(ior.value.profiles, 0, profiles, 0, |
| ior.value.profiles.length); |
| ior.value.profiles = profiles; |
| ior.value.profiles[len - 1] = new org.omg.IOP.TaggedProfile(); |
| ior.value.profiles[len - 1].tag = org.omg.IOP.TAG_INTERNET_IOP.value; |
| org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(); |
| OutputStream out = new OutputStream(buf); |
| out._OB_writeEndian(); |
| org.omg.IIOP.ProfileBody_1_1Helper.write(out, body); |
| ior.value.profiles[len - 1].profile_data = new byte[buf |
| .length()]; |
| System.arraycopy(buf.data(), 0, |
| ior.value.profiles[len - 1].profile_data, 0, buf |
| .length()); |
| } |
| } else { |
| // |
| // Add a single tagged profile. If there are additional |
| // hosts, add a tagged component for each host. |
| // |
| |
| org.omg.IIOP.ProfileBody_1_1 body = new org.omg.IIOP.ProfileBody_1_1(); |
| body.iiop_version = new org.omg.IIOP.Version(profileInfo.major, |
| profileInfo.minor); |
| body.host = hosts_[0]; |
| if (policies.zeroPortPolicy()) { |
| body.port = 0; |
| } |
| else { |
| if (port_ >= 0x8000) |
| body.port = (short) (port_ - 0xffff - 1); |
| else |
| body.port = (short) port_; |
| } |
| body.object_key = profileInfo.key; |
| |
| for (int i = 1; i < hosts_.length; i++) { |
| org.omg.IOP.TaggedComponent c = new org.omg.IOP.TaggedComponent(); |
| c.tag = org.omg.IOP.TAG_ALTERNATE_IIOP_ADDRESS.value; |
| org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(); |
| OutputStream out = new OutputStream(buf); |
| out._OB_writeEndian(); |
| out.write_string(hosts_[i]); |
| out.write_ushort(body.port); |
| c.component_data = new byte[buf.length()]; |
| System.arraycopy(buf.data(), 0, c.component_data, 0, buf |
| .length()); |
| components.addElement(c); |
| } |
| body.components = new org.omg.IOP.TaggedComponent[components |
| .size()]; |
| components.copyInto(body.components); |
| |
| int len = ior.value.profiles.length + 1; |
| org.omg.IOP.TaggedProfile[] profiles = new org.omg.IOP.TaggedProfile[len]; |
| System.arraycopy(ior.value.profiles, 0, profiles, 0, |
| ior.value.profiles.length); |
| ior.value.profiles = profiles; |
| ior.value.profiles[len - 1] = new org.omg.IOP.TaggedProfile(); |
| ior.value.profiles[len - 1].tag = org.omg.IOP.TAG_INTERNET_IOP.value; |
| org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(); |
| OutputStream out = new OutputStream(buf); |
| out._OB_writeEndian(); |
| org.omg.IIOP.ProfileBody_1_1Helper.write(out, body); |
| ior.value.profiles[len - 1].profile_data = new byte[buf |
| .length()]; |
| System.arraycopy(buf.data(), 0, |
| ior.value.profiles[len - 1].profile_data, 0, buf |
| .length()); |
| } |
| } |
| } |
| |
| public org.apache.yoko.orb.OCI.ProfileInfo[] get_local_profiles( |
| org.omg.IOP.IOR ior) { |
| // |
| // Get local profiles for all hosts |
| // |
| org.apache.yoko.orb.OCI.ProfileInfoSeqHolder profileInfoSeq = new org.apache.yoko.orb.OCI.ProfileInfoSeqHolder(); |
| profileInfoSeq.value = new org.apache.yoko.orb.OCI.ProfileInfo[0]; |
| |
| for (int i = 0; i < hosts_.length; i++) { |
| Util.extractAllProfileInfos(ior, profileInfoSeq, true, hosts_[i], |
| port_, true, codec_); |
| } |
| |
| return profileInfoSeq.value; |
| } |
| |
| public org.apache.yoko.orb.OCI.AcceptorInfo get_info() { |
| return info_; |
| } |
| |
| // ------------------------------------------------------------------ |
| // Yoko internal functions |
| // Application programs must not use these functions directly |
| // ------------------------------------------------------------------ |
| |
| public Acceptor_impl(String address, String[] hosts, boolean multiProfile, |
| int port, int backlog, boolean keepAlive, ConnectionHelper helper, ExtendedConnectionHelper extendedConnectionHelper, ListenerMap lm, String[] params, Codec codec) { |
| // System.out.println("Acceptor_impl"); |
| Assert._OB_assert((helper == null) ^ (extendedConnectionHelper == null)); |
| hosts_ = hosts; |
| multiProfile_ = multiProfile; |
| keepAlive_ = keepAlive; |
| connectionHelper_ = helper; |
| extendedConnectionHelper_ = extendedConnectionHelper; |
| codec_ = codec; |
| info_ = new AcceptorInfo_impl(this); |
| listenMap_ = lm; |
| |
| if (backlog == 0) |
| backlog = 50; // 50 is the JDK's default value |
| |
| // |
| // Get the local address for use by connect_self |
| // |
| try { |
| if (address == null) { |
| //Since we are |
| // binding to all network interfaces, we'll use the loopback |
| // address. |
| localAddress_ = java.net.InetAddress.getLocalHost(); |
| } else { |
| localAddress_ = java.net.InetAddress.getByName(address); |
| } |
| } catch (java.net.UnknownHostException ex) { |
| logger.log(Level.FINE, "Host resolution failure", ex); |
| throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE( |
| org.apache.yoko.orb.OB.MinorCodes |
| .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorGethostbyname) |
| + ": " + ex.getMessage(), |
| org.apache.yoko.orb.OB.MinorCodes.MinorGethostbyname, |
| org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex); |
| } |
| |
| // |
| // Create socket and bind to requested network interface |
| // |
| try { |
| if (address == null) { |
| if (connectionHelper_ != null) { |
| socket_ = connectionHelper_.createServerSocket(port, backlog); |
| } else { |
| socket_ = extendedConnectionHelper_.createServerSocket(port, backlog, params); |
| } |
| } else { |
| if (connectionHelper_ != null) { |
| socket_ = connectionHelper_.createServerSocket(port, backlog, localAddress_); |
| } else { |
| socket_ = extendedConnectionHelper_.createServerSocket(port, backlog, localAddress_, params); |
| } |
| } |
| |
| // |
| // Read back the port. This is needed if the port was selected by |
| // the operating system. |
| // |
| port_ = socket_.getLocalPort(); |
| logger.fine("Acceptor created using socket " + socket_); |
| } catch (java.net.BindException ex) { |
| logger.log(Level.FINE, "Failure creating server socket for host=" + localAddress_ + ", port=" + port, ex); |
| throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE( |
| org.apache.yoko.orb.OB.MinorCodes |
| .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorBind) |
| + ": " + ex.getMessage(), |
| org.apache.yoko.orb.OB.MinorCodes.MinorBind, |
| org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex); |
| } catch (java.io.IOException ex) { |
| logger.log(Level.FINE, "Failure creating server socket for host=" + localAddress_ + ", port=" + port, ex); |
| throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE( |
| org.apache.yoko.orb.OB.MinorCodes |
| .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorSocket) |
| + ": " + ex.getMessage(), |
| org.apache.yoko.orb.OB.MinorCodes.MinorSocket, |
| org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex); |
| } |
| |
| // |
| // Add this entry to the listenMap_ as an endpoint to remap |
| // |
| synchronized (listenMap_) { |
| for (int i = 0; i < hosts_.length; i++) |
| listenMap_.add(hosts_[i], (short) port_); |
| } |
| } |
| |
| public void finalize() throws Throwable { |
| // System.out.println("~Acceptor_impl"); |
| if (socket_ != null) { |
| close(); |
| } |
| |
| // |
| // remove this acceptor from the listenMap_ |
| // |
| synchronized (listenMap_) { |
| for (int i = 0; i < hosts_.length; i++) |
| listenMap_.remove(hosts_[i], (short) port_); |
| } |
| |
| super.finalize(); |
| } |
| |
| public String toString() { |
| return "Acceptor listening on " + socket_; |
| } |
| } |