Source code: com/flexstor/common/util/AppServerClient.java
1 /*
2 * AppServerClient.java
3 *
4 * Copyright $Date: 2003/08/11 02:22:31 $ FLEXSTOR.net Inc.
5 *
6 * This work is licensed for use and distribution under license terms found at
7 * http://www.flexstor.org/license.html
8 *
9 */
10
11 package com.flexstor.common.util;
12
13 import java.io.IOException;
14 import java.io.PrintWriter;
15 import java.io.StringWriter;
16 import java.rmi.Naming;
17 import java.rmi.RemoteException;
18
19 import com.flexstor.common.constants.ServicesI;
20 import com.flexstor.common.data.ActionData;
21 import com.flexstor.common.data.ActionResult;
22 import com.flexstor.common.exceptions.AppServiceFailedException;
23 import com.flexstor.common.resources.Resources;
24 import com.flexstor.common.services.RMIServiceBrokerI;
25 import com.flexstor.common.settings.Settings;
26
27 /**
28 * This class wraps around the proxy and encapsulates any CORBA specific
29 * code and mappings.
30 */
31 public class AppServerClient
32 implements Runnable
33 {
34 private static String sVersion;
35 private static RMIServiceBrokerI broker = null;
36 private static boolean bRetryRequest = true; // To retry remote request just once in
37 // case of failure.
38
39 public AppServerClient()
40 {
41 super();
42 sVersion = Resources.get(5049);
43 }
44
45 /**
46 * Initializes the remote connection in a new thread,
47 * tests after n milliseconds for success, otherwise throws a NamingException
48 * @param nMilliSeconds ms to wait for check
49 */
50 public static void initialize(int nMilliSeconds)
51 throws RemoteException
52 {
53 long time = 0L;
54 long duration = 0L;
55
56 Thread t = new Thread( new AppServerClient(), "OAS Lookup Thread");
57 time = System.currentTimeMillis();
58
59 t.start();
60 try
61 {
62 t.join(nMilliSeconds); // wait nMilliSeconds to perform lookup, then cancel
63 duration = System.currentTimeMillis() - time;
64 Diagnostic.trace(Diagnostic.CAT_OAS, "Lookup duration[ms]=" + duration);
65 }
66 catch(InterruptedException e) {}
67 if (broker == null)
68 {
69 if (duration >= nMilliSeconds )
70 Diagnostic.trace(Diagnostic.CAT_OAS, "Naming lookup timed out after " + nMilliSeconds + "ms." );
71 throw new RemoteException("Unable to connect to application server");
72 }
73 }
74
75
76 private void init ( )
77 throws Exception
78 {
79
80 Diagnostic.trace(Diagnostic.CAT_OAS, "Initalizing Service Broker");
81
82 // Try the naming lookup.
83 String sServer = Settings.getString( Settings.CLIENT_RMI_HOST );
84 String sPort = Settings.getString( Settings.CLIENT_RMI_PORT );
85 String sLookupString = "rmi://" + sServer;
86 if ( sPort != null && sPort.equals("") == false )
87 sLookupString += ":" + sPort;
88 sLookupString += "/" + ServicesI.SERVICE_BROKER;
89
90 Diagnostic.trace(Diagnostic.CAT_OAS, " Looking for: " + sLookupString);
91 broker = (RMIServiceBrokerI) Naming.lookup(sLookupString);
92 Diagnostic.trace(Diagnostic.CAT_OAS, "Broker: " + broker);
93 Diagnostic.trace(Diagnostic.CAT_OAS, "Naming lookup completed successfully." );
94
95 sVersion = broker.ping();
96 Diagnostic.trace(Diagnostic.CAT_OAS, "ServiceBroker version: " + sVersion);
97 Settings.addString ( Settings.APP_SERVER_VERSION, sVersion );
98 }
99 /**
100 * Perform initialization in a new thread, ignores any exceptions
101 */
102 public void run()
103 {
104 try
105 {
106 init();
107 }
108 catch(Throwable t)
109 {
110 Diagnostic.trace(Diagnostic.CAT_OAS, "Error initializing ServiceBroker: " + t);
111 }
112 }
113
114 public static int getUniqueNo()
115 throws RemoteException
116 {
117 try
118 {
119 if ( broker == null )
120 // this might throw a NamingException
121 initialize( 120000 ); // wait up to 10 seconds
122
123 int nTransId = broker.getUniqueNo();
124 if ( nTransId == -1 )
125 throw new Throwable();
126
127 Diagnostic.trace( Diagnostic.CAT_OAS, "Retrieved Transaction Id = " + nTransId );
128
129 bRetryRequest = true;
130
131 return nTransId;
132 }
133 catch( Throwable e )
134 {
135 broker = null;
136 if (bRetryRequest)
137 {
138 // Set to false, no more retries after this
139 bRetryRequest = false;
140 return getUniqueNo();
141 }
142 else
143 {
144 // Set to true, so next request has a chance to retry
145 bRetryRequest = true;
146 throw ( new RemoteException( "Unable to retrieve Transaction Id.", e.fillInStackTrace() ) );
147 }
148 }
149 }
150
151
152 /**
153 * Adds the QItem (data wrapper) to the remote service queue.
154 * This is an asynchronous invocation. i.e. the call returns
155 * before the service has finished.
156 * @param qi the new QItem
157 * @return the result data containing the assigned transaction id
158 */
159 public static ActionResult addQItem(ActionData qi)
160 throws RemoteException
161 {
162 return remoteRequest(false, qi);
163 }
164
165 /**
166 * Invokes the service synchronously, i.e. the call
167 * return after the service has completed.
168 * @param qi the QItem
169 * @return the result data containing the assigned transaction id
170 */
171 public static ActionResult invokeImmediately(ActionData qi)
172 throws RemoteException
173 {
174 return remoteRequest(true, qi);
175 }
176
177 /**
178 * Performs the remote request.
179 * Re-throws any exceptions and wraps them into a RemoteException.
180 * This avoids code changes in all users of this class.
181 * @param bImmediately indicates if this is a synchronous request
182 * @param the QItem
183 * @throw java.rmi.RemoteException
184 */
185 private static ActionResult remoteRequest(boolean bImmediately, ActionData qi)
186 throws AppServiceFailedException
187 {
188 ActionResult result;
189
190 try
191 {
192 if (broker == null)
193 // this might throw a NamingException
194 initialize(120000); // wait up to 10 seconds
195
196 if (bImmediately)
197 result = (ActionResult)broker.invokeImmediately ( qi );
198 else
199 result = (ActionResult)broker.addQItem ( qi );
200
201 Diagnostic.trace(Diagnostic.CAT_OAS, "Transaction created. Id=" + result.getId());
202
203 // Set to true, so next request has a chance to retry.
204 bRetryRequest = true;
205 return result;
206 }
207
208
209 // any unchecked exception/error
210 catch(Throwable e)
211 {
212 broker = null;
213 int resID;
214 String trace = null;
215 if (bRetryRequest)
216 {
217 // Set to false, no more retries after this
218 bRetryRequest = false;
219 return remoteRequest(bImmediately, qi);
220 }
221 else
222 {
223 bRetryRequest = true;
224 }
225 if ( e instanceof RemoteException )
226 {
227 resID = 6188;
228 trace = getStackTrace(e);
229 }
230 else if (e instanceof NoClassDefFoundError)
231 {
232 resID = 6190;
233 trace = getStackTrace(e);
234 }
235 else if (e instanceof ClassNotFoundException)
236 {
237 resID = 6190;
238 trace = getStackTrace(e);
239 }
240 else
241 {
242 resID = 6189;
243 trace = getStackTrace(e);
244 }
245 throw ( new AppServiceFailedException ( resID, trace, e ) );
246 }
247 } // remoteRequest
248
249 private static String getStackTrace(Throwable t)
250 {
251 String sTrace = "";
252
253 try
254 {
255 StringWriter sw = new StringWriter();
256 PrintWriter pw = new PrintWriter(sw, true);
257 t.printStackTrace(pw);
258 sTrace = sw.toString();
259 pw.close();
260 sw.close();
261
262 // Needed for JDK 1.1 (Only Java2 throws this exception)
263 if ( false )
264 throw new IOException();
265 }
266 catch ( IOException e )
267 {
268 }
269
270 return sTrace;
271 }
272
273 } // end of class