KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jonas > discovery > DiscoveryGreetingResponder


1 /**
2  * JOnAS: Java(TM) Open Application Server
3  * Copyright (C) 2005 Bull S.A.
4  * Contact: jonas-team@objectweb.org
5  *
6  * This library is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by the
8  * Free Software Foundation; either version 2.1 of the License, or any later
9  * version.
10  *
11  * This library is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
14  * for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
19  * --------------------------------------------------------------------------
20  * $Id: DiscoveryGreetingResponder.java,v 1.4 2005/05/23 07:33:44 vivekl Exp $
21  * --------------------------------------------------------------------------
22  */

23
24 package org.objectweb.jonas.discovery;
25
26 import java.io.ByteArrayInputStream JavaDoc;
27 import java.io.IOException JavaDoc;
28 import java.io.ObjectInputStream JavaDoc;
29 import java.net.DatagramPacket JavaDoc;
30 import java.net.DatagramSocket JavaDoc;
31 import java.net.InetAddress JavaDoc;
32 import java.net.SocketException JavaDoc;
33 import java.net.SocketTimeoutException JavaDoc;
34 import java.net.UnknownHostException JavaDoc;
35
36 import org.objectweb.jonas.common.Log;
37 import org.objectweb.jonas.common.NetUtils;
38 import org.objectweb.jonas.service.ServiceException;
39 import org.objectweb.util.monolog.api.BasicLevel;
40 import org.objectweb.util.monolog.api.Logger;
41
42 /**
43  * This class sends a multicast message stating the servername and
44  * the port at which it will listen for messages. It listens at the
45  * unicast port for a pre-determined time (greetingTimeOut) and if
46  * it receives a message indicating that a server with the same ID
47  * already exists in the domain then it terminates the discovery service.
48  *
49  * @author Vivek Lakshmanan
50  * @version 1.0
51  */

