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

import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.felix.framework.util.MapToDictionary;
import org.apache.felix.framework.util.StringMap;
import org.apache.felix.framework.util.Util;
import org.apache.felix.framework.wiring.BundleCapabilityImpl;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleReference;
import org.osgi.framework.Constants;
import org.osgi.framework.PrototypeServiceFactory;
import org.osgi.framework.ServiceException;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.BundleWire;

class ServiceRegistrationImpl implements ServiceRegistration
{
    // Service registry.
    private final ServiceRegistry m_registry;
    // Bundle providing the service.
    private final Bundle m_bundle;
    // Interfaces associated with the service object.
    private final String[] m_classes;
    // Service Id associated with the service object.
    private final Long m_serviceId;
    // Service object.
    private volatile Object m_svcObj;
    // Service factory interface.
    private volatile ServiceFactory m_factory;
    // Associated property dictionary.
    private volatile Map<String, Object> m_propMap = new StringMap();
    // Re-usable service reference.
    private final ServiceReferenceImpl m_ref;
    // Flag indicating that we are unregistering.
    private volatile boolean m_isUnregistering = false;
    // This threadlocal is used to detect cycles.
    private final ThreadLocal<Boolean> m_threadLoopDetection = new ThreadLocal<Boolean>();

    private final Object syncObject = new Object();

    public ServiceRegistrationImpl(
        ServiceRegistry registry, Bundle bundle,
        String[] classes, Long serviceId,
        Object svcObj, Dictionary dict)
    {
        m_registry = registry;
        m_bundle = bundle;
        m_classes = classes;
        m_serviceId = serviceId;
        m_svcObj = svcObj;
        m_factory = (m_svcObj instanceof ServiceFactory)
            ? (ServiceFactory) m_svcObj : null;

        initializeProperties(dict);

        // This reference is the "standard" reference for this
        // service and will always be returned by getReference().
        m_ref = new ServiceReferenceImpl();
    }

    protected boolean isValid()
    {
        return (m_svcObj != null);
    }

    protected synchronized void invalidate()
    {
        m_svcObj = null;
    }

    public synchronized ServiceReference getReference()
    {
        // Make sure registration is valid.
        if (!isValid())
        {
            throw new IllegalStateException(
                "The service registration is no longer valid.");
        }
        return m_ref;
    }

    public void setProperties(Dictionary dict)
    {
        Map oldProps;
        synchronized (this)
        {
            // Make sure registration is valid.
            if (!isValid())
            {
                throw new IllegalStateException(
                    "The service registration is no longer valid.");
            }
            // Remember old properties.
            oldProps = m_propMap;
            // Set the properties.
            initializeProperties(dict);
        }
        // Tell registry about it.
        m_registry.servicePropertiesModified(this, new MapToDictionary(oldProps));
    }

    public void unregister()
    {
        synchronized (this)
        {
            if (!isValid() || m_isUnregistering)
            {
                throw new IllegalStateException("Service already unregistered.");
            }
            m_isUnregistering = true;
        }
        m_registry.unregisterService(m_bundle, this);
        synchronized (this)
        {
            m_svcObj = null;
            m_factory = null;
        }
    }

    //
    // Utility methods.
    //

