/////////////////////////////////////////////////////////////////////////
//
// © Institute for Software Science, University of Vienna, 2004
//
// Copyright in this software belongs to Institute for Software Science, 
// University of Vienna, Nordbergstrasse 15/C/3, 1090 Vienna, Austria
//
// This software may not be used, sold, licensed, transferred, copied
// or reproduced in whole or in part in any manner or form or in or
// on any media by any person other than in accordance with the terms
// of the Licence Agreement supplied with the software, or otherwise
// without the prior written consent of the copyright owners.
//
// This software is distributed WITHOUT ANY WARRANTY, without even the
// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE, except where stated in the Licence Agreement supplied with
// the software.
//
//	Created By :		Aleksandar Dimitrov
//	Created Date :		2004/02/24
//	Created for Project:	GEMSS
//
////////////////////////////////////////////////////////////////////////
//
// Dependencies: None
//
/////////////////////////////////////////////////////////////////////////
//
//	Last commit info:	$Author: dimitrov $
//					$Date: 2004/07/21 12:09:33 $
//					$Revision: 1.6 $
//
/////////////////////////////////////////////////////////////////////////

package at.ac.univie.iss.registry;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.IOException;
import java.io.PrintWriter;

import java.net.ConnectException;
import java.net.MalformedURLException;
import java.net.UnknownHostException;
import java.net.UnknownServiceException;
import java.net.URL;
import java.net.URLConnection;

import java.rmi.RemoteException;

import java.util.Date;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Vector;

import javax.xml.rpc.ServiceException;

import at.ac.univie.iss.registry.generated.*;


public class RegistryTool {

    private PrintWriter exceptionWriter;
    private final String FILE_NAME = "exceptions.log";
    private Date currentDate = new Date(); 

    private String registryURI = new String(""); 
    private String serviceURI = new String(""); 
    private String attributesFile = new String("");
    private String commandArgument = new String("");
  
    public RegistryTool(String[] args) {
       
        try {
            // creates an output file if some exceptions are occured
            exceptionWriter = new PrintWriter(
                    new BufferedWriter(new FileWriter(FILE_NAME, true)));                         
        } catch (IOException writeProblem) {
            System.err.println("Error writing in " + FILE_NAME);
            System.err.println(writeProblem);           
        }                    
                      
        boolean commands = true;
        
        // for the properly work of registry tool are needed 4 or 6 parameters as arguments
        if (args.length == 4 || args.length == 6 || (args.length == 3 && args[2].equals("-l"))) {
           
            if (processArguments(args)) {
                
                System.out.println("\n========== registry-tool ==========");
                System.out.println("uri2REGISTRYwsdl: " + registryURI);
                System.out.println("uri2SERVICEwsdl: " + serviceURI);
                System.out.println("attributesFile: " + attributesFile + "\n"); 

                try {
                    // creates a stub 
                    at.ac.univie.iss.registry.generated.RegistryImpl stub = createStub();
                    
                    // if a created stub is not null then makes the 
                    // publishing or removing of the service description                    
                    if (stub != null) {
                        // publishes the service description
                        if (commandArgument.equals("-r")) {
                            System.out.println("publishService()...");
                            stub.publishService(
                                    makeService(serviceURI, attributesFile));	                        
                        } else // removes the service description
                        if (commandArgument.equals("-u")) {
                            System.out.println("removeService()...");                    
                            stub.removeService(serviceURI);	
                        } else // takes all published service
                        if (commandArgument.equals("-l")) {
                            System.out.println("list()...\n");                    
                            List publishedServices = stub.query(null);
                            list (publishedServices);	
                        } else {
                            commands = false;
                        }
                    } else {
                        System.out.println(
                                "The specified registry: " + registryURI
                                + " is incorrect!");
                    }
                } catch (RemoteException remoteException) {
                    System.out.println(remoteException.getMessage());
                    exceptionLog("");  
                    remoteException.printStackTrace(exceptionWriter);
                }                    

            } else {
                commands = false;
            }
        } else {
            commands = false;
        }
        if (!commands) {
            System.out.println("\nPlease start registry tool as follow:");
            System.out.println(
//                    "Usage:java -jar tool" + File.separator + "registry-tool.jar -d uri2REGISTRYwsdl"
//                            + " -r|-u uri2SERVICEwsdl [-attrfile someAttributeFile]");            
                    "\nUsage: java -jar tool" + File.separator + "registry-tool.jar -d uri2REGISTRYwsdl <options>\n"
                    + "\nwhere possible options include:"
                    + "\n     -r uri2SERVICEwsdl [-attrfile someAttributeFile]    publish a service"
                    + "\n     -u uri2SERVICEwsdl                                  remove a service"
                    + "\n     -l                                                  print a list of all published services");
        
        }
        exceptionWriter.close();			                                                             
    }


    private void list (List services) {                

        if (services != null) {
        
            Iterator iter = services.iterator();            

            System.out.println("Published services:");

            // iterate through list of services        
            while (iter.hasNext()) {
                
                at.ac.univie.iss.registry.generated.ServiceDescription service = (at.ac.univie.iss.registry.generated.ServiceDescription) iter.next();
                
                // get list of attributes from each service                    
                at.ac.univie.iss.registry.generated.Attribute[] attrList = service.getAttributes();

                // print wsdl endpoint and all attributes
                System.out.println(
                        "--> Service WSDL endpoint " + service.getWsdlEndpoint());

                if (attrList != null) {     
                                     
                    for (int i = 0; i < attrList.length; i++) {
                        System.out.println(
                                "    - Attribute name: "
                                        + attrList[i].getName() + ", value: "
                                        + attrList[i].getValue());
                    }
                }  
            }               
        }       
    }

    /**
     * Creates a stub for the specified registry URI
     *
     * @throws  MalformedURLException if an error occured
     *		    if a specified registry URI is not found
     *          ServiceException if an error occured
     *			during the stub generation  
     */
    private at.ac.univie.iss.registry.generated.RegistryImpl createStub() {	

        RegistryImplService service;
        at.ac.univie.iss.registry.generated.RegistryImpl stub = null; 
        
        if (checkURI(registryURI)) {    
            
            service = new RegistryImplServiceLocator();
    	    
            try {
                stub = service.getreg(new java.net.URL(registryURI));
            } catch (MalformedURLException malformedURLExc) {
                System.out.print("java.net.MalformedURLException: ");
                exceptionLog("");          
                malformedURLExc.printStackTrace(exceptionWriter);
            } catch (ServiceException serviceExc) {
                System.out.print("javax.xml.rpc.ServiceException: ");
                exceptionLog("");          
                serviceExc.printStackTrace(exceptionWriter);
            }            
        }   
        return stub;
    }   

    /**
     * Checks if the specified registry URI is correct
     */
    private boolean checkURI(String sameURL) {
    
        try {
            URL checkURL = new URL(sameURL);
            URLConnection connection = checkURL.openConnection();

            connection.connect();
            InputStream testConnection = connection.getInputStream();

            return true;
        } catch (MalformedURLException malformedURLExc) {
            System.out.print("java.net.MalformedURLException: ");
            exceptionLog("");          
            malformedURLExc.printStackTrace(exceptionWriter);
        } catch (UnknownHostException unknownHostExc) {
            System.out.print("java.net.UnknownHostException: ");
            exceptionLog("");
            unknownHostExc.printStackTrace(exceptionWriter);
        } catch (ConnectException connectExc) {
            System.out.print("java.net.ConnectException: ");
            exceptionLog("");
            connectExc.printStackTrace(exceptionWriter);
        } catch (UnknownServiceException unknownServiceExc) {
            System.out.print("java.net.UnknownServiceException: ");
            exceptionLog("");
            unknownServiceExc.printStackTrace(exceptionWriter);
        } catch (IOException exc) {
            System.out.print("java.io.IOException: ");
            exceptionLog("");
            exc.printStackTrace(exceptionWriter);
        }
        return false;
    }

    /**
     * Creates exception logger
     */
    private void exceptionLog(String message) {
	 
        currentDate.setTime(System.currentTimeMillis());
        exceptionWriter.println(currentDate + ": " + message);  
    }

    /**
     * Creates service descrption 
     */
    private at.ac.univie.iss.registry.generated.ServiceDescription makeService(String serviceURI, String attrFile) {

        String temp;
        int count = 0;
        int itterator = 0;        
        at.ac.univie.iss.registry.generated.ServiceDescription newService = new at.ac.univie.iss.registry.generated.ServiceDescription(); 
        
        try {            
            if (!attrFile.equals("")) {                                
                Properties prop = new Properties();

                prop.load(new FileInputStream(attrFile));
                
                for (Enumeration e = prop.propertyNames(); e.hasMoreElements();) {
                    e.nextElement();
                    count++;
                }    
                
                at.ac.univie.iss.registry.generated.Attribute[] attr = new at.ac.univie.iss.registry.generated.Attribute[count];
        
                for (Enumeration e = prop.propertyNames(); e.hasMoreElements();) {
                   
                    temp = (String) e.nextElement();
                    
                    attr[itterator] = new at.ac.univie.iss.registry.generated.Attribute();
                    attr[itterator].setName(temp);
                    attr[itterator++].setValue(prop.getProperty(temp));	
                }
        				        
                newService.setAttributes(attr);
                newService.setWsdlEndpoint(serviceURI);
            } else {
                newService.setWsdlEndpoint(serviceURI);
            }
        } catch (FileNotFoundException fnExc) {
            System.out.print(fnExc);
            exceptionLog("");
            fnExc.printStackTrace(exceptionWriter);              
        } catch (IOException ioExc) {
            System.out.print(ioExc);
            exceptionLog("");
            ioExc.printStackTrace(exceptionWriter);
        } catch (Exception exc) {
            System.out.print(exc);
            exceptionLog("");
            exc.printStackTrace(exceptionWriter);
        }            
        return newService;
    }

    /**
     * checks if the specified arguments match the
     * parameter -d, -r, -u, -attrfile
     */       
    private boolean processArguments(String[] args) {	

        int count = 0;
        String element;
        boolean regFlag = false;
        boolean serFlag = false;
		
        while (count < (args.length)) {
					
            element = args[count];
			
            if (element.equals("-d") && (args.length==3 || args.length==4 || args.length==6)) {				
                regFlag = true;
                registryURI = args[count + 1];
            } else if (element.equals("-l") && args.length==3) {
                serFlag = true;
                commandArgument = element;               
            } else if (element.equals("-r")) {
                serFlag = true;
                commandArgument = element;
                serviceURI = args[count + 1];
            } else if (element.equals("-u") && args.length==4) {
                serFlag = true;
                commandArgument = element;
                serviceURI = args[count + 1];
            } else if (element.equals("-attrfile")) {				
                attributesFile = args[count + 1];
            } else {
                
                return false;
            }			 
            count = count + 2;
        }
        if (regFlag && serFlag) {
            return true;
        } else {
            return false;
        }
    }

    public static void main(String[] args) {          

        new RegistryTool(args);       
    }
}
