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

import org.apache.lucene.index.*;
import org.apache.lucene.search.*;
import org.apache.lucene.queryParser.ParseException;
import org.apache.solr.search.QParserPlugin;
import org.apache.solr.search.QParser;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.MapSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.StrUtils;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.ShardParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.handler.component.ResponseBuilder;
import org.apache.solr.handler.component.SearchComponent;
import org.apache.solr.core.CloseHook;
import org.apache.solr.util.plugin.SolrCoreAware;
import org.apache.solr.core.SolrCore;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.*;
import org.apache.commons.httpclient.params.*;
import org.slf4j.*;

import java.io.*;
import java.util.*;
import java.net.*;

/**
* Query parser plugin for ManifoldCF-specific document-level access control.
*/
public class ManifoldCFQParserPlugin extends QParserPlugin
{
  /** The component name */
  static final public String COMPONENT_NAME = "mcf";
  /** The parameter that is supposed to contain the authenticated user name, possibly including the AD domain */
  static final public String AUTHENTICATED_USER_NAME = "AuthenticatedUserName";
  /** The parameter that is supposed to contain the MCF authorization domain, if any */
  static final public String AUTHENTICATED_USER_DOMAIN = "AuthenticatedUserDomain";
  /** If there are more than one user/domain, this prefix will allow us to get the users... */
  static final public String AUTHENTICATED_USER_NAME_PREFIX = "AuthenticatedUserName_";
  /** If there are more than one user/domain, this prefix will allow us to get the authorization domains... */
  static final public String AUTHENTICATED_USER_DOMAIN_PREFIX = "AuthenticatedUserDomain_";

  /** The parameter that is supposed to contain token_directory for filtering */
  static final public String AUTH_DIRECTORYCOUNT = COMPONENT_NAME+".auth.directoryCount";

  /** This parameter is an array of strings, which contain the tokens to use if there is no authenticated user name.
   * It's meant to work with mod_authz_annotate,
   * running under Apache */
  static final public String USER_TOKENS = "UserTokens";
  
  /** Special token for null security fields */
  static final public String NOSECURITY_TOKEN = "__nosecurity__";
  
  /** The queries that we will not attempt to interfere with */
  static final private String[] globalAllowed = { "solrpingquery" };
  
  /** A logger we can use */
  private static final Logger LOG = LoggerFactory.getLogger(ManifoldCFQParserPlugin.class);

  // Member variables
  String authorityBaseURL = null;
  String fieldAllowDocument = null;
  String fieldDenyDocument = null;
  String fieldAllowShare = null;
  String fieldDenyShare = null;
  String fieldAllowDirectory = null;
  String fieldDenyDirectory = null;
  int socketTimeOut;
  Integer connectionManagerSynchronizer = new Integer(0);
  MultiThreadedHttpConnectionManager httpConnectionManager = null;
  HttpClient client = null;
  int poolSize;
  
  public ManifoldCFQParserPlugin()
  {
    super();
  }

  public void init(NamedList args)
  {
    authorityBaseURL = (String)args.get("AuthorityServiceBaseURL");
    if (authorityBaseURL == null)
      authorityBaseURL = "http://localhost:8345/mcf-authority-service";
    Integer timeOut = (Integer)args.get("SocketTimeOut");
    socketTimeOut = timeOut == null ? 300000 : timeOut;
    String allowAttributePrefix = (String)args.get("AllowAttributePrefix");
    String denyAttributePrefix = (String)args.get("DenyAttributePrefix");
    if (allowAttributePrefix == null)
      allowAttributePrefix = "allow_token_";
    if (denyAttributePrefix == null)
      denyAttributePrefix = "deny_token_";
    fieldAllowDocument = allowAttributePrefix+"document";
    fieldDenyDocument = denyAttributePrefix+"document";
    fieldAllowShare = allowAttributePrefix+"share";
    fieldDenyShare = denyAttributePrefix+"share";
    fieldAllowDirectory = allowAttributePrefix+"directory_";
    fieldDenyDirectory = denyAttributePrefix+"directory_";
    Integer connectionPoolSize = (Integer)args.get("ConnectionPoolSize");
    poolSize = (connectionPoolSize==null)?50:connectionPoolSize.intValue();
  }
  
