blob: 5e181edf160f53bd715b205100b07a2716f0cb34 [file] [log] [blame]
/*
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.felix.jmood.compendium;
import java.util.*;
import javax.management.*;
import javax.management.openmbean.*;
import org.apache.felix.jmood.AgentConstants;
import org.apache.felix.jmood.AgentContext;
import org.apache.felix.jmood.utils.*;
import org.osgi.framework.*;
import org.osgi.service.log.*;
/**
*
* This class enables remote management of
* org.osgi.service.log.LogReaderService It enables the operator to read
* the system log.
*/
// FUTURE WORK: limitations of Log manager: if the service appears or
// disappears, and/or there ismore than one service available, correct
// functioning is not guaranteed. A New manager should be branched for each
// available log service, and info should be merged to expose it afterwards.
// FUTURE WORK: Log Listener should be an anonymous class
// FUTURE WORK: Add persistence to the log manager
public class LogManager extends NotificationBroadcasterSupport implements
LogListener, MBeanRegistration, LogManagerMBean {
private LogReaderService logReader = null;
private ServiceReference[] refs;
private LogService log = null;
private String[][] Log;
private static final int DefaultLogLevel = 0;
private int LogLevel;
private Vector entryVector;
private static int sequenceNumber = 0;
private AgentContext ac;
private ServiceRegistration registration;
// FUTURE WORK: add persistence to sequence numbers
public LogManager(AgentContext ac) {
this.ac = ac;
}
public void setLogLevel(int level) {
// FUTURE WORK This setting only affects to the agent. Extend it to the
// service. This is implementation dependent.
this.LogLevel = level;
}
public int getLogLevel() {
return LogLevel;
}
public CompositeData[] getLog() {
if (entryVector == null) {
return null;
} else {
try {
CompositeData[] value = new CompositeData[entryVector.size()];
for (int i = 0; i < entryVector.size(); i++) {
value[i] = OSGi2JMXCodec
.encodeLogEntry((LogEntry) entryVector.elementAt(i));
}
return value;
} catch (Exception e) {
ac.error("Unexpected exception", e);
return null;
}
}
}
/**
* This method exposes the attribute LogFromReader for remote management.
* The main difference with the log attribute is that the later uses the
* level configuration specified by the log level attribute and as a
* drawback does not include log entries registered before the log manager
* was started.
*
* @return
*/
public String[] getLogMessages() {
if (entryVector == null)
return null;
String[] msgs = new String[entryVector.size()];
for (int i = 0; i < msgs.length; i++) {
LogEntry entry = (LogEntry) entryVector.elementAt(i);
msgs[i] = "BUNDLE " + entry.getBundle().getBundleId() + " ("
+ entry.getBundle().getLocation() + "): LEVEL="
+ this.getLevelAsString(entry.getLevel()) + "; MESSAGE="
+ entry.getMessage();
}
return msgs;
}
/**
* @see javax.management.MBeanRegistration#postDeregister()
*
*/
public void postDeregister() {
}
/**
* @see javax.management.MBeanRegistration#postRegister(java.lang.Boolean)
* @param registrationDone
*/
public void postRegister(Boolean registrationDone) {
}
/**
* @see javax.management.MBeanRegistration#preDeregister()
* @throws java.lang.Exception
*/
public void preDeregister() throws Exception {
registration.unregister();
}
/**
* @see javax.management.MBeanRegistration#preRegister(javax.management.MBeanServer,
* javax.management.ObjectName)
* @param server
* @param name
* @return
* @throws java.lang.Exception
*/
public ObjectName preRegister(MBeanServer server, ObjectName name) {
this.entryVector = new Vector();
this.LogLevel = DefaultLogLevel;
registration=ac.getBundleContext().registerService(LogListener.class.getName(), this, null);
return name;
}
/**
* @see org.osgi.service.log.LogListener#logged(org.osgi.service.log.LogEntry)
* @param arg0
*/
public void logged(LogEntry entry) {
if (entry.getLevel() >= this.LogLevel) {
this.notifyLogEntry(entry);
entryVector.add(entry);
}
}
private void notifyLogEntry(LogEntry entry) {
// TEST: See if user data are correctly received. This we cannot do with
// MC4J
String Level = this.getLevelAsString(entry.getLevel());
try {
ObjectName source = new ObjectName(ObjectNames.LOG_SERVICE);
String message = "Log entry added: Bundle "
+ entry.getBundle().getLocation() + " with id "
+ entry.getBundle().getBundleId()
+ " has added a new log entry of level " + Level
+ ". The message is: " + entry.getMessage();
Notification notification = new Notification(
AgentConstants.LOG_NOTIFICATION_TYPE, source,
sequenceNumber++, message);
// User data is CompositeData with the info of the log entry
CompositeData userData = OSGi2JMXCodec.encodeLogEntry(entry);
// Before using composite data, we used a simple string array:
/*
* String[] userData = new String[4]; userData[0] =
* entry.getBundle().getLocation(); userData[1] = new
* Long(entry.getBundle().getBundleId()).toString(); userData[2] =
* Level; userData[3] = entry.getMessage();
*/
notification.setUserData(userData);
sendNotification(notification);
} catch (Exception e) {
ac.error("Unexpected exception", e);
}
}
private String getLevelAsString(int level) {
String Level;
switch (level) {
case LogService.LOG_DEBUG:
Level = "DEBUG";
break;
case LogService.LOG_WARNING:
Level = "WARNING";
break;
case LogService.LOG_INFO:
Level = "INFO";
break;
case LogService.LOG_ERROR:
Level = "ERROR";
break;
default:
Level = "UserDefined: " + level;
break;
}
return Level;
}
}