View Javadoc

1   /* (c) Copyright 2003 Caleigo AB, All rights reserved. 
2    * 
3    * This library is free software; you can redistribute it and/or
4    * modify it under the terms of the GNU Lesser General Public
5    * License as published by the Free Software Foundation; either
6    * version 2.1 of the License, or (at your option) any later version.
7    * 
8    * This library is distributed in the hope that it will be useful,
9    * but WITHOUT ANY WARRANTY; without even the implied warranty of
10   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11   * Lesser General Public License for more details.
12   * 
13   * You should have received a copy of the GNU Lesser General Public
14   * License along with this library; if not, write to the Free Software
15   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16   *  
17   */
18  
19  package org.caleigo.toolkit.tunnel;
20  
21  
22  import java.io.*;
23  import java.net.*;
24  
25  import org.caleigo.toolkit.log.*;
26  
27  /***
28   *
29   * @author  Mattias Hagstrand
30   * @version 1.00
31   * 
32   *//* 
33   *
34   * WHEN        WHO               WHY & WHAT
35   * -----------------------------------------------------------------------------
36   * 2002-07-02  Mattias Hagstrand Creation
37   */
38  public class SocketTunnel extends AbstractTunnel
39  {
40      // Data members ------------------------------------------------------------
41      protected InetAddress mAddress;
42      protected int mPort;
43      protected Socket mSocket;
44      private boolean mIsInitialized;
45      
46      private String mDescription;
47      
48      // Constructors ------------------------------------------------------------
49      protected SocketTunnel(Socket socket)
50      {
51          mSocket = socket;
52          mDescription = mSocket.getInetAddress().getHostAddress();
53      }
54      
55      public SocketTunnel(InetAddress address, int port)
56      {
57          super();
58          
59          mAddress = address;
60          mPort = port;
61          mDescription = mAddress.getHostAddress();
62      }
63      
64      public SocketTunnel(InetAddress address, int port, ITunnelCodec codec)
65      {
66          super(codec);
67          
68          mAddress = address;
69          mPort = port;
70          mDescription = mAddress.getHostAddress();
71      }
72      
73      // Superclass overrides ----------------------------------------------------
74      public synchronized void initialize()
75          throws IllegalStateException, TunnelException
76      {
77          if (mIsInitialized)
78              throw new IllegalStateException("The tunnel is initialized");
79  
80          try
81          {
82              /* If mSocket is null this is a new connection:
83               * Set up a connection to the server
84               *
85               * If mSocket is not null then a connection allready exists.
86               */
87              
88              if (mSocket == null)
89              {
90                  mSocket = new Socket(mAddress, mPort);
91                  this.setUpConnection();
92              }
93              mIsInitialized = true;    
94              
95              super.initialize();
96          }
97          catch (Exception e)
98          {
99              mIsInitialized = false;
100             throw new TunnelException(e);
101         }
102     }
103     
104     public synchronized void finalize()
105         throws IllegalStateException, TunnelException
106     {
107         if (!mIsInitialized)
108             throw new IllegalStateException("The tunnel is not initialized");
109         
110         try
111         {
112             if (super.isActive())
113                 super.finalize();
114             mSocket.close();
115         }
116         catch (Exception e)
117         {
118             throw new TunnelException(e);
119         }
120         finally
121         {
122             mSocket = null;
123             mIsInitialized = false;
124         }
125     }
126     
127     /*** Returns <code>true</code> if this tunnel is active, that is, if it is
128      * correctly initialized. If this method returns <code>true</code> then
129      * a call to finalize must not throw an IllegalStateException.
130      */
131     public synchronized boolean isActive()
132     {
133         return mIsInitialized;
134     }
135     
136     /***
137      * Returns an OutputStream that should be used to send messages.
138      */
139     protected OutputStream getOutputStream()
140     {
141         if (mSocket != null)
142             try
143             {
144                 return mSocket.getOutputStream();
145             }
146             catch (Exception e)
147             {
148                 if (this.getLogLevel() <= AbstractTunnel.ERROR)
149                     Log.printError(this, "Couldn't get output stream", e);
150             }
151         
152         return null;
153     }
154     
155     /***
156      * Returns an InputStream that should be used to receive messages.
157      */
158     protected InputStream getInputStream()
159     {
160         if (mSocket != null)
161             try
162             {
163                 return mSocket.getInputStream();
164             }
165             catch (Exception e)
166             {
167                 if (this.getLogLevel() <= ERROR)
168                     Log.printError(this, "Couldn't get input stream", e);
169             }
170         
171         return null;
172     }
173     
174     /*** Returns a humanly readably text that describes the ITunnel.
175      */
176     public String getDescription()
177     {
178         return mDescription;
179     }
180     
181     // Help methods ------------------------------------------------------------
182     protected void setUpConnection()
183         throws TunnelException
184     {
185         IStatusMessage statusMessage = null;
186         
187         try
188         {
189             ObjectOutputStream objectOutputStream = new ObjectOutputStream(this.getOutputStream());
190             ObjectInputStream objectInputStream = new ObjectInputStream(this.getInputStream());
191             
192             // Send connection message
193             objectOutputStream.writeObject(this.createConnectionMessage());
194             objectOutputStream.flush();
195             
196             // Wait for reply from server
197             statusMessage = (IStatusMessage) objectInputStream.readObject();
198         }
199         catch (Exception e)
200         {
201             throw new TunnelException(e);
202         }
203         
204         if (statusMessage.getStatus() == IStatusMessage.OK)
205         {
206             if (this.getLogLevel() <= AbstractTunnel.INFO)
207                 Log.print(this, "Status message received: " + statusMessage.toString());
208             for (int i = 0; i < mStatusCallbacks.size(); i++)
209                 ((IStatusCallback) mStatusCallbacks.get(i)).handleInfo("Connection established");
210         }
211         else
212         {
213             if (this.getLogLevel() <= AbstractTunnel.ERROR)
214                 Log.printError(this, "Couldn't establish connection: " + statusMessage.getMessage());
215             for (int i = 0; i < mStatusCallbacks.size(); i++)
216                 ((IStatusCallback) mStatusCallbacks.get(i)).handleError("Couldn't establish connection: " + statusMessage.getMessage(), null);
217             throw new TunnelException("Couldn't establish connection: " + statusMessage.getMessage());
218         }
219     }
220 }