/*
 * 
 * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
 * 
 * The contents of this file are subject to the Sun Community Source
 * License v3.0/Jini Technology Specific Attachment v 1.0 (the
 * "License"). You may not use this file except in compliance with the
 * License. You may obtain a copy of the License at
 * http://wwws.sun.com/software/jini/licensing/SCSL3_JiniTSA1.html.
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 * the License for the specific language governing rights and limitations
 * under the License.
 * 
 * The Reference Code is Jini Technology Core Platform code, v2.0. The
 * Developer of the Reference Code is Sun Microsystems, Inc.
 * 
 * Contributor(s): Sun Microsystems, Inc.
 * 
 * The contents of this file comply with the Jini Technology Core
 * Platform Compatibility Kit, v2.0A.
 * 
 * Tester(s): Sun Microsystems, Inc.
 * 
 * Test Platform(s):
 * Java 2 SDK, Standard Edition, Version 1.4.2_03 for Solaris(TM)SPARC/x86
 * Java 2 SDK, Standard Edition, Version 1.4.2_03 for Linux (Intel x86)
 * Java 2 SDK, Standard Edition, Version 1.4.2_03 for Windows (Intel Platform)
 * 
 */

package com.sun.jini.example.hello;

import java.security.PrivilegedExceptionAction;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import net.jini.config.Configuration;
import net.jini.config.ConfigurationProvider;
import net.jini.config.NoSuchEntryException;
import net.jini.core.lookup.ServiceItem;
import net.jini.core.lookup.ServiceTemplate;
import net.jini.discovery.LookupDiscovery;
import net.jini.lookup.ServiceDiscoveryManager;
import net.jini.security.BasicProxyPreparer;
import net.jini.security.ProxyPreparer;

/**
 * Defines an application that makes calls to a remote Hello server.
 *
 * The application uses the following arguments:
 *
 * [all] - All arguments are used as options when getting the configuration
 *
 * The application uses the following configuration entries, with component
 * com.sun.jini.example.hello.Client:
 *
 * loginContext
 *   type: LoginContext
 *   default: null
 *   If non-null, specifies the JAAS login context to use for performing a JAAS
 *   login and supplying the Subject to use when running the client. If null,
 *   no JAAS login is performed.
 *
 * preparer
 *   type: ProxyPreparer
 *   default: new BasicProxyPreparer()
 *   Proxy preparer for the server proxy
 *
 * serviceDiscovery
 *   type: ServiceDiscoveryManager
 *   default: new ServiceDiscoveryManager(
 *                new LookupDiscovery(new String[] { "" }, config),
 *                null, config)
 *   Object used for discovering a server that implement Hello.
 *
 * @author Sun Microsystems, Inc.
 */
public class Client {

    /**
     * Starts an application that makes calls to a remote Hello implementation.
     */
    public static void main(String[] args) throws Exception {
	/*
	 * The configuration contains information about constraints to apply to
	 * the server proxy.
	 */
	final Configuration config = ConfigurationProvider.getInstance(args);
	LoginContext loginContext = (LoginContext) config.getEntry(
	    "com.sun.jini.example.hello.Client", "loginContext",
	    LoginContext.class, null);
	if (loginContext == null) {
	    mainAsSubject(config);
	} else {
	    loginContext.login();
	    Subject.doAsPrivileged(
		loginContext.getSubject(),
		new PrivilegedExceptionAction() {
		    public Object run() throws Exception {
			mainAsSubject(config);
			return null;
		    }
		},
		null);
	}
    }

    /**
     * Performs the main operations of the application with the specified
     * configuration and assuming that the appropriate subject is in effect.
     */
    static void mainAsSubject(Configuration config) throws Exception {

	/* Get the service discovery manager, for discovering other services */
	ServiceDiscoveryManager serviceDiscovery;
	try {
	    serviceDiscovery = (ServiceDiscoveryManager) config.getEntry(
		"com.sun.jini.example.hello.Client", "serviceDiscovery",
		ServiceDiscoveryManager.class);
	} catch (NoSuchEntryException e) {
	    /* Default to search in the public group */
	    serviceDiscovery = new ServiceDiscoveryManager(
		new LookupDiscovery(new String[] { "" }, config),
		null, config);
	}

	/* Look up the remote server */
	ServiceItem serviceItem = serviceDiscovery.lookup(
	    new ServiceTemplate(null, new Class[] { Hello.class }, null),
	    null, Long.MAX_VALUE);
	Hello server = (Hello) serviceItem.service;

	/* Prepare the server proxy */
	ProxyPreparer preparer = (ProxyPreparer) config.getEntry(
	    "com.sun.jini.example.hello.Client",
	    "preparer", ProxyPreparer.class, new BasicProxyPreparer());
	server = (Hello) preparer.prepareProxy(server);

	/* Use the server */
	System.out.println("Server says: " + server.sayHello());

	/* Exit to close any thread created by the callback handler's GUI */
	System.exit(0);
    }
}
