/*
 * eXist Open Source Native XML Database
 * Copyright (C) 2001-2015 The eXist Project
 * http://exist-db.org
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */
package org.exist.xquery;

import org.exist.security.Subject;

/**
 * Base class for XQuery functions which switch the current user
 *
 * Provides the function {@link #switchUser(Subject)} to allow us
 * to switch the current broker to a user and then have it switched
 * back when the XQuery expression is reset
 *
 * @author <a href="mailto:adam.retter@googlemail.com">Adam Retter</a>
 */
public abstract class UserSwitchingBasicFunction extends BasicFunction {

    /**
     * Flag which indicates that we have pushed a subject and so we must later
     * pop the subject when the expression is reset, see {@link UserSwitchingBasicFunction#resetState(boolean)}
     */
    private boolean pushedSubject = false;

    public UserSwitchingBasicFunction(final XQueryContext context, final FunctionSignature signature) {
        super(context, signature);
    }

    /**
     * Switches the current broker to the provided user
     *
     * @param user the user to switch to
     */
    protected void switchUser(final Subject user) {
        context.getBroker().pushSubject(user);
        pushedSubject = true;
    }

    /**
     * Takes care to switch the broker back from the switched
     * user before calling @{link super#resetState(boolean)}
     */
    @Override
    public void resetState(final boolean postOptimization) {
        //if we pushed a subject, we must pop it
        if(this.pushedSubject) {
            try {
                context.getBroker().popSubject();
            } finally {
                this.pushedSubject = false;
            }
        }

        super.resetState(postOptimization);
    }
}

@@ -1351,20 +1351,33 @@
 dicates 
-that
+how many subjects
  we have
@@ -1383,26 +1383,17 @@
 e pushed
- a subject
+,
  and so 
@@ -1421,23 +1421,39 @@
 pop the 
+same number of 
 subject
+s
  when th
@@ -1554,23 +1554,19 @@
 private 
-boolean
+int
  pushedS
@@ -1571,24 +1571,21 @@
 dSubject
+s
  = 
-false
+0
 ;%0A%0A    p
@@ -1969,15 +1969,11 @@
 ject
- = true
+s++
 ;%0A  
@@ -2252,16 +2252,15 @@
     
-if(this.
+while (
 push
@@ -2272,34 +2272,17 @@
 ject
-) %7B%0A            try %7B%0A    
+s %3E 0) %7B%0A
     
@@ -2339,77 +2339,25 @@
     
-%7D finally %7B%0A                this.pushedSubject = false;%0A            %7D
+pushedSubjects--;
 %0A   

Fix user leak in XQuery User Switching functions