//
// CIMOMHandleXML.java
//
// The contents of this file are subject to the SNIA Public License Version 1.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.snia.org/resources/openSource.html
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the 
// License for the specific language governing rights and limitations
// under the License.
//
// The Original Code is CIMOMHandleXML.java
// 
// The Initial Developer of the Original Code is David Simons.
//
// Contributor(s):
//
//
// This source uses the Solaris WBEM APIs dated June 1999. Synchronization
// will be maintained with the Solaris WBEM APIS, which are being
// standardized through the Java Community Process.
//
//
// $Id: CIMOMHandleXML.java,v 1.1 2003/07/17 18:32:55 kumpf Exp $
//
//
package org.snia.wbemcmd.cimom;


import java.util.*;
import java.util.Enumeration;
import java.util.Vector;
import org.snia.wbem.cim.*;
import org.snia.wbem.client.*;
import org.snia.wbemcmd.utils.SimpleEnum;
import org.snia.wbemcmd.utils.Log;
import org.snia.wbemcmd.xml.*;


//
// This class provides XML access from a client
//
public class CIMOMHandleXML implements CIMOMHandleSNIA 
{
    HTTPOutput output=null;
    static Class classForOutput=null;
     
   /*** 
    * @param ns  The name space that is to be referenced through this handle
    */
    public CIMOMHandleXML(CIMNameSpace ns) 
    {
        //
        // Locate class that handles the CIM client http functionality
        //
        if (classForOutput==null) 
        {
            String httpModule=org.snia.wbemcfg.GlobalConfig.httpClient;

            try 
            {
                classForOutput=Class.forName(httpModule);
            } 
            catch (Exception e) 
            {
                Log.println("Failed to load class for http client:"+e);
            }

            if (classForOutput==null) 
            {
                Log.println("Failed to load class:"+httpModule);
                throw new java.lang.InstantiationError("Failed to load class:" + 
                    httpModule);
            }
        }

        //
        // Create instance for this handle
        //
        output=null;
        try 
        {    
            output=(HTTPOutput)classForOutput.newInstance();
        } 
        catch(InstantiationException ie) 
        {
            Log.println("failed to instantiate "+ie);
        }  
        catch(IllegalAccessException ie) 
        {
            Log.println("failed to instantiate (IllegalAccessException) "+ ie);
        } 

        if (output == null)
            throw new java.lang.InstantiationError(
                "Failed to create instance of " + 
                org.snia.wbemcfg.GlobalConfig.httpClient);

        //
        // output.setHostAndPort(ns.getHost(),ns.getHostURL().getPort());
        // Added by Bapu ( 07/22/02)
        //
        output.setHostURL(ns.getProtocol(), ns.getHost(), ns.getHostURL().getPort());
    }
    

    public void authenticate(String userName,String password) throws CIMException
    {
        output.authenticate(userName,password);
    }
    
    //
    // Set socket timeout
    //
    public void setTimeout(int timeout)
    {
        output.setTimeout(timeout);
    }
    

    //
    // Get socket timeout
    //
    public int getTimeout()
    {
        return (output.getTimeout());
    }

    //close 
    public void close() throws CIMException 
    {
        output.close();
    }


