/**********************************************************************
 * Copyright (c) 2003 Hyades project.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 *
 * Contributors:
 * IBM - Initial API and implementation
 **********************************************************************/

package org.eclipse.hyades.execution.trace.sample;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetAddress;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;

import org.eclipse.hyades.collection.correlation.BaseApplicationImpl;
import org.eclipse.hyades.collection.correlation.ServiceRegistry;
import org.eclipse.hyades.execution.trace.IiopProfiler;
import org.eclipse.hyades.execution.trace.ThreadComparator;
import org.eclipse.hyades.execution.trace.TraceCorrelator;
import org.eclipse.hyades.execution.trace.TraceHandler;


/**
 * This is the client using two simple services: saying hello and adding two integers.
 * 
 * @author Richard Duggan, Qiayn Li
 */
public class Client {

    /**
     * the distributed trace profiler
     */
    private static IiopProfiler app;

    // BEGIN INSTRUMENTED STATIC BLOCK
    static {
        app = IiopProfiler.getInstance();
        app.initialize();
        app.registerHandler(new TraceHandler());
        ServiceRegistry.getRegistry().registerApplication(app);

        /* Pause for the user to attach to the agent to log everything. */
        System.out.println("Please attach to the client agent and press [Enter] to start profiling...");
        try {
            (new BufferedReader(new InputStreamReader(System.in))).readLine();
        } catch (Exception e) {
            e.printStackTrace();
        }
    } // END INSTRUMENTED STATIC BLOCK


    /**
     * This is the client entry point.
     * 
     * @param args  the parameters from the command line
     */
    public static void main(String[] args) {

        // BEGIN ENTRY INSTRUMENTATION
        BaseApplicationImpl app = (BaseApplicationImpl) ServiceRegistry.getRegistry().getApplicationById(IiopProfiler.ID);
        TraceCorrelator correlator = (TraceCorrelator) app.createCorrelatorData();
        correlator.setInvocation(Client.class.hashCode(), Client.class, "main",
            new Class[] {String[].class}, new Object[] {args}, void.class);
        correlator.setParmNames(new String[] {"args"});
        app.pushChild(new ThreadComparator(), correlator);
        // END ENTRY INSTRUMENTATION

        try {

            /* Prepare to obtain a reference to the remote object. */
            Context initialContext = new InitialContext();
            String service = "RMI-IIOPSampleServer";

            // BEGIN ENTRY INSTRUMENTATION
            app = (BaseApplicationImpl) ServiceRegistry.getRegistry().getApplicationById(IiopProfiler.ID);
            correlator = (TraceCorrelator) app.createCorrelatorData();
            correlator.setInvocation(initialContext.hashCode(), initialContext.getClass(), "lookup",
                new Class[] {service.getClass()}, new Object[] {service}, Object.class);
            correlator.setParmNames(new String[] {"name"});
            app.pushChild(new ThreadComparator(), correlator);
            // END ENTRY INSTRUMENTATION

            Object objRef = initialContext.lookup(service);

            // BEGIN EXIT INSTRUMENTATION
            app = (BaseApplicationImpl) ServiceRegistry.getRegistry().getApplicationById(IiopProfiler.ID);
            correlator = (TraceCorrelator) app.getActiveCorrelatorByKey(new ThreadComparator());
            correlator.setReturnValue(objRef);
            app.returnCorrelatorData(app.popChild(new ThreadComparator()).getChild());
            // END EXIT INSTRUMENTATION

            /* Prepare to call the services. */
            IService svr = (IService) PortableRemoteObject.narrow(objRef, IService.class);
            String hostname = InetAddress.getLocalHost().getHostName();

            // BEGIN ENTRY INSTRUMENTATION
            app = (BaseApplicationImpl) ServiceRegistry.getRegistry().getApplicationById(IiopProfiler.ID);
            correlator = (TraceCorrelator) app.createCorrelatorData();
            correlator.setInvocation(svr.hashCode(), svr.getClass(), "hello",
                new Class[] {hostname.getClass()}, new Object[] {hostname}, String.class);
            correlator.setParmNames(new String[] {"name"});
            app.pushChild(new ThreadComparator(), correlator);
            // END ENTRY INSTRUMENTATION

            /* Call the two services on the server. */
            String helloMessage = svr.hello(hostname);

            // BEGIN EXIT INSTRUMENTATION
            app = (BaseApplicationImpl) ServiceRegistry.getRegistry().getApplicationById(IiopProfiler.ID);
            correlator = (TraceCorrelator) app.getActiveCorrelatorByKey(new ThreadComparator());
            correlator.setReturnValue(helloMessage);
            app.returnCorrelatorData(app.popChild(new ThreadComparator()).getChild());
            // END EXIT INSTRUMENTATION

            /* Output the result, and prepare the next call. */
            System.out.println("Greetings from the server: " + helloMessage);
            int x = 5, y = 17;

            // BEGIN ENTRY INSTRUMENTATION
            app = (BaseApplicationImpl) ServiceRegistry.getRegistry().getApplicationById(IiopProfiler.ID);
            correlator = (TraceCorrelator) app.createCorrelatorData();
            correlator.setInvocation(svr.hashCode(), svr.getClass(), "add",
                new Class[] {int.class, int.class}, new Object[] {new Integer(x), new Integer(y)}, Long.class);
            correlator.setParmNames(new String[] {"x", "y"});
            app.pushChild(new ThreadComparator(), correlator);
            // END ENTRY INSTRUMENTATION

            Long z = svr.add(x, y);
            System.out.println("Addition: " + x + " + " + y + " = " + z);

            // BEGIN EXIT INSTRUMENTATION
            app = (BaseApplicationImpl) ServiceRegistry.getRegistry().getApplicationById(IiopProfiler.ID);
            correlator = (TraceCorrelator) app.getActiveCorrelatorByKey(new ThreadComparator());
            correlator.setReturnValue(z);
            app.returnCorrelatorData(app.popChild(new ThreadComparator()).getChild());
            // END EXIT INSTRUMENTATION

        } catch (Exception e) {
            e.printStackTrace();
        }

        // BEGIN EXIT INSTRUMENTATION
        app = (BaseApplicationImpl) ServiceRegistry.getRegistry().getApplicationById(IiopProfiler.ID);
        app.returnCorrelatorData(app.popChild(new ThreadComparator()).getChild());
        // END EXIT INSTRUMENTATION
    }
}