Package org.apache.sling.commons.log

Source Code of org.apache.sling.commons.log.LogSupport$LogListenerProxy

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.sling.commons.log;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.NoSuchElementException;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleException;
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.ServiceListener;
import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogEntry;
import org.osgi.service.log.LogListener;
import org.osgi.service.log.LogService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* The <code>LogReaderServiceFactory</code> TODO
* <p>
* <blockquote> When a bundle which registers a LogListener object is stopped or
* otherwise releases the Log Reader Service, the Log Reader Service must remove
* all of the bundle's listeners.</blockquote>
* <p>
* TODO: To support configuration, we will implement ManagedService here !
*/
public class LogSupport implements BundleListener, ServiceListener,
        FrameworkListener {

    /**
     * The service property name of the component name (value is
     * "component.name"). Note: We use a private constant here to not create a
     * unneded dependency on the org.osgi.service.component package.
     */
    private static final String COMPONENT_NAME = "component.name";

    private final Object lock = new Object();

    private LogListenerProxy[] listeners;

    /* package */LogSupport() {
    }

    /* package */void shutdown() {
        synchronized (this.lock) {
            this.listeners = null;
        }
    }

    // ---------- LogReaderService interface -----------------------------------

    /* package */void addLogListener(Bundle bundle, LogListener listener) {
        synchronized (this.lock) {
            LogListenerProxy llp = new LogListenerProxy(bundle, listener);
            if (this.listeners == null) {
                this.listeners = new LogListenerProxy[] { llp };
            } else if (this.getListener(listener) < 0) {
                LogListenerProxy[] newListeners = new LogListenerProxy[this.listeners.length + 1];
                System.arraycopy(this.listeners, 0, newListeners, 0,
                    this.listeners.length);
                newListeners[this.listeners.length] = llp;
                this.listeners = newListeners;
            }
        }
    }

    /* package */void removeLogListener(LogListener listener) {
        synchronized (this.lock) {
            // no listeners registered, nothing to do
            if (this.listeners == null) {
                return;
            }

            // listener is not registered, nothing to do
            int idx = this.getListener(listener);
            if (idx < 0) {
                return;
            }

            LogListenerProxy[] newListeners = new LogListenerProxy[this.listeners.length - 1];
            if (idx > 0) {
                System.arraycopy(this.listeners, 0, newListeners, 0, idx);
            }
            if (idx < this.listeners.length) {
                System.arraycopy(this.listeners, idx + 1, newListeners, 0,
                    newListeners.length - idx);
            }
            this.listeners = newListeners;
        }
    }

    /* package */void removeLogListeners(Bundle bundle) {
        // grab an immediate copy of the array
        LogListenerProxy[] current = this.getListeners();
        if (current == null) {
            return;
        }

        // check for listeners by bundle
        for (int i = 0; i < current.length; i++) {
            if (current[i].hasBundle(bundle)) {
                this.removeLogListener(current[i]);
            }
        }
    }

    private int getListener(LogListener listener) {
        if (this.listeners != null) {
            for (int i = 0; i < this.listeners.length; i++) {
                if (this.listeners[i].isSame(listener)) {
                    return i;
                }
            }
        }

        // fall back to not found
        return -1;
    }

    private LogListenerProxy[] getListeners() {
        synchronized (this.lock) {
            return this.listeners;
        }
    }

    @SuppressWarnings("unchecked")
    private final Enumeration EMPTY = new Enumeration() {
        public boolean hasMoreElements() {
            return false;
        }

        public Object nextElement() {
            throw new NoSuchElementException("Empty");
        }
    };

    /* package */@SuppressWarnings("unchecked")
    Enumeration getLog() {
        return this.EMPTY;
    }

    // ---------- Firing a log event -------------------------------------------

    /* package */void fireLogEvent(LogEntry entry) {
        this.logOut(entry);

        // grab an immediate copy of the array
        LogListener[] current = this.getListeners();
        if (current == null) {
            return;
        }

        // fire the events outside of the lock
        for (int i = 0; i < current.length; i++) {
            current[i].logged(entry);
        }
    }

    // ---------- BundleListener -----------------------------------------------

    public void bundleChanged(BundleEvent event) {
        String message;
        switch (event.getType()) {
            case BundleEvent.INSTALLED:
                message = "BundleEvent INSTALLED";
                break;
            case BundleEvent.STARTED:
                message = "BundleEvent STARTED";
                break;
            case BundleEvent.STOPPED:
                // this is special, as we have to fix the listener list for
                // stopped bundles
                this.removeLogListeners(event.getBundle());
                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;
            default:
                message = "BundleEvent " + event.getType();
        }

        LogEntry entry = new LogEntryImpl(event.getBundle(), null,
            LogService.LOG_INFO, message, null);
        this.fireLogEvent(entry);
    }

    // ---------- ServiceListener ----------------------------------------------

    public void serviceChanged(ServiceEvent event) {
        int level = LogService.LOG_INFO;
        String message;
        switch (event.getType()) {
            case ServiceEvent.REGISTERED:
                message = "ServiceEvent REGISTERED";
                break;
            case ServiceEvent.MODIFIED:
                message = "ServiceEvent MODIFIED";
                level = LogService.LOG_DEBUG;
                break;
            case ServiceEvent.UNREGISTERING:
                message = "ServiceEvent UNREGISTERING";
                break;
            default:
                message = "ServiceEvent " + event.getType();
        }

        String s = (event.getServiceReference().getBundle() == null)
                ? null
                : "Bundle " + event.getServiceReference().getBundle();
        s = (s == null) ? message : s + " " + message;

        LogEntry entry = new LogEntryImpl(
            event.getServiceReference().getBundle(),
            event.getServiceReference(), level, message, null);
        this.fireLogEvent(entry);
    }

    // ---------- FrameworkListener --------------------------------------------

    public void frameworkEvent(FrameworkEvent event) {
        int level = LogService.LOG_INFO;
        String message;
        Throwable exception = event.getThrowable();
        switch (event.getType()) {
            case FrameworkEvent.STARTED:
                message = "FrameworkEvent STARTED";
                break;
            case FrameworkEvent.ERROR:
                message = "FrameworkEvent ERROR";

                // special precaution for Felix.loadBundleClass event overkill
                // FIXME: actually, the error is ok, if the bundle failed to
                // resolve
                if (exception instanceof BundleException) {
                    StackTraceElement[] ste = exception.getStackTrace();
                    if (ste != null && ste.length > 0
                        && "loadBundleClass".equals(ste[0].getMethodName())) {
                        message += ": Class " + exception.getMessage()
                            + " not found";
                        if (event.getBundle() != null) {
                            message += " in bundle "
                                + event.getBundle().getSymbolicName() + " ("
                                + event.getBundle().getBundleId() + ")";
                        }
                        level = LogService.LOG_INFO;
                        exception = null; // don't care for a stack trace here
                        break;
                    }
                }

                level = LogService.LOG_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;
            default:
                message = "FrameworkEvent " + event.getType();
        }

        String s = (event.getBundle() == null) ? null : "Bundle "
            + event.getBundle();
        s = (s == null) ? message : s + " " + message;

        LogEntry entry = new LogEntryImpl(event.getBundle(), null, level,
            message, exception);
        this.fireLogEvent(entry);
    }

    // ---------- Effective logging --------------------------------------------

    private Map<Long, Logger> loggers = new HashMap<Long, Logger>();

    private Logger getLogger(Bundle bundle) {
        Long bundleId = new Long((bundle == null) ? 0 : bundle.getBundleId());
        Logger log = this.loggers.get(bundleId);
        if (log == null) {
           
            String name;
            if (bundle == null) {
               
                // if we have no bundle, use the system bundle's name
                name = Constants.SYSTEM_BUNDLE_SYMBOLICNAME;
               
            } else {
               
                // otherwise use the bundle symbolic name
                name = bundle.getSymbolicName();
               
                // if the bundle has no symbolic name, use the location
                if (name == null) {
                    name = bundle.getLocation();
                }
               
                // if the bundle also has no location, use the bundle Id
                if (name == null) {
                    name = String.valueOf(bundle.getBundleId());
                }
            }
           
            log = LoggerFactory.getLogger(name);
            this.loggers.put(bundleId, log);
        }
        return log;
    }

    private void logOut(LogEntry logEntry) {
        // /* package */ void logOut(Bundle bundle, ServiceReference sr, int
        // level, String message, Throwable exception) {

        // get the logger for the bundle
        Logger log = this.getLogger(logEntry.getBundle());

        StringBuffer msg = new StringBuffer();

        ServiceReference sr = logEntry.getServiceReference();
        if (sr != null) {
            msg.append("Service [");
            if (sr.getProperty(Constants.SERVICE_PID) != null) {
                msg.append(sr.getProperty(Constants.SERVICE_PID)).append(',');
            } else if (sr.getProperty(COMPONENT_NAME) != null) {
                msg.append(sr.getProperty(COMPONENT_NAME)).append(',');
            } else if (sr.getProperty(Constants.SERVICE_DESCRIPTION) != null) {
                msg.append(sr.getProperty(Constants.SERVICE_DESCRIPTION)).append(
                    ',');
            }
            msg.append(sr.getProperty(Constants.SERVICE_ID)).append("] ");
        }

        if (logEntry.getMessage() != null) {
            msg.append(logEntry.getMessage());
        }

        Throwable exception = logEntry.getException();
        if (exception != null) {
            msg.append(" (").append(exception).append(')');
        }

        String message = msg.toString();
        switch (logEntry.getLevel()) {
            case LogService.LOG_DEBUG:
                log.debug(message, exception);
                break;
            case LogService.LOG_INFO:
                log.info(message, exception);
                break;
            case LogService.LOG_WARNING:
                log.warn(message, exception);
                break;
            case LogService.LOG_ERROR:
                log.error(message, exception);
                break;
            default:
                if (logEntry.getLevel() > LogService.LOG_DEBUG) {
                    log.trace(message, exception);
                } else if (logEntry.getLevel() < LogService.LOG_ERROR) {
                    log.error(message, exception);
                }
                break;
        }
    }

    // ---------- internal class -----------------------------------------------

    private static class LogListenerProxy implements LogListener {

        private final int runningBundle = Bundle.STARTING | Bundle.ACTIVE
            | Bundle.STOPPING;

        private final Bundle bundle;

        private final LogListener delegatee;

        public LogListenerProxy(Bundle bundle, LogListener delegatee) {
            this.bundle = bundle;
            this.delegatee = delegatee;
        }

        public void logged(LogEntry entry) {
            if ((this.bundle.getState() & this.runningBundle) != 0) {
                this.delegatee.logged(entry);
            }
        }

        /* package */boolean isSame(LogListener listener) {
            return listener == this.delegatee || listener == this;
        }

        /* package */boolean hasBundle(Bundle bundle) {
            return this.bundle == bundle;
        }
    }
}
TOP

Related Classes of org.apache.sling.commons.log.LogSupport$LogListenerProxy

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.