    /**
     * This method determines if the class loader of the service object
     * has access to the specified class.
     * @param clazz the class to test for reachability.
     * @return <tt>true</tt> if the specified class is reachable from the
     *         service object's class loader, <tt>false</tt> otherwise.
    **/
    private boolean isClassAccessible(Class clazz)
    {
        // We need to see if the class loader of the service object has
        // access to the specified class; however, we may not have a service
        // object. If we only have service factory, then we will assume two
        // different scenarios:
        // 1. The service factory is provided by the bundle providing the
        //    service.
        // 2. The service factory is NOT provided by the bundle providing
        //    the service.
        // For case 1, we will use the class loader of the service factory
        // to find the class. For case 2, we will assume we have an extender
        // at work here and always return true, since we have no real way of
        // knowing the wiring of the provider unless we actually get the
        // service object, which defeats the lazy aspect of service factories.

        // Case 2.
        if ((m_factory != null)
            && (Felix.m_secureAction.getClassLoader(m_factory.getClass()) instanceof BundleReference)
            && !((BundleReference) Felix.m_secureAction.getClassLoader(m_factory.getClass())).getBundle().equals(m_bundle))
        {
            try
            {
                Class providedClazz = m_bundle.loadClass(clazz.getName());
                if (providedClazz != null)
                {
                    return providedClazz == clazz;
                }
            }
            catch (ClassNotFoundException ex)
            {
                // Ignore and try interface class loaders.
            }
            return true;
        }

        // Case 1.
        Class sourceClass = (m_factory != null) ? m_factory.getClass() : m_svcObj.getClass();
        return Util.loadClassUsingClass(sourceClass, clazz.getName(), Felix.m_secureAction) == clazz;
    }

    Object getProperty(String key)
    {
        return m_propMap.get(key);
    }

    private String[] getPropertyKeys()
    {
        Set s = m_propMap.keySet();
        return (String[]) s.toArray(new String[s.size()]);
    }

    private Bundle[] getUsingBundles()
    {
        return m_registry.getUsingBundles(m_ref);
    }

    /**
     * This method provides direct access to the associated service object;
     * it generally should not be used by anyone other than the service registry
     * itself.
     * @return The service object associated with the registration.
    **/
    Object getService()
    {
        return m_svcObj;
    }

    Object getService(Bundle acqBundle)
    {
        // If the service object is a service factory, then
        // let it create the service object.
        if (m_factory != null)
        {
            Object svcObj = null;
            try
            {
                if (System.getSecurityManager() != null)
                {
                    svcObj = AccessController.doPrivileged(
                        new ServiceFactoryPrivileged(acqBundle, null));
                }
                else
                {
                    svcObj = getFactoryUnchecked(acqBundle);
                }
            }
            catch (PrivilegedActionException ex)
            {
                if (ex.getException() instanceof ServiceException)
                {
                    throw (ServiceException) ex.getException();
                }
                else
                {
                    throw new ServiceException(
                        "Service factory exception: " + ex.getException().getMessage(),
                        ServiceException.FACTORY_EXCEPTION, ex.getException());
                }
            }
            return svcObj;
        }
        else
        {
            return m_svcObj;
        }
    }

    void ungetService(Bundle relBundle, Object svcObj)
    {
        // If the service object is a service factory, then
        // let it release the service object.
        if (m_factory != null)
        {
            try
            {
                if (System.getSecurityManager() != null)
                {
                    AccessController.doPrivileged(
                        new ServiceFactoryPrivileged(relBundle, svcObj));
                }
                else
                {
                    ungetFactoryUnchecked(relBundle, svcObj);
                }
            }
            catch (Throwable ex)
            {
                m_registry.getLogger().log(
                    m_bundle,
                    Logger.LOG_ERROR,
                    "ServiceRegistrationImpl: Error ungetting service.",
                    ex);
            }
        }
    }

    private void initializeProperties(Dictionary<String, Object> dict)
    {
        // Create a case-insensitive map for the properties.
        Map<String, Object> props = new StringMap();

        if (dict != null)
        {
            // Make sure there are no duplicate keys.
            Enumeration<String> keys = dict.keys();
            while (keys.hasMoreElements())
            {
                String key = keys.nextElement();
                if (props.get(key) == null)
                {
                    props.put(key, dict.get(key));
                }
                else
                {
                    throw new IllegalArgumentException("Duplicate service property: " + key);
                }
            }
        }

        // Add the framework assigned properties.
        props.put(Constants.OBJECTCLASS, m_classes);
        props.put(Constants.SERVICE_ID, m_serviceId);
        props.put(Constants.SERVICE_BUNDLEID, m_bundle.getBundleId());
        if ( m_factory != null )
        {
            props.put(Constants.SERVICE_SCOPE,
                      (m_factory instanceof PrototypeServiceFactory
                       ? Constants.SCOPE_PROTOTYPE : Constants.SCOPE_BUNDLE));
        }
        else
        {
            props.put(Constants.SERVICE_SCOPE, Constants.SCOPE_SINGLETON);
        }

        // Update the service property map.
        m_propMap = props;
    }

