
org.glassfish.admin.amx.impl.ext.LoggingImpl Maven / Gradle / Ivy
Show all versions of amx-ext-impl Show documentation
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package org.glassfish.admin.amx.impl.ext;
import org.glassfish.external.amx.AMXGlassfish;
import org.glassfish.admin.amx.core.Util;
import org.glassfish.admin.amx.logging.Logging;
import org.glassfish.admin.amx.logging.LogQueryResult;
import static org.glassfish.admin.amx.logging.Logging.*;
import com.sun.common.util.logging.LoggingConfigImpl;
import org.glassfish.admin.amx.util.jmx.JMXUtil;
import org.glassfish.admin.amx.util.jmx.NotificationBuilder;
import org.glassfish.admin.amx.util.*;
import com.sun.enterprise.server.logging.GFFileHandler;
import com.sun.enterprise.server.logging.logviewer.backend.LogFilter;
import com.sun.enterprise.server.logging.diagnostics.MessageIdCatalog;
//import com.sun.enterprise.server.logging.ModuleToLoggerNameMapper;
import org.glassfish.admin.amx.impl.util.InjectedValues;
import org.glassfish.server.ServerEnvironmentImpl;
import org.glassfish.admin.amx.util.CollectionUtil;
import javax.management.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Serializable;
import java.util.*;
import java.util.logging.Logger;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import org.glassfish.admin.amx.impl.mbean.AMXImplBase;
import static org.glassfish.admin.amx.logging.LogRecordEmitter.*;
import static org.glassfish.admin.amx.logging.LogFileAccess.*;
import static org.glassfish.admin.amx.logging.LogAnalyzer.*;
import org.jvnet.hk2.annotations.Service;
import org.jvnet.hk2.component.Habitat;
//import com.sun.enterprise.server.logging.LoggingImplHook;
/**
Implementation of {@link Logging}.
The following is a GlassFish V2 comment, and needs work for v3:
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.
*/
@Service
public final class LoggingImpl extends AMXImplBase
//implements /*Logging,*/ LoggingImplHook
{
private final Map mLevelToNotificationTypeMap;
private final Map mNotificationTypeToNotificationBuilderMap;
private static final String SERVER_LOG_NAME = "server.log";
private static final String ACCESS_LOG_NAME = "access.log";
private final LoggingConfigImpl loggingConfig;
private final GFFileHandler gfFileHandler;
private final LogFilter logFilter;
private final MessageIdCatalog msgIdCatalog;
private final Logger logger;
private final Habitat mHabitat;
final String FILE_SEP;
private final String mServerName;
/**
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.
*/
public static ObjectName
getObjectName( final String serverName )
{
final String requiredProps = Util.makeRequiredProps( Util.deduceType(Logging.class), serverName );
final String ServerRootMonitorType = "ServerRootMonitor";
final String parentProp = Util.makeProp( ServerRootMonitorType, serverName );
final String props = Util.concatenateProps( requiredProps, parentProp );
return Util.newObjectName( AMXGlassfish.DEFAULT.amxJMXDomain(), props );
}
/**
*/
public LoggingImpl( final ObjectName parent, final String serverName)
{
super( parent, Logging.class );
mServerName = serverName;
FILE_SEP = System.getProperty( "file.separator" );
mLevelToNotificationTypeMap = initLevelToNotificationTypeMap();
mNotificationTypeToNotificationBuilderMap = new HashMap();
final ServerEnvironmentImpl env = InjectedValues.getInstance().getServerEnvironment();
loggingConfig = new LoggingConfigImpl();
loggingConfig.setupConfigDir(env.getConfigDirPath(), env.getLibPath());
msgIdCatalog = new MessageIdCatalog();
mHabitat = InjectedValues.getInstance().getHabitat();
gfFileHandler = mHabitat.getComponent(GFFileHandler.class);
logFilter = mHabitat.getComponent(LogFilter.class);
logger = Logger.getAnonymousLogger();
}
/**
Hook for subclass to modify anything in MBeanInfo.
@Override
*/
/*
@Override
protected MBeanInfo
postRegisterModifyMBeanInfo( final MBeanInfo info )
{
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 static MBeanNotificationInfo[] SELF_NOTIFICATION_INFOS = null;
/**
getMBeanInfo() can be called frequently. By making this static,
we avoid needlessly creating new Objects.
*/
private static synchronized MBeanNotificationInfo[]
getSelfNotificationInfos()
{
if ( SELF_NOTIFICATION_INFOS == null )
{
final String[] types = SetUtil.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 );
}
public MBeanNotificationInfo[]
getNotificationInfo()
{
final MBeanNotificationInfo[] superInfos = super.getNotificationInfo();
final MBeanNotificationInfo[] all =
JMXUtil.mergeMBeanNotificationInfos( superInfos, getSelfNotificationInfos() );
return all;
}
/** FIXME */
private void unimplemented()
{
throw new RuntimeException( "Not implemented.");
}
public void
setModuleLogLevel(
final String module,
final String level )
{
try {
loggingConfig.setLoggingProperty( module+".level", level );
} catch (java.io.IOException e) {
logger.log (Level.SEVERE, "Can not set module log level");
}
}
public String
getModuleLogLevel( final String module)
{
try {
Map props = loggingConfig.getLoggingProperties();
if (props != null)
return props.get(module+".level");
return null;
} catch (java.io.IOException e){
logger.log (Level.SEVERE, "Can not get module log level");
return null;
}
}
public Map
getLoggingProperties( )
{
try {
Map props = loggingConfig.getLoggingProperties();
return props;
} catch (java.io.IOException e){
logger.log (Level.WARNING, "Can not get module log level");
return null;
}
}
public void
updateLoggingProperties(final Map properties)
{
try {
loggingConfig.updateLoggingProperties(properties);
} catch (java.io.IOException e){
logger.log (Level.WARNING, "Can not get module log level");
}
}
public int
getLogLevelListenerCount( final Level logLevel )
{
final String notifType = logLevelToNotificationType( logLevel );
final int count = getNotificationEmitter().getNotificationTypeListenerCount( notifType );
return( count );
}
public String[]
getLogFileKeys()
{
unimplemented();
return new String[] { SERVER_KEY, ACCESS_KEY };
}
public synchronized String[]
getLogFileNames( final String key )
{
String[] result = null;
if ( SERVER_KEY.equals( key ) )
{
}
else
{
throw new IllegalArgumentException( key );
}
return result;
}
public Map getLoggingAttributes( )
{
String gfHandler = "com.sun.enterprise.server.logging.GFFileHandler";
String sysHandler = "com.sun.enterprise.server.logging.SyslogHandler";
try {
Map props = loggingConfig.getLoggingProperties();
if ( props == null)
return null;
Map attributes = new HashMap();
attributes.put(gfHandler+".file", props.get(gfHandler+".file"));
attributes.put(gfHandler+".rotationTimelimitInMinutes", props.get(gfHandler+".rotationTimelimitInMinutes"));
attributes.put(gfHandler+".rotationLimitInBytes", props.get(gfHandler+".rotationLimitInBytes"));
attributes.put(gfHandler+".logtoConsole", props.get(gfHandler+".logtoConsole"));
attributes.put(gfHandler+".flushFrequency", props.get(gfHandler+".flushFrequency"));
attributes.put("handlers", props.get("handlers"));
attributes.put(sysHandler+".useSystemLogging", props.get(sysHandler+".useSystemLogging"));
return attributes;
} catch (java.io.IOException e){
logger.log (Level.WARNING, "Can not get logging attributes");
return null;
}
}
public void updateLoggingAttributes( final Map properties)
{
try {
loggingConfig.updateLoggingProperties(properties);
} catch (java.io.IOException e){
logger.log (Level.WARNING, "Can not set logging attributes");
}
}
public synchronized void
rotateAllLogFiles()
{
gfFileHandler.rotate( );
}
public synchronized void
rotateLogFile( final String key )
{
if ( ACCESS_KEY.equals( key ) )
{
throw new IllegalArgumentException( "not supported: " + key );
//getLogMBean().rotateAccessLog();
}
else if ( SERVER_KEY.equals( key ) )
{
gfFileHandler.rotate( );
}
else
{
throw new IllegalArgumentException( "" + key );
}
}
private Properties
attributesToProps( 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 List
convertQueryResult( final 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> srcRecords = TypeCast.asList(
((Attribute)queryResult.get( 1 )).getValue() );
// create the new results, making the first Object[] be the field headers
final List results = new ArrayList( srcRecords.size() );
results.add( fieldHeaders );
// extract every record
for( int recordIdx = 0; recordIdx < srcRecords.size(); ++recordIdx )
{
final List 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;
}
// code in LogBean.java code in v2
public List
queryServerLog(
String name,
long startIndex,
boolean searchForward,
int maximumNumberOfResults,
Long fromTime,
Long toTime,
String logLevel,
Set modules,
List nameValuePairs,
String anySearch)
{
final List result = queryServerLogInternal(
name, startIndex, searchForward, maximumNumberOfResults,
fromTime, toTime, logLevel, modules, nameValuePairs, anySearch );
return result;
}
private List
queryServerLogInternal(
final String name,
final long startIndex,
final boolean searchForward,
final int maximumNumberOfResults,
final Long fromTime,
final Long toTime,
final String logLevel,
final Set modules,
final List nameValuePairs,
final String anySearch)
{
if ( name == null )
{
throw new IllegalArgumentException( "use MOST_RECENT_NAME, not null" );
}
boolean sortAscending = true;
final List moduleList = null;
if (modules != null )
ListUtil.newListFromCollection( modules );
final Properties props = attributesToProps( nameValuePairs );
String actualName;
if ( MOST_RECENT_NAME.equals( name ) )
{
actualName = null;
}
else
{
actualName = name;
}
if (!searchForward)
sortAscending = false;
final AttributeList result= logFilter.getLogRecordsUsingQuery(actualName,
Long.valueOf(startIndex),
searchForward, sortAscending,
maximumNumberOfResults,
fromTime == null ? null
: new Date(fromTime),
toTime == null ? null
: new Date(toTime),
logLevel, false, moduleList, props,anySearch);
return convertQueryResult( result );
}
public Map[]
getErrorInfo()
{
unimplemented();
final List