  protected void initializeClient(SolrCore core)
  {
    synchronized (connectionManagerSynchronizer)
    {
      if (client == null)
      {
        // Initialize the connection pool
        HttpConnectionManagerParams params = new HttpConnectionManagerParams();
        params.setTcpNoDelay(true);
        params.setStaleCheckingEnabled(false);
        params.setDefaultMaxConnectionsPerHost(poolSize);
        params.setMaxTotalConnections(poolSize);
        httpConnectionManager = new MultiThreadedHttpConnectionManager();
        httpConnectionManager.setParams(params);
        client = new HttpClient(httpConnectionManager);
        core.addCloseHook(new CloseHandler());
      }
    }
  }

  @Override
  public QParser createParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req)
  {
    initializeClient(req.getCore());
    return new ManifoldCFQueryParser(qstr,localParams,params,req);
  }

  protected class ManifoldCFQueryParser extends QParser
  {
    public ManifoldCFQueryParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req)
    {
      super(qstr,localParams,params,req);
    }
        
    @Override
    /** Create and return the <code>Query</code> object represented by <code>qstr</code>
    * @see #getQuery()
    **/
    public Query parse() throws ParseException
    {
      SolrParams params = req.getParams();

      List<String> userAccessTokens;
      
      // Map from domain to user
      Map<String,String> domainMap = new HashMap<String,String>();
      
      // Get the authenticated user name from the parameters
      String authenticatedUserName = params.get(AUTHENTICATED_USER_NAME);
      if (authenticatedUserName != null)
      {
        String authenticatedUserDomain = params.get(AUTHENTICATED_USER_DOMAIN);
        if (authenticatedUserDomain == null)
          authenticatedUserDomain = "";
        domainMap.put(authenticatedUserDomain, authenticatedUserName);
      }
      else
      {
        // Look for user names/domains using the prefix
        int i = 0;
        while (true)
        {
          String userName = params.get(AUTHENTICATED_USER_NAME_PREFIX+i);
          String domain = params.get(AUTHENTICATED_USER_DOMAIN+i);
          if (userName == null)
            break;
          if (domain == null)
            domain = "";
          domainMap.put(domain,userName);
          i++;
        }
      }
      
      // If this parameter is empty or does not exist, we have to presume this is a guest, and treat them accordingly
      if (domainMap.size() == 0)
      {
        // No authenticated user name.
        // mod_authz_annotate may be in use upstream, so look for tokens from it.
        userAccessTokens = new ArrayList<String>();
        String[] passedTokens = params.getParams(USER_TOKENS);
        if (passedTokens == null)
        {
          // Only return 'public' documents (those with no security tokens at all)
          LOG.info("Default no-user response (open documents only)");
        }
        else
        {
          // Only return 'public' documents (those with no security tokens at all)
          LOG.info("Group tokens received from caller");
          for (String passedToken : passedTokens)
          {
            userAccessTokens.add(passedToken);
          }
        }
      }
      else
      {
        StringBuilder sb = new StringBuilder("[");
        boolean first = true;
        for (String domain : domainMap.keySet())
        {
          if (!first)
            sb.append(",");
          else
            first = false;
          sb.append(domain).append(":").append(domainMap.get(domain));
        }
        sb.append("]");
        LOG.info("Trying to match docs for user '"+sb.toString()+"'");
        // Valid authenticated user name.  Look up access tokens for the user.
        // Check the configuration arguments for validity
        if (authorityBaseURL == null)
        {
          throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Error initializing ManifoldCFSecurityFilter component: 'AuthorityServiceBaseURL' init parameter required");
        }
        try
        {
          userAccessTokens = getAccessTokens(domainMap);
        }
        catch (IOException e)
        {
          LOG.error("IO exception communicating with MCF authority service: "+e.getMessage(),e);
          throw new ParseException("IO exception communicating with MCF authority service: "+e.getMessage());
        }
      }

      // Get the auth directory field count from the parameter
      int directoryCount = params.getInt(AUTH_DIRECTORYCOUNT, 0);

      BooleanQuery bq = new BooleanQuery();
      //bf.setMaxClauseCount(100000);
      
      Query allowShareOpen = new TermQuery(new Term(fieldAllowShare,NOSECURITY_TOKEN));
      Query denyShareOpen = new TermQuery(new Term(fieldDenyShare,NOSECURITY_TOKEN));
      Map<Integer,Query> allowDirectoryOpenMap = new HashMap<Integer,Query>();
      Map<Integer,Query> denyDirectoryOpenMap = new HashMap<Integer,Query>();
      int q = 0;
      while (q < directoryCount)
      {
        Query allowDirectoryOpen = new TermQuery(new Term(fieldAllowDirectory+q,NOSECURITY_TOKEN));
        Query denyDirectoryOpen = new TermQuery(new Term(fieldDenyDirectory+q,NOSECURITY_TOKEN));
        allowDirectoryOpenMap.put(Integer.valueOf(q), allowDirectoryOpen);
        denyDirectoryOpenMap.put(Integer.valueOf(q), denyDirectoryOpen);
        q++;
      }
      Query allowDocumentOpen = new TermQuery(new Term(fieldAllowDocument,NOSECURITY_TOKEN));
      Query denyDocumentOpen = new TermQuery(new Term(fieldDenyDocument,NOSECURITY_TOKEN));
      
      if (userAccessTokens.size() == 0)
      {
        // Only open documents can be included.
        // That query is:
        // (fieldAllowShare is empty AND fieldDenyShare is empty AND fieldAllowDocument is empty AND fieldDenyDocument is empty)
        // We're trying to map to:  -(fieldAllowShare:*) , which should be pretty efficient in Solr because it is negated.  If this turns out not to be so, then we should
        // have the SolrConnector inject a special token into these fields when they otherwise would be empty, and we can trivially match on that token.
        bq.add(allowShareOpen,BooleanClause.Occur.MUST);
        bq.add(denyShareOpen,BooleanClause.Occur.MUST);
        int r = 0;
        while (r < directoryCount)
        {
          Integer index = Integer.valueOf(r);
          Query allowDirectoryOpen = allowDirectoryOpenMap.get(index);
          Query denyDirectoryOpen = denyDirectoryOpenMap.get(index);
          bq.add(allowDirectoryOpen,BooleanClause.Occur.MUST);
          bq.add(denyDirectoryOpen,BooleanClause.Occur.MUST);
          r++;
        }
        bq.add(allowDocumentOpen,BooleanClause.Occur.MUST);
        bq.add(denyDocumentOpen,BooleanClause.Occur.MUST);
      }
      else
      {
        // Extend the query appropriately for each user access token.
        bq.add(calculateCompleteSubquery(fieldAllowShare,fieldDenyShare,allowShareOpen,denyShareOpen,userAccessTokens),
          BooleanClause.Occur.MUST);
        int r = 0;
        while (r < directoryCount)
        {
          Integer index = Integer.valueOf(r);
          Query allowDirectoryOpen = allowDirectoryOpenMap.get(index);
          Query denyDirectoryOpen = denyDirectoryOpenMap.get(index);
          bq.add(calculateCompleteSubquery(fieldAllowDirectory+r,fieldDenyDirectory+r,allowDirectoryOpen,denyDirectoryOpen,userAccessTokens),
            BooleanClause.Occur.MUST);
          r++;
        }
        bq.add(calculateCompleteSubquery(fieldAllowDocument,fieldDenyDocument,allowDocumentOpen,denyDocumentOpen,userAccessTokens),
          BooleanClause.Occur.MUST);
      }

      return new ConstantScoreQuery(bq);
    }

    /** Calculate a complete subclause, representing something like:
    * ((fieldAllowShare is empty AND fieldDenyShare is empty) OR fieldAllowShare HAS token1 OR fieldAllowShare HAS token2 ...)
    *     AND fieldDenyShare DOESN'T_HAVE token1 AND fieldDenyShare DOESN'T_HAVE token2 ...
    */
    protected Query calculateCompleteSubquery(String allowField, String denyField, Query allowOpen, Query denyOpen, List<String> userAccessTokens)
    {
      BooleanQuery bq = new BooleanQuery();
      bq.setMaxClauseCount(1000000);
      
      // Add the empty-acl case
      BooleanQuery subUnprotectedClause = new BooleanQuery();
      subUnprotectedClause.add(allowOpen,BooleanClause.Occur.MUST);
      subUnprotectedClause.add(denyOpen,BooleanClause.Occur.MUST);
      bq.add(subUnprotectedClause,BooleanClause.Occur.SHOULD);
      for (String accessToken : userAccessTokens)
      {
        bq.add(new TermQuery(new Term(allowField,accessToken)),BooleanClause.Occur.SHOULD);
        bq.add(new TermQuery(new Term(denyField,accessToken)),BooleanClause.Occur.MUST_NOT);
      }
      return bq;
    }
    
    // Protected methods
    
    /** Get access tokens given a username */
    protected List<String> getAccessTokens(Map<String,String> domainMap)
      throws IOException
    {
      // We can make this more complicated later, with support for https etc., but this is enough to demonstrate how it all should work.
      StringBuilder urlBuffer = new StringBuilder(authorityBaseURL);
      urlBuffer.append("/UserACLs");
      int i = 0;
      for (String domain : domainMap.keySet())
      {
        if (i == 0)
          urlBuffer.append("?");
        else
          urlBuffer.append("&");
        // For backwards compatibility, handle the singleton case specially
        if (domainMap.size() == 1 && domain.length() == 0)
        {
          urlBuffer.append("username=").append(URLEncoder.encode(domainMap.get(domain),"utf-8"));
        }
        else
        {
          urlBuffer.append("username_").append(Integer.toString(i)).append("=").append(URLEncoder.encode(domainMap.get(domain),"utf-8")).append("&")
            .append("domain_").append(Integer.toString(i)).append("=").append(URLEncoder.encode(domain,"utf-8"));
        }
        i++;
      }
      String theURL = urlBuffer.toString();
        
      GetMethod method = new GetMethod(theURL);
      try
      {
        method.getParams().setParameter("http.socket.timeout", socketTimeOut);
        method.setFollowRedirects(true);
        int rval = client.executeMethod(method);
        if (rval != 200)
        {
          String response = method.getResponseBodyAsString();
          throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,"Couldn't fetch user's access tokens from ManifoldCF authority service: "+Integer.toString(rval)+"; "+response);
        }
        InputStream is = method.getResponseBodyAsStream();
        try
        {
          Reader r = new InputStreamReader(is,method.getResponseCharSet());
          try
          {
            BufferedReader br = new BufferedReader(r);
            try
            {
              // Read the tokens, one line at a time.  If any authorities are down, we have no current way to note that, but someday we will.
              List<String> tokenList = new ArrayList<String>();
              while (true)
              {
                String line = br.readLine();
                if (line == null)
                  break;
                if (line.startsWith("TOKEN:"))
                {
                  tokenList.add(line.substring("TOKEN:".length()));
                }
                else
                {
                  // It probably says something about the state of the authority(s) involved, so log it
                  LOG.info("Saw authority response "+line);
                }
              }
              return tokenList;
            }
            finally
            {
              br.close();
            }
          }
          finally
          {
            r.close();
          }
        }
        finally
        {
          is.close();
        }
      }
      finally
      {
        method.releaseConnection();
      }
    }
  }

  /** CloseHook implementation.
  */
  protected class CloseHandler extends CloseHook
  {
    public CloseHandler()
    {
    }
    
    @Override
    public void preClose(SolrCore core)
    {
    }
    
    @Override
    public void postClose(SolrCore core)
    {
      // Close the connection pool
      if (httpConnectionManager != null)
      {
        httpConnectionManager.shutdown();
        httpConnectionManager = null;
        client = null;
      }
    }
    
  }

}