Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/flexstor/common/gateway/Gateway.java


1   /*
2    * Gateway.java
3    *
4    * Copyright $Date: 2003/08/11 02:22:29 $ 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.gateway;
12  
13  import java.io.InterruptedIOException;
14  import java.rmi.RemoteException;
15  import java.util.Vector;
16  
17  import com.flexstor.common.constants.EjbHomeInterfacesI;
18  import com.flexstor.common.exceptions.ejb.EjbException;
19  import com.flexstor.common.gateway.debug.GatewayDebugOutput;
20  import com.flexstor.common.gateway.debug.GatewayDebugUtil;
21  import com.flexstor.common.gateway.engine.GatewayEngineI;
22  import com.flexstor.common.gateway.exceptions.GatewayInitException;
23  import com.flexstor.common.gateway.exceptions.TransactionFailedException;
24  import com.flexstor.common.resources.Resources;
25  import com.flexstor.ejb.EjbHome;
26  import com.flexstor.ejb.EjbObject;
27  
28  /**
29   * Core class of the Server Gateway Framework
30   * @author Dan Schroeder
31   * @version 3.0
32   */
33  public abstract class Gateway
34     implements EjbHomeInterfacesI
35  {
36     /** Refrence to the current engine */
37     protected static GatewayEngineI    engine        = null;
38  
39     /** True if the gateway framework has been initialized */
40     protected static boolean             bInitialized  = false;
41     
42     /** Debug objects */
43     protected static boolean             bSaveObjects  = false;
44     protected static boolean             bLoadObjects  = false;
45     protected static GatewayDebugUtil  util          = null;
46     
47     /** Manages gateway heartbeats. */
48     private   static long                nBeatDuration = 120000; // 2 Min.
49     private   static HeartbeatManager  heartbeat     = null;
50  
51     
52     /**
53      * Returns the name of the home interface.
54      * @return the home interface name
55      */
56     protected abstract String getHomeName ( );
57  
58  
59     /**
60      * Returns the instance of the current bean, or null if the bean has not been created.
61      * @return an instance of EjbObject.
62      */
63     protected abstract EjbObject getBeanObject ( );
64  
65     /**
66      * Checks to see if the gateway framework has been properly initialized.
67      * @return true if the gateway has been initalized.
68      */
69     public static boolean isInitalized ( )
70     {
71        return bInitialized;
72     }
73  
74     /**
75      * Returns the home interface for the specified published name.
76      * @param sPubName the name of the home interface to retrieve.
77      * @return the home interface
78      * @throws Exception throws if sPubName is not found,
79      */
80     protected EjbHome getHome ( )
81        throws Exception
82     {
83        // Check to see if the gateway was initialized.
84        if ( !bInitialized )
85           throw new GatewayInitException ( "Gateway not initialized." );
86  
87        return engine.getHome ( getHomeName() );
88     }
89  
90     /**
91      * Reformats the given exception to a TransactionFailedException.
92      * This method also performs error logging, so it is important that this method be called
93      * whenever an incoming exception occurs.
94      * @param The generic exception.
95      * @return The TransactionFailedException.
96      */
97     protected TransactionFailedException buildException ( Throwable e )
98     {
99        return buildException( e, "", "" );
100    }
101 
102    /**
103     * Reformats the given exception to a TransactionFailedException.
104     * This method also performs error logging, so it is important that this method be called
105     * whenever an incoming exception occurs.
106     * @param e The generic exception.
107     * @param sSourceModule The Source Module where the exception was originated.
108     * @param sClassIndentifier The Identifier for the Class where the exception was originated.
109     * @return The TransactionFailedException.
110     */
111    protected TransactionFailedException buildException ( Throwable e, String sSourceModule, String sClassIdentifier )
112    {
113       String sMessage = null;
114 
115       if ( e instanceof EjbException )
116       {
117          EjbException ejb       = (EjbException)e;
118          int            nResource = ejb.getResourceId();
119          Vector         vParams   = ejb.getParmeters();
120 
121          String sa[] = { "", "", "", "", "" };
122          if ( vParams != null )
123             vParams.copyInto ( sa );
124 
125          sMessage = Resources.get ( nResource, true, sa[0], sa[1], sa[2], sa[3], sa[4] );
126       }
127       else if ( e instanceof Error )
128          sMessage = Resources.get ( 5839, true );
129       else
130          sMessage = Resources.get ( 5840, true );
131 
132       if ( e instanceof RemoteException && ((RemoteException)e).detail instanceof InterruptedIOException )
133          Thread.currentThread().interrupt(); // reassert the interrupt
134       else
135       {
136          // Send error to Diagnostic
137          GatewayDebugOutput.printStackTrace ( sMessage, e );
138 
139          // Log error
140          GatewayDebugOutput.logError( sMessage, e, sSourceModule, sClassIdentifier );
141       }
142 
143       // Future code should reformat this exception.
144       return new TransactionFailedException ( e );
145    }
146 
147 
148    /**
149     * Shuts down the gatway framework by stopping the heartbeat thread and closing all open JNDI contexts.
150     */
151    protected void shutdown ( )
152    {
153       if ( heartbeat != null )
154          heartbeat.terminate();
155 
156       engine.closeAllContexts();
157    }
158 
159 
160    /**
161     * Cleans up the gateway.
162     * NOTE: This method MUST be called to stop heartbeats from going to the EJB if beginHeartbeats() has been called.
163     * NOTE: This methos MUST be called if you wish the server to immediately cleanup (passivate) this EJB.
164     */
165    public void dispose ( )
166    {
167       try
168       {
169          // Get the object.
170          EjbObject o = getBeanObject();
171 
172          // Debug message.
173          if ( o != null )
174          {
175             GatewayDebugOutput.println ( 4, "Dispose " + EBJObjectToString(o) );
176 
177             // Stop heartbeats if they are on.
178             if ( heartbeat != null )
179                heartbeat.removeObject ( o );
180 
181 
182             // This code is disabled due to bugs in Oracle 8i.  This code should be enabled when
183             // oracle stops throwing exceptions on a remove().
184             if ( !canLoadObject() )
185                o.remove();
186          }
187       }
188       catch ( Throwable e )  { }
189    }
190 
191 
192    /**
193     * Enables debugging (serialization of objects to files).
194     * @param sBasePath the platform specific path of the directory to store objects in.
195     * @param bSave incoming objects are saved if true.
196     * @param bLoad loads objects from files instead of getting them from the server.
197     * @throws GatewayInitException if both bSave and bLoad are true.
198     */
199    public static void enableDebugging ( String sBasePath, boolean bSave, boolean bLoad )
200       throws GatewayInitException
201    {
202       if ( bSaveObjects && bLoadObjects )
203          throw new GatewayInitException ( "Cannot save and load objects in same debug session." );
204          
205       util = new GatewayDebugUtil ( sBasePath, 4096 );
206       bSaveObjects = bSave;
207       bLoadObjects = bLoad;
208    }
209    
210    
211    /**
212     * Returns true if object saving is on.
213     */
214    protected boolean canSaveObject ( )
215    {
216       return bSaveObjects;
217    }
218    
219 
220    /**
221     * Returns true if object loading is on.
222     */
223    protected boolean canLoadObject ( )
224    {
225       return bLoadObjects;
226    }
227 
228    
229    /**
230     * Stores an object to a file.
231     * @param sName   a unique name for the object.
232     * @param o       the object to store.
233     * @param bUpdate update the CSO Database if true.
234     */
235    protected void storeObject ( String sName, Object o, boolean bUpdate )
236       throws Throwable
237    {
238       util.storeObject ( sName, o, bUpdate );
239    }
240 
241 
242    /**
243     * Stores an object to a file.
244     * @param sName a unique name for the object.
245     * @param o the object to store.
246     */
247    protected void storeObject ( String sName, Object o )
248       throws Throwable
249    {
250       util.storeObject ( sName, o, true );
251    }
252 
253 
254    /**
255     * Loads an object from a file.
256     * @param sName a unique name for the object.
257     * @return the object.
258     */
259    protected Object retrieveObject ( String sName )
260       throws Throwable
261    {
262       return util.retrieveObject ( sName );
263    }
264    
265    
266    /**
267     * Converts an ROEJBObject reference to a String and limits it to 100 characters.
268     * @param o the EjbObject
269     * @return the string form of o
270     */
271    public String EBJObjectToString ( EjbObject o )
272    {
273       String s = "" + o;
274       if ( s.length() > 100 )
275          s = s.substring ( 0, 100 );
276 
277       return s;
278    }
279 
280    
281    /**
282     * Starts sending heartbeats to the EJB server for the specified object.  Call dispose() 
283     * to stop the heartbeats for this bean.
284     *
285     * This method does not cause the heartbeat to be sent right away.  In the worst case it will take the
286     * full heartbeat duration (nBeatDuration) before a heartbeat is sent.
287     */
288    public void beginHeartbeats ( )
289    {
290       if ( heartbeat == null )
291          heartbeat = new HeartbeatManager ( nBeatDuration );
292 
293       heartbeat.addObject ( getBeanObject() );
294    }
295 
296 
297    /**
298     * Manages heartbeats for all instances of the server gateway framework.
299     */
300    private class HeartbeatManager
301       extends Thread
302    {
303       private boolean bStop;
304       private long    nBeatDuration;
305       private Vector  vObjects;
306 
307       public HeartbeatManager ( long nBeatDuration )
308       {
309          super ( "Server Gateway Heartbeat Thread" );
310          setPriority ( NORM_PRIORITY - 1 );
311          
312          GatewayDebugOutput.println ( 6, "Initalizing Server Gateway Heartbeat Manager"  );
313 
314          this.bStop         = false;
315          this.vObjects      = new Vector();
316          this.nBeatDuration = nBeatDuration;
317          this.start();
318       }
319 
320       public void run ( )
321       {
322          if ( canLoadObject() )
323             return;
324 
325          while ( !bStop )
326          {
327             service();
328 
329             try
330             {
331                sleep ( nBeatDuration );
332             }
333             catch ( InterruptedException e )
334             {
335                GatewayDebugOutput.println ( 6, "Heartbeat thread was interrupted."  );
336             }
337          }
338       }
339 
340       public void service ( )
341       {
342          // Broadcast heartbeats.
343          GatewayDebugOutput.println ( 6, "Servicing heartbeat thread..."  );
344 
345          EjbObject o;
346          for ( int i = 0; i < vObjects.size(); i++ )
347          {
348             o = (EjbObject)vObjects.elementAt(i);
349             GatewayDebugOutput.println ( 6, "Calling keepAlive() for " + EBJObjectToString(o) + "." );
350 
351             try
352             {
353                o.keepAlive();
354             }
355             catch ( Throwable t )
356             {
357                GatewayDebugOutput.printStackTrace ( "keepAlive() failed!!!", t );
358             }
359          }
360       }
361 
362       private synchronized void terminate ( )
363       {
364          GatewayDebugOutput.println ( 6, "Terminating heartbeat thread..."  );
365          bStop = true;
366          interrupt();
367 
368          // Make sure that dispose() is called on all the active beans.
369          EjbObject o;
370          for ( int i = 0; i < vObjects.size(); i++ )
371          {
372             o = (EjbObject)vObjects.elementAt(i);
373 
374             try
375             {
376                o.remove();
377                GatewayDebugOutput.println ( 6, "Heartbeat manager disposed of " + EBJObjectToString(o) );
378             }
379             catch ( Exception e )
380             {
381                GatewayDebugOutput.println ( 6, "Heartbeat manager could not dispose of " + EBJObjectToString(o) );
382             }
383          }
384       }
385 
386       public synchronized void addObject ( EjbObject o )
387       {
388          if ( canLoadObject() )
389             return;
390 
391          GatewayDebugOutput.println ( 6, "Adding heartbeat for " + EBJObjectToString(o) + "." );
392          if ( !vObjects.contains(o) )
393             vObjects.addElement ( o );
394       }
395 
396       public synchronized void removeObject ( EjbObject o )
397       {
398          if ( vObjects.contains(o) )
399          {
400             GatewayDebugOutput.println ( 6, "Removing heartbeat for " + EBJObjectToString(o) + "." );
401             vObjects.removeElement ( o );
402          }
403       }
404    }
405 }