FileDocCategorySizeDatePackage
LoggingImpl.javaAPI DocGlassfish v2 API27925Fri May 04 22:23:28 BST 2007com.sun.enterprise.management.ext.logging

LoggingImpl

public final class LoggingImpl extends com.sun.enterprise.management.support.AMXImplBase implements com.sun.enterprise.server.logging.LoggingImplHook
Implementation of {@link Logging}.

AMX Logging MBean is hooked directly into the logging subsystem via com.sun.enterprise.server.logging.FileandSyslogHandler which uses com.sun.enterprise.server.logging.AMXLoggingHook to instantiate and call an instance of LoggingImpl.

Fields Summary
private LogMBeanIntf
mLogMBean
private final Map
mLevelToNotificationTypeMap
private final Map
mNotificationTypeToNotificationBuilderMap
private static final String
SERVER_LOG_NAME
private static final String
ACCESS_LOG_NAME
final String
FILE_SEP
private final String
mServerName
private static final String
LOGMBEAN_OBJECT_NAME_PREFIX
private static MBeanNotificationInfo[]
SELF_NOTIFICATION_INFOS
private static final Integer
INTEGER_0
private static final Map
EMPTY_ERROR_DISTRIBUTION_MAP
private static final Set
LEGAL_DISTRIBUTION_LEVELS
private static final Object[]
LEVELS_AND_NOTIF_TYPES
private long
mMyThreadID
Constructors Summary
public LoggingImpl(String serverName)

    
         
         
    
        mServerName = serverName;
    	mLogMBean	= null;
        FILE_SEP   = System.getProperty( "file.separator" );
    	
    	mLevelToNotificationTypeMap = initLevelToNotificationTypeMap();
        mNotificationTypeToNotificationBuilderMap  = new HashMap<String,NotificationBuilder>();
    
Methods Summary
private java.util.PropertiesattributesToProps(java.util.List attrs)

    	final Properties	props	= new Properties();
    	
    	if ( attrs != null )
    	{
    		for( Attribute attr: attrs)
    		{
    			final Object	value	= attr.getValue();
    			if ( value == null )
    			{
    				throw new IllegalArgumentException( attr.getName() + "=" + null);
    			}
    			
    			props.put( attr.getName(), value.toString() );
    		}
    	}
    	
    	return( props );
    
private java.util.ListconvertQueryResult(javax.management.AttributeList queryResult)

        // extract field descriptions into a String[]
        final AttributeList   fieldAttrs    = (AttributeList)((Attribute)queryResult.get( 0 )).getValue();
        final String[]  fieldHeaders  = new String[ fieldAttrs.size() ];
        for( int i = 0; i < fieldHeaders.length; ++i )
        {
            final Attribute attr    = (Attribute)fieldAttrs.get( i );
            fieldHeaders[ i ] = (String)attr.getValue();
        }
        
        final List<List<Serializable>> srcRecords    = TypeCast.asList(
                ((Attribute)queryResult.get( 1 )).getValue() );
        
        // create the new results, making the first Object[] be the field headers
        final List<Serializable[]>  results = new ArrayList<Serializable[]>( srcRecords.size() );
        results.add( fieldHeaders );
        
        // extract every record
        for( int recordIdx = 0; recordIdx < srcRecords.size(); ++recordIdx )
        {
            final List<Serializable> record    = srcRecords.get( recordIdx );
            
            assert( record.size() == fieldHeaders.length );
            final Serializable[]  fieldValues = new Serializable[ fieldHeaders.length ];
            for( int fieldIdx = 0; fieldIdx < fieldValues.length; ++fieldIdx )
            {
                fieldValues[ fieldIdx ] = record.get( fieldIdx );
            }
            
            results.add( fieldValues );
        }
        
        return results;
    
protected synchronized javax.management.ObjectNamegetContainerObjectName(javax.management.ObjectName selfObjectName)

        ObjectName  containerObjectName = null;
        
        // work is needed to flesh out the hierarchy in non-DAS server instances.
        // return null for now if that hierarchy is missing
        try
        {
            containerObjectName = super.getContainerObjectName( selfObjectName );
        }
        catch( Exception e )
        {
            // can occur for non-DAS instances
            containerObjectName = null;
        }
        return containerObjectName;
    
