/***********************************************************************/
/* Copyright (c) 1999-2005, The Rector and Board of Visitors of the    */
/* University of Virginia.                                             */
/* All rights reserved.                                                */
/*                                                                     */
/* This program is being made available under the terms of version 2.1 */
/* of theGNU Lesser General Public License ("LGPL") as published as of */
/* February, 1999 by the Free Software  Foundation; and subject to the */
/* restrictions of the LGPL, you are authorized to  modify and/or      */
/* redistribute it.                                                    */
/*                                                                     */
/* As stated in the LGPL, THIS PROGRAM IS BEING MADE AVAILABLE "AS IS",*/
/* AND WITHOUT A WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,    */
/* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF            */
/* MERCHANTABILITY AND  FITNESS FOR A PARTICULAR PURPOSE. FURTHER, YOU */
/* AGREE NOT TO HOLD THE COPYRIGHT  OWNER(S) LIABLE FOR DAMAGES,       */
/* INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES,*/
/* ARISING OUT OF THE USE OR INABILITY TO USE  THE PROGRAM.            */
/* See the GNU General Public License for more details.                */
/*                                                                     */
/* You should have received a copy of version 2.1 of the GNU General   */
/* Public License along with this program; if not, you may obtain a    */
/* copy  from the Free Software Foundation website at the following URL*/
/* address (link  active as of September 1, 2005):                     */
/* http://www.fsf.org/licensing/licenses/lgpl.html; or that failing,   */
/* you can request a copy from Free Software Foundation,  Inc., 51     */
/* Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.                */
/*                                                                     */
/* This program is part of the HyperCast software distribution. To     */
/* learn more about HyperCast, please visit the website at             */
/* http://www.hypercast.org.                                           */
/***********************************************************************/

/** HelloWorld_OverlayServer
 *
 *       The HyperCast HelloWorld programs demonstrate various aspects of
 *       the HyperCast API.  The programs create an overlay socket that
 *       sends and receives messages.
 *
 *       In HelloWorld_OverlayServer, the ususal call to
 *            ConfObj = HyperCastConfig.createConfig("hypercast.xml");
 *       is replaced by lines of code in the implementation of the createConfig
 *       method. The example shows the logic of accessing an overlay server.
 *       Note: This program should have a configuration that uses an overlay server,
 *       e.g.,
 *
 *          
 *          http://128.100.11.240:8080
 *          
 *      all receive operations are nonblocking.
 *      This file corresponds to an example program in the HyperCast API description
 *      (see Chapter:  "API - Advanced Topics", Section: "3.5.  CONFIGURING OVERLAY SOCKETS  ADVANCED TOPICS").
 *
 *       The file is a bit more complex than the example in the chapter.
 *
 * @author HyperCast Team, University of Toronto
 * @version 2006 (version 3.0)
 *
 */


import java.net.URL;

import org.apache.xpath.XPath;
import org.w3c.dom.Document;

import hypercast.*;

public class HelloWorld_Overlayserver implements I_ReceiveCallback {

//  The string we send
    String MyString = new String("Hello World");

//  The overlay socket
    I_OverlaySocket MySocket = null;

//  The configuration object
    HyperCastConfig ConfObj = null;

    public static void main(String[] args) {

        // Create a new HelloWorld_CallBack instance
        HelloWorld_Overlayserver hw = new HelloWorld_Overlayserver();
    }

    public void ReceiveCallback (I_OverlayMessage msg) {

        // Extract the payload and the logical address of the source
        byte[] data = msg.getPayload();
        String Src = msg.getSourceAddress().toString();

        // Print the payload (Skip messages sent by this program)
        if(!msg.getSourceAddress().equals(MySocket.getLogicalAddress()))
            System.out.println("Received <"+ new String(data) + "> from logical address: " + Src + ".");
    }

    public  HelloWorld_Overlayserver () {

        // Replacement for "ConfObj = HyperCastConfig.createConfig("hypercast.xml");"
        HyperCastConfig ConfObj = new HyperCastConfig ("hypercast.xml");
        try {
            String overlayId =  ConfObj.getTextAttribute (new XPath("/Public/OverlayID", null, null, XPath.MATCH));
            String overlayServer = ConfObj.getTextAttribute (new XPath("/Public/OverlayServer", null, null, XPath.MATCH));
            System.out.println("overlayId: >"+overlayId+"< overlayServer: >"+overlayServer+"<");
            System.out.println("overlay hash: >"+ConfObj.getOverlayHash()+"<");

            boolean existOverlayId = !((overlayId == null) || (overlayId.equals ("")));
            boolean existOverlayServer =
                !((overlayServer == null) || (overlayServer.equals (""))|| (overlayServer.equalsIgnoreCase ("None")));
            if (!existOverlayId && ! existOverlayServer) {
                System.out.println("No overlay server and no overlayID.");
                ConfObj.createandsetOverlayId();
            }

            if ( existOverlayServer ) {
                URL serverURL = ConfObj.getURLAttribute(new XPath("/Public/OverlayServer/HTTPServer", null, null, XPath.MATCH));

                String OverlayId = overlayId;

                if ((!existOverlayId) || (!ConfObj.doesOverlayExist(serverURL, overlayId)))
                {

                    System.out.println("Overlay " + overlayId + " doesn't exist!");

                    OverlayId = ConfObj.UploadConfig(serverURL);
                    System.out.println("overlayID after uploading is "+OverlayId+".");
                }

                Document DConfig  = ConfObj.DownloadConfig(serverURL, OverlayId);
                ConfObj.MergeConfig (DConfig);

            }

        } catch (Exception e) {
            System.err.println("Exception when creating overlay  configuration object.");
            System.err.println("Exception: " + e.getMessage());
            System.err.println("Exiting.");
            e.printStackTrace(System.err);
            System.exit(1);
        }


    // Create an overlay socket with the configuration object
    MySocket=ConfObj.createOverlaySocket(this);


    try{
        System.out.println("After Creation of overlay socket:");
    String overlayId =  ConfObj.getTextAttribute (new XPath("/Public/OverlayID", null, null, XPath.MATCH));
    String overlayServer = ConfObj.getTextAttribute (new XPath("/Public/OverlayServer", null, null, XPath.MATCH));
    System.out.println("overlayId: >"+overlayId+"< overlayServer: >"+overlayServer+"<");
    System.out.println("overlay hash: >"+ConfObj.getOverlayHash()+"<");
    }catch (Exception e){};


    // Join the overlay network
    MySocket.joinOverlay();

    // Print the logical address */
    String MyLogicalAddress = MySocket.getLogicalAddress().toString();
    System.out.println("Logical address is " + MyLogicalAddress + ".");

    // Repeat forever
    for(int i=1;i<100;i++) {

        // wait 2 seconds
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {}

        // Convert the string to a byte array and create a message
        byte[] MyData = MyString.getBytes();
        I_OverlayMessage MyMessage = MySocket.createMessage(MyData);

        // The message is sent to all members of the overlay //
        MySocket.sendToAll(MyMessage);
        System.out.println(" message sent to other members ...");
    }
    MySocket.closeSocket();
}
}