   /**
    * creates a  new name space to hold CIM Classes and Instances
    *
    * @param ns
    *      The namespace to be created
    *
    * @throws  CIMException
    *      CIMException if the namespace already exist
    */
    public void createNameSpace(CIMNameSpace ns) throws CIMException
    {
        String parentPath;
        String nameSpace=ns.getNameSpace();
        int index=nameSpace.lastIndexOf('/');
        Vector keys=new Vector();

        if (index==-1)
            throw new CIMException(CIMException.CIM_ERR_NOT_FOUND,
                     "A Namespace must only be created in an existing Namespace");

        parentPath=nameSpace.substring(0, index);
        String newNameSpace=nameSpace.substring(nameSpace.lastIndexOf('/')+1);

        CIMObjectPath path=new CIMObjectPath(XMLNameSpace.NAMESPACECLASS,parentPath);

        // ATTN: 06/06/02 - Bapu Patil 
        // We must be talking to Pegasus-CIMserver
        // As Pegasus-Cimserver does not support getClass on __NameSpace
        // provider, we will just create one.
        CIMClass nsClass = new CIMClass(XMLNameSpace.NAMESPACECLASS);
                             //NAMESPACECLASS="__Namespace"

        //
        // Add qualifiers for the Class
        //
        CIMQualifierType cqtc = new CIMQualifierType();
        cqtc.setType(CIMDataType.getPredefinedType(CIMDataType.STRING));
        CIMQualifier cqc = new CIMQualifier("Provider", cqtc);
        cqc.addFlavor(CIMFlavor.getFlavor(CIMFlavor.DISABLEOVERRIDE));
        CIMValue cvqc=new CIMValue("org.snia.wbemcmd.providers.namespace.__Namespace");
        cqc.setValue(cvqc);
        nsClass.addQualifier(cqc);


        CIMValue cv=new CIMValue(newNameSpace,
                             CIMDataType.getPredefinedType(CIMDataType.STRING));
        CIMProperty cp=new CIMProperty();
        cp.setName(XMLNameSpace.NAMEPROPERTY); //NAMEPROPERTY="Name"
        cp.setOriginClass(XMLNameSpace.NAMESPACECLASS);
        cp.setValue(cv);
        cp.setType(CIMDataType.getPredefinedType(CIMDataType.STRING)); //="string";


        //
        // Add qualifiers for the property
        //
        CIMQualifierType cqtp = new CIMQualifierType();
        cqtp.setType(CIMDataType.getPredefinedType(CIMDataType.STRING));
        CIMQualifier cqp = new CIMQualifier("Key", cqtp);
        cqp.addFlavor(CIMFlavor.getFlavor(CIMFlavor.DISABLEOVERRIDE));
        CIMValue cvpq=new CIMValue("true");
        cqp.setValue(cvpq);
        cp.addQualifier(cqp);

        nsClass.addProperty(cp);
        CIMInstance cimInstance = nsClass.newInstance();
        Vector v=new Vector();
        v.addElement(cp);

        cimInstance.setProperty(XMLNameSpace.NAMEPROPERTY, cv); //NAMEPROPERTY="Name";
        CIMObjectPath cimPath=new CIMObjectPath(XMLNameSpace.NAMESPACECLASS, v);
        cimPath.setNameSpace(parentPath);

        createInstance(cimPath,cimInstance) ;

        return; 

/*
ATTN:  Original SNIA code -  TODO - Remove please ( Bapu)

        CIMClass cimClass=getClass(path,false);
        if (cimClass==null)
            throw new CIMException(CIMException.CIM_ERR_NOT_FOUND,
                                    "Could not find internal class "+XMLNameSpace.NAMESPACECLASS);
       CIMInstance cimInstance=cimClass.newInstance();
        CIMValue cv=new CIMValue(newNameSpace,CIMDataType.getPredefinedType(CIMDataType.STRING));
        cimInstance.setProperty(XMLNameSpace.NAMEPROPERTY,cv);

        CIMObjectPath cimPath=new CIMObjectPath(XMLNameSpace.NAMESPACECLASS,
                            cimInstance.getKeyValuePairs());
        cimPath.setNameSpace(parentPath);

        createInstance(cimPath,cimInstance) ;
*/
    }

    //ATTN: Does not work with SNIA CIMOM
    //
    // deleteNameSpace 
    // 
    public void deleteNameSpace(CIMNameSpace cns) throws CIMException
    {
        String parentPath;
        String nameSpace=cns.getNameSpace();

        // For Pegasus Server - we changed this like this
        //int index=nameSpace.lastIndexOf('/');
        //
        int index=nameSpace.indexOf('/');
        Vector keys=new Vector();

        if (index==-1)
            throw new CIMException(CIMException.CIM_ERR_NOT_FOUND,
                                    "Invalid Namespace specified");

        parentPath=nameSpace.substring(0,index);
        //String newNameSpace=nameSpace.substring(nameSpace.lastIndexOf('/')+1);
        String newNameSpace=nameSpace.substring(nameSpace.indexOf('/')+1);


        Vector v=new Vector();
        CIMValue cv=new CIMValue(newNameSpace,CIMDataType.getPredefinedType(CIMDataType.STRING));
        CIMProperty cp=new CIMProperty();
        cp.setName(XMLNameSpace.NAMEPROPERTY);
        cp.setValue(cv);
        cp.setType(CIMDataType.getPredefinedType(CIMDataType.STRING));
        v.addElement(cp);

        CIMObjectPath path=new CIMObjectPath(XMLNameSpace.NAMESPACECLASS,v);
        path.setNameSpace(parentPath);
        deleteInstance(path);
    }

    
    private void enumNameSpaceULM( 
        CIMObjectPath path,
        SimpleEnum enum, 
        boolean deep) throws CIMException
    {
        Enumeration e=XMLEnumerateInstanceNames.enumInstances(output,path);
        String name;

        while(e.hasMoreElements()) 
        {
            CIMProperty nameProp=null;

            Object obj=e.nextElement();
            if (obj instanceof CIMObjectPath) 
            {
                Vector keys=((CIMObjectPath)obj).getKeys();
                if (keys.size()==1) 
                    nameProp=(CIMProperty)(keys.elementAt(0));
                else 
                {
                    for(int i=0;i<keys.size();i++) 
                    {
                        CIMProperty cp=(CIMProperty)(keys.elementAt(i));
                        if (cp.getName().equalsIgnoreCase("Name")) 
                        {
                            nameProp=cp;
                            break;
                        }
                    }
                    throw new CIMException(CIMException.CIM_ERR_FAILED,
                        "Name of namespace not found");
                }
                name = path.getNameSpace()+"/"+nameProp.getValue();

                if (!enum.contains(name))
                {
                    enum.addElement(name); 
                }

                if (deep==CIMClient.DEEP) 
                {
                    CIMObjectPath newObjPath=new CIMObjectPath(
                        XMLNameSpace.NAMESPACECLASS, path.getNameSpace() + 
                        "/" + nameProp.getValue());
                    enumNameSpaceULM(newObjPath,enum,deep);
                }
            } 
        }
    }

    // enumerateNameSpaces 
    //
    public Enumeration enumNameSpace(
        CIMObjectPath path,
        boolean deep) throws CIMException 
    {
        CIMObjectPath cop=new CIMObjectPath(
            XMLNameSpace.NAMESPACECLASS,path.getNameSpace());
        SimpleEnum enum=new SimpleEnum();
        enum.addElement(path.getNameSpace());
        enumNameSpaceULM(cop,enum,deep);
        return(enum);
    }


    public Enumeration enumerateNameSpaces(
        CIMObjectPath path, 
        boolean deepInheritance) throws CIMException

    {
        CIMObjectPath cop=new CIMObjectPath(
            XMLNameSpace.NAMESPACECLASS,path.getNameSpace());
        SimpleEnum enum=new SimpleEnum();
        enum.addElement(path.getNameSpace());
        enumNameSpaceULM(cop,enum,deepInheritance); 
        return(enum);
    }
        

    // deleteClass 
    //
    public void deleteClass(CIMObjectPath path) throws CIMException
    {
        XMLDeleteClass.deleteClass(output,path);
    }


    // deleteInstance 
    //
    public void deleteInstance(CIMObjectPath path) throws CIMException
    {
        XMLDeleteInstance.deleteInstance(output,path);
    }

    // deleteQualifier
    //
    public void deleteQualifier(CIMObjectPath path) throws CIMException{
        XMLDeleteQualifier.deleteQualifier(output,path);
    }

    // deleteQualifierType - same as deleteQualifier
    //
    public void deleteQualifierType(CIMObjectPath path) throws CIMException{
        XMLDeleteQualifier.deleteQualifier(output,path);
    }


    // enumClass 
    //
    public Enumeration enumClass(
        CIMObjectPath path,
        boolean deep, 
        boolean localOnly) throws CIMException 
    {
        return(XMLEnumerateClasses.enumerateClasses(output, path, deep, 
            localOnly, true, false));
    }

    // enumerateClasses
    //
    public Enumeration enumerateClasses(
        CIMObjectPath path,
        boolean deepInheritance,
        boolean localOnly,
        boolean includeQualifiers,
        boolean includeClassOrigin) throws CIMException
    {
        return(XMLEnumerateClasses.enumerateClasses(output, path, 
            deepInheritance, localOnly, includeQualifiers, includeClassOrigin));
    }
           
    
    // enumClass 
    //
    public Enumeration enumClass(
        CIMObjectPath path,
        boolean deep) throws CIMException 
    {
        return(XMLEnumerateClassNames.enumerateClassNames(output, path, deep));
    }

    public Enumeration enumerateClassNames(
        CIMObjectPath path,
        boolean deepInheritance) throws CIMException
    {
        return(XMLEnumerateClassNames.enumerateClassNames(output, path, 
            deepInheritance));
    }