public java.lang.String[]getDiagnosticCauses(java.lang.String messageID)

    	final List<String>	causes	= TypeCast.checkList( 
    		getLogMBean().getDiagnosticCausesForMessageId( messageID ), String.class );
    	
    	String[]	result = null;
    	if ( causes != null )
    	{
    	    result  = (String[])causes.toArray( new String[causes.size()] );
    	}
    	
        return result;
    
public java.lang.String[]getDiagnosticChecks(java.lang.String messageID)

    	final List<String>	checks	= TypeCast.checkList( 
    		getLogMBean().getDiagnosticChecksForMessageId( messageID ), String.class );
    	
    	String[]	result = null;
    	if ( checks != null )
    	{
    	    result  = new String[checks.size()];
    	    checks.toArray( result );
    	}
    	        
    	return	result;
    
public java.lang.StringgetDiagnosticURI(java.lang.String messageID)

    	return getLogMBean().getDiagnosticURIForMessageId( messageID );
    
public java.util.MapgetErrorDistribution(long timestamp, java.lang.String level)

        
    
   
         
       
    
        if ( ! LEGAL_DISTRIBUTION_LEVELS.contains( level ) )
        {
            throw new IllegalArgumentException( level );
        }
        
        Map<String,Integer>  result =
            getLogMBean().getErrorDistribution( timestamp, Level.parse( level ) );
        
        // query may return null instead of an empty Map
        if ( result != null )
        {
            final Set<String>  moduleIDs   = result.keySet();
            
    	     // Ensure that no module has a null count
            for( final String moduleID : moduleIDs )
            {
                if ( result.get( moduleID ) == null )
                {
                    result.put( moduleID, INTEGER_0 );
                }
	        }
        }
        else
        {
            // never return a null Map, only an empty one
            result  = EMPTY_ERROR_DISTRIBUTION_MAP;
        }
            
        return result;
    
public java.util.Map[]getErrorInfo()

        final List<Map<String,Object>>  infos    = getLogMBean().getErrorInformation();
        
        final Map<String,Number>[]  results  = TypeCast.asArray( new HashMap[ infos.size() ] );
        
        for( int i = 0; i < results.length; ++i )
        {
            final Map<String,Object>  info  = infos.get( i );
            
            assert( info.keySet().size() == 3 );
            
            final Long  timestamp   = Long.parseLong( info.get( TIMESTAMP_KEY ).toString() );
            final Integer  severeCount = Integer.parseInt( info.get( SEVERE_COUNT_KEY ).toString() );
            final Integer  warningCount= Integer.parseInt( info.get( WARNING_COUNT_KEY ).toString() );
            
            final Map<String,Number>    item  = new HashMap<String,Number>( info.size() );
            item.put( TIMESTAMP_KEY, timestamp);
            item.put( SEVERE_COUNT_KEY, severeCount);
            item.put( WARNING_COUNT_KEY, warningCount);
            
            results[ i ] = item;
        }
        
        return results;
    
public longgetErrorStatisticsIntervalMinutes()

        return getLogMBean().getErrorStatisticsIntervalDuration();
    
public java.lang.StringgetGroup()

		return( AMX.GROUP_MONITORING );
	
public intgetKeepErrorStatisticsForIntervals()

        return getLogMBean().getKeepErrorStatisticsForIntervals();
    
public synchronized java.lang.StringgetLogFile(java.lang.String key, java.lang.String fileName)

        if ( ! SERVER_KEY.equals( key ) )
        {
            throw new IllegalArgumentException( "" + key );
        }
        
        final String  dir   = getLogMBean().getLogFilesDirectory();
        final String  file  = dir + FILE_SEP + fileName;
        
        try
        {
             return FileUtils.fileToString( new File( file ) );
        }
        catch( FileNotFoundException e )
        {
            throw new RuntimeException( e );
        }
        catch( IOException e )
        {
            throw new RuntimeException( e );
        }
    
public java.lang.String[]getLogFileKeys()

    	return new String[]	{ SERVER_KEY, ACCESS_KEY };
    
