All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.papoose.log.LogServiceImpl Maven / Gradle / Ivy

The newest version!
/**
 *
 * Copyright 2010 (C) The original author or authors
 *
 * 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.papoose.log;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.logging.Logger;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;
import org.osgi.framework.Constants;
import org.osgi.framework.FrameworkEvent;
import org.osgi.framework.FrameworkListener;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.event.Event;
import org.osgi.service.log.LogEntry;
import org.osgi.service.log.LogListener;
import org.osgi.service.log.LogReaderService;
import org.osgi.service.log.LogService;
import org.papoose.log.util.EventAdminTracker;
import org.papoose.log.util.LogListenerHolder;
import org.papoose.log.util.SerialExecutor;


/**
 * @version $Revision: $ $Date: $
 */
public class LogServiceImpl implements LogService, BundleListener, ServiceListener, FrameworkListener
{
    private final static String CLASS_NAME = LogServiceImpl.class.getName();
    private final static Logger LOGGER = Logger.getLogger(CLASS_NAME);
    private final List listeners = new CopyOnWriteArrayList();
    private final LinkedList log = new LinkedList();
    private final ExecutorService executorService;
    private final EventAdminTracker eventAdmin;
    private int limit = 1000;

    /**
     * Create an instance of a log service that implements both the
     * LogService and LogReaderService.
     * 

* The default log limit is 1000. * * @param context the bundle context to use to search for event admins * @param executorService the executor service used to deliver log entries to log listeners */ public LogServiceImpl(BundleContext context, ExecutorService executorService) { if (context == null) throw new IllegalArgumentException("Bundle context is null"); if (executorService == null) throw new IllegalArgumentException("Executor service is null"); this.executorService = executorService; this.eventAdmin = new EventAdminTracker(context); } /** * Use this method to set the maximum number of log entries kept in the * log service. * * @param limit the maximum number of log entries kept in the log service */ public void setLimit(int limit) { this.limit = limit; } /** * Start this logging service. */ public void start() { eventAdmin.open(); } /** * Stop this logging service. */ public void stop() { eventAdmin.close(); } /** * {@inheritDoc} */ public void log(int level, String message) { LOGGER.entering(CLASS_NAME, "log", new Object[]{level, message}); log(level, message, null); LOGGER.exiting(CLASS_NAME, "log"); } /** * {@inheritDoc} */ public void log(int level, String message, Throwable exception) { LOGGER.entering(CLASS_NAME, "log", new Object[]{level, message, exception}); LogEntryImpl entry = new LogEntryImpl(null, null, level, message, exception); insert(entry); broadcast(entry); LOGGER.exiting(CLASS_NAME, "log"); } /** * {@inheritDoc} */ public void log(ServiceReference sr, int level, String message) { LOGGER.entering(CLASS_NAME, "log", new Object[]{sr, level, message}); log(sr, level, message, null); LOGGER.exiting(CLASS_NAME, "log"); } /** * {@inheritDoc} */ public void log(ServiceReference sr, int level, String message, Throwable exception) { LOGGER.entering(CLASS_NAME, "log", new Object[]{sr, level, message, exception}); LogEntryImpl entry = new LogEntryImpl(sr.getBundle(), sr, level, message, exception); insert(entry); broadcast(entry); LOGGER.exiting(CLASS_NAME, "log"); } /** * {@inheritDoc} */ void addLogListener(LogListener listener) { LOGGER.entering(CLASS_NAME, "addLogListener", listener); if (listener == null) return; listeners.add(new LogListenerHolder(listener, new SerialExecutor(executorService))); LOGGER.exiting(CLASS_NAME, "addLogListener"); } /** * {@inheritDoc} */ void removeLogListener(LogListener listener) { LOGGER.entering(CLASS_NAME, "removeLogListener", listener); if (listener == null) return; listeners.remove(new LogListenerHolder(listener)); LOGGER.exiting(CLASS_NAME, "removeLogListener"); } /** * {@inheritDoc} */ Enumeration getLog() { LOGGER.entering(CLASS_NAME, "getLog"); synchronized (log) { Enumeration enumeration = new Enumeration() { private final Iterator iterator = log.iterator(); public boolean hasMoreElements() { return iterator.hasNext(); } public Object nextElement() { return iterator.next(); } }; LOGGER.exiting(CLASS_NAME, "getLog", enumeration); return enumeration; } } /** * {@inheritDoc} */ public void bundleChanged(BundleEvent event) { LOGGER.entering(CLASS_NAME, "bundleChanged", event); String message = null; switch (event.getType()) { case BundleEvent.INSTALLED: message = "BundleEvent INSTALLED"; break; case BundleEvent.STARTED: message = "BundleEvent STARTED"; break; case BundleEvent.STOPPED: message = "BundleEvent STOPPED"; break; case BundleEvent.UPDATED: message = "BundleEvent UPDATED"; break; case BundleEvent.UNINSTALLED: message = "BundleEvent UNINSTALLED"; break; case BundleEvent.RESOLVED: message = "BundleEvent RESOLVED"; break; case BundleEvent.UNRESOLVED: message = "BundleEvent UNRESOLVED"; break; } insert(new LogEntryImpl(event.getBundle(), null, LogService.LOG_INFO, message, null)); LOGGER.exiting(CLASS_NAME, "bundleChanged"); } /** * {@inheritDoc} */ public void serviceChanged(ServiceEvent event) { LOGGER.entering(CLASS_NAME, "serviceChanged", event); int type = event.getType(); String message = null; switch (type) { case ServiceEvent.REGISTERED: message = "ServiceEvent REGISTERED"; break; case ServiceEvent.MODIFIED: message = "ServiceEvent MODIFIED"; break; case ServiceEvent.UNREGISTERING: message = "ServiceEvent UNREGISTERING"; break; } ServiceReference reference = event.getServiceReference(); insert(new LogEntryImpl(reference.getBundle(), reference, type == ServiceEvent.MODIFIED ? LogService.LOG_DEBUG : LogService.LOG_INFO, message, null)); LOGGER.exiting(CLASS_NAME, "serviceChanged"); } /** * {@inheritDoc} */ public void frameworkEvent(FrameworkEvent event) { LOGGER.entering(CLASS_NAME, "frameworkEvent", event); int type = event.getType(); String message = null; switch (type) { case FrameworkEvent.STARTED: message = "FrameworkEvent STARTED"; break; case FrameworkEvent.ERROR: message = "FrameworkEvent ERROR"; break; case FrameworkEvent.PACKAGES_REFRESHED: message = "FrameworkEvent PACKAGES_REFRESHED"; break; case FrameworkEvent.STARTLEVEL_CHANGED: message = "FrameworkEvent STARTLEVEL_CHANGED"; break; case FrameworkEvent.WARNING: message = "FrameworkEvent WARNING"; break; case FrameworkEvent.INFO: message = "FrameworkEvent INFO"; break; } insert(new LogEntryImpl(event.getBundle(), null, type == FrameworkEvent.ERROR ? LogService.LOG_ERROR : LogService.LOG_INFO, message, event.getThrowable())); LOGGER.exiting(CLASS_NAME, "frameworkEvent"); } /** * Insert a log entry into the log. Make sure that the log does not * exceed the limit. * * @param entry the log entry to be inserted into the log */ private void insert(final LogEntry entry) { LOGGER.entering(CLASS_NAME, "insert", entry); synchronized (log) { log.addFirst(entry); while (log.size() > limit) log.removeLast(); } for (LogListenerHolder holder : listeners) { final LogListener listener = holder.getListener(); holder.getExecutor().execute(new Runnable() { public void run() { listener.logged(entry); } }); } LOGGER.exiting(CLASS_NAME, "insert"); } /** * Log events must be delivered by the Log Service implementation to the * Event Admin service (if present) asynchronously. *

* The properties of a log event are: *

    *
  1. bundle.id ? (Long) The source bundle's id.
  2. *
  3. bundle.symbolicName ? (String) The source bundle's symbolic name. Only set if not null.
  4. *
  5. bundle ? (Bundle) The source bundle.
  6. *
  7. log.level ? (Integer) The log level.
  8. *
  9. message ? (String) The log message.
  10. *
  11. timestamp ? (Long) The log entry's timestamp.
  12. *
  13. log.entry ? (LogEntry) The LogEntry object.
  14. *
* If the log entry has an associated Exception: *
    *
  1. exception.class ? (String) The fully-qualified class name of the attached exception. Only set if the getExceptionmethod returns a non-null value.
  2. *
  3. exception.message ? (String) The message of the attached Exception. Only set if the Exception message is not null.
  4. *
  5. exception ? (Throwable) The Exception returned by the getException method.
  6. *
* If the getServiceReference method returns a non-null value: *
    *
  1. service ? (ServiceReference) The result of the getServiceReference method.
  2. *
  3. service.id ? (Long) The id of the service.
  4. *
  5. service.pid ? (String) The service's persistent identity. Only set if the service.pid service property is not null.
  6. *
  7. service.objectClass ? (String[]) The object class of the service object.
  8. *
* * @param entry the log entry to be mapped to an event and delivered via the Event Admin service */ private void broadcast(final LogEntry entry) { LOGGER.entering(CLASS_NAME, "broadcast", entry); if (eventAdmin.size() > 0) { LOGGER.exiting(CLASS_NAME, "broadcast"); return; } String code; switch (entry.getLevel()) { case LogService.LOG_ERROR: code = "ERROR"; break; case LogService.LOG_WARNING: code = "WARNING"; break; case LogService.LOG_INFO: code = "INFO"; break; case LogService.LOG_DEBUG: code = "DEBUG"; break; default: code = "OTHER"; break; } Map map = new HashMap(); Bundle bundle = entry.getBundle(); if (bundle != null) { map.put("bundle.id", bundle.getBundleId()); map.put("bundle", bundle); if (bundle.getSymbolicName() != null) map.put("bundle.symbolicName", bundle.getSymbolicName()); } map.put("log.level", entry.getLevel()); map.put("message", entry.getMessage()); map.put("timestamp", entry.getTime()); map.put("log.entry", entry); Throwable exception = entry.getException(); if (exception != null) { map.put("exception.class", exception.getClass().getName()); map.put("exception.message", exception.getMessage()); map.put("exception", exception); } ServiceReference reference = entry.getServiceReference(); if (reference != null) { map.put("service", reference); map.put("service.id", reference.getProperty(Constants.SERVICE_ID)); if (reference.getProperty(Constants.SERVICE_PID) != null) map.put("service.pid", reference.getProperty(Constants.SERVICE_PID)); map.put("service.objectClass", reference.getProperty(Constants.OBJECTCLASS)); } eventAdmin.postEvent(new Event("org/osgi/service/log/LogEntry/" + code, map)); LOGGER.exiting(CLASS_NAME, "broadcast"); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy