/*
 * 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.io.File;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;

import org.osgi.framework.AdminPermission;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.BundleListener;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkListener;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceObjects;
import org.osgi.framework.ServicePermission;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.SynchronousBundleListener;

class BundleContextImpl implements BundleContext
{
    private Logger m_logger = null;
    private Felix m_felix = null;
    private BundleImpl m_bundle = null;
    private boolean m_valid = true;

    protected BundleContextImpl(Logger logger, Felix felix, BundleImpl bundle)
    {
        m_logger = logger;
        m_felix = felix;
        m_bundle = bundle;
    }

    protected void invalidate()
    {
        m_valid = false;
    }

    public String getProperty(String name)
    {
        checkValidity();

        // CONCURRENCY NOTE: This is a check-then-act situation,
        // but we ignore it since the time window is small and
        // the result is the same as if the calling thread had
        // won the race condition.

        Object sm = System.getSecurityManager();

        if (sm != null)
        {
            if (!(Constants.FRAMEWORK_VERSION.equals(name) ||
                Constants.FRAMEWORK_VENDOR.equals(name) ||
                Constants.FRAMEWORK_LANGUAGE.equals(name)||
                Constants.FRAMEWORK_OS_NAME.equals(name) ||
                Constants.FRAMEWORK_OS_VERSION.equals(name) ||
                Constants.FRAMEWORK_PROCESSOR.equals(name)))
            {
                ((SecurityManager) sm).checkPermission(
                    new java.util.PropertyPermission(name, "read"));
            }
        }

        return m_felix.getProperty(name);
    }

    public Bundle getBundle()
    {
        checkValidity();

        // CONCURRENCY NOTE: This is a check-then-act situation,
        // but we ignore it since the time window is small and
        // the result is the same as if the calling thread had
        // won the race condition.

        return m_bundle;
    }

    public Filter createFilter(String expr)
        throws InvalidSyntaxException
    {
        checkValidity();

        // CONCURRENCY NOTE: This is a check-then-act situation,
        // but we ignore it since the time window is small and
        // the result is the same as if the calling thread had
        // won the race condition.

        return new FilterImpl(expr);
    }

    public Bundle installBundle(String location)
        throws BundleException
    {
        return installBundle(location, null);
    }

    public Bundle installBundle(String location, InputStream is)
        throws BundleException
    {
        checkValidity();

        // CONCURRENCY NOTE: This is a check-then-act situation,
        // but we ignore it since the time window is small and
        // the result is the same as if the calling thread had
        // won the race condition.

        Bundle result = null;

        Object sm = System.getSecurityManager();

        if (sm != null)
        {
            result = m_felix.installBundle(m_bundle, location, is);
            // Do check the bundle again in case that is was installed
            // already.
            ((SecurityManager) sm).checkPermission(
                new AdminPermission(result, AdminPermission.LIFECYCLE));
        }
        else
        {
            result = m_felix.installBundle(m_bundle, location, is);
        }

        return result;
    }

    public Bundle getBundle(long id)
    {
        checkValidity();

        // CONCURRENCY NOTE: This is a check-then-act situation,
        // but we ignore it since the time window is small and
        // the result is the same as if the calling thread had
        // won the race condition.

        return m_felix.getBundle(this, id);
    }

    public Bundle getBundle(String location)
    {
        checkValidity();

        // CONCURRENCY NOTE: This is a check-then-act situation,
        // but we ignore it since the time window is small and
        // the result is the same as if the calling thread had
        // won the race condition.

        return m_felix.getBundle(location);
    }

    public Bundle[] getBundles()
    {
        checkValidity();

        // CONCURRENCY NOTE: This is a check-then-act situation,
        // but we ignore it since the time window is small and
        // the result is the same as if the calling thread had
        // won the race condition.

        return m_felix.getBundles(this);
    }

    public void addBundleListener(BundleListener l)
    {
        checkValidity();

        // CONCURRENCY NOTE: This is a check-then-act situation, but
        // internally the event dispatcher double checks whether or not
        // the bundle context is valid before adding the service listener
        // while holding the event queue lock, so it will either succeed
        // or fail.

        Object sm = System.getSecurityManager();

        if (sm != null)
        {
            if (l instanceof SynchronousBundleListener)
            {
                ((SecurityManager) sm).checkPermission(new AdminPermission(m_bundle,
                    AdminPermission.LISTENER));
            }
        }

        m_felix.addBundleListener(m_bundle, l);
    }

    public void removeBundleListener(BundleListener l)
    {
        checkValidity();

        // CONCURRENCY NOTE: This is a check-then-act situation,
        // but we ignore it since the time window is small and
        // the result is the same as if the calling thread had
        // won the race condition.

        Object sm = System.getSecurityManager();

        if (sm != null)
        {
            if (l instanceof SynchronousBundleListener)
            {
                ((SecurityManager) sm).checkPermission(new AdminPermission(m_bundle,
                    AdminPermission.LISTENER));
            }
        }

        m_felix.removeBundleListener(m_bundle, l);
    }

    public void addServiceListener(ServiceListener l)
    {
        try
        {
            addServiceListener(l, null);
        }
        catch (InvalidSyntaxException ex)
        {
            // This will not happen since the filter is null.
        }
    }

    public void addServiceListener(ServiceListener l, String s)
        throws InvalidSyntaxException
    {
        checkValidity();

        // CONCURRENCY NOTE: This is a check-then-act situation, but
        // internally the event dispatcher double checks whether or not
        // the bundle context is valid before adding the service listener
        // while holding the event queue lock, so it will either succeed
        // or fail.

        m_felix.addServiceListener(m_bundle, l, s);
    }

    public void removeServiceListener(ServiceListener l)
    {
        checkValidity();

        // CONCURRENCY NOTE: This is a check-then-act situation,
        // but we ignore it since the time window is small and
        // the result is the same as if the calling thread had
        // won the race condition.

        m_felix.removeServiceListener(m_bundle, l);
    }

    public void addFrameworkListener(FrameworkListener l)
    {
        checkValidity();

        // CONCURRENCY NOTE: This is a check-then-act situation, but
        // internally the event dispatcher double checks whether or not
        // the bundle context is valid before adding the service listener
        // while holding the event queue lock, so it will either succeed
        // or fail.

        m_felix.addFrameworkListener(m_bundle, l);
    }

    public void removeFrameworkListener(FrameworkListener l)
    {
        checkValidity();

        // CONCURRENCY NOTE: This is a check-then-act situation,
        // but we ignore it since the time window is small and
        // the result is the same as if the calling thread had
        // won the race condition.

        m_felix.removeFrameworkListener(m_bundle, l);
    }

    public ServiceRegistration<?> registerService(
        String clazz, Object svcObj, Dictionary<String, ? > dict)
    {
        return registerService(new String[] { clazz }, svcObj, dict);
    }

    public ServiceRegistration<?> registerService(
        String[] clazzes, Object svcObj, Dictionary<String, ? > dict)
    {
        checkValidity();

        // CONCURRENCY NOTE: This is a NOT a check-then-act situation,
        // because internally the framework acquires the bundle state
        // lock to ensure state consistency.

        Object sm = System.getSecurityManager();

        if (sm != null)
        {
            if (clazzes != null)
            {
                for (int i = 0;i < clazzes.length;i++)
                {
                    ((SecurityManager) sm).checkPermission(
                        new ServicePermission(clazzes[i], ServicePermission.REGISTER));
                }
            }
        }

        return m_felix.registerService(this, clazzes, svcObj, dict);
    }

    public <S> ServiceRegistration<S> registerService(
        Class<S> clazz, S svcObj, Dictionary<String, ? > dict)
    {
        return (ServiceRegistration<S>)
            registerService(new String[] { clazz.getName() }, svcObj, dict);
    }

    public ServiceReference<?> getServiceReference(String clazz)
    {
        checkValidity();

        // CONCURRENCY NOTE: This is a check-then-act situation,
        // but we ignore it since the time window is small and
        // the result is the same as if the calling thread had
        // won the race condition.

        try
        {
            ServiceReference[] refs = getServiceReferences(clazz, null);
            return getBestServiceReference(refs);
        }
        catch (InvalidSyntaxException ex)
        {
            m_logger.log(m_bundle, Logger.LOG_ERROR, "BundleContextImpl: " + ex);
        }
        return null;
    }

    public <S> ServiceReference<S> getServiceReference(Class<S> clazz)
    {
        return (ServiceReference<S>) getServiceReference(clazz.getName());
    }

    private ServiceReference getBestServiceReference(ServiceReference[] refs)
    {
        if (refs == null)
        {
            return null;
        }

        if (refs.length == 1)
        {
            return refs[0];
        }

        // Loop through all service references and return
        // the "best" one according to its rank and ID.
        ServiceReference bestRef = refs[0];
        for (int i = 1; i < refs.length; i++)
        {
            if (bestRef.compareTo(refs[i]) < 0)
            {
                bestRef = refs[i];
            }
        }

        return bestRef;
    }

    public ServiceReference<?>[] getAllServiceReferences(String clazz, String filter)
        throws InvalidSyntaxException
    {
        checkValidity();

        // CONCURRENCY NOTE: This is a check-then-act situation,
        // but we ignore it since the time window is small and
        // the result is the same as if the calling thread had
        // won the race condition.

        return m_felix.getAllowedServiceReferences(m_bundle, clazz, filter, false);

    }

    public ServiceReference<?>[] getServiceReferences(String clazz, String filter)
        throws InvalidSyntaxException
    {
        checkValidity();

        // CONCURRENCY NOTE: This is a check-then-act situation,
        // but we ignore it since the time window is small and
        // the result is the same as if the calling thread had
        // won the race condition.

        return m_felix.getAllowedServiceReferences(m_bundle, clazz, filter, true);

    }

    public <S> Collection<ServiceReference<S>> getServiceReferences(
        Class<S> clazz, String filter)
        throws InvalidSyntaxException
    {
        ServiceReference<S>[] refs =
            (ServiceReference<S>[]) getServiceReferences(clazz.getName(), filter);
        return (refs == null)
            ? Collections.EMPTY_LIST
            : (Collection<ServiceReference<S>>) Arrays.asList(refs);
    }

    public <S> S getService(ServiceReference<S> ref)
    {
        checkValidity();

        // CONCURRENCY NOTE: This is a check-then-act situation,
        // but we ignore it since the time window is small and
        // the result is the same as if the calling thread had
        // won the race condition.

        if (ref == null)
        {
            throw new NullPointerException("Specified service reference cannot be null.");
        }

        Object sm = System.getSecurityManager();

        if (sm != null)
        {
           ((SecurityManager) sm).checkPermission(new ServicePermission(ref, ServicePermission.GET));
        }

        return m_felix.getService(m_bundle, ref, false);
    }

    public boolean ungetService(ServiceReference<?> ref)
    {
        checkValidity();

        if (ref == null)
        {
            throw new NullPointerException("Specified service reference cannot be null.");
        }

        // Unget the specified service.
        return m_felix.ungetService(m_bundle, ref, null);
    }

    public File getDataFile(String s)
    {
        checkValidity();

        // CONCURRENCY NOTE: This is a check-then-act situation,
        // but we ignore it since the time window is small and
        // the result is the same as if the calling thread had
        // won the race condition.

        return m_felix.getDataFile(m_bundle, s);
    }

    private void checkValidity()
    {
        if (m_valid)
        {
            switch (m_bundle.getState())
            {
                case Bundle.ACTIVE:
                case Bundle.STARTING:
                case Bundle.STOPPING:
                    return;
            }
        }

        throw new IllegalStateException("Invalid BundleContext.");
    }

    /**
     * @see org.osgi.framework.BundleContext#registerService(java.lang.Class, org.osgi.framework.ServiceFactory, java.util.Dictionary)
     */
    public <S> ServiceRegistration<S> registerService(Class<S> clazz,
            ServiceFactory<S> factory, Dictionary<String, ?> properties)
    {
        return (ServiceRegistration<S>)
                registerService(new String[] { clazz.getName() }, factory, properties);
    }

    /**
     * @see org.osgi.framework.BundleContext#getServiceObjects(org.osgi.framework.ServiceReference)
     */
    public <S> ServiceObjects<S> getServiceObjects(final ServiceReference<S> ref)
    {
    	checkValidity();

        Object sm = System.getSecurityManager();

        if (sm != null)
        {
           ((SecurityManager) sm).checkPermission(new ServicePermission(ref, ServicePermission.GET));
        }

        ServiceRegistrationImpl reg =
                ((ServiceRegistrationImpl.ServiceReferenceImpl) ref).getRegistration();
        if ( reg.isValid() )
        {
        	return new ServiceObjectsImpl(ref);
        }
        return null;
    }

    //
    // ServiceObjects implementation
    //
    class ServiceObjectsImpl<S> implements ServiceObjects<S>
    {
        private final ServiceReference<S> m_ref;

        public ServiceObjectsImpl(final ServiceReference<S> ref)
        {
            this.m_ref = ref;
        }

        public S getService() {
            checkValidity();

            // CONCURRENCY NOTE: This is a check-then-act situation,
            // but we ignore it since the time window is small and
            // the result is the same as if the calling thread had
            // won the race condition.

            final Object sm = System.getSecurityManager();

            if (sm != null)
            {
               ((SecurityManager) sm).checkPermission(new ServicePermission(m_ref, ServicePermission.GET));
            }

            return m_felix.getService(m_bundle, m_ref, true);
        }

        public void ungetService(final S srvObj)
        {
            checkValidity();

            // Unget the specified service.
            if ( !m_felix.ungetService(m_bundle, m_ref, srvObj) )
            {
            	throw new IllegalArgumentException();
            }
        }

        public ServiceReference<S> getServiceReference()
        {
            return m_ref;
        }
    }

}