public synchronized java.lang.String[]getLogFileNames(java.lang.String key)

    	String[]	result	= null;
    	
    	if ( SERVER_KEY.equals( key ) )
    	{
    		result	= getLogMBean().getArchivedLogfiles();
    	}
    	else
    	{
    		throw new IllegalArgumentException( key );
    	}
    	
        return result;
    
public intgetLogLevelListenerCount(java.util.logging.Level logLevel)

        final String    notifType   = logLevelToNotificationType( logLevel );
        
        final int count = getNotificationEmitter().getNotificationTypeListenerCount( notifType );
        return( count );
    
private LogMBeanIntfgetLogMBean()

        initLogMBean();
    	return mLogMBean;
    
public java.lang.String[]getLoggerNames()

	    final List<String>  names   =
	        TypeCast.checkList( getLogMBean().getLoggerNames(), String.class );
	    
	    return names.toArray( EMPTY_STRING_ARRAY );
	
public java.lang.String[]getLoggerNamesUnder(java.lang.String loggerName)

	    final List<String>  names   = TypeCast.checkList(
	        getLogMBean().getLoggerNamesUnder( loggerName ), String.class );
	    
	    return names.toArray( EMPTY_STRING_ARRAY );
    
public java.lang.StringgetModuleLogLevel(java.lang.String module)

    	return getLogMBean().getLogLevel( module );
    
public javax.management.MBeanNotificationInfo[]getNotificationInfo()

		final MBeanNotificationInfo[]   superInfos = super.getNotificationInfo();
		
		final MBeanNotificationInfo[]   all =
		    JMXUtil.mergeMBeanNotificationInfos( superInfos, getSelfNotificationInfos() );
		
		return all;
    
public static javax.management.ObjectNamegetObjectName(java.lang.String serverName)
Used internally to get the Logging ObjectName for a particular server Logging MBean is a special-case because it needs to load as early as possible.

    
                                                    
          
        
    
        final String requiredProps  = Util.makeRequiredProps( XTypes.LOGGING, serverName );
        final String parentProp     = Util.makeProp( XTypes.SERVER_ROOT_MONITOR, serverName );
        final String props          = Util.concatenateProps( requiredProps, parentProp );
        
        return Util.newObjectName( AMX.JMX_DOMAIN, props );
    
private static synchronized javax.management.MBeanNotificationInfo[]getSelfNotificationInfos()
getMBeanInfo() can be called frequently. By making this static, we avoid needlessly creating new Objects.

                                       
            
    
    
        if ( SELF_NOTIFICATION_INFOS == null )
        {
    		final String[]  types   = GSetUtil.toStringArray( ALL_LOG_RECORD_NOTIFICATION_TYPES );
    	    final MBeanNotificationInfo selfInfo  = new MBeanNotificationInfo(
    	        types, Notification.class.getName(),  "LogRecord notifications" );
    	    
    	    SELF_NOTIFICATION_INFOS = new MBeanNotificationInfo[]   { selfInfo };
	    }
	    return( SELF_NOTIFICATION_INFOS );
    
private static java.util.MapinitLevelToNotificationTypeMap()

    
          
    
    
        final Map<Level,String>    m   = new HashMap<Level,String>();

        for( int i = 0; i < LEVELS_AND_NOTIF_TYPES.length; i += 2 )
        {
            final Level    level       = (Level)LEVELS_AND_NOTIF_TYPES[ i ];
            final String   notifType   = (String)LEVELS_AND_NOTIF_TYPES[ i + 1 ];
            m.put( level, notifType );
        }

        return( Collections.unmodifiableMap( m ) );
    
private voidinitLogMBean()

        if ( mLogMBean == null )
         synchronized( this )
        {
            if ( mLogMBean == null )
            {
        		final ObjectName logMBeanObjectName	=
        		Util.newObjectName( LOGMBEAN_OBJECT_NAME_PREFIX + mServerName );
        		
        		mLogMBean	= (LogMBeanIntf)newProxy( logMBeanObjectName, LogMBeanIntf.class );
            }
        }
    