    private Object getFactoryUnchecked(Bundle bundle)
    {
        Object svcObj = null;
        try
        {
            svcObj = m_factory.getService(bundle, this);
        }
        catch (Throwable th)
        {
            throw new ServiceException(
                "Service factory exception: " + th.getMessage(),
                ServiceException.FACTORY_EXCEPTION, th);
        }
        if (svcObj != null)
        {
            for (int i = 0; i < m_classes.length; i++)
            {
                Class clazz = Util.loadClassUsingClass(
                    svcObj.getClass(), m_classes[i], Felix.m_secureAction);
                if ((clazz == null) || !clazz.isAssignableFrom(svcObj.getClass()))
                {
                    if (clazz == null)
                    {
                        throw new ServiceException(
                            "Service cannot be cast due to missing class: " + m_classes[i],
                            ServiceException.FACTORY_ERROR);
                    }
                    else
                    {
                        throw new ServiceException(
                            "Service cannot be cast: " + m_classes[i],
                            ServiceException.FACTORY_ERROR);
                    }
                }
            }
        }
        else
        {
            throw new ServiceException(
                "Service factory returned null. (" + m_factory + ")", ServiceException.FACTORY_ERROR);
        }
        return svcObj;
    }

    private void ungetFactoryUnchecked(Bundle bundle, Object svcObj)
    {
        m_factory.ungetService(bundle, this, svcObj);
    }

    /**
     * This simple class is used to ensure that when a service factory
     * is called, that no other classes on the call stack interferes
     * with the permissions of the factory itself.
    **/
    private class ServiceFactoryPrivileged implements PrivilegedExceptionAction
    {
        private Bundle m_bundle = null;
        private Object m_svcObj = null;

        public ServiceFactoryPrivileged(Bundle bundle, Object svcObj)
        {
            m_bundle = bundle;
            m_svcObj = svcObj;
        }

        public Object run() throws Exception
        {
            if (m_svcObj == null)
            {
                return getFactoryUnchecked(m_bundle);
            }
            else
            {
                ungetFactoryUnchecked(m_bundle, m_svcObj);
            }
            return null;
        }
    }

    //
    // ServiceReference implementation
    //

    class ServiceReferenceImpl extends BundleCapabilityImpl implements ServiceReference
    {
        private final ServiceReferenceMap m_map;

        private ServiceReferenceImpl()
        {
            super(null, null, Collections.EMPTY_MAP, Collections.EMPTY_MAP);
            m_map = new ServiceReferenceMap();
        }

        ServiceRegistrationImpl getRegistration()
        {
            return ServiceRegistrationImpl.this;
        }

        //
        // Capability methods.
        //

