/*
 * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package com.sun.ejte.ccl.webrunner.webtest;

import java.io.FileInputStream;
import java.io.File;

/**
 *This is the main class for Web Test.It takes a text script file as an argument.
 *
 * @author       Deepa Singh (deepa.singh@sun.com)
 *Company       Sun Microsystems Inc.
 *
 */
public class WebTest
{
    private String ws_root="appserv-tests";
    private String testsuite_id="";

    WebTest(){}

    public void setTestSuiteID(String testsuiteid)
    {
        this.testsuite_id=testsuiteid;
    }

    public void setResultFileLocation(String workspace_root)
    {
        this.ws_root=workspace_root;
    }

    /**
     *Reads script file and converts into a byte array.Sends byte array to SendRequest class.
     *@author Deepa Singh deepa.singh@sun.com
     *@param file String fully qualified location of file
     *@param host String host name of web server where web application is to be run.
     *
     */
    public void readFile(String file,String s_host,String s_port)
    {
        try
        {
            FileInputStream fin=new FileInputStream(file);
            File f=new File(file);
            byte buffer[]=new byte[(int)f.length()];
            System.out.println("size of buffer is"+buffer.length);
            int pos=0;
            int n;
            while((n=fin.read())>=0)
            {
                if(pos>(int)f.length())
                {
                    System.out.println("EOF reached");
                    break;
                }
                buffer[pos]=(byte)n;
                pos=pos+1;
            }

            fin.close();
            SendRequest sendRequest=new SendRequest(ws_root,testsuite_id);
            int port=new Integer(s_port).intValue();
            sendRequest.setServerProperties(s_host,port);
            sendRequest.processUrl(buffer);
        }
        catch(Exception e)
        {
            System.out.println("Error in reading Script File");
            e.printStackTrace();
        }
    }



    public static void main(String [] args)
    {

        if(args.length<4)
        {
            System.err.println("usage:\t WebTest <<full_file_name>> <<web_server_host_name>> <<web_server_port>> <<outputfile>> <<testsuiteid>>");
            System.exit(0);
        }
        String file= args[0];
        String serverhost=args[1];
        String serverport=args[2];
        String ws_root=args[3];
        String testsuiteid=args[4];

        WebTest webTest=new WebTest();
        webTest.setResultFileLocation(ws_root);
        webTest.setTestSuiteID(testsuiteid);
        webTest.readFile(file,serverhost,serverport);

    }
}


