00001 /************************************************************************** 00002 Copyright (c) 2000-2001, Tony Garnock-Jones 00003 All rights reserved. 00004 00005 Redistribution and use in source and binary forms, with or without 00006 modification, are permitted provided that the following conditions are 00007 met: 00008 00009 * Redistributions of source code must retain the above copyright 00010 notice, this list of conditions and the following disclaimer. 00011 00012 * Redistributions in binary form must reproduce the above 00013 copyright notice, this list of conditions and the following 00014 disclaimer in the documentation and/or other materials provided 00015 with the distribution. 00016 00017 * Neither the names of the copyright holders nor the names of this 00018 software's contributors may be used to endorse or promote 00019 products derived from this software without specific prior 00020 written permission. 00021 00022 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00023 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00024 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00025 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR 00026 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00027 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00028 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00029 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00030 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00031 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00032 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00033 **************************************************************************/ 00034 00035 package org.hebe.mps; 00036 00037 import java.io.*; 00038 import java.net.*; 00039 import java.util.*; 00040 import org.hebe.mps.naming.Binding; 00041 00042 /** 00043 * Manages client-side connections to an MPS server. Contains the 00044 * looked-up/resolved address of the remote server (ie. the canonical 00045 * name of the server), and a Socket for communication with the 00046 * server. This class is only used internally, and should never be 00047 * exposed to client objects outside this package. 00048 * 00049 * @author Tony Garnock-Jones <tonyg@kcbbs.gen.nz> 00050 * @see org.hebe.mps.Proxy 00051 * @see org.hebe.mps.InputStream 00052 * @see org.hebe.mps.OutputStream */ 00053 class Connection { 00054 /** mps:inet:<host>:<port>:<oid> - server's canonical (bound) name */ 00055 private String resolvedName; 00056 00057 /** Socket that connects us to the remote server */ 00058 private Socket connection; 00059 00060 /** Transport name - always "inet", for the Java implementation, currently */ 00061 private String method; 00062 /** Hostname of the remote server - taken from resolvedName */ 00063 private String hostname; 00064 /** Port number of the remote server - taken from resolvedName */ 00065 private int portnumber; 00066 /** OID (Object ID) of the remote server - taken from resolvedName */ 00067 private int oid; 00068 00069 /** 00070 * Creates a fresh Connection given the resolved name of a remote 00071 * object to connect to. 00072 * 00073 * @param name the resolved name of the MPS server to connect to 00074 * @exception MPSException if the resolved name is ill-formed or unsupported 00075 */ 00076 public Connection(String name) throws MPSException { 00077 resolvedName = name; 00078 connection = null; 00079 parseResolvedName(); 00080 } 00081 00082 /** 00083 * Obtains a (simple) human-readable representation of this 00084 * connection object. 00085 * 00086 * @return the printable string 00087 */ 00088 public String toString() { 00089 return "MPSConnection(" + resolvedName + ")"; 00090 } 00091 00092 /** 00093 * Splits up the resolvedName of this object into its components. 00094 * 00095 * @exception MPSException if the resolvedName of this object is ill-formed or unsupported 00096 */ 00097 private void parseResolvedName() throws MPSException { 00098 try { 00099 StringTokenizer st = new StringTokenizer(resolvedName, ":"); 00100 st.nextToken(); // skip "mps:" 00101 method = st.nextToken(); 00102 hostname = st.nextToken(); 00103 portnumber = Integer.parseInt(st.nextToken()); 00104 oid = Integer.parseInt(st.nextToken()); 00105 } catch (Exception e) { 00106 throw new MPSException("Invalid object name " + toString()); 00107 } 00108 00109 if (!method.equals("inet")) { 00110 throw new MPSException("Invalid transport name " + method); 00111 } 00112 } 00113 00114 /** 00115 * Opens the connection to the remote server. Only called on 00116 * demand. 00117 * 00118 * @exception MPSException if the resolvedName of this object is ill-formed or unsupported 00119 * @exception MPSException if the server is refusing connections 00120 */ 00121 public void open() throws MPSException { 00122 if (connection != null) 00123 return; 00124 00125 parseResolvedName(); 00126 00127 try { 00128 connection = new Socket(hostname, portnumber); 00129 } catch (Exception e) { 00130 throw new MPSException("Could not connect to object " + toString()); 00131 } 00132 } 00133 00134 /** 00135 * Closes the connection to the remote server. 00136 * 00137 * @exception MPSException if there was a problem closing the socket. 00138 */ 00139 public void close() throws MPSException { 00140 try { 00141 connection.close(); 00142 } catch (IOException e) { 00143 throw new MPSException("Error closing connection " + toString()); 00144 } finally { 00145 connection = null; 00146 } 00147 } 00148 00149 /** 00150 * Allows clients access to the input (server-to-client) 00151 * facilities of the socket connected to the remote server. 00152 * 00153 * @return a Java input stream for reading bytes from the server 00154 * @exception MPSException from open() if the connection was closed and wouldn't open 00155 * @exception MPSException if the socket failed to create an InputStream for us 00156 */ 00157 public java.io.InputStream getInputStream() throws MPSException { 00158 try { 00159 open(); 00160 return connection.getInputStream(); 00161 } catch (IOException e) { 00162 throw new MPSException("Could not get input stream for " + toString()); 00163 } 00164 } 00165 00166 /** 00167 * Allows clients access to the output (client-to-server) 00168 * facilities of the socket connected to the remote server. 00169 * 00170 * @return a Java output stream for reading bytes from the server 00171 * @exception MPSException from open() if the connection was closed and wouldn't open 00172 * @exception MPSException if the socket failed to create an OutputStream for us 00173 */ 00174 public java.io.OutputStream getOutputStream() throws MPSException { 00175 try { 00176 open(); 00177 return connection.getOutputStream(); 00178 } catch (IOException e) { 00179 throw new MPSException("Could not get output stream for " + toString()); 00180 } 00181 } 00182 00183 /** 00184 * Allows clients to inspect the canonical name for the server we 00185 * are connected to. 00186 */ 00187 public String getResolvedName() { 00188 return resolvedName; 00189 } 00190 00191 /** 00192 * Returns the OID of the remote object. For use by 00193 * {Input,Output}Stream's constructors. 00194 */ 00195 int getOid() { 00196 return oid; 00197 } 00198 }