/*
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999 Bull S.A.
 * Contact: jonas-team@objectweb.org
 * 
 * This library 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.1 of the License, or any later version.
 * 
 * This library 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 library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * Initial developer(s): ____________________________________.
 * Contributor(s):
 * 
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */

package org.objectweb.jonas.resource;

import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.XMLReader;
import org.xml.sax.InputSource;
import org.xml.sax.helpers.XMLReaderFactory;
import org.xml.sax.SAXException;
import java.io.IOException;
import java.io.FileReader;
import java.io.PrintStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Vector;
import java.util.Stack;
import java.net.URLClassLoader;
import java.net.URL;
import java.net.MalformedURLException;


/**
 * This class may be used to parse a resource adapter deployment descriptor
 * and generate the corresponding properties files for the jca service
 * 
 * java org.objectweb.jonas.resource.RAXml2Prop ra.xml -o ra.out
 *
 */

public class RAXml2Prop extends DefaultHandler {
    

    /** Syntaxic name for  elements */
    static final String ELT_CONNECTOR = "connector";
    static final String ELT_AUT_MEC = "authentication-mechanism";
    static final String ELT_AUT_MEC_TYPE = "authentication-mechanism-type";
    static final String ELT_CONF_PROP = "config-property";
    static final String ELT_CONF_PROP_NAME = "config-property-name";
    static final String ELT_CONF_PROP_TYPE = "config-property-type";
    static final String ELT_CONF_PROP_VALUE = "config-property-value";
    static final String ELT_CONN_IMPL_CLASS = "connection-impl-class";
    static final String ELT_CONN_INTERFACE = "connection-interface";
    static final String ELT_CONNFACT_IMPL_CLASS = "connectionfactory-impl-class"; 
    static final String ELT_CONNFACT_INTERFACE = "connectionfactory-interface"; 
    static final String ELT_CREDENTIAL_INTERFACE = "credential-interface"; 
    static final String ELT_DESCRIPTION = "description"; 
    static final String ELT_DISPLAY_NAME = "display-name"; 
    static final String ELT_EIS_TYPE = "eis-type"; 
    static final String ELT_ICON = "icon"; 
    static final String ELT_LARGE_ICON = "large-icon"; 
    static final String ELT_LICENSE = "license"; 
    static final String ELT_LICENSE_REQUIRED = "license-required"; 
    static final String ELT_MANAGEDCONNFACT_CLASS = "managedconnectionfactory-class"; 
    static final String ELT_REAUTH_SUPPORT = "reauthentication-support"; 
    static final String ELT_RESOURCEADAPTER = "resourceadapter"; 
    static final String ELT_SECURITY_PERMISSION = "security-permission"; 
    static final String ELT_SECURITY_PERMISSION_SPEC = "security-permission-spec"; 
    static final String ELT_SMALL_ICON = "small-icon"; 
    static final String ELT_SPEC_VERSION = "spec-version"; 
    static final String ELT_TRANS_SUPPORT = "transaction-support"; 
    static final String ELT_VENDOR_NAME = "vendor-name"; 
    static final String ELT_VERSION = "version"; 

    static boolean genopt = true;

    Stack heap = new Stack();
    Connector  connector = null;

    // Constructor
    public RAXml2Prop (String fileName) {
	super();
	FileReader r = null;
	
	try {
	    XMLReader xr = XMLReaderFactory.createXMLReader(System.getProperty("org.xml.sax.driver",
			   "org.apache.xerces.parsers.SAXParser"));

	    xr.setContentHandler(this);
	    xr.setErrorHandler(this);
	    InputSource inputsource  = null;
	    if(fileName.endsWith(".xml")){
	       r = new FileReader(fileName);
	       inputsource  = new InputSource(r);
	    }else{
		System.err.println("RAXml2Prop Incorrect Input file (must .xml)");
		System.exit(2);
	    }
 
	    //  Parse the Document      
	
	    xr.parse(inputsource);
	} catch (SAXException e) {
	    System.err.println("RAXml2Prop SAXException caught "+e);
	}catch (FileNotFoundException e) {
	    System.err.println("RAXml2Prop File not found : "+fileName);
	    System.exit(2);
	} catch (IOException e) {
	    System.err.println("RAXml2Prop IOException caught "+e);
	}

    }
       
    public void startDocument (){
    }


    public void endDocument (){
    }     
   
    //  Start Element Event Handler
    public void startElement (String uri, String localName,
			      String qName, Attributes atts)  {
	heap.push(localName);
	if(localName.equals(ELT_CONNECTOR))
	    connector = new Connector();
	else if(localName.equals(ELT_RESOURCEADAPTER))
	    connector.resourceadapter = new RA();
	else if(localName.equals(ELT_CONF_PROP)){
	    ConfigProp cp = new ConfigProp();	    
	    connector.resourceadapter.configproperties.add(cp);
	}else if(localName.equals(ELT_AUT_MEC)){
	    AuthMecanism am = new AuthMecanism();
	    connector.resourceadapter.authmecanisms.add(am);
	}
    }
      
    public void endElement (String uri, String name, String qName){
	heap.pop();
    }

    public void characters (char ch[], int start, int length) {
	String chars = new String(ch, start,length);

	String elem = (String)heap.peek();	
	if(elem.equals(ELT_CONNECTOR)){
	}
	else if(elem.equals(ELT_DISPLAY_NAME))
	    connector.displayname = chars;
	else if(elem.equals(ELT_SPEC_VERSION))
	    connector.specversion = chars;
	else if(elem.equals(ELT_EIS_TYPE))
	    connector.eistype = chars;
	else if(elem.equals(ELT_SPEC_VERSION))
	    connector.specversion = chars;
	else if(elem.equals(ELT_VERSION))
	    connector.version = chars;
	else if(elem.equals(ELT_LICENSE))
	    connector.license = chars;
	else if(elem.equals(ELT_VENDOR_NAME))
	    connector.vendorname = chars;
	else if(elem.equals(ELT_RESOURCEADAPTER)){
	    
	}else if(elem.equals(ELT_MANAGEDCONNFACT_CLASS))
	    connector.resourceadapter.managedconnectionfactoryclass = chars;
	else if(elem.equals(ELT_CONNFACT_INTERFACE))
	    connector.resourceadapter.connectionfactoryinterface = chars;
	else if(elem.equals(ELT_CONNFACT_IMPL_CLASS))
	    connector.resourceadapter.connectionfactoryimplclass = chars;
	else if(elem.equals(ELT_CONN_INTERFACE))
	    connector.resourceadapter.connectioninterface = chars;
	else if(elem.equals( ELT_CONN_IMPL_CLASS))
	    connector.resourceadapter.connectionimplclass = chars;
	else if(elem.equals(ELT_TRANS_SUPPORT))
	    connector.resourceadapter.transactionsupport = chars;
	else if(elem.equals(ELT_CONF_PROP)){

	}else if(elem.equals(ELT_CONF_PROP_NAME)){
	    ConfigProp cp = (ConfigProp)connector.resourceadapter.configproperties.lastElement();
	    cp.name = chars;
	}else if(elem.equals(ELT_CONF_PROP_TYPE)){
	    ConfigProp cp = (ConfigProp)connector.resourceadapter.configproperties.lastElement();
	    cp.type = chars;
	}else if(elem.equals(ELT_CONF_PROP_VALUE)){
	    ConfigProp cp = (ConfigProp)connector.resourceadapter.configproperties.lastElement();
	    cp.value = chars;
	}else if(elem.equals(ELT_AUT_MEC)){

	}else if(elem.equals(ELT_AUT_MEC_TYPE)){
	    AuthMecanism am = (AuthMecanism)connector.resourceadapter.authmecanisms.lastElement();
	    am.authmecanismtype = chars;
	}else if(elem.equals(ELT_CREDENTIAL_INTERFACE)){
	    AuthMecanism am = (AuthMecanism)connector.resourceadapter.authmecanisms.lastElement();
	    am.credentialinterface = chars;
	}else if(elem.equals(ELT_SECURITY_PERMISSION)){
	    
	}else if(elem.equals(ELT_SECURITY_PERMISSION_SPEC)){
	    connector.resourceadapter.securitypermissions.add(chars);
	}else if(elem.equals(ELT_REAUTH_SUPPORT)){
	    connector.resourceadapter.reauthenticationsupport = chars;
	}else {
	    System.err.println("SAX Parsing error unknown element: "+elem);
	}
		
    }

    public Connector getConnector(){
	return connector;
    }
        

    public static void usage() {
	System.out.println("");
	System.out.println("Usage: java org.objectweb.jonas.resource.RAXml2Prop <Options> <Input_File>");
	System.out.println("         to generate the properties file for a Resource Adapter.");
	System.out.println("");
	System.out.println("           With Options:");
	System.out.println("             -? or -help to print this help message");
        System.out.println("             -o <outputfilename>  specifies the name of the generated file");
	System.out.println("             -j <jndiname>  specifies the jndiname RA");
	System.out.println("             -verbose   output the contains of the  deployment descriptor ");   
	System.out.println("");
	System.out.println("           Input_File        Resource Adapter deployment descriptor file's name ");
	System.out.println("");
    }

