Package org.apache.felix.eventadmin.bridge.upnp

Source Code of org.apache.felix.eventadmin.bridge.upnp.UPnPEventToEventAdminBridge

/*
* 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.bridge.upnp;

import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;

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.framework.ServiceRegistration;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;
import org.osgi.service.event.EventConstants;
import org.osgi.service.event.EventHandler;
import org.osgi.service.upnp.UPnPDevice;
import org.osgi.service.upnp.UPnPEventListener;
import org.osgi.service.upnp.UPnPService;

/**
* This class registers itself as an UPnPEventListener service with the
* framework whenever both, at least one EventAdmin and at least one
* EventHandler is present and subsequently, bridges UPnPEvents received to the
* EventAdmin service. In order to track EventAdmin services this class
* registers a ServiceListener for EventAdmin services as well as a
* ServiceListener for EventHandlers in order to determine EventHandler
* availability.
*
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class UPnPEventToEventAdminBridge implements UPnPEventListener
{
    private static final String EVENT_HANDLER_FILTER = "(&("
        + Constants.OBJECTCLASS + "=" + EventHandler.class.getName() + ")(|("
        + EventConstants.EVENT_TOPIC + "=\\*)(" + EventConstants.EVENT_TOPIC
        + "=org/\\*)(" + EventConstants.EVENT_TOPIC + "=org/osgi/\\*)("
        + EventConstants.EVENT_TOPIC + "=org/osgi/service/\\*)("
        + EventConstants.EVENT_TOPIC + "=org/osgi/service/upnp/\\*)("
        + EventConstants.EVENT_TOPIC + "=org/osgi/service/upnp/UPnPEvent)))";

    final Object m_lock = new Object();

    // The references to the EventAdmins
    final Set m_adminRefs = new HashSet();

    // The references to the EventHandlers
    final Set m_handlerRefs = new HashSet();

    private final BundleContext m_context;

    private ServiceRegistration m_reg = null;

    /**
     * This class registers itself as an UPnPEventListener service with the
     * framework whenever both, at least one EventAdmin and at least one
     * EventHandler is present and subsequently, bridges UPnPEvents received to
     * the EventAdmin service. In order to track EventAdmin services this class
     * registers a ServiceListener for EventAdmin services as well as a
     * ServiceListener for EventHandlers in order to determine EventHandler
     * availability.
     *
     * @param context
     *            The context to register with.
     */
    public UPnPEventToEventAdminBridge(final BundleContext context)
    {
        synchronized(m_lock)
        {
            m_context = context;

            try
            {
                m_context.addServiceListener(new ServiceListener()
                {

                    public void serviceChanged(final ServiceEvent event)
                    {
                        synchronized(m_lock)
                        {
                            switch(event.getType())
                            {
                                case ServiceEvent.REGISTERED:
                                    m_adminRefs
                                        .add(event.getServiceReference());
                                    break;
                                case ServiceEvent.UNREGISTERING:
                                    m_adminRefs.remove(event
                                        .getServiceReference());
                                    break;
                            }

                            check();
                        }
                    }
                }, "(" + Constants.OBJECTCLASS + "="
                    + EventAdmin.class.getName() + ")");

                final ServiceReference[] adminRefs = m_context
                    .getServiceReferences(EventAdmin.class.getName(), null);

                if(null != adminRefs)
                {
                    for(int i = 0; i < adminRefs.length; i++)
                    {
                        m_adminRefs.add(adminRefs[i]);
                    }
                }

                m_context.addServiceListener(new ServiceListener()
                {
                    public void serviceChanged(final ServiceEvent event)
                    {
                        synchronized(m_lock)
                        {
                            switch(event.getType())
                            {
                                case ServiceEvent.REGISTERED:
                                    m_handlerRefs.add(event
                                        .getServiceReference());
                                    break;
                                case ServiceEvent.UNREGISTERING:
                                    m_handlerRefs.remove(event
                                        .getServiceReference());
                                    break;
                            }

                            check();
                        }
                    }
                }, EVENT_HANDLER_FILTER);

                final ServiceReference[] handlerRefs = m_context
                    .getServiceReferences(EventHandler.class.getName(),
                        EVENT_HANDLER_FILTER);

                if(null != handlerRefs)
                {
                    for(int i = 0; i < handlerRefs.length; i++)
                    {
                        m_handlerRefs.add(handlerRefs[i]);
                    }
                }
            } catch(InvalidSyntaxException e)
            {
                // This will never happen
            }

            check();
        }
    }

    // The set contains the last used filter parts. It will be null in case the
    // last
    // time we registered with a null property. It will be an empty HashSet in
    // case we have been unregistered previously
    private Set last = new HashSet();

    // Registers itself as an UPnPEventListener with the framework in case there
    // is both, at least one EventAdmin (i.e., !m_adminRefs.isEmpty()) and at
    // least one EventHandler (i.e., !m_handlerRefs.isEmpty()) present and it is
    // not already registers. Respectively, it unregisters itself in case one of
    // the above is false.
    void check()
    {
        // do we need to be registered?
        if(m_adminRefs.isEmpty() || m_handlerRefs.isEmpty())
        {
            // no we don't but do we need to unregister?
            if(null != m_reg)
            {
                // yes
                m_reg.unregister();
                m_reg = null;
                last = new HashSet();
            }
        }
        else
        // yes we need to be registered
        {
            final Set parts = new HashSet();
            final StringBuffer result = new StringBuffer().append("(|");

            for(Iterator iter = m_handlerRefs.iterator(); iter.hasNext();)
            {
                final String filter = (String) ((ServiceReference) iter.next())
                    .getProperty(EventConstants.EVENT_FILTER);

                // if any filter is not set we need to register with a null and
                // can
                // return
                if(null == filter)
                {
                    // but only if we are not currently registered with a null
                    if(last != null)
                    {
                        last = null;
                        change(null);
                    }
                    return;
                }

                // if we don't already have this filter part we need to check if
                // it is a valid filter
                if(!parts.contains(filter))
                {
                    try
                    {
                        m_context.createFilter(filter);
                        parts.add(filter);
                        result.append(filter);
                    } catch(InvalidSyntaxException e)
                    {
                        // and it is not a valid filter - hence, drop it
                        e.printStackTrace();
                    }
                }
            }

            // parts will only be empty if there is no handler with a valid
            // filter and we only need to register with the new filter if it
            // doesn't equals the last filter
            if(!parts.isEmpty() && !parts.equals(last))
            {
                last = parts;

                try
                {
                    final Hashtable properties = new Hashtable();
                   
                    properties.put(UPnPEventListener.UPNP_FILTER,
                        m_context.createFilter(replaceAll(replaceAll(
                        result.append(")").toString().toCharArray(),
                        serviceChars, UPnPService.ID).toCharArray(),
                        deviceChars, UPnPDevice.ID)));
                   
                    change(properties);
                } catch(InvalidSyntaxException e)
                {
                    // This will never happen
                    e.printStackTrace();
                }
            }
        }
    }
   
    private static final char[] serviceChars = new char[]{'u','p','n','p','.','s','e','r','v','i','c','e','i','d'};
    private static final char[] deviceChars = new char[]{'u','p','n','p','.','d','e','v','i','c','e','i','d'};
   
    private String replaceAll(final char[] source, final char[] pattern, final String target)
    {
        StringBuffer result = new StringBuffer();
       
        int pos = 0, matchPos = 0;
       
        while(true)
        {  
            if(pattern[matchPos] == Character.toLowerCase(source[pos]))
            {
                matchPos++;
                if(matchPos == pattern.length)
                {
                    result.append(target);
                    matchPos = 0;
                }
            }
            else if(matchPos > 0 )
            {
                result.append(source, pos - matchPos, matchPos + 1);
                matchPos = 0;
            }
            else
            {
                result.append(source[pos]);
            }
           
            pos++;
           
            if(pos >= source.length)
            {
                if(matchPos > 0)
                {
                    result.append(source, pos - matchPos, matchPos);
                }
               
                break;
            }
        }
       
        return result.toString();
    }

    private void change(final Dictionary filter)
    {
        if(null == m_reg)
        {
            m_reg = m_context.registerService(
                UPnPEventListener.class.getName(), this, filter);
        }
        else
        {
            m_reg.setProperties(filter);
        }
    }

    /**
     * Bridge any event to the EventAdmin service.
     *
     * @param deviceId
     *            Bridged to <tt>upnp.deviceId</tt>
     * @param serviceId
     *            Bridged to <tt>upnp.serviceId</tt>
     * @param events
     *            Bridged to <tt>upnp.events</tt>
     *
     * @see org.osgi.service.upnp.UPnPEventListener#notifyUPnPEvent(java.lang.String,
     *      java.lang.String, java.util.Dictionary)
     */
    public void notifyUPnPEvent(final String deviceId, final String serviceId,
        final Dictionary events)
    {
        final ServiceReference ref = m_context
            .getServiceReference(EventAdmin.class.getName());

        if(null != ref)
        {
            final EventAdmin eventAdmin = (EventAdmin) m_context
                .getService(ref);

            if(null != eventAdmin)
            {
                final Dictionary immutableEvents = new Dictionary()
                {
                    public int size()
                    {
                        return events.size();
                    }

                    public boolean isEmpty()
                    {
                        return events.isEmpty();
                    }

                    public Enumeration keys()
                    {
                        return events.keys();
                    }

                    public Enumeration elements()
                    {
                        return events.elements();
                    }

                    public Object get(Object arg0)
                    {
                        return events.get(arg0);
                    }

                    public Object put(Object arg0, Object arg1)
                    {
                        throw new IllegalStateException(
                            "Event Properties may not be changed");
                    }

                    public Object remove(Object arg0)
                    {
                        throw new IllegalStateException(
                            "Event Properties may not be changed");
                    }

                    public boolean equals(Object arg0)
                    {
                        return events.equals(arg0);
                    }

                    public int hashCode()
                    {
                        return events.hashCode();
                    }

                    public String toString()
                    {
                        return events.toString();
                    }
                };

                final Hashtable properties = new Hashtable();
               
                properties.put(UPnPDevice.ID, deviceId);
                properties.put(UPnPService.ID, serviceId);
                properties.put("upnp.serviceId", serviceId);
                properties.put("upnp.deviceId", deviceId);
                properties.put("upnp.events", immutableEvents);
               
                eventAdmin.postEvent(
                    new Event("org/osgi/service/upnp/UPnPEvent", properties));

                m_context.ungetService(ref);
            }
        }
    }
}
TOP

Related Classes of org.apache.felix.eventadmin.bridge.upnp.UPnPEventToEventAdminBridge

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.