/*
 * 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.felix.eventadmin.impl.adapter;

import java.util.Dictionary;
import java.util.Hashtable;

import org.apache.felix.eventadmin.impl.util.LogWrapper;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;
import org.osgi.service.event.EventConstants;

/**
 * This class registers itself as a listener for <tt>LogReaderService</tt> services
 * with the framework and subsequently, a <tt>LogListener</tt> callback with any
 * currently available <tt>LogReaderService</tt>. Any received log event is then
 * posted via the EventAdmin as specified in 113.6.6 OSGi R4 compendium.
 * Note that this class does not create a hard dependency on the org.osgi.service.log
 * packages. The adaption only takes place if it is present or once it becomes
 * available hence, combined with a DynamicImport-Package no hard dependency is
 * needed.
 *
 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
 */
public class LogEventAdapter extends AbstractAdapter implements ServiceListener
{
    // The internal lock for this object used instead synchronized(this)
    private final Object m_lock = new Object();

    private BundleContext m_context;

    // A singleton instance of the used log listener that is the adapter
    private Object m_logListener;

    /**
     * The constructor of the adapter. This will register the adapter with the
     * given context as a listener for <tt>LogReaderService</tt> services and
     * subsequently, a <tt>LogListener</tt> callback with any currently available
     * <tt>LogReaderService</tt>. Any received log event is then posted via the given
     * EventAdmin.
     *
     * @param context The bundle context with which to register as a listener.
     * @param admin The <tt>EventAdmin</tt> to use for posting events.
     */
    public LogEventAdapter(final BundleContext context, final EventAdmin admin)
    {
        super(admin);
        m_context = context;

        try
        {
            m_context.addServiceListener(this, "(" + Constants.OBJECTCLASS
                + "=org.osgi.service.log.LogReaderService)");

            final ServiceReference[] refs;

            refs = m_context.getServiceReferences(
                "org.osgi.service.log.LogReaderService", null);

            if (null != refs)
            {
                for (int i = 0; i < refs.length; i++)
                {
                    final org.osgi.service.log.LogReaderService logReader =
                        (org.osgi.service.log.LogReaderService) m_context
                        .getService(refs[i]);

                    if (null != logReader)
                    {
                        logReader.addLogListener((org.osgi.service.log.LogListener)
                            getLogListener());
                    }
                }
            }
        } catch (InvalidSyntaxException e)
        {
            // This never happens
        }
    }

    @Override
    public void destroy(BundleContext context) {
        context.removeServiceListener(this);
    }

    /**
     * Once a <tt>LogReaderService</tt> register event is received this method
     * registers a <tt>LogListener</tt> with the received service that assembles
     * and posts any log event via the <tt>EventAdmin</tt> as specified in
     * 113.6.6 OSGi R4 compendium.
     *
     * @param event The event to adapt.
     */
    @Override
    public void serviceChanged(final ServiceEvent event)
    {
        if (ServiceEvent.REGISTERED == event.getType())
        {
            final org.osgi.service.log.LogReaderService logReader =
                (org.osgi.service.log.LogReaderService) m_context
                .getService(event.getServiceReference());

            if (null != logReader)
            {
                logReader.addLogListener((org.osgi.service.log.LogListener)
                    getLogListener());
            }
        }
    }

    /*
     * Constructs a LogListener that assembles and posts any log event via the
     * EventAdmin as specified in 113.6.6 OSGi R4 compendium. Note that great
     * care is taken to not create a hard dependency on the org.osgi.service.log
     * package.
     */
    private Object getLogListener()
    {
        synchronized (m_lock)
        {
            if (null != m_logListener)
            {
                return m_logListener;
            }

            m_logListener = new org.osgi.service.log.LogListener()
            {
                @Override
                public void logged(final org.osgi.service.log.LogEntry entry)
                {
                    // This is where the assembly as specified in 133.6.6 OSGi R4
                    // compendium is taking place (i.e., the log entry is adapted to
                    // an event and posted via the EventAdmin)

                    final Dictionary<String, Object> properties = new Hashtable<String, Object>();

                    final Bundle bundle = entry.getBundle();

                    if (null != bundle)
                    {
                        properties.put("bundle.id", new Long(bundle
                            .getBundleId()));

                        final String symbolicName = bundle.getSymbolicName();

                        if (null != symbolicName)
                        {
                            properties.put(EventConstants.BUNDLE_SYMBOLICNAME,
                                symbolicName);
                        }

                        properties.put("bundle", bundle);
                    }

                    properties.put("log.level", new Integer(entry.getLevel()));

		    properties.put(EventConstants.MESSAGE,
				   (entry.getMessage()) != null ? entry.getMessage() : "" );

                    properties.put(EventConstants.TIMESTAMP, new Long(
                        entry.getTime()));

                    properties.put("log.entry", entry);

                    final Throwable exception = entry.getException();

                    if (null != exception)
                    {
                        properties.put(EventConstants.EXCEPTION_CLASS,
                            exception.getClass().getName());

                        final String message = exception.getMessage();

                        if (null != message)
                        {
                            properties.put(EventConstants.EXCEPTION_MESSAGE,
                                message);
                        }

                        properties.put(EventConstants.EXCEPTION, exception);
                    }

                    final ServiceReference service = entry
                        .getServiceReference();

                    if (null != service)
                    {
                        properties.put(EventConstants.SERVICE, service);

                        final Object id = service
                            .getProperty(EventConstants.SERVICE_ID);

                        if (null != id)
                        {
                            try
                            {
                                properties.put(EventConstants.SERVICE_ID,
                                    new Long(id.toString()));
                            } catch (NumberFormatException ne)
                            {
                                // LOG and IGNORE
                                LogWrapper.getLogger().log(
                                    entry.getServiceReference(),
                                    LogWrapper.LOG_WARNING, "Exception parsing " +
                                    EventConstants.SERVICE_ID + "=" + id, ne);
                            }
                        }

                        final Object pid = service.getProperty(
                            EventConstants.SERVICE_PID);

                        if (null != pid)
                        {
                            properties.put(EventConstants.SERVICE_PID,
                                pid.toString());
                        }

                        final Object objectClass = service.getProperty(
                            Constants.OBJECTCLASS);

                        if (null != objectClass)
                        {
                            if (objectClass instanceof String[])
                            {
                                properties.put(
                                    EventConstants.SERVICE_OBJECTCLASS,
                                    objectClass);
                            }
                            else
                            {
                                properties.put(
                                    EventConstants.SERVICE_OBJECTCLASS,
                                    new String[] { objectClass.toString() });
                            }
                        }
                    }

                    final StringBuffer topic = new StringBuffer(
                        org.osgi.service.log.LogEntry.class.getName().replace(
                            '.', '/')).append('/');

                    switch (entry.getLevel())
                    {
                        case org.osgi.service.log.LogService.LOG_ERROR:
                            topic.append("LOG_ERROR");
                            break;
                        case org.osgi.service.log.LogService.LOG_WARNING:
                            topic.append("LOG_WARNING");
                            break;
                        case org.osgi.service.log.LogService.LOG_INFO:
                            topic.append("LOG_INFO");
                            break;
                        case org.osgi.service.log.LogService.LOG_DEBUG:
                            topic.append("LOG_DEBUG");
                            break;
                        default:
                            topic.append("LOG_OTHER");
                            break;
                    }

                    try {
                        getEventAdmin().postEvent(new Event(topic.toString(), properties));
                    } catch(IllegalStateException e) {
                        // This is o.k. - indicates that we are stopped.
                    }
                }
            };

            return m_logListener;
        }
    }
}