    // enumInstances
    //
    public Enumeration enumInstances(
        CIMObjectPath path,
        boolean deep, 
        boolean localOnly) throws CIMException
    {
        return(XMLEnumerateInstances.enumerateInstances(output, path,
            deep, localOnly, false, false, null)); 
    }

    public Enumeration enumerateInstances(
        CIMObjectPath path,
        boolean deepInheritance,
        boolean localOnly,
        boolean includeQualifiers,
        boolean includeClassOrigin,
        String propertyList[]) throws CIMException
    {
        return(XMLEnumerateInstances.enumerateInstances(output, path,
            deepInheritance, localOnly, includeQualifiers, 
            includeClassOrigin, propertyList));
    }   
               
    // enumInstances
    //
    public Enumeration enumInstances(
        CIMObjectPath path,
        boolean deep) throws CIMException
    {
        //
        // SUNDIFF: Note that while the SUN API allows deep the
        // XML encodings don't so we simply assume deep
        //
        return(XMLEnumerateInstanceNames.enumerateInstanceNames(output, path));
    }

    
    public Enumeration enumerateInstanceNames(
        CIMObjectPath path) throws CIMException
    {
        return(XMLEnumerateInstanceNames.enumerateInstanceNames(output, path));
    }

    public Enumeration enumerateQualifiers(
        CIMObjectPath path) throws CIMException
    {
        return(XMLEnumerateQualifiers.enumerateQualifiers(output,path));
    }

    //enumQualifierTypes - same as enumerateQualifiers
    //
    public Enumeration enumQualifierTypes(CIMObjectPath path) throws CIMException
    {
        return(XMLEnumerateQualifiers.enumerateQualifiers(output,path));
    }

    public CIMClass getClass(
        CIMObjectPath path,
        boolean localOnly,
        boolean includeQualifiers,
        boolean includeClassOrigin,
        String [] propertyList) throws CIMException
    {
        return(XMLGetClass.getClass(output, path, localOnly, 
            includeQualifiers, includeClassOrigin, propertyList));
    }

    /**
     * @deprecated
     * @see #getClass
     */
    public CIMClass getClass(CIMObjectPath path,
            boolean localOnly) throws CIMException
    {
        return(XMLGetClass.getClass(output, path, localOnly, 
            true, false, null));
    }


    public CIMInstance getInstance(
        CIMObjectPath path,
        boolean localOnly,
        boolean includeQualifiers,
        boolean includeClassOrigin,
        String propertyList[]) throws CIMException
    {
        return(XMLGetInstance.getInstance(output, path, localOnly, 
            includeQualifiers, includeClassOrigin, propertyList));
    }
             
    /**
     * @deprecated
     * @see #getInstance
     */
    public CIMInstance getInstance(
        CIMObjectPath path,
        boolean localOnly) throws CIMException 
    {
        return(XMLGetInstance.getInstance(output, path, localOnly, 
            false, false, null));
    }
             
    // invokeMethod 
    //
    public CIMValue invokeMethod(
        CIMObjectPath path, 
        String methodName, 
        Vector inParams, 
        Vector outParams) throws CIMException
    {
        return(XMLInvokeMethod.invokeMethod(output, path, 
            methodName, inParams, outParams));
    }

    // getQualifier
    //
    public CIMQualifierType getQualifier(CIMObjectPath path)
            throws CIMException{
            return(XMLGetQualifier.getQualifier(output,path));
    }

    // getQualifierType - same as getQualifier
    //
    public CIMQualifierType getQualifierType(CIMObjectPath path)
            throws CIMException{
            return(XMLGetQualifier.getQualifier(output,path));
    }

    // setQualifier
    //
    public void setQualifier(CIMObjectPath path,
                   CIMQualifierType qt) throws CIMException{
        XMLSetQualifier.setQualifier(output,path,qt);
    }
                                  
    // setQualifierType - same as setQualifier
    //
    public void setQualifierType(CIMObjectPath path,
                   CIMQualifierType qt) throws CIMException{
        XMLSetQualifier.setQualifier(output,path,qt);
    }
                                  
    // createQualifierType - same as setQualifier
    //
    public void createQualifierType(CIMObjectPath path,
                      CIMQualifierType qt) throws CIMException{
        XMLSetQualifier.setQualifier(output,path,qt);
    }