        @Override
        public BundleRevision getRevision()
        {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public String getNamespace()
        {
            return "service-reference";
        }

        @Override
        public Map<String, String> getDirectives()
        {
            return Collections.EMPTY_MAP;
        }

        @Override
        public Map<String, Object> getAttributes()
        {
            return m_map;
        }

        @Override
        public List<String> getUses()
        {
            return Collections.EMPTY_LIST;
        }

        //
        // ServiceReference methods.
        //

        public Object getProperty(String s)
        {
            return ServiceRegistrationImpl.this.getProperty(s);
        }

        public String[] getPropertyKeys()
        {
            return ServiceRegistrationImpl.this.getPropertyKeys();
        }

        public Bundle getBundle()
        {
            // The spec says that this should return null if
            // the service is unregistered.
            return (isValid()) ? m_bundle : null;
        }

        public Bundle[] getUsingBundles()
        {
            return ServiceRegistrationImpl.this.getUsingBundles();
        }

        @Override
        public String toString()
        {
            String[] ocs = (String[]) getProperty("objectClass");
            String oc = "[";
            for(int i = 0; i < ocs.length; i++)
            {
                oc = oc + ocs[i];
                if (i < ocs.length - 1)
                    oc = oc + ", ";
            }
            oc = oc + "]";
            return oc;
        }

        public boolean isAssignableTo(Bundle requester, String className)
        {
            // Always return true if the requester is the same as the provider.
            if (requester == m_bundle)
            {
                return true;
            }

            // Boolean flag.
            boolean allow = true;
            // Get the package.
            String pkgName =
                Util.getClassPackage(className);
            // Get package wiring from service requester.
            BundleRevision requesterRevision = requester.adapt(BundleRevision.class);
            BundleWire requesterWire = Util.getWire(requesterRevision, pkgName);
            BundleCapability requesterCap = Util.getPackageCapability(requesterRevision, pkgName);
            // Get package wiring from service provider.
            BundleRevision providerRevision = m_bundle.adapt(BundleRevision.class);
            BundleWire providerWire = Util.getWire(providerRevision, pkgName);
            BundleCapability providerCap = Util.getPackageCapability(providerRevision, pkgName);

            // There are four situations that may occur here:
            //   1. Neither the requester, nor provider have wires for the package.
            //   2. The requester does not have a wire for the package.
            //   3. The provider does not have a wire for the package.
            //   4. Both the requester and provider have a wire for the package.
            // For case 1, if the requester does not have access to the class at
            // all, we assume it is using reflection and do not filter. If the
            // requester does have access to the class, then we make sure it is
            // the same class as the service. For case 2, we do not filter if the
            // requester is the exporter of the package to which the provider of
            // the service is wired. Otherwise, as in case 1, if the requester
            // does not have access to the class at all, we do not filter, but if
            // it does have access we check if it is the same class accessible to
            // the providing revision. For case 3, the provider will not have a wire
            // if it is exporting the package, so we determine if the requester
            // is wired to it or somehow using the same class. For case 4, we
            // simply compare the exporting revisions from the package wiring to
            // determine if we need to filter the service reference.

            // Case 1: Both requester and provider have no wire.
            if ((requesterWire == null) && (providerWire == null))
            {
                // If requester has no access then true, otherwise service
                // registration must have same class as requester.
                try
                {
                    Class requestClass =
                        ((BundleWiringImpl) requesterRevision.getWiring())
                            .getClassByDelegation(className);
                    allow = getRegistration().isClassAccessible(requestClass);
                }
                catch (Exception ex)
                {
                    // Requester has no access to the class, so allow it, since
                    // we assume the requester is using reflection.
                    allow = true;
                }
            }
            // Case 2: Requester has no wire, but provider does.
            else if ((requesterWire == null) && (providerWire != null))
            {
                // If the requester exports the package, then the provider must
                // be wired to it.
                if (requesterCap != null)
                {
                    allow = providerWire.getProviderWiring().getRevision().equals(requesterRevision);
                }
                // Otherwise, check if the requester has access to the class and,
                // if so, if it is the same class as the provider.
                else
                {
                    try
                    {
                        // Try to load class from requester.
                        Class requestClass =((BundleWiringImpl)
                            requesterRevision.getWiring()).getClassByDelegation(className);
                        try
                        {
                            // If requester has access to the class, verify it is the
                            // same class as the provider.
                            allow = (((BundleWiringImpl)
                                providerRevision.getWiring())
                                    .getClassByDelegation(className) == requestClass);
                        }
                        catch (Exception ex)
                        {
                            allow = false;
                        }
                    }
                    catch (Exception ex)
                    {
                        // Requester has no access to the class, so allow it, since
                        // we assume the requester is using reflection.
                        allow = true;
                    }
                }
            }
            // Case 3: Requester has a wire, but provider does not.
            else if ((requesterWire != null) && (providerWire == null))
            {
                // If the provider exports the package, then the requester must
                // be wired to it.
                if (providerCap != null)
                {
                    allow = requesterWire.getProviderWiring().getRevision().equals(providerRevision);
                }
                // If the provider is not the exporter of the requester's package,
                // then try to use the service registration to see if the requester's
                // class is accessible.
                else
                {
                    try
                    {
                        // Load the class from the requesting bundle.
                        Class requestClass = ((BundleWiringImpl)
                            requesterRevision.getWiring())
                                .getClassByDelegation(className);
                        // Get the service registration and ask it to check
                        // if the service object is assignable to the requesting
                        // bundle's class.
                        allow = getRegistration().isClassAccessible(requestClass);
                    }
                    catch (Exception ex)
                    {
                        // Filter to be safe.
                        allow = false;
                    }
                }
            }
            // Case 4: Both requester and provider have a wire.
            else
            {
                // Include service reference if the wires have the
                // same source revision.
                allow = providerWire.getProviderWiring().getRevision()
                    .equals(requesterWire.getProviderWiring().getRevision());
            }

            return allow;
        }

        public int compareTo(Object reference)
        {
            ServiceReference other = (ServiceReference) reference;

            Long id = (Long) getProperty(Constants.SERVICE_ID);
            Long otherId = (Long) other.getProperty(Constants.SERVICE_ID);

            if (id.equals(otherId))
            {
                return 0; // same service
            }

            Object rankObj = getProperty(Constants.SERVICE_RANKING);
            Object otherRankObj = other.getProperty(Constants.SERVICE_RANKING);

            // If no rank, then spec says it defaults to zero.
            rankObj = (rankObj == null) ? new Integer(0) : rankObj;
            otherRankObj = (otherRankObj == null) ? new Integer(0) : otherRankObj;

            // If rank is not Integer, then spec says it defaults to zero.
            Integer rank = (rankObj instanceof Integer)
                ? (Integer) rankObj : new Integer(0);
            Integer otherRank = (otherRankObj instanceof Integer)
                ? (Integer) otherRankObj : new Integer(0);

            // Sort by rank in ascending order.
            if (rank.compareTo(otherRank) < 0)
            {
                return -1; // lower rank
            }
            else if (rank.compareTo(otherRank) > 0)
            {
                return 1; // higher rank
            }

            // If ranks are equal, then sort by service id in descending order.
            return (id.compareTo(otherId) < 0) ? 1 : -1;
        }

        @Override
        public Dictionary<String, Object> getProperties() {
            return new Hashtable<String, Object>(ServiceRegistrationImpl.this.m_propMap);
        }
    }

    private class ServiceReferenceMap implements Map
    {
        public int size()
        {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public boolean isEmpty()
        {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public boolean containsKey(Object o)
        {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public boolean containsValue(Object o)
        {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public Object get(Object o)
        {
            return ServiceRegistrationImpl.this.getProperty((String) o);
        }

        public Object put(Object k, Object v)
        {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public Object remove(Object o)
        {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public void putAll(Map map)
        {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public void clear()
        {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public Set<Object> keySet()
        {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public Collection<Object> values()
        {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public Set<Entry<Object, Object>> entrySet()
        {
            return Collections.EMPTY_SET;
        }
    }

    boolean currentThreadMarked()
    {
        return m_threadLoopDetection.get() != null;
    }

    void markCurrentThread()
    {
        m_threadLoopDetection.set(Boolean.TRUE);
    }

    void unmarkCurrentThread()
    {
        m_threadLoopDetection.set(null);
    }
}