/*
 * This file is part of the OpenNMS(R) Application.
 *
 * OpenNMS(R) is Copyright (C) 2008 The OpenNMS Group, Inc.  All rights reserved.
 * OpenNMS(R) is a derivative work, containing both original code, included code and modified
 * code that was published under the GNU General Public License. Copyrights for modified
 * and included code are below.
 *
 * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
 *
 * Modifications;
 * Created 10/16/2008
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * For more information contact:
 * OpenNMS Licensing       <license@opennms.org>
 *     http://www.opennms.org/
 *     http://www.opennms.com/
 */
package org.opennms.netmgt.provision.support;

import java.io.IOException;
import java.io.InterruptedIOException;
import java.lang.reflect.UndeclaredThrowableException;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.NoRouteToHostException;

import org.opennms.netmgt.provision.DetectorMonitor;
import org.opennms.netmgt.provision.SyncServiceDetector;
import org.opennms.netmgt.provision.support.Client;
import org.opennms.netmgt.provision.support.ClientConversation.RequestBuilder;
import org.opennms.netmgt.provision.support.ClientConversation.ResponseValidator;

/**
 * 
 * @author <a href=mailto:desloge@opennms.com>Donald Desloge</a>
 *
 */

public abstract class BasicDetector<Request, Response> extends AbstractDetector implements SyncServiceDetector {
    
    private ClientConversation<Request, Response> m_conversation = new ClientConversation<Request, Response>();
    
    protected BasicDetector(int defaultPort, int defaultTimeout, int defaultRetries) {
        super(defaultPort, defaultTimeout, defaultRetries);
    }
    
    abstract protected void onInit();
    
    public boolean isServiceDetected(InetAddress address, DetectorMonitor detectorMonitor) {
        int port = getPort();
        int retries = getRetries();
        int timeout = getTimeout();
        System.out.printf("Address: %s || port: %s || \n", address, getPort());
        detectorMonitor.start(this, "Checking address: %s for %s capability", address, getServiceName());
                
        Client<Request, Response> client = getClient();
        for (int attempts = 0; attempts <= retries; attempts++) {

            try {
                
                client.connect(address, port, timeout);
                
                detectorMonitor.attempt(this, attempts, "Attempting to connect to address: %s attempt #%s",address.getHostAddress(),attempts);
                
                if (attemptConversation(client)) {
                    return true;
                }
                
            } catch (ConnectException cE) {
                // Connection refused!! Continue to retry.
                System.out.println("put before");
                cE.printStackTrace();
                detectorMonitor.info(this, cE, "Attempting to connect to address: %s attempt #%s",address.getHostAddress(),attempts);
            } catch (NoRouteToHostException e) {
                // No Route to host!!!
                e.printStackTrace();
                detectorMonitor.info(this, e, "%s: No route to address %s was available", getServiceName(), address.getHostAddress());
                throw new UndeclaredThrowableException(e);
            } catch (InterruptedIOException e) {
                // Expected exception
                e.printStackTrace();
                detectorMonitor.info(this, e, "%s: Did not connect to to address within timeout: %d attempt: %d", getServiceName(), timeout, attempts);
            } catch (IOException e) {
                e.printStackTrace();
                detectorMonitor.info(this, e, "%s: An unexpected I/O exception occured contacting address %s",getServiceName(), address.getHostAddress());
            } catch (Throwable t) {
                t.printStackTrace();
                detectorMonitor.failure(this, "%s: Failed to detect %s on address %s", getServiceName(), getServiceName(), address.getHostAddress());
                detectorMonitor.error(this, t, "%s: An undeclared throwable exception was caught contating address %s", getServiceName(), address.getHostAddress());
            } finally {
                client.close();
            }
        }
        return false;
    }

    /**
     * @return
     */
    abstract protected Client<Request, Response> getClient();

    private boolean attemptConversation(Client<Request, Response> client) throws IOException, Exception {
        return getConversation().attemptConversation(client);
    }
    
    protected void expectBanner(ResponseValidator<Response> bannerValidator) {
        getConversation().expectBanner(bannerValidator);
    }
    
    protected void send(RequestBuilder<Request> requestBuilder, ResponseValidator<Response> responseValidator) {
        getConversation().addExchange(requestBuilder, responseValidator);
    }
    protected void send(Request request, ResponseValidator<Response> responseValidator) {
        getConversation().addExchange(request, responseValidator);
    }
    
    protected ClientConversation<Request, Response> getConversation() {
        return m_conversation;
    }
    
}

@@ -1716,60 +1716,8 @@
 or;%0A
-import org.opennms.netmgt.provision.support.Client;%0A
 impo
@@ -2480,24 +2480,74 @@
 rMonitor) %7B%0A
+        String ipAddr = address.getHostAddress();%0A
         int 
@@ -3156,32 +3156,40 @@
  to address: %25s 
+port %25d 
 attempt #%25s%22,add
@@ -3189,32 +3189,19 @@
 %25s%22,
-address.getHostAddress()
+ipAddr,port
 ,att
@@ -3583,17 +3583,31 @@
 s, cE, %22
-A
+%25s: Excpetion a
 ttemptin
@@ -3633,16 +3633,25 @@
 ress: %25s
+ port %25d,
  attempt
@@ -3660,33 +3660,39 @@
 %25s%22,
-address.getHostAddress(),
+getServiceName(), ipAddr,port, 
 atte
@@ -3935,32 +3935,14 @@
 (), 
-address.getHostAddress()
+ipAddr
 );%0A 
@@ -4204,16 +4204,27 @@
 address 
+%25s port %25d 
 within t
@@ -4265,16 +4265,30 @@
 eName(),
+ ipAddr, port,
  timeout
@@ -4483,16 +4483,24 @@
 dress %25s
+ port %25d
 %22,getSer
@@ -4515,32 +4515,20 @@
 (), 
-address.getHostAddress()
+ipAddr, port
 );%0A 
@@ -4675,32 +4675,40 @@
 %25s on address %25s
+ port %25d
 %22, getServiceNam
@@ -4734,32 +4734,20 @@
 (), 
-address.getHostAddress()
+ipAddr, port
 );%0A 
@@ -4862,16 +4862,24 @@
 dress %25s
+ port %25d
 %22, getSe
@@ -4895,32 +4895,20 @@
 (), 
-address.getHostAddress()
+ipAddr, port
 );%0A 

clean up log message