    // createClass 
    //
    public void createClass(
        CIMObjectPath path,
        CIMClass newClass) throws CIMException
    {
        XMLCreateClass.createClass(output, path, newClass); 
    }

    // modifyClass()
    // 
    public void modifyClass(
        CIMObjectPath path,
        CIMClass modifiedClass) throws CIMException
    {
       XMLModifyClass.modifyClass(output, path, modifiedClass);
    }

    // setClass()
    /**
     * @deprecated
     * @see #modifyClass
     */
    public void setClass(
        CIMObjectPath path,
        CIMClass cimClass) throws CIMException 
    {
       XMLModifyClass.modifyClass(output, path, cimClass);
    }


    // createInstance 
    //
    public CIMObjectPath createInstance(
        CIMObjectPath path,
        CIMInstance newInstance) throws CIMException
    {
        return(XMLCreateInstance.createInstance(output, path, newInstance));
    }

    // modifyInstance
    //
    public void modifyInstance(
        CIMObjectPath path,
        CIMInstance modifiedInstance,
        boolean includeQualifiers,
        String propertyList[]) throws CIMException
    {
        XMLModifyInstance.modifyInstance(output, path, modifiedInstance, 
            includeQualifiers, propertyList);
    }

    // setInstance
    /**
     * @deprecated
     * @see #modifyInstance
     */
    public void setInstance(
        CIMObjectPath path,
        CIMInstance cimInstance) throws CIMException
    {
        XMLModifyInstance.modifyInstance(output, path, cimInstance, 
            true, null);
    }


    // getProperty 
    //
    public CIMValue getProperty(
        CIMObjectPath path,
        String propertyName)throws CIMException
    {
        return(XMLGetProperty.getProperty(output,path,propertyName));
    }


    // setProperty 
    //
    public void setProperty(
        CIMObjectPath path,
        String propertyName,
        CIMValue newValue) throws CIMException
    {
        XMLSetProperty.setProperty(output,path,propertyName,newValue);
    }


    //
    // associatorNames
    //
    public Enumeration associatorNames(
        CIMObjectPath path,
        String assocClass,
        String resultClass,
        String role,
        String resultRole) throws CIMException
    {
        return(XMLAssociatorNames.getNames(output, path, assocClass, 
            resultClass, role, resultRole));
    }

    //
    // associators
    //
    public Enumeration associators(
        CIMObjectPath path,
        String assocClass,
        String resultClass,
        String role,
        String resultRole,
        boolean includeQualifiers,
        boolean includeClassOrigin,
        String propertyList[])throws CIMException 
    {
        return(XMLAssociators.getNames(output,path, assocClass, 
            resultClass, role, resultRole, includeQualifiers, 
            includeClassOrigin, propertyList));
    }


    //
    // referenceNames
    //
    public Enumeration referenceNames(
        CIMObjectPath path,
        String resultClass,
        String role) throws CIMException 
    {
        return(XMLReferenceNames.getNames(output, path, resultClass, role));                                 
    }


    //
    // references
    //
    public Enumeration references(
        CIMObjectPath path,
        String resultClass,
        String role,
        boolean includeQualifiers,
        boolean includeClassOrigin,
        String propertyList[])throws CIMException 
    {
        return(XMLReferences.getNames(output, path, resultClass, role, 
            includeQualifiers, includeClassOrigin, propertyList));
    }


    public Enumeration execQuery(
        CIMObjectPath path,
        String query,
        int queryLanguage) throws CIMException
    {
        return(XMLQuery.execQuery(output, path, query, queryLanguage));
    }


/*ATTN: For Later release..
    // addCIMListener is irrelevant for this particular class.
    public void addCIMListener(CIMListener listener) throws CIMException 
    {
        throw new CIMException(CIMException.CIM_ERR_METHOD_NOT_AVAILABLE);
    }

    // removeCIMListener is irrelevant for this particular class.
    public void removeCIMListener(CIMListener listener) throws CIMException 
    {
        throw new CIMException(CIMException.CIM_ERR_METHOD_NOT_AVAILABLE);
    }

*/

    //
    // getServerFeatures
    //
    public CIMFeatures getServerFeatures() throws CIMException
    {
        XMLFeatures features=new XMLFeatures();
        features.getFeatures(output);
        return(features);
    }

    //public String encryptData(String data) throws CIMException 
    //{
    //    return(data);    // SUNDIFF - no encryption 
    //}

}
