KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > management > support > Loader


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23  
24 /*
25  */

26
27 package com.sun.enterprise.management.support;
28
29 import java.util.List JavaDoc;
30 import java.util.ArrayList JavaDoc;
31 import java.util.Map JavaDoc;
32 import java.util.HashMap JavaDoc;
33 import java.util.Collections JavaDoc;
34 import java.util.Iterator JavaDoc;
35 import java.io.IOException JavaDoc;
36
37 import java.lang.reflect.Proxy JavaDoc;
38
39 import javax.management.ObjectName JavaDoc;
40 import javax.management.MBeanServer JavaDoc;
41 import javax.management.Notification JavaDoc;
42 import javax.management.MBeanServerNotification JavaDoc;
43 import javax.management.InstanceNotFoundException JavaDoc;
44 import javax.management.MBeanRegistrationException JavaDoc;
45 import javax.management.InstanceAlreadyExistsException JavaDoc;
46 import javax.management.NotCompliantMBeanException JavaDoc;
47
48 import javax.management.relation.MBeanServerNotificationFilter JavaDoc;
49
50
51 import com.sun.appserv.management.base.XTypes;
52 import com.sun.appserv.management.base.Util;
53
54 import com.sun.appserv.management.util.jmx.stringifier.NotificationStringifier;
55 import com.sun.appserv.management.util.jmx.JMXUtil;
56 import com.sun.appserv.management.util.jmx.MBeanProxyHandler;
57 import com.sun.appserv.management.util.jmx.MBeanServerConnectionSource;
58 import com.sun.appserv.management.util.jmx.stringifier.StringifierRegistryIniter;
59
60 import com.sun.appserv.management.util.misc.ExceptionUtil;
61
62 import com.sun.appserv.management.util.stringifier.StringifierRegistryIniterImpl;
63 import com.sun.appserv.management.util.stringifier.StringifierRegistryImpl;
64
65 import com.sun.appserv.management.DomainRoot;
66 import com.sun.appserv.management.client.ProxyFactory;
67
68 import com.sun.enterprise.management.support.TypeInfos;
69 import com.sun.enterprise.management.DomainRootImpl;
70
71 /**
72     Implements loading of all MBean API MBeans WITHIN the DAS (Domain Admin Server).
73  */