private voidinitNotificationTypeToNotificationBuilderMap(javax.management.ObjectName objectName)

        mNotificationTypeToNotificationBuilderMap.clear();
        for( final String notifType : ALL_LOG_RECORD_NOTIFICATION_TYPES )
        {
            mNotificationTypeToNotificationBuilderMap.put(
                notifType,
                new NotificationBuilder( notifType, objectName ) );
        }
    
private java.lang.StringlogLevelToNotificationType(java.util.logging.Level level)

        String notificationType = mLevelToNotificationTypeMap.get( level );

        if ( notificationType == null )
        {
        }

        return notificationType;
    
private java.util.MaplogRecordToMap(java.util.logging.LogRecord record, java.lang.String recordAsString)

        final Map<String,Serializable>    m   = new HashMap<String,Serializable>();
        
        m.put( LOG_RECORD_AS_STRING_KEY, recordAsString );
        m.put( LOG_RECORD_LEVEL_KEY, record.getLevel() );
        m.put( LOG_RECORD_LOGGER_NAME_KEY, record.getLoggerName() );
        m.put( LOG_RECORD_MESSAGE_KEY, record.getMessage() );
        m.put( LOG_RECORD_MILLIS_KEY, record.getMillis() );
        m.put( LOG_RECORD_SEQUENCE_NUMBER_KEY, record.getSequenceNumber() );
        m.put( LOG_RECORD_SOURCE_CLASS_NAME_KEY, record.getSourceClassName() );
        m.put( LOG_RECORD_SOURCE_METHOD_NAME_KEY, record.getSourceMethodName() );
        m.put( LOG_RECORD_THREAD_ID_KEY, record.getThreadID() );
        final Throwable thrown  = record.getThrown();
        if ( thrown != null )
        {
            final Throwable mapped  = new ThrowableMapper( thrown ).map();
            m.put( LOG_RECORD_THROWN_KEY, mapped );
            
            final Throwable rootCause   = ExceptionUtil.getRootCause( thrown );
            if ( rootCause != thrown )
            {
                final Throwable mappedRootCause  = new ThrowableMapper( rootCause ).map();
                m.put( LOG_RECORD_ROOT_CAUSE_KEY, mappedRootCause );
            }
        }
        return m;
    
protected javax.management.MBeanInfomodifyMBeanInfo(javax.management.MBeanInfo info)
Hook for subclass to modify anything in MBeanInfo.

Override

	    final MBeanOperationInfo[]  ops = info.getOperations();
	    
	    final int   idx = JMXUtil.findMBeanOperationInfo( info, "queryServerLog", null);
	    
	    final MBeanOperationInfo    op  = ops[idx];
	    ops[idx]    = new MBeanOperationInfo( op.getName(), op.getDescription(),
	                    op.getSignature(), Map.class.getName(),
	                    MBeanOperationInfo.INFO );
	    
	    return JMXUtil.newMBeanInfo( info, ops );
	
private java.lang.ObjectnewProxy(javax.management.ObjectName target, java.lang.Class interfaceClass)

    	return( MBeanServerInvocationHandler.newProxyInstance(
    				getMBeanServer(), target, interfaceClass, true ) );
    
private com.sun.appserv.management.util.jmx.NotificationBuildernotificationTypeToNotificationBuilder(java.lang.String notificationType)

        NotificationBuilder builder =
            mNotificationTypeToNotificationBuilderMap.get( notificationType );
            
        assert( builder != null );
        
        return builder;
    
protected voidpreRegisterDone()

        initNotificationTypeToNotificationBuilderMap( getObjectName() );
	