52 public class DiscoveryGreetingResponder extends DiscoveryComm {
53     /**
54      * Used to recieve responses to the initial greeting message sent out on the multicast port.
55      */

56     protected DatagramSocket JavaDoc recvUnicastSocket;
57
58     /**
59      * Port to listen to for greeting responses.
60      */

61     protected int greetingPort;
62
63     /**
64      * Time out period to listen to greetingPort for replies.
65      */

66     protected int greetingTimeOut;
67
68     /**
69      * The greeting to be sent out identifying the server.
70      */

71     private DiscGreeting greeting = null;
72     
73     /**
74      * logger
75      */

76     private static Logger logger = Log.getLogger(Log.JONAS_DISCOVERY_PREFIX);
77
78     /**
79      * Constructs a DiscoveryGreetingResponder associated to the DiscoveryManager
80      *
81      * @param dm
82      * DiscoveryManager to which this instance is associated
83      */

84     public DiscoveryGreetingResponder(DiscoveryManager dm) {
85         super(dm);
86         this.greetingPort = dm.getGreetingListeningPort();
87         this.greetingTimeOut = dm.getGreetingAckTimeOut();
88     }
89
90
91     /**
92      * Create a discovery greeting message
93      *
94      * @param startup -
95      * true: means that is a greeting message at the point of start
96      * up of the discovery service. false: means this is a reply to
97      * a previous greeting message.
98      * @return a Discovery Greeting message.
99      */

100     protected DiscGreeting createDiscGreeting(boolean startup) {
101         String JavaDoc theHostAddress;
102         try {
103             theHostAddress = NetUtils.getLocalAddress();
104         } catch (UnknownHostException JavaDoc e) {
105             logger.log(BasicLevel.ERROR, "Unknown host", e);
106             return null;
107         }
108
109         return new DiscGreeting(theHostAddress, this.greetingPort,
110                 this.jonasName, this.domainName, startup, this.serverId);
111     }
112
113     /**
114      * Handle the case where the received DiscGreeting indicates that a server
115      * with the same name already exists in the domain.
116      *
117      * @param msg
118      * a discovery greeting received.
119      *
120      * @throws DuplicateServerNameException
121      */

122     private void handleReceivedMessage(DiscGreeting msg)
123             throws DuplicateServerNameException {
124
125         if (logger.isLoggable(BasicLevel.ERROR)) {
126             logger.log(BasicLevel.ERROR, "A server with the given name already"
127                     + " exists in the domain, received a rejection message: "
128                     + msg);
129         }
130         stop();
131
132     }
133
134
135     /* (non-Javadoc)
136      * @see java.lang.Runnable#run()
137      */

138     public void run() {
139         if(logger.isLoggable(BasicLevel.DEBUG)){
140             logger.log(BasicLevel.DEBUG, "Sending the greeting.");
141         }
142         // Send the greeting out.
143
if (greeting != null) {
144             sendNotif(greeting);
145         }
146     }
147
148
149     /**
150      *
151      * Creates a new thread to send the greeting message and listens for
152      * rejection messages in response.
153      * @throws DuplicateServerNameException - If a server with the same ID
154      * is found in the domain.
155      */

156     public void handleGreeting() throws DuplicateServerNameException {
157         // Create a DatagramPacket to receive messages
158
DatagramPacket JavaDoc datagram = new DatagramPacket JavaDoc(
159                 new byte[RECEIVE_BUFFER_SIZE], RECEIVE_BUFFER_SIZE);
160         // Object reveived in a message
161
Object JavaDoc objReceived = null;
162         ObjectInputStream JavaDoc in = null;
163
164         // Join the group in order to receive multicast messages
165
join();
166         // Create the greeting representing a start up.
167
greeting = createDiscGreeting(true);
168         
169         // Create a unicast socket to receive responses
170
try {
171             recvUnicastSocket = new DatagramSocket JavaDoc(greetingPort);
172         } catch (SocketException JavaDoc e2) {
173             logger.log(BasicLevel.ERROR,
174                     "DiscComm : Unable to create a Datagram socket", e2);
175             // If the port is used throw a service exception.
176
throw new ServiceException("Unable to create a datagram socket on port " + greetingPort +
177                     " to listen for rejections. Port is still in use.");
178         }
179         
180         try {
181             // Set timeout for reading from the socket. If responses take longer
182
// than the timeout set, they will now be ignored.
183
recvUnicastSocket.setSoTimeout(greetingTimeOut);
184             
185             // Dont wait for messages beyond a pre-defined period of lapsed time.
186
long lastTime = greetingTimeOut + System.currentTimeMillis();
187             
188             // Create thread which will send the greeting message out.
189
Thread JavaDoc sender = new Thread JavaDoc(this, "greeting sender");
190             
191             boolean msgSent = false;
192             
193             // Listen for a specified amount of time to see if there
194
// is a server already present with the ID used.
195
while ((notStopped) && System.currentTimeMillis() <= lastTime) {
196                 // Send the discovery message out in a seperate thread
197
// if it has not been sent.
198
if(!msgSent){
199                     sender.start();
200                     msgSent = true;
201                 }
202                 // TODO: Should ideally be listening in a seperate thread and sending
203
// the discovery message shortly afterwards.
204
recvUnicastSocket.receive(datagram);
205                 in = new ObjectInputStream JavaDoc(new ByteArrayInputStream JavaDoc(datagram
206                         .getData()));
207                 objReceived = in.readObject();
208                 if (objReceived != null) {
209                     if (objReceived instanceof DiscGreeting) {
210                         DiscGreeting greet = (DiscGreeting) objReceived;
211                         // Trust the datagram packet instead of the message for address.
212
greet.setSourceAddress(datagram.getAddress().getHostAddress());
213                         handleReceivedMessage(greet);
214                     }
215                 }
216             }
217
218         } catch (SocketException JavaDoc e) {
219             logger.log(BasicLevel.ERROR,
220                     "DiscoveryGreetingResponder : Socket closed", e);
221             notStopped = false;
222         } catch (IOException JavaDoc e1) {
223             if (e1 instanceof SocketTimeoutException JavaDoc) {
224                 if (logger.isLoggable(BasicLevel.WARN)) {
225                     logger.log(BasicLevel.WARN,
226                             "No rejections receieved within the set timeout period: "
227                                 + greetingTimeOut
228                                 + " ms. Assuming the server ID used is unique in the domain."
229                                 + " The timeout period can be changed under jonas.properties:"
230                                 + " jonas.service.discovery.greeting.timeout");
231                 }
232             } else {
233                 logger.log(BasicLevel.ERROR,
234                         "DiscoveryGreetingResponder IOException", e1);
235             }
236         } catch (ClassNotFoundException JavaDoc e) {
237             logger.log(BasicLevel.ERROR,
238                     "DiscoveryGreetingResponder ClassNotFoundException ", e);
239         }
240
241     }
242
243     /**
244      * Throw the run time exception to state that a server with the same
245      * name already exists.
246      */

247     public void stop() {
248         throw new DuplicateServerNameException();
249     }
250
251 }
252
Popular Tags