74 public final class Loader extends LoaderBase
75 {
76     private boolean mQueuedAll;
77     private List JavaDoc<LoaderOfOld> mLoaders;
78     private Map JavaDoc<ObjectName JavaDoc,ObjectName JavaDoc> mOldToNewObjectNames;
79     private LoaderRegThread mRegThread;
80     
81     private final DeferredRegistrationThread mDeferredRegistrationThread;
82     
83         public
84     Loader()
85     {
86         mOldToNewObjectNames =
87             Collections.synchronizedMap( new HashMap JavaDoc<ObjectName JavaDoc,ObjectName JavaDoc>() );
88         
89         mQueuedAll = false;
90         
91         mLoaders = null;
92         
93         mRegThread = null;
94         
95         mDeferredRegistrationThread = new DeferredRegistrationThread();
96         mDeferredRegistrationThread.start();
97                 
98     }
99     
100         protected void
101     preRegisterHook()
102     {
103         mRegThread = new LoaderRegThread( this, mLogger );
104         mRegThread.start();
105     }
106     
107     /**
108         WORKAROUND_FOR_BUG_SRIDATTA_FOUND (force synchronous handling)
109         (not an AMX bug, rather an internal bug in server startup sequence).
110      */

111     private static final boolean SYNCHRONOUS_NOTIFICATION_HANDLING = true;
112         
113         public void
114     handleNotification(
115         final Notification JavaDoc notifIn,
116         final Object JavaDoc handback)
117     {
118         final String JavaDoc type = notifIn.getType();
119         
120         if ( notifIn instanceof MBeanServerNotification JavaDoc )
121         {
122             trace( "Loader.handleNotification: received: " +
123                 NotificationStringifier.toString( notifIn ) );
124                 
125             final MBeanServerNotification JavaDoc notif = (MBeanServerNotification JavaDoc)notifIn;
126             
127             final ObjectName JavaDoc objectName = notif.getMBeanName();
128             
129             if ( shouldSync( objectName ) )
130             {
131                 final boolean register =
132                     type == MBeanServerNotification.REGISTRATION_NOTIFICATION;
133                     
134                 /** WORKAROUND_FOR_BUG_SRIDATTA_FOUND (force synchronous handling) */
135                 if ( SYNCHRONOUS_NOTIFICATION_HANDLING )
136                 {
137                     if ( register )
138                     {
139                         mRegThread.processRegistration( objectName );
140                     }
141                     else
142                     {
143                         mRegThread.processUnregistration( objectName );
144                     }
145                 }
146                 else
147                 {
148                     mRegThread.enqueue( register, objectName );
149                 }
150             }
151         }
152     }
153     
154     private static final long WAIT_THRESHOLD_MILLIS = 5 * 1000; // 5 seconds
155

156         public void
157     handleMBeanRegistered( final ObjectName JavaDoc oldObjectName )
158         throws InstanceNotFoundException JavaDoc
159     {
160         trace( "handleMBeanRegistered: " + oldObjectName );
161         
162         if ( shouldSync( oldObjectName ) )
163         {
164             final long start = now();
165             
166             while ( ! getMBeanServer().isRegistered( oldObjectName ) &&
167                     (now() - start) < WAIT_THRESHOLD_MILLIS )
168             {
169                 mySleep( 50 );
170             }
171             
172             if ( ! getMBeanServer().isRegistered( oldObjectName ) )
173             {
174                 trace( "Loader.handleMBeanRegistered: not found!!!" );
175                 throw new InstanceNotFoundException JavaDoc( oldObjectName.toString() );
176             }
177             
178             try
179             {
180                 sync( oldObjectName );
181             }
182             catch( Exception JavaDoc e )
183             {
184                 final Throwable JavaDoc rootCause = ExceptionUtil.getRootCause( e );
185                 if ( rootCause instanceof DeferRegistrationException )
186                 {
187                     mDeferredRegistrationThread.defer( oldObjectName );
188                 }
189             }
190         }
191     }
192     
193     /**
194         Cascaded MBeans are problematic because some of them get registered before
195         MBeans that contain them. For most MBeans this is a non-issue, but the workaround
196         code in LoaderOfOldMonitor.MyOldTypes.oldTypeToJ2EEType() can't deal with this situation,
197         thus this facility exists to allow retry of problematically-registered MBeans.
198         
199         The need will go away if the underlying monitoring MBeans are fixed so that the workaround
200         code is no longer needed.
201      */

202     private final class DeferredRegistrationThread extends Thread JavaDoc
203     {
204         private final List JavaDoc<DeferredItem> mDeferredItems;
205         private boolean mSleeping;
206         
207         private final class DeferredItem
208         {
209             public long mStartMillis;
210             public final ObjectName JavaDoc mObjectName;
211             
212                 public
213             DeferredItem( final ObjectName JavaDoc objectName )
214             {
215                 mObjectName = objectName;
216                 mStartMillis = now();
217             }
218         };
219         
220         private final long RETRY_INTERVAL_MILLIS = 1000;
221         private final long MAX_DELAY_MILLIS = 1 * 60 * 1000;
222         
223             public
224         DeferredRegistrationThread( )
225         {
226             mDeferredItems = Collections.synchronizedList( new ArrayList JavaDoc<DeferredItem>() );
227             
228             mSleeping = false;
229         }
230         
231             private synchronized void
232         internalDefer( final DeferredItem item )
233         {
234             // even though it's a synchronized List, we still need to do this because
235
// takeAllItems() needs to be able to make an array the clearing the list,
236
// which is two operations.
237
synchronized( mDeferredItems )
238             {
239                 mDeferredItems.add( item );
240             }
241         }
242         
243             public synchronized void
244         defer( final ObjectName JavaDoc oldObjectName )
245         {
246             logFine( "Deferring registration for " + quote( oldObjectName ) );
247             
248             internalDefer( new DeferredItem( oldObjectName ) );
249             
250             if ( mSleeping )
251             {
252                 this.interrupt();
253             }
254             
255         }
256         
257             private DeferredItem[]
258         takeAllItems()
259         {
260             synchronized( mDeferredItems )
261             {
262                 final DeferredItem[] items = new DeferredItem[ mDeferredItems.size() ];
263                 mDeferredItems.toArray( items );
264                 mDeferredItems.clear();
265                 return( items );
266             }
267         }
268         
269             private ObjectName JavaDoc
270         retry( final ObjectName JavaDoc oldObjectName )
271         {
272             return sync( oldObjectName );
273         }
274         
275         
276             private void
277         retryItem( final DeferredItem item)
278         {
279             final ObjectName JavaDoc oldObjectName = item.mObjectName;
280             
281             final String JavaDoc prefix = "DeferredRegistrationThread.retryItem: ";
282             final long elapsed = now() - item.mStartMillis;
283             try
284             {
285                 final ObjectName JavaDoc result = retry( oldObjectName );
286                 
287                 final String JavaDoc msg = prefix + "deferred registration SUCCEEDED after " +
288                     elapsed + " milliseconds for " + quote( oldObjectName ) +
289                     ", amx ObjectName = " + quote( result );
290                 
291                 getMBeanLogger().info( msg );
292             }
293             catch( Throwable JavaDoc t )
294             {
295                 final Throwable JavaDoc rootCause = ExceptionUtil.getRootCause( t );
296                 
297                 if ( rootCause instanceof DeferRegistrationException )
298                 {
299                     if ( elapsed < MAX_DELAY_MILLIS )
300                     {
301                         logWarning( prefix +
302                         "deferred registration RETRY failed after " +
303                             elapsed + " milliseconds for " + quote( oldObjectName ) + " (DEFERRING AGAIN)" );
304                         internalDefer( item );
305                     }
306                     else
307                     {
308                         logWarning( prefix +
309                             "Deferred registration FAILED for " + quote( oldObjectName ) +
310                             "after deferral of " + elapsed + " ms, ignoring MBean." );
311                     }
312                 }
313                 else
314                 {
315                     logWarning( prefix +
316                         "Deferred registration FAILED for " + quote( oldObjectName ) +
317                         "due to Exception of type " + rootCause.getClass().getName() );
318                 }
319             }
320         }
321         
322             private void
323         checkList()
324         {
325             final DeferredItem[] items = takeAllItems();
326             
327             logFine( "DeferredRegistrationThread.checkList: numItems = " + items.length );
328                     
329             for( int i = 0; i < items.length; ++i )
330             {
331                 final DeferredItem item = items[ i ];
332                 
333                 if ( getMBeanServer().isRegistered( item.mObjectName ) )
334                 {
335                     retryItem( item );
336                 }
337                 else
338                 {
339                     logInfo(
340                         "DeferredRegistrationThread.checkList: " +
341                         "MBean is no longer registered: " + quote( item.mObjectName ) );
342                 }
343             }
344         }
345         
346             public void
347         run()
348         {
349             while ( true )
350             {
351                 try
352                 {
353                     getMBeanLogger().fine( "DeferredRegistrationThread.run: CHECKING LIST@" + now() );
354                     checkList();
355                     
356                     // force a delay for efficiency in batching deferred items
357
final long sleepMillis = mDeferredItems.size() == 0 ? 60 * 1000 : RETRY_INTERVAL_MILLIS;
358                     getMBeanLogger().fine( "DeferredRegistrationThread.run: SLEEPING FOR: " + sleepMillis + "@" + now() );
359                     mSleeping = true;
360                     final boolean interrupted = mySleep( sleepMillis );
361                     mSleeping = false;
362                 }
363                 catch( Throwable JavaDoc t )
364                 {
365                     getMBeanLogger().warning( "DeferredRegistrationThread.run: caught Throwable:\n" +
366                         ExceptionUtil.getStackTrace( t ) );
367                 }
368             }
369         }
370     }
371     
372         public void
373     handleMBeanUnregistered( final ObjectName JavaDoc oldObjectName )
374         throws InstanceNotFoundException JavaDoc, MBeanRegistrationException JavaDoc
375     {
376         trace( "handleMBeanUnregistered: " + oldObjectName );
377         
378         final ObjectName JavaDoc newObjectName =
379             mOldToNewObjectNames.remove( oldObjectName );
380             
381         if ( newObjectName != null && getMBeanServer().isRegistered( newObjectName ) )
382         {
383             debug( "unregistering: " + newObjectName + " corresponding to " + oldObjectName );
384             getMBeanServer().unregisterMBean( newObjectName );
385         }
386     }
387     
388         synchronized ObjectName JavaDoc
389     registerNew(
390         final Object JavaDoc impl,
391         final ObjectName JavaDoc implObjectName,
392         final ObjectName JavaDoc oldObjectName )
393         throws MBeanRegistrationException JavaDoc,
394             InstanceAlreadyExistsException JavaDoc, NotCompliantMBeanException JavaDoc
395     {
396         debug( "registering: " + implObjectName + " corresponding to " + oldObjectName );
397             
398         final ObjectName JavaDoc resultName =
399             getMBeanServer().registerMBean( impl, implObjectName ).getObjectName();
400             
401         mOldToNewObjectNames.put( oldObjectName, resultName );
402         
403         return( resultName );
404     }
405     
406         public ObjectName JavaDoc
407     loadSystemInfo( final MBeanServer JavaDoc server )
408         throws NotCompliantMBeanException JavaDoc, MBeanRegistrationException JavaDoc,
409         InstanceAlreadyExistsException JavaDoc
410     {
411         final BootUtil bootUtil = BootUtil.getInstance();
412         
413         final SystemInfoImpl systemInfo = new SystemInfoImpl( server, bootUtil );
414         
415         final ObjectName JavaDoc tempName = mObjectNames.getSingletonObjectName( systemInfo.J2EE_TYPE );
416         
417         final ObjectName JavaDoc objectName = mServer.registerMBean( systemInfo, tempName ).getObjectName();
418         
419         debug( "loaded SystemInfo" );
420         return( objectName );
421     }
422         
423         private void
424     addLoaders()
425     {
426         assert( getMBeanServer() != null );
427         assert( getMBeanLogger() != null );
428         
429         final List JavaDoc<LoaderOfOld> loaders = new ArrayList JavaDoc<LoaderOfOld>();
430         loaders.add( new LoaderOfOldConfig( this ) );
431         loaders.add( new LoaderOfOld77( this ) );
432         loaders.add( new LoaderOfOldMonitor( this ) );
433         mLoaders = Collections.unmodifiableList( loaders );
434     }
435         
436
437     
438         private boolean
439     shouldSync( ObjectName JavaDoc oldObjectName )
440     {
441         return( findLoaderOfOld( oldObjectName ) != null );
442     }
443     
444         private LoaderOfOld
445     findLoaderOfOld( final ObjectName JavaDoc candidate )
446     {
447         LoaderOfOld oldLoader = null;
448         
449         for( final LoaderOfOld loo : mLoaders )
450         {
451             if ( loo.shouldSync( candidate ) )
452             {
453                 oldLoader = loo;
454                 break;
455             }
456         }
457         return( oldLoader );
458     }
459
460         public ObjectName JavaDoc
461     sync( final ObjectName JavaDoc oldObjectName )
462     {
463         if ( ! mStarted )
464         {
465             throw new IllegalArgumentException JavaDoc();
466         }
467         
468         if ( ! shouldSync( oldObjectName ) )
469         {
470             throw new IllegalArgumentException JavaDoc( oldObjectName.toString() );
471         }
472         
473         
474         // for remote testing--ensure that oldObjectName is present
475
// should never happen when in-process
476
long millis = 200;
477         while ( ! getMBeanServer().isRegistered( oldObjectName ) )
478         {
479             mySleep( millis );
480             millis *= 2;
481             if ( millis > 500 )
482             {
483                 getMBeanLogger().info( "Loader.sync: waiting for MBean to load: " + oldObjectName );
484             }
485         }
486         
487         
488         ObjectName JavaDoc result = null;
489         try
490         {
491             final LoaderOfOld loaderOfOld = findLoaderOfOld( oldObjectName );
492             
493             if ( loaderOfOld != null )
494             {
495                 result = loaderOfOld.syncWithOld( oldObjectName );
496                 if ( result == null )
497                 {
498                     throw new IllegalArgumentException JavaDoc( oldObjectName.toString() );
499                 }
500             }
501         }
502         catch( Exception JavaDoc e )
503         {
504             final String JavaDoc msg = ExceptionUtil.toString( e );
505             debug( msg );
506             getMBeanLogger().fine( msg );
507             
508             if ( e instanceof RuntimeException JavaDoc )
509             {
510                 throw (RuntimeException JavaDoc)e;
511             }
512             else
513             {
514                 throw new RuntimeException JavaDoc( e );
515             }
516         }
517         
518         return( result );
519     }
520     
521         private void
522     queueAll()
523     {
524         for( final LoaderOfOld oldLoader : mLoaders )
525         {
526             final List JavaDoc oldObjectNames = oldLoader.findAllOld();
527             mRegThread.enqueue( true, oldObjectNames );
528             
529             getMBeanLogger().fine( "Loader: Queued " + oldObjectNames.size() +
530                 " MBeans for loader " + oldLoader.getClass().getName() );
531         }
532     }
533     
534     
535         protected void
536     startHook()
537     {
538         super.startHook();
539         
540         addLoaders();
541         queueAll();
542         mQueuedAll = true;
543     }
544     
545         public boolean
546     isStarted( )
547     {
548         return super.isStarted() && mQueuedAll &&
549             mRegThread.getRegistrationQueueSize() == 0;
550     }
551     
552         protected Object JavaDoc
553     createDomainRoot()
554     {
555         return new DomainRootImpl();
556     }
557     
558         public boolean
559     isDAS()
560     {
561         return true;
562     }
563     
564         public ObjectName JavaDoc
565     resyncAMXMBean( final ObjectName JavaDoc amx )
566         throws InstanceNotFoundException JavaDoc, MBeanRegistrationException JavaDoc
567     {
568         if ( ! getMBeanServer().isRegistered( amx ) )
569         {
570             throw new InstanceNotFoundException JavaDoc();
571         }
572         if ( ! getAMXJMXDomainName().equals( amx.getDomain() ) )
573         {
574             throw new IllegalArgumentException JavaDoc( "" + amx );
575         }
576         
577         debug( "resyncAMXMBean: looking for matching delegate MBean" );
578         ObjectName JavaDoc old = null;
579         for( final ObjectName JavaDoc oldTemp : mOldToNewObjectNames.keySet() )
580         {
581             if ( mOldToNewObjectNames.get( oldTemp ).equals( amx ) )
582             {
583                 old = oldTemp;
584                 debug( "resyncAMXMBean: found matching delegate MBean: " + old );
585                 break;
586             }
587         }
588         
589         if ( old == null )
590         {
591             throw new IllegalArgumentException JavaDoc( "" + amx );
592         }
593         
594         debug( "resyncAMXMBean: removing mapping from: " + old + " TO " + amx );
595         mOldToNewObjectNames.remove( old );
596         debug( "resyncAMXMBean: unregistering: " + amx );
597         getMBeanServer().unregisterMBean( amx );
598         debug( "resyncAMXMBean: handleMBeanRegistered: " + amx );
599         handleMBeanRegistered( old );
600             
601         final ObjectName JavaDoc newAMX = mOldToNewObjectNames.get( old );
602         assert( newAMX != null );
603         
604         debug( "resyncAMXMBean: new ObjectName: " + newAMX );
605         return newAMX;
606     }
607     
608 }
609
610
611
612
613
614
615
616
617
Popular Tags