public voidprivateLoggingHook(java.util.logging.LogRecord logRecord, java.util.logging.Formatter formatter)
Internal use only, called by com.sun.enterprise.server.logging.AMXLoggingHook.

                      
         
    
          
           
    
        //debug( "LoggingImpl.privateLoggingHook: " + formatter.format( logRecord ) );
            
        if ( logRecord.getThreadID() == mMyThreadID )
        {
            debug( "privateLoggingHook: recusive call!!!" );
            throw new RuntimeException( "recursive call" );
        }
        synchronized( this )
        {
            mMyThreadID  = Thread.currentThread().getId();
            
            final Level level       = logRecord.getLevel();
            
            try
            {
                // don't construct a Notification if there are no listeners.
                if ( getLogLevelListenerCount( level ) != 0 )
                {
                    final String notifType  = logLevelToNotificationType( level );
                    
                    final NotificationBuilder   builder =
                        notificationTypeToNotificationBuilder( notifType );
                    
                    // Notification.getMessage() will be the formatted log record
                    final String    logRecordAsString    = formatter.format( logRecord );
                    
                    final Map<String,Serializable>  userData    =
                        logRecordToMap( logRecord, logRecordAsString );
                        
                    final Notification notif    =
                        builder.buildNewWithMap( logRecordAsString, userData);
                        
                    debug( "privateLoggingHook: sending: " + notif );
                    sendNotification( notif );
                }
                else
                {
                   // debug( "privateLogHook: no listeners for level " + level );
                }
            }
            finally
            {
                mMyThreadID = -1;
            }
        }
    
public java.util.ListqueryServerLog(java.lang.String name, long startIndex, boolean searchForward, int maximumNumberOfResults, java.lang.Long fromTime, java.lang.Long toTime, java.lang.String logLevel, java.util.Set modules, java.util.List nameValuePairs)

        final List<Serializable[]>    result  = queryServerLogInternal(
                 name, startIndex, searchForward, maximumNumberOfResults,
                 fromTime, toTime, logLevel, modules, nameValuePairs );
        return result;
    
private java.util.ListqueryServerLogInternal(java.lang.String name, long startIndex, boolean searchForward, int maximumNumberOfResults, java.lang.Long fromTime, java.lang.Long toTime, java.lang.String logLevel, java.util.Set modules, java.util.List nameValuePairs)

        if ( name == null )
        {
            throw new IllegalArgumentException( "use MOST_RECENT_NAME, not null" );
        }
        
    	final boolean  sortAscending	= true;
    	final List<String>     moduleList	= ListUtil.newListFromCollection( modules );
    	final Properties  props	= attributesToProps( nameValuePairs );
    	
    	String  actualName;
    	if ( MOST_RECENT_NAME.equals( name ) )
    	{
    	    actualName  = null;
    	}
    	else
    	{
    	    actualName  = name;
    	}
        final AttributeList result	= getLogMBean().getLogRecordsUsingQuery(actualName,
                                              Long.valueOf(startIndex),
                                              searchForward, sortAscending,
                                              maximumNumberOfResults,
                                              fromTime == null ? null
                                                               : new Date(fromTime),
                                              toTime == null ? null
                                                             : new Date(toTime),
                                              logLevel, true, moduleList, props) ;
            
        return convertQueryResult( result );
    
public synchronized voidrotateAllLogFiles()

    	getLogMBean().rotateNow( );
    
public synchronized voidrotateLogFile(java.lang.String key)

    	if ( ACCESS_KEY.equals( key ) )
    	{
    	    throw new IllegalArgumentException( "not supported: " + key );
    		// getLogMBean().rotateAccessLog();
    	}
    	else if ( SERVER_KEY.equals( key ) )
    	{
    		rotateAllLogFiles();
    	}
    	else
    	{
    		throw new IllegalArgumentException( "" + key );
    	}
    
public voidsetErrorStatisticsIntervalMinutes(long minutes)

        getLogMBean().setErrorStatisticsIntervalDuration( minutes );
    
public voidsetKeepErrorStatisticsForIntervals(int num)

        getLogMBean().setKeepErrorStatisticsForIntervals( num );
    
public voidsetModuleLogLevel(java.lang.String module, java.lang.String level)

    	getLogMBean().setLogLevel( module, level );
    
public voidtestEmitLogMessage(java.lang.String level, java.lang.String message)

        final Level saveLevel   = getMBeanLogLevel();
        
        setMBeanLogLevel( Level.parse( level ) );
        try
        {
            debug( "testEmitLogMessage: logging: message = " + message );
            getLogger().log( Level.parse( level ), message );
        }
        finally
        {
            setMBeanLogLevel( saveLevel );
        }