/////////////////////////////////////////////////////////////////////////
//
// © 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 :		Nikolay Terziev
//	Created Date :		2004/02/10
//	Created for Project:	GEMSS
//
/////////////////////////////////////////////////////////////////////////
//
// Dependencies: None
//
/////////////////////////////////////////////////////////////////////////
//
//	Last commit info:	$Author: niki $
//					$Date: 2004/01/07 15:20:12 $
//					$Revision: 1.10 $
//
/////////////////////////////////////////////////////////////////////////
package at.ac.univie.iss.discovery.impl;


import java.io.File;
import java.net.URL;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Vector;
import java.util.logging.Logger;
import java.util.logging.Level;

import eu.gemss.components.discovery.Attribute;
import eu.gemss.components.discovery.Discovery;
import eu.gemss.components.discovery.ServiceDescription;
import eu.gemss.components.discovery.DiscoveryGridException;
import eu.gemss.components.discovery.RegistryGridException;

import at.ac.univie.iss.discovery.AttributeImpl; 
import at.ac.univie.iss.discovery.generated.*;
import at.ac.univie.iss.discovery.util.EndpointReader;


public class DiscoveryImpl extends Discovery {
   
    private static Logger logger = Logger.getLogger(DiscoveryImpl.class.getName());
    
    private final String registryEndpointsConfig = new String("registry.endpoints.config");
    
    List registryURIs = null;
    List servicesList = null;
	  
    public DiscoveryImpl() { 
                  
        servicesList = new Vector(); 
    }
    
    /** Initialize Discovery component with given set of URLs (endpoints) to registry services */
    public void init() throws DiscoveryGridException {
        String endpointsFile = "";
		
        try {
            endpointsFile = System.getProperty("gemss.discovery.config") + File.separatorChar + registryEndpointsConfig;
			
            logger.log(java.util.logging.Level.FINE, "System property (gemss.discovery.config): " + endpointsFile);

            if (endpointsFile == null) {
				
                // enpoint file given by constant (wihtout gemss.home)
				
                endpointsFile = new String("config" + File.separatorChar + registryEndpointsConfig);
                logger.log(java.util.logging.Level.FINE, "Trying endpoints file: " + endpointsFile);
				
                if (!new File(endpointsFile).exists()) {
				
                    // enpoint file given by constant (wihtout gemss.home)
	
                    endpointsFile = new String(
                            System.getProperty("gemss.home") + File.separatorChar + "config" + File.separatorChar
                            + registryEndpointsConfig);
                    logger.log(java.util.logging.Level.FINE, "Trying endpoints file: " + endpointsFile);
					
                    if (!new File(endpointsFile).exists()) {
	
                        // if endpoint file is away ?!? -> throw exception			
	
                        throw new DiscoveryGridException("endpoints file missing/not found/whatever!",
                                "endpoints file missing/not found/whatever!");
                    } else {
                        logger.log(java.util.logging.Level.CONFIG, "endpoints file (" + endpointsFile + ") found!");
                    }					
                } else {
                    logger.log(java.util.logging.Level.CONFIG, "endpoints file (" + endpointsFile + ") found!");
                }			
            } else {
				
                // if endpoint file	given by system property (relative to exec dir or absolute)

                if (!new File(endpointsFile).exists()) {
					
                    // if endpoint file	given by system property (relative to gemss home dir)

                    endpointsFile = new String(
                            System.getProperty("gemss.home") + File.separatorChar + "config" + File.separatorChar
                            + registryEndpointsConfig);
                    logger.log(java.util.logging.Level.FINE, "Trying endpoints file: " + endpointsFile);
					
                    if (!new File(endpointsFile).exists()) {
				
                        // if endpoint file is away ?!? -> throw exception			
                        throw new DiscoveryGridException(
                                "endpoint file given by system property (" + endpointsFile
                                + ") missing/not found/whatever!",
                                "endpoint file given by system property (" + endpointsFile
                                + ") missing/not found/whatever!");
                         
                    } else {
                        logger.log(java.util.logging.Level.CONFIG, "endpoints file (" + endpointsFile + ") found!");
                    }
                } else {
                    logger.log(java.util.logging.Level.CONFIG, "endpoints file (" + endpointsFile + ") found!");
                }
            }
            // System.out.println("endpointfile: " + endpointsFile);
		
            EndpointReader endpointReader = new EndpointReader(endpointsFile);
		
            registryURIs = endpointReader.getURIs();
		 
        } catch (java.io.IOException e) {
		    
            logger.log(java.util.logging.Level.SEVERE, e.toString(), e);
            
            throw new DiscoveryGridException("Error opening the  " + endpointsFile, e.toString());
        
        } catch (java.lang.Exception ex) {
		    
            logger.log(java.util.logging.Level.SEVERE, ex.toString(), ex);
            
            throw new DiscoveryGridException("Discovery exception", ex.toString());
        }
        
    }
	
    public List discoverServices(Attribute[] attributes) throws DiscoveryGridException, RegistryGridException {
        
        AttributeImpl[] attrImpl = null;
        RegistryImpl stub;
        String registryURL = null;
         
        if (servicesList == null) {
            
            throw new DiscoveryGridException("The service list can not be null", "The service list can not be null");
             
        }
            
        servicesList.clear();
         
        RegistryImplService service = new RegistryImplServiceLocator();
    
        Iterator registryIter = registryURIs.iterator();
        
        if (attributes != null) {
        
            attrImpl = new AttributeImpl[attributes.length];
          
            for (int i = 0; i < attributes.length; i++) {
              
                attrImpl[i] = new AttributeImpl();
                attrImpl[i].setName(attributes[i].getName());
                attrImpl[i].setValue(attributes[i].getValue());
            }
        }
        
        while (registryIter.hasNext()) {
                 
            try {  
               
                registryURL = (String) registryIter.next();
                
                logger.log(Level.INFO, "next registryURL " + registryURL); 
               
                URL url = new  URL(registryURL);  
                
                stub = service.getreg(url);
           
                List services = stub.query(attrImpl);
                
                if (services != null) {
                
                    Iterator iter = services.iterator();
        
                    while (iter.hasNext()) {
                   
                        servicesList.add((ServiceDescription) iter.next());
                    } 
                }
               
            } catch (java.net.MalformedURLException mue) {
             
                logger.log(java.util.logging.Level.SEVERE, mue.toString(), mue);
                
                throw new DiscoveryGridException("The " + registryURL + " specifies an unknown protocol", mue.toString());
              
            } catch (org.apache.axis.AxisFault af) {
             
                String faultReason = af.getFaultReason(); 
                   
                if (faultReason.startsWith("(404)")) {
                
                    logger.log(java.util.logging.Level.SEVERE,
                            "The " + registryURL + " is not fond! " + af.getFaultReason(), af);
                
                } else if (faultReason.endsWith("Connection refused")) {
                
                    logger.log(java.util.logging.Level.SEVERE,
                            "The connection to " + registryURL + " is refused!" + af.getFaultReason(), af);
                
                } else if (faultReason.endsWith("java.lang.NullPointerException") && (registryURL.startsWith("https"))) {
                
                    logger.log(java.util.logging.Level.SEVERE,
                            "It seems that you use security connection :" + registryURL
                            + ". This exception might be caused, because of your wrong entries in the "
                            + registryEndpointsConfig + " file. " + af.getFaultReason(),
                            af);
                
                } else {           
                    logger.log(java.util.logging.Level.SEVERE, af.getFaultReason(), af);
                }
                
               throw new DiscoveryGridException(af.getFaultReason(), af.toString());
                
            } catch (java.rmi.RemoteException re) { 
                   
                logger.log(java.util.logging.Level.SEVERE, re.toString(), re);
             
                throw new RegistryGridException("java.rmi.RemoteException.", re.toString());
                
            } catch (javax.xml.rpc.ServiceException se) {
             
                logger.log(java.util.logging.Level.SEVERE, se.toString(), se);
                
                throw new DiscoveryGridException("javax.xml.rpc.ServiceException.",
                        se.toString());
            
            } catch (java.lang.Exception ex) {
             
                logger.log(java.util.logging.Level.SEVERE, ex.toString(), ex);
                
                throw new DiscoveryGridException("Discovery exception : ", ex.toString());
            }
              
        }
        return servicesList;
    }
    
    public List getServices() {
    
        return servicesList;
    }

}