    // Main Method
    public static void main (String[] args) {
	PrintStream out = null;
	boolean  isHelp          = false;
	boolean  isVerbose       = false;
	String outputname   = null;
	String fileInputName = null;
	String jndiname = "adapt_1";
	
	// Get command args

	if (args.length <1){
	    System.err.println("RAXml2Prop: Arguments missing");
	    usage();
	    System.exit(2);
	}
	for (int argn = 0; argn < args.length; argn++) {
	    String arg = args[argn];
	    if (arg.equals("-help") || arg.equals("-?")) {
		isHelp = true;
		continue;
	    }
	    if (arg.equals("-verbose")) {
		isVerbose = true;
		continue;
	    }
	    if (arg.equals("-o")) {
		argn++;
		outputname = args[argn];
		try{
		    out = new PrintStream(new FileOutputStream(outputname));
		}catch(FileNotFoundException e){
		    System.err.println("File not found: "+outputname);
		    System.exit(2);
		}
		continue;
	    }
	    if (arg.equals("-j")) {
		argn++;
		jndiname  = args[argn];
		continue;
	    }
	    fileInputName = args[argn];

	}
	
	// Usage ?
	if (isHelp) {
	    usage();
	    System.exit(0);
	}
	if(outputname == null){
	    out = System.out;
	}

	RAXml2Prop basicSAX = new RAXml2Prop (fileInputName);
	Connector conn = basicSAX.getConnector();
	RA ra = conn.resourceadapter;


	out.println("###");
	out.println("# Properties file generated from "+fileInputName);
	out.println("# Vendor "+conn.vendorname);
	out.println("# Version "+conn.specversion);
	out.println("# Eis type "+conn.eistype);
	out.println("###");
	out.println("");
	out.println("managedconnectionfactoryclass "+ra.managedconnectionfactoryclass);
	out.println("jndiname "+jndiname);
	int sz = ra.configproperties.size();

	for(int i=0; i<sz;i++){
	    ConfigProp cp = (ConfigProp)ra.configproperties.elementAt(i);
	    String name = cp.name;
	    out.println(cp.name+"   "+cp.value);
	    
	}

	if(isVerbose){

	    System.out.println("+++ "+ELT_DISPLAY_NAME+" "+conn.displayname);
	    System.out.println("+++ "+ELT_EIS_TYPE +" "+conn.eistype);
	
	    System.out.println("+++ "+ELT_MANAGEDCONNFACT_CLASS+" "+ra.managedconnectionfactoryclass);
	    System.out.println("+++ "+ELT_CONNFACT_INTERFACE+" "+ra.connectionfactoryinterface);
	    System.out.println("+++ "+ELT_CONNFACT_IMPL_CLASS+" "+ra.connectionfactoryimplclass);
	    System.out.println("+++ "+ELT_CONN_INTERFACE+" "+ra.connectioninterface); 
	    System.out.println("+++ "+ELT_CONN_IMPL_CLASS+" "+ra.connectionimplclass);
	    System.out.println("+++ "+ELT_TRANS_SUPPORT+" "+ra.transactionsupport);
	
			   
	    for(int i=0; i<ra.configproperties.size();i++){
		ConfigProp cp = (ConfigProp)ra.configproperties.elementAt(i);
		System.out.println("+++ "+ELT_CONF_PROP_NAME+" "+cp.name);
		System.out.println("+++ "+ELT_CONF_PROP_VALUE+" "+cp.value);
	    }

	    for(int i=0; i<ra.authmecanisms.size();i++){
		AuthMecanism am  = (AuthMecanism)ra.authmecanisms.elementAt(i);
		System.out.println("+++ "+ELT_AUT_MEC_TYPE +" "+am.authmecanismtype);
		System.out.println("+++ "+ELT_CREDENTIAL_INTERFACE+" "+am.credentialinterface);
	    }
	    for(int i=0; i<ra.securitypermissions.size();i++){
		String s = (String)ra.securitypermissions.elementAt(i);
		System.out.println("+++ "+ELT_SECURITY_PERMISSION_SPEC+" "+s);
	    }
	}
    }
}

class Connector{
    public  String displayname = null;
    public  String description = null;
    public  Icon  icon = null;
    public  String vendorname = null;
    public  String specversion = null;
    public  String eistype = null;
    public  String version = null;
    public  String license = null;
    public  RA  resourceadapter = null;
    public  Connector(){
	icon = new Icon();
	resourceadapter = new RA();
    }
}

class Icon{
    public   String smallicon = null;
    public   String largeicon = null;

}

class RA{
    public    String managedconnectionfactoryclass = null;
    public    String connectionfactoryinterface = null; 
    public    String connectionfactoryimplclass = null;
    public    String connectioninterface = null;
    public    String connectionimplclass = null;
    public    String transactionsupport = null;
    public    Vector configproperties = null;
    public    Vector authmecanisms = null; 
    public    String reauthenticationsupport = null;
    public    Vector securitypermissions = null;

    public    RA(){
	configproperties = new Vector();
	authmecanisms = new Vector(); 
	securitypermissions = new Vector();
    }
}

class ConfigProp{
    public String name = null;
    public String value = null;
    public String type = null;
    public   ConfigProp(){
    }

}
class AuthMecanism{
    public String authmecanismtype = null;
    public String credentialinterface = null;
    public AuthMecanism(){
    }
}
