/* | |
* 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; | |
} | |
} |