org.glassfish.admin.amx.impl.mbean.LoggingImpl Maven / Gradle / Ivy
Show all versions of payara-embedded-all Show documentation
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2012 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.mbean;
import com.sun.common.util.logging.LoggingConfigImpl;
import com.sun.enterprise.server.logging.GFFileHandler;
import com.sun.enterprise.server.logging.diagnostics.MessageIdCatalog;
import com.sun.enterprise.server.logging.logviewer.backend.LogFilter;
import java.io.Serializable;
import java.util.*;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import javax.management.*;
import org.glassfish.admin.amx.core.Util;
import org.glassfish.admin.amx.impl.util.InjectedValues;
import static org.glassfish.admin.amx.logging.LogAnalyzer.*;
import static org.glassfish.admin.amx.logging.LogFileAccess.*;
import static org.glassfish.admin.amx.logging.LogRecordEmitter.*;
import org.glassfish.admin.amx.logging.Logging;
import org.glassfish.admin.amx.util.*;
import org.glassfish.admin.amx.util.jmx.JMXUtil;
import org.glassfish.admin.amx.util.jmx.NotificationBuilder;
import org.glassfish.external.amx.AMXGlassfish;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.server.ServerEnvironmentImpl;
import org.jvnet.hk2.annotations.Service;
//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.
*/
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 ServiceLocator 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.getService(GFFileHandler.class);
logFilter = mHabitat.getService(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;
List moduleList = null;
if (modules != null) {
moduleList = 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