/*
 * $Header: /home/cvspublic/jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/datastore/XAuthenticator.java,v 1.4 2005/01/19 15:19:01 pnever Exp $
 * $Revision: 1.4 $
 * $Date: 2005/01/19 15:19:01 $
 *
 * ====================================================================
 *
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * Licensed 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.slide.store.tamino.datastore;

import com.softwareag.common.instrumentation.logging.Logger;
import com.softwareag.common.instrumentation.logging.LoggerFactory;
import com.softwareag.common.instrumentation.logging.LoggerUtil;
import com.softwareag.tamino.db.api.accessor.TAdministrationAccessor;
import com.softwareag.tamino.db.api.accessor.TSystemAccessor;
import com.softwareag.tamino.db.api.common.TException;
import com.softwareag.tamino.db.api.connection.TConnection;
import com.softwareag.tamino.db.api.connection.TConnectionFactory;
import com.softwareag.tamino.db.api.connection.TConnectionImpl;
import com.softwareag.tamino.db.api.io.TInputStream;
import com.softwareag.tamino.db.api.response.TServerEcho;
import java.io.IOException;
import java.util.Hashtable;
import org.apache.slide.store.tamino.common.XDatastoreException;
import org.apache.slide.util.ClassName;
import org.apache.slide.util.JDom;
import org.apache.slide.util.XAssertionFailed;
import org.apache.slide.util.XUri;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;


/**
 *
 * @author ehm@softwareag.com
 *
 * @version $Revision: 1.4 $
 */
public class XAuthenticator extends XDbSession {
    
    private static final String LOGNAME = LoggerUtil.getThisClassName();
    private static final String CLASSNAME = new ClassName(LOGNAME).getPlainName();
    private static Logger logger = LoggerFactory.getLogger(LOGNAME);
    
    
    /**
     * Tests if the non-authenticated user is enabled.
     *
     * @pre        (contentId != null)
     * @post       true
     * @param      taminoBase      taminoBase
     * @param      database         database
     * @return     true if enabled
     */
    public static boolean getNonAuthenticatedUserIsEnabled (String taminoBase,
                                                            String database,
                                                            String domain,
                                                            String user, String password) throws XDatastoreException, IOException {
        
        
        XConnectionKey  conKey = getConnectionKey (taminoBase, database, domain,
                                                   user, password);
        
        String param = showAdminCommandAuthentication (conKey);
        boolean result = !"OFF".equals (param);
        
        return result;
    }
    
    
    /**
     * Tests if the authentication flags web server.
     *
     * @pre        (contentId != null)
     * @post       true
     * @param      taminoBase      taminoBase
     * @param      database         database
     * @return     true if enabled
     */
    public static boolean isWebseverEnabled (String taminoBase,
                                             String database,
                                             String domain,
                                             String user, String password)
        throws XDatastoreException, IOException
    {
        
        XConnectionKey  conKey = getConnectionKey (taminoBase, database, domain,
                                                   user, password);
        
        String param = showAdminCommandAuthentication (conKey);
        
        boolean result = param.equalsIgnoreCase ("web server");
        return result;
    }
    /**
     * Tests if the authentication flags tamino.
     *
     * @pre        (contentId != null)
     * @post       true
     * @param      taminoBase      taminoBase
     * @param      database         database
     * @return     true if enabled
     */
    public static boolean isTaminoEnabled (String taminoBase, String database,
                                           String domain, String user,
                                           String password)
        throws XDatastoreException, IOException
    {
        XConnectionKey  conKey = getConnectionKey (taminoBase, database, domain,
                                                   user, password);
        
        String param = showAdminCommandAuthentication (conKey);
        boolean result = param.equalsIgnoreCase("tamino");
        
        return result;
    }
    
    
    private static Hashtable authenticationTypeCache = new Hashtable();
    /**
     * Returns the currently enabled authentication type
     *
     * @pre        (contentId != null)
     * @post       true
     * @param      taminoBase      taminoBase
     * @param      database         database
     * @return     String, authentication type
     */
    public static String getAuthenticationType( String taminoBase, String database, String domain, String user, String password) throws TException{
        TConnection taminoConnection = null;
        String taminoFull = new String(taminoBase + "/" + database);
        //Create the connection to Tamino
        TConnectionFactory connectionFactory = TConnectionFactory.getInstance();
        if (domain.equals("")) {
            taminoConnection = connectionFactory.newConnection(taminoFull, user, password);
        } else {
            taminoConnection = connectionFactory.newConnection(taminoFull, domain, user, password);
        }
        String result = (String)authenticationTypeCache.get(((TConnectionImpl)taminoConnection).getDatabaseURI());
        if (result != null) return result;
        
        TSystemAccessor systemAccessor = taminoConnection.newSystemAccessor();
        TServerEcho echo = systemAccessor.getServerEcho();
        result = echo.getAuthenticationType();
        authenticationTypeCache.put(((TConnectionImpl)taminoConnection).getDatabaseURI(), result);
        return result;
    }
    
    // -------------------------------------------------------------------------
    
    
    
    
    private static Hashtable issueAdminCommandCache = new Hashtable();
    
    
    /**
     * This method returns the url cache key
     *
     */
    public static String getIssueAdminCommandKey (XConnection xCon) {
        return xCon.getPoolId().getDatabaseUri();
    }
    
    
    /**
     * issues an Tamino ADMIN command
     *
     * @param    taminoBase          a  String
     * @param    database            a  String
     * @param    domain              a  String
     * @param    user                a  String
     * @param    password            a  String
     * @param    command             a  String
     *
     * @return   the taminoresponse as Element
     *
     */
    private static String showAdminCommandAuthentication (XConnectionKey conKey)
        throws XDatastoreException, IOException
    {
        Element result;
        String value;
        
        XConnection xCon = null;
        xCon = XConnectionPool.getInstance().getXConnection (conKey);
        try {
            
            String version = xCon.getServerVersion();
            
            String para;
            if (version.startsWith ("3"))
                para = "allow non-authenticated users";
            else
                para = "authentication";
            
            String command = "ino:ShowServerParameter(\"" + para + "\")";
                       
            value = (String)issueAdminCommandCache.get (getIssueAdminCommandKey (xCon));

            // if (value != null) return value;
            if (value != null) {
                xCon.close();
                return value;
            }
            
            TConnection tCon = xCon.getTConnection();
            TAdministrationAccessor adminAccessor = tCon.newAdministrationAccessor();
            
            TInputStream response = adminAccessor.execute (command);
            result = new SAXBuilder().build (response).getRootElement();
            xCon.close();
            
        } catch (JDOMException e) {
            xCon.close();
            throw new XAssertionFailed("invalid response from Tamino", e);
        }
        catch (TException e) {
            xCon.close();
            throw new XDatastoreException (e);
        }
        
        value = JDom.getXElement(result, "parameters").getChildText ("parameter");
        if (value == null) {
            throw new XAssertionFailed("missing parameter value: " + JDom.toString(result));
//            System.out.println("missing parameter value: " + JDom.toString(result));
//            return "";
        }
        
        issueAdminCommandCache.put (getIssueAdminCommandKey (xCon), value);
        
        return value;
    }
    
    
    private static XConnectionKey getConnectionKey (String taminoBase,
                                                    String database,
                                                    String domain,
                                                    String user,
                                                    String password)
    {
        if (!taminoBase.endsWith (XUri.SEP))
            taminoBase = taminoBase + XUri.SEP;
        
        int lastSlashIndex = taminoBase.lastIndexOf (XUri.SEP);
        String     url     = taminoBase.substring(0, lastSlashIndex) + XUri.SEP + database;
        
        XConnectionKey conKey = new XConnectionKey (url, domain, user, password, "Authenticate");
        return conKey;
    }
}



