001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: *
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */
018:
019: /**
020: * @author Mikhail A. Markov
021: * @version $Revision: 1.1.2.2 $
022: */package org.apache.harmony.rmi.client;
023:
024: import java.io.BufferedInputStream;
025: import java.io.BufferedOutputStream;
026: import java.io.DataOutputStream;
027: import java.io.InputStream;
028: import java.io.IOException;
029: import java.io.OutputStream;
030: import java.net.Socket;
031: import java.rmi.ConnectException;
032: import java.rmi.ConnectIOException;
033: import java.rmi.RemoteException;
034: import java.rmi.server.UID;
035:
036: import org.apache.harmony.rmi.common.RMILog;
037: import org.apache.harmony.rmi.common.RMIUtil;
038: import org.apache.harmony.rmi.internal.nls.Messages;
039: import org.apache.harmony.rmi.transport.Endpoint;
040: import org.apache.harmony.rmi.transport.RMIProtocolConstants;
041:
042: /**
043: * Connection opened by client side. It acknowledges RMI protocol version,
044: * RMI protocol type etc.
045: *
046: * @author Mikhail A. Markov
047: * @version $Revision: 1.1.2.2 $
048: */
049: public abstract class ClientConnection implements RMIProtocolConstants {
050:
051: /** Connected socket. */
052: protected Socket s;
053:
054: /** InputStream open from the socket. */
055: protected InputStream in;
056:
057: /** OutputStream open from the socket. */
058: protected OutputStream out;
059:
060: /** Endpoint this connection connected to. */
061: protected Endpoint ep;
062:
063: /* Log for logging tcp connections activity. */
064: private static final RMILog transportLog = RMILog.getTransportLog();
065:
066: /* log for logging dgc activity. */
067: private static final RMILog dgcLog = RMILog.getDGCLog();
068:
069: /**
070: * Constructs ClientConnection, obtains input/output streams and acknowledge
071: * protocol with server side.
072: *
073: * @param s Connected socket
074: * @param ep server's endpoint
075: *
076: * @throws RemoteException if any I/O error occurred during connection
077: * creation
078: */
079: public ClientConnection(Socket s, Endpoint ep)
080: throws RemoteException {
081: this .s = s;
082: this .ep = ep;
083:
084: try {
085: out = new BufferedOutputStream(s.getOutputStream());
086: in = new BufferedInputStream(s.getInputStream());
087: } catch (IOException ioe) {
088: // rmi.40=Unable to establish connection to server
089: throw new ConnectException(
090: Messages.getString("rmi.40"), ioe); //$NON-NLS-1$
091: }
092: serverProtocolAck();
093: }
094:
095: /**
096: * Opens a connection to the given Endpoint and writes DGC ack there.
097: *
098: * @param uid UID to be send
099: */
100: public void sendDGCAck(UID uid) {
101: ClientConnection conn = null;
102:
103: try {
104: conn = ClientConnectionManager.getConnection(ep);
105: DataOutputStream dout = new DataOutputStream(out);
106: dout.writeByte(RMIProtocolConstants.DGCACK_MSG);
107: uid.write(dout);
108: dout.flush();
109: conn.releaseOutputStream();
110: conn.done();
111: } catch (IOException ioe) {
112: if (conn != null) {
113: conn.close();
114: }
115: }
116:
117: if (dgcLog.isLoggable(RMILog.VERBOSE)) {
118: // rmi.log.93=Sent DGC ack to {0} for {1}
119: dgcLog.log(RMILog.VERBOSE, Messages.getString(
120: "rmi.log.93", ep, uid)); //$NON-NLS-1$
121: }
122: }
123:
124: /**
125: * Acknowledge protocol with server side.
126: *
127: * @return acknowledged protocol number
128: *
129: * @throws RemoteException if any I/O exception occurred during protocol
130: * acknowledgement
131: */
132: protected abstract int serverProtocolAck() throws RemoteException;
133:
134: /**
135: * Writes RMI protocol header and RMI protocol version to the open
136: * OutputStream.
137: *
138: * @param dout DataOutputStream to write header to
139: *
140: * @throws RemoteException if any I/O error occurred while writing header
141: */
142: protected void writeHeader(DataOutputStream dout)
143: throws RemoteException {
144: try {
145: dout.writeInt(RMI_HEADER);
146: dout.writeShort(PROTOCOL_VER);
147: } catch (IOException ioe) {
148: // rmi.41=Unable to write RMI protocol header
149: throw new ConnectIOException(
150: Messages.getString("rmi.41"), ioe); //$NON-NLS-1$
151: }
152:
153: if (transportLog.isLoggable(RMILog.VERBOSE)) {
154: // rmi.log.94=Using protocol version {0}
155: transportLog.log(RMILog.VERBOSE, Messages.getString(
156: "rmi.log.94", //$NON-NLS-1$
157: PROTOCOL_VER));
158: }
159: }
160:
161: /**
162: * Closes this connection (i.e. closes opened Socket) and remove this
163: * Connection from the list of active connections in ConnectionManager.
164: */
165: public void close() {
166: close(true);
167: }
168:
169: /**
170: * Closes this connection (i.e. closes opened Socket) and if remove
171: * parameter is true then remove this Connection from the list of active
172: * connections in ConnectionManager.
173: *
174: * @param remove if true then remove this Connection from the list of active
175: * connections in ConnectionManager
176: */
177: public void close(boolean remove) {
178: try {
179: s.close();
180: } catch (Exception ex) {
181: }
182:
183: if (remove) {
184: ClientConnectionManager.removeConnection(this );
185: }
186: }
187:
188: /**
189: * Returns open input stream.
190: *
191: * @return open input stream
192: */
193: public InputStream getInputStream() {
194: return in;
195: }
196:
197: /**
198: * Returns open output stream.
199: *
200: * @return open output stream
201: */
202: public OutputStream getOutputStream() {
203: return out;
204: }
205:
206: /**
207: * Signals to the connection that remote call is done.
208: */
209: public abstract void done();
210:
211: /**
212: * By default flushes output stream of this connection.
213: *
214: * @throws IOException if any I/O error occurred
215: */
216: public void releaseOutputStream() throws IOException {
217: out.flush();
218: }
219:
220: /**
221: * If this connection is reusable and available then reuse it.
222: *
223: * @return true if this connection was successfully prepared for reusing
224: */
225: public abstract boolean reuse();
226:
227: /**
228: * Returns true if this connection is reusable and has no active
229: * remote calls.
230: *
231: * @return true if this connection is reusable and has no active
232: * remote calls
233: */
234: public abstract boolean isAvailable();
235:
236: /**
237: * True if this connection could be reused for another remote call.
238: *
239: * @return true if this connection could be reused for another remote call
240: */
241: public abstract boolean isReusable();
242:
243: /**
244: * If this connection is available returns time when it could be closed
245: * (if it'll be still in available state).
246: *
247: * @return returns time when the connection could be closed
248: */
249: public abstract long getExpiration();
250:
251: /**
252: * Returns endpoint this connection connected to.
253: *
254: * @return endpoint this connection connected to
255: */
256: public Endpoint getEndpoint() {
257: return ep;
258: }
259:
260: /**
261: * Returns string representation of this connection.
262: *
263: * @return string representation of this connection
264: */
265: public String toString() {
266: return RMIUtil.getShortName(getClass()) + ": endpoint:" + ep; //$NON-NLS-1$
267: }
268: }
|