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

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.net.URL;
import java.security.AccessControlContext;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Permission;
import java.security.Principal;
import java.security.ProtectionDomain;
import java.security.PublicKey;
import java.security.SignatureException;
import java.security.cert.X509Certificate;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.Map.Entry;

import org.apache.felix.framework.BundleProtectionDomain;
import org.apache.felix.framework.BundleRevisionImpl;
import org.apache.felix.framework.security.permissionadmin.PermissionAdminImpl;
import org.apache.felix.framework.security.util.Conditions;
import org.apache.felix.framework.security.util.LocalPermissions;
import org.apache.felix.framework.security.util.Permissions;
import org.apache.felix.framework.security.util.PropertiesCache;
import org.apache.felix.framework.util.manifestparser.NativeLibrary;

/*
import org.apache.felix.moduleloader.ICapability;
import org.apache.felix.moduleloader.IContent;
import org.apache.felix.moduleloader.IModule;
import org.apache.felix.moduleloader.IRequirement;
import org.apache.felix.moduleloader.IWire;
*/
import org.apache.felix.framework.cache.Content;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.Version;
import org.osgi.service.condpermadmin.ConditionInfo;
import org.osgi.service.condpermadmin.ConditionalPermissionAdmin;
import org.osgi.service.condpermadmin.ConditionalPermissionInfo;
import org.osgi.service.condpermadmin.ConditionalPermissionUpdate;
import org.osgi.service.permissionadmin.PermissionInfo;

/**
 * An implementation of the ConditionalPermissionAdmin service that doesn't need
 * to have a framework specific security manager set. It use the DomainGripper
 * to know what bundleprotectiondomains are expected.
 */
public final class ConditionalPermissionAdminImpl implements
    ConditionalPermissionAdmin
{
    private static class OrderedHashMap extends HashMap
    {
        private final List m_order = new ArrayList();

        public Object put(Object key, Object value)
        {
            Object result = super.put(key, value);
            if (result != value)
            {
                m_order.remove(key);
                m_order.add(key);
            }
            return result;
        };

        public void putAll(Map map)
        {
            for (Iterator iter = map.entrySet().iterator(); iter.hasNext();)
            {
                Entry entry = (Entry) iter.next();
                put(entry.getKey(), entry.getValue());
            }
        };

        public Set keySet()
        {
            return new AbstractSet()
            {
                public Iterator iterator()
                {
                    return m_order.iterator();
                }

                public int size()
                {
                    return m_order.size();
                }

            };
        };

        public Set entrySet()
        {
            return new AbstractSet()
            {

                public Iterator iterator()
                {
                    return new Iterator()
                    {
                        Iterator m_iter = m_order.iterator();

                        public boolean hasNext()
                        {
                            return m_iter.hasNext();
                        }

                        public Object next()
                        {
                            final Object key = m_iter.next();
                            return new Entry()
                            {

                                public Object getKey()
                                {
                                    return key;
                                }

                                public Object getValue()
                                {
                                    return get(key);
                                }

                                public Object setValue(Object arg0)
                                {
                                    throw new IllegalStateException(
                                        "Not Implemented");
                                }
                            };
                        }

                        public void remove()
                        {
                            throw new IllegalStateException("Not Implemented");
                        }

                    };
                }

                public int size()
                {
                    return m_order.size();
                }

            };
        };

        public Collection values()
        {
            List result = new ArrayList();
            for (Iterator iter = m_order.iterator(); iter.hasNext();)
            {
                result.add(super.get(iter.next()));
            }
            return result;
        };

        public Object remove(Object key)
        {
            Object result = super.remove(key);
            if (result != null)
            {
                m_order.remove(key);
            }
            return result;
        };

        public void clear()
        {
            super.clear();
            m_order.clear();
        };
    };

    private static final ConditionInfo[] EMPTY_CONDITION_INFO = new ConditionInfo[0];
    private static final PermissionInfo[] EMPTY_PERMISSION_INFO = new PermissionInfo[0];
    private final Map m_condPermInfos = new OrderedHashMap();
    private final PropertiesCache m_propertiesCache;
    private final Permissions m_permissions;
    private final Conditions m_conditions;
    private final LocalPermissions m_localPermissions;
    private final PermissionAdminImpl m_pai;

    public ConditionalPermissionAdminImpl(Permissions permissions,
        Conditions condtions, LocalPermissions localPermissions,
        PropertiesCache cache, PermissionAdminImpl pai) throws IOException
    {
        m_propertiesCache = cache;
        m_permissions = permissions;
        m_conditions = condtions;
        m_localPermissions = localPermissions;
        Map old = new OrderedHashMap();
        // Now try to restore the cache.
        m_propertiesCache.read(ConditionalPermissionInfoImpl.class, old);
        for (Iterator iter = old.entrySet().iterator(); iter.hasNext();)
        {
            Entry entry = (Entry) iter.next();
            String name = (String) entry.getKey();
            ConditionalPermissionInfoImpl cpi = ((ConditionalPermissionInfoImpl) entry
                .getValue());
            m_condPermInfos.put(name, new ConditionalPermissionInfoImpl(name,
                cpi._getConditionInfos(), cpi._getPermissionInfos(), this, cpi
                    .isAllow()));
        }
        m_pai = pai;
    }

    public ConditionalPermissionInfo addConditionalPermissionInfo(
        ConditionInfo[] conditions, PermissionInfo[] permissions)
    {
        Object sm = System.getSecurityManager();
        if (sm != null)
        {
            ((SecurityManager) sm).checkPermission(Permissions.ALL_PERMISSION);
        }
        ConditionalPermissionInfoImpl result = new ConditionalPermissionInfoImpl(
            notNull(conditions), notNull(permissions), this, true);

        return write(result.getName(), result);
    }

    ConditionalPermissionInfoImpl write(String name,
        ConditionalPermissionInfoImpl cpi)
    {
        synchronized (m_propertiesCache)
        {
            Map tmp = null;

            synchronized (m_condPermInfos)
            {
                tmp = new OrderedHashMap();
                tmp.putAll(m_condPermInfos);

                if ((name != null) && (cpi != null))
                {
                    m_condPermInfos.put(name, cpi);
                }
                else if (name != null)
                {
                    m_condPermInfos.remove(name);
                }
                else
                {
                    tmp = null;
                }
            }

            try
            {
                m_propertiesCache.write(m_condPermInfos);
            }
            catch (IOException ex)
            {
                synchronized (m_condPermInfos)
                {
                    if (tmp != null)
                    {
                        m_condPermInfos.clear();
                        m_condPermInfos.putAll(tmp);
                    }
                }
                ex.printStackTrace();
                throw new IllegalStateException(ex.getMessage());
            }
        }
        synchronized (m_condPermInfos)
        {
            return (ConditionalPermissionInfoImpl) m_condPermInfos.get(name);
        }
    }

    private static class FakeBundle implements Bundle
    {
        private final Map m_certs;

        public FakeBundle(Map certs)
        {
            m_certs = Collections.unmodifiableMap(certs);
        }

        public Enumeration findEntries(String arg0, String arg1, boolean arg2)
        {
            return null;
        }

        public BundleContext getBundleContext()
        {
            return null;
        }

        public long getBundleId()
        {
            return -1;
        }

        public URL getEntry(String arg0)
        {
            return null;
        }

        public Enumeration getEntryPaths(String arg0)
        {
            return null;
        }

        public Dictionary getHeaders()
        {
            return new Hashtable();
        }

        public Dictionary getHeaders(String arg0)
        {
            return new Hashtable();
        }

        public long getLastModified()
        {
            return 0;
        }

        public String getLocation()
        {
            return "";
        }

        public ServiceReference[] getRegisteredServices()
        {
            return null;
        }

        public URL getResource(String arg0)
        {
            return null;
        }

        public Enumeration getResources(String arg0) throws IOException
        {
            return null;
        }

        public ServiceReference[] getServicesInUse()
        {
            return null;
        }

        public Map getSignerCertificates(int arg0)
        {
            return m_certs;
        }

        public int getState()
        {
            return Bundle.UNINSTALLED;
        }

        public String getSymbolicName()
        {
            return null;
        }

        public Version getVersion()
        {
            return Version.emptyVersion;
        }

        public boolean hasPermission(Object arg0)
        {
            return false;
        }

        public Class loadClass(String arg0) throws ClassNotFoundException
        {
            return null;
        }

        public void start() throws BundleException
        {
            throw new IllegalStateException();
        }

        public void start(int arg0) throws BundleException
        {
            throw new IllegalStateException();
        }

        public void stop() throws BundleException
        {
            throw new IllegalStateException();
        }

        public void stop(int arg0) throws BundleException
        {
            throw new IllegalStateException();
        }

        public void uninstall() throws BundleException
        {
            throw new IllegalStateException();
        }

        public void update() throws BundleException
        {
            throw new IllegalStateException();
        }

        public void update(InputStream arg0) throws BundleException
        {
            throw new IllegalStateException();
        }

        public boolean equals(Object o)
        {
            return this == o;
        }

        public int hashCode()
        {
            return System.identityHashCode(this);
        }

		public int compareTo(Bundle o) {
			// TODO Auto-generated method stub
			return 0;
		}

		public Object adapt(Class arg0) {
			// TODO Auto-generated method stub
			return null;
		}

		public File getDataFile(String arg0) {
			// TODO Auto-generated method stub
			return null;
		}

        public int compareTo(Object t)
        {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }

    private static class FakeCert extends X509Certificate
    {
        private final Principal m_principal;

        public FakeCert(final String principal)
        {
            m_principal = new Principal()
            {
                public String getName()
                {
                    return principal;
                }
            };
        }

        public void checkValidity()
            throws java.security.cert.CertificateExpiredException,
            java.security.cert.CertificateNotYetValidException
        {

        }

        public void checkValidity(Date date)
            throws java.security.cert.CertificateExpiredException,
            java.security.cert.CertificateNotYetValidException
        {
        }

        public int getBasicConstraints()
        {
            return 0;
        }

        public Principal getIssuerDN()
        {
            return null;
        }

        public boolean[] getIssuerUniqueID()
        {
            return null;
        }

        public boolean[] getKeyUsage()
        {
            return null;
        }

        public Date getNotAfter()
        {
            return null;
        }

        public Date getNotBefore()
        {
            return null;
        }

        public BigInteger getSerialNumber()
        {
            return null;
        }

        public String getSigAlgName()
        {
            return null;
        }

        public String getSigAlgOID()
        {
            return null;
        }

        public byte[] getSigAlgParams()
        {
            return null;
        }

        public byte[] getSignature()
        {
            return null;
        }

        public Principal getSubjectDN()
        {
            return m_principal;
        }

        public boolean[] getSubjectUniqueID()
        {
            return null;
        }

        public byte[] getTBSCertificate()
            throws java.security.cert.CertificateEncodingException
        {
            return null;
        }

        public int getVersion()
        {
            return 0;
        }

        public byte[] getEncoded()
            throws java.security.cert.CertificateEncodingException
        {
            return null;
        }

        public PublicKey getPublicKey()
        {
            return null;
        }

        public String toString()
        {
            return m_principal.getName();
        }

        public void verify(PublicKey key)
            throws java.security.cert.CertificateException,
            NoSuchAlgorithmException, InvalidKeyException,
            NoSuchProviderException, SignatureException
        {

        }

        public void verify(PublicKey key, String sigProvider)
            throws java.security.cert.CertificateException,
            NoSuchAlgorithmException, InvalidKeyException,
            NoSuchProviderException, SignatureException
        {

        }

        public Set getCriticalExtensionOIDs()
        {
            return null;
        }

        public byte[] getExtensionValue(String arg0)
        {
            return null;
        }

        public Set getNonCriticalExtensionOIDs()
        {
            return null;
        }

        public boolean hasUnsupportedCriticalExtension()
        {
            return false;
        }

        public boolean equals(Object o)
        {
            return this == o;
        }

        public int hashCode()
        {
            return System.identityHashCode(this);
        }

    }

    public AccessControlContext getAccessControlContext(final String[] signers)
    {
        Map certificates = new HashMap();
        for (int i = 0; i < signers.length; i++)
        {
            StringTokenizer tok = new StringTokenizer(signers[i], ";");
            List certsList = new ArrayList();
            while (tok.hasMoreTokens())
            {
                certsList.add(tok.nextToken());
            }
            String[] certs = (String[]) certsList.toArray(new String[certsList
                .size()]);

            X509Certificate key = new FakeCert(certs[0]);
            List certList = new ArrayList();
            certificates.put(key, certList);
            certList.add(key);
            for (int j = 1; j < certs.length; j++)
            {
                certList.add(new FakeCert(certs[j]));
            }
        }
        final Bundle fake = new FakeBundle(certificates);
        ProtectionDomain domain = new ProtectionDomain(null, null)
        {
            public boolean implies(Permission permission)
            {
                List posts = new ArrayList();
                Boolean result = m_pai.hasPermission("", fake, permission,
                    ConditionalPermissionAdminImpl.this, this, null);
                if (result != null)
                {
                    return result.booleanValue();
                }
                if (eval(posts, new BundleRevisionImpl(fake, Long.toString(fake.getBundleId())), permission, m_pai))
                {
                    if (!posts.isEmpty())
                    {
                        return m_conditions.evalRecursive(posts);
                    }
                    return true;
                }
                return false;
            }
        };
        return new AccessControlContext(new ProtectionDomain[] { domain });
    }

    public ConditionalPermissionInfo getConditionalPermissionInfo(String name)
    {
        if (name == null)
        {
            throw new IllegalArgumentException("Name may not be null");
        }
        ConditionalPermissionInfoImpl result = null;

        synchronized (m_condPermInfos)
        {
            result = (ConditionalPermissionInfoImpl) m_condPermInfos.get(name);
        }

        if (result == null)
        {
            result = new ConditionalPermissionInfoImpl(this, name, true);

            result = write(result.getName(), result);
        }

        return result;
    }

    public Enumeration getConditionalPermissionInfos()
    {
        synchronized (m_condPermInfos)
        {
            return Collections.enumeration(new ArrayList(m_condPermInfos
                .values()));
        }
    }

    public ConditionalPermissionInfo setConditionalPermissionInfo(String name,
        ConditionInfo[] conditions, PermissionInfo[] permissions)
    {
        Object sm = System.getSecurityManager();
        if (sm != null)
        {
            ((SecurityManager) sm).checkPermission(Permissions.ALL_PERMISSION);
        }

        ConditionalPermissionInfoImpl result = null;
        conditions = notNull(conditions);
        permissions = notNull(permissions);

        if (name != null)
        {
            synchronized (m_condPermInfos)
            {
                result = (ConditionalPermissionInfoImpl) m_condPermInfos
                    .get(name);

                if (result == null)
                {
                    result = new ConditionalPermissionInfoImpl(name,
                        conditions, permissions, this, true);
                }
                else
                {
                    result.setConditionsAndPermissions(conditions, permissions);
                }
            }
        }
        else
        {
            result = new ConditionalPermissionInfoImpl(conditions, permissions,
                this, true);
        }

        return write(result.getName(), result);
    }

    private PermissionInfo[] notNull(PermissionInfo[] permissions)
    {
        if (permissions == null)
        {
            return ConditionalPermissionInfoImpl.PERMISSION_INFO;
        }
        return (PermissionInfo[]) notNull((Object[]) permissions).toArray(
            EMPTY_PERMISSION_INFO);
    }

    private ConditionInfo[] notNull(ConditionInfo[] conditions)
    {
        if (conditions == null)
        {
            return ConditionalPermissionInfoImpl.CONDITION_INFO;
        }
        return (ConditionInfo[]) notNull((Object[]) conditions).toArray(
            EMPTY_CONDITION_INFO);
    }

    private List notNull(Object[] elements)
    {
        List result = new ArrayList();

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

        return result;
    }

    // The thread local stack used to keep track of bundle protection domains we
    // still expect to see.
    private final ThreadLocal m_stack = new ThreadLocal();

    /**
     * This method does the actual permission check. If it is not a direct check
     * it will try to determine the other bundle domains that will follow
     * automatically in case this is the first check in one permission check. If
     * not then it will keep track of which domains we have already see. While
     * it keeps track it builds up a list of postponed tuples which it will
     * evaluate at the last domain. See the core spec 9.5.1 and following for a
     * general description.
     *
     * @param felixBundle
     *            the bundle in question.
     * @param loader
     *            the content loader of the bundle to get access to the jar to
     *            check for local permissions.
     * @param root
     *            the bundle id.
     * @param signers
     *            the signers (this is to support the ACC based on signers)
     * @param pd
     *            the bundle protection domain
     * @param permission
     *            the permission currently checked
     * @param direct
     *            whether this is a direct check or not. direct check will not
     *            expect any further bundle domains on the stack
     * @return true in case the permission is granted or there are postponed
     *         tuples false if not. Again, see the spec for more explanations.
     */
    public boolean hasPermission(BundleRevisionImpl module, Content content,
        ProtectionDomain pd, Permission permission, boolean direct, Object admin)
    {
        // System.out.println(felixBundle + "-" + permission);
        List domains = null;
        List tuples = null;
        Object[] entry = null;
        // first see whether this is the normal case (the special case is for
        // the ACC based on signers).
        // In case of a direct call we don't need to look for other pds
        if (direct)
        {
            domains = new ArrayList();
            tuples = new ArrayList();
            domains.add(pd);
        }
        else
        {
            // Get the other pds from the stck
            entry = (Object[]) m_stack.get();

            // if there are none then get them from the gripper
            if (entry == null)
            {
                entry = new Object[] { new ArrayList(DomainGripper.grab()),
                    new ArrayList() };
            }
            else
            {
                m_stack.set(null);
            }

            domains = (List) entry[0];
            tuples = (List) entry[1];
            if (!domains.contains(pd))
            {
                // We have been called directly without the direct flag
                domains.clear();
                domains.add(pd);
            }
        }

        // check the local permissions. they need to all the permission if there
        // are any
        if (!impliesLocal(module.getBundle(), content, permission))
        {
            return false;
        }

        List posts = new ArrayList();

        boolean result = eval(posts, module, permission, admin);

        domains.remove(pd);

        // We postponed tuples
        if (!posts.isEmpty())
        {
            tuples.add(posts);
        }

        // Are we at the end or this was a direct call?
        if (domains.isEmpty())
        {
            m_stack.set(null);
            // Now eval the postponed tupels. if the previous eval did return
            // false
            // tuples will be empty so we don't return from here.
            if (!tuples.isEmpty())
            {
                return m_conditions.evalRecursive(tuples);
            }
        }
        else
        {
            // this is to support recursive permission checks. In case we
            // trigger
            // a permission check while eval the stack is null until this point
            m_stack.set(entry);
        }

        return result;
    }

    public boolean impliesLocal(Bundle felixBundle, Content content,
        Permission permission)
    {
        return m_localPermissions.implies(content, felixBundle, permission);
    }

    public boolean isEmpty()
    {
        synchronized (m_condPermInfos)
        {
            return m_condPermInfos.isEmpty();
        }
    }

    // we need to find all conditions that apply and then check whether they
    // de note the permission in question unless the conditions are postponed
    // then we make sure their permissions imply the permission and add them
    // to the list of posts. Return true in case we pass or have posts
    // else falls and clear the posts first.
    private boolean eval(List posts, BundleRevisionImpl module, Permission permission,
        Object admin)
    {
        List condPermInfos = null;

        synchronized (m_condPermInfos)
        {
            if (isEmpty() && (admin == null))
            {
                return true;
            }
            condPermInfos = new ArrayList(m_condPermInfos.values());
        }

        // Check for implicit permissions like access to file area
        if (m_permissions.getPermissions(
            m_permissions.getImplicit(module.getBundle())).implies(permission,
            module.getBundle()))
        {
            return true;
        }
        List pls = new ArrayList();
        // now do the real thing
        for (Iterator iter = condPermInfos.iterator(); iter.hasNext();)
        {
            ConditionalPermissionInfoImpl cpi = (ConditionalPermissionInfoImpl) iter
                .next();

            ConditionInfo[] conditions = cpi._getConditionInfos();

            List currentPosts = new ArrayList();

            Conditions conds = m_conditions.getConditions(module, conditions);
            if (!conds.isSatisfied(currentPosts, m_permissions
                .getPermissions(cpi._getPermissionInfos()), permission))
            {
                continue;
            }

            if (!m_permissions.getPermissions(cpi._getPermissionInfos())
                .implies(permission, null))
            {
                continue;
            }

            if (currentPosts.isEmpty())
            {
                pls.add(new Object[] { cpi, null });
                break;
            }
            pls.add(new Object[] { cpi, currentPosts, conds });
        }
        while (pls.size() > 1)
        {
            if (!((ConditionalPermissionInfoImpl) ((Object[]) pls.get(pls
                .size() - 1))[0]).isAllow())
            {
                pls.remove(pls.size() - 1);
            }
            else
            {
                break;
            }
        }
        if (pls.size() == 1)
        {
            if (((Object[]) pls.get(0))[1] != null)
            {
                posts.add(pls.get(0));
            }
            return ((ConditionalPermissionInfoImpl) ((Object[]) pls.get(0))[0])
                .isAllow();
        }
        for (Iterator iter = pls.iterator(); iter.hasNext();)
        {
            posts.add(iter.next());
        }
        return !posts.isEmpty();
    }

    public ConditionalPermissionInfo newConditionalPermissionInfo(
        String encodedConditionalPermissionInfo)
    {
        return new ConditionalPermissionInfoImpl(
            encodedConditionalPermissionInfo);
    }

    public ConditionalPermissionInfo newConditionalPermissionInfo(String name,
        ConditionInfo[] conditions, PermissionInfo[] permissions, String access)
    {
        return new ConditionalPermissionInfoImpl(name, conditions, permissions,
            ConditionalPermissionAdminImpl.this, access
                .equals(ConditionalPermissionInfo.ALLOW));
    }

    public ConditionalPermissionUpdate newConditionalPermissionUpdate()
    {
        return new ConditionalPermissionUpdate()
        {
            List current = null;
            List out = null;
            {
                synchronized (m_condPermInfos)
                {
                    current = new ArrayList(m_condPermInfos.values());
                    out = new ArrayList(m_condPermInfos.values());
                }
            }

            public boolean commit()
            {
                synchronized (m_condPermInfos)
                {
                    if (current.equals(new ArrayList(m_condPermInfos.values())))
                    {
                        m_condPermInfos.clear();
                        write(null, null);
                        for (Iterator iter = out.iterator(); iter.hasNext();)
                        {
                            ConditionalPermissionInfoImpl cpii = (ConditionalPermissionInfoImpl) iter
                                .next();
                            write(cpii.getName(), cpii);
                        }
                    }
                    else
                    {
                        return false;
                    }
                }
                return true;
            }

            public List getConditionalPermissionInfos()
            {
                return out;
            }
        };
    }

    public boolean handlePAHandle(BundleProtectionDomain pd)
    {
        Object[] entry = (Object[]) m_stack.get();

        if (entry == null)
        {
            entry = new Object[] { new ArrayList(DomainGripper.grab()),
                new ArrayList() };
        }

        ((List) entry[0]).remove(pd);
        if (((List) entry[0]).isEmpty())
        {
            m_stack.set(null);
            if (!((List) entry[1]).isEmpty())
            {
                return m_conditions.evalRecursive(((List) entry[1]));
            }
        }
        else
        {
            m_stack.set(entry);
        }

        return true;
    }

    public void clearPD()
    {
        m_stack.set(null);
    }
}
