/*******************************************************************************
 * Copyright (c) 2000, 2003 IBM Corporation and others.
 * 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 Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.update.tests.mirror;

import java.io.*;
import java.util.ArrayList;
import java.util.StringTokenizer;

import org.eclipse.core.runtime.*;
import org.eclipse.update.configurator.*;
import org.eclipse.update.internal.core.UpdateCore;
import org.eclipse.update.tests.UpdateManagerTestCase;


public class MirrorManagerTestCase extends UpdateManagerTestCase{
	public static int exitValue=-1;
	public static StringBuffer errOutput;
	
	public MirrorManagerTestCase(String arg0){
		super(arg0);
	}
	
	//WatchDog thread to kill mirroring process if it hangs (or takes too long)
	public static class Timer extends Thread{
		private Process proc;
		
		public Timer(Process proc){
			super();
			this.setDaemon(true);
			this.proc = proc;
		}
		
		public void run(){
			try {
				// Note: normal test on 2.2Ghz P4 is 2.9s 
				//:. giving 100x leeway to complete process before killing it
				sleep(300000); 
				proc.destroy();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	// structure to hold category definition names and descriptions
	class CategoryDefinition {
		private String name;
		private String desc;
		public void setName(String name) {
			this.name = name;
		}
		public void setDesc(String desc) {
			this.desc = desc;
		}
		public String getName() {
			return name;
		}
		public String getDesc() {
			return desc;
		}
	}
	
	// structure to hold feature IDs and their category names
	public class FeatureCategory{
		private String featureId;
		private ArrayList category;
		
		public FeatureCategory(){
			category = new ArrayList();
		}
		
		public void setFeatureID(String fid){
			featureId = fid;
		}
		
		public void addCategory(String cat){
			category.add(cat);
		}
		
		public String getFeatureID(){
			return featureId;
		}
		
		public String[] getCategories(){
			return (String[])category.toArray(new String[category.size()]);
		}
	}
	
	// StreamConsumer to display output to output files or console
	public static class StreamConsumer extends Thread {
		private BufferedReader bReader;

		public StreamConsumer(InputStream inputStream) {
			super();
			setDaemon(true);
			bReader = new BufferedReader(new InputStreamReader(inputStream));
		}

		public void run() {
			try {
				String line;
				while (null != (line = bReader.readLine())) {
					System.out.println(line);
					errOutput.append(line);
					errOutput.append("\n");
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * Returns a string array consisting of commands and their arguments to
	 * be run.
	 * @param remoteLoc - path of remote site (site being mirrored)
	 * @param toLocalSiteUrl - path of local site (new mirror site)
	 * @param fid - feature id of featuring being mirror (optional - can be null)
	 * @param ver - version of feature to be mirrored (optional - can be null)
	 * @param mirUrl - directory location of policy.xml (optional - can be mull)
	 * @return
	 */
	public String[] getCommand(
		String remoteLoc,
		String toLocalSiteUrl,
		String fid,
		String ver,
		String mirUrl) {
		final String classpath = "startup.jar";
		final String launcher = "org.eclipse.core.launcher.Main";
		final String command = "mirror";
		final String application = "org.eclipse.update.core.standaloneUpdate";
		final String FLAG_CP = "-cp";
		final String FLAG_APP = "-application";
		final String FLAG_CMD = "-command";
		final String FLAG_FID = "-featureId";
		final String FLAG_DATA = "-data";
		final String FLAG_VERSION = "-version";
		final String FLAG_FROM = "-from";
		final String FLAG_TO = "-to";
		final String FLAG_URL = "-mirrorURL";
		final String FLAG_SPLASH = "-nosplash";
		final String FLAG_CONSOLELOG = "-consolelog";
		final String data =
			UpdateCore.getPlugin().getStateLocation().toOSString();
		String[] cmd =
			new String[] {
				getJavaVMPath(),
				FLAG_CP,
				classpath,
				launcher,
				FLAG_APP,
				application,
				FLAG_CMD,
				command,
				FLAG_FROM,
				(remoteLoc !=null ? remoteLoc : ""),
				FLAG_TO,
				toLocalSiteUrl,
				(fid != null ? FLAG_FID : ""),
				(fid != null ? fid : ""),
				(ver != null ? FLAG_VERSION : ""),
				(ver != null ? ver : ""),
				(mirUrl != null ? FLAG_URL : ""),
				(mirUrl != null ? mirUrl : ""),
				FLAG_SPLASH,
				FLAG_DATA,
				data,
				FLAG_CONSOLELOG};
		return cmd;
	}
	
	public boolean checkFeatureInSiteXMLExists(String url, String fid, String ver){
		File site = new File(url + "/site.xml");
		assertTrue(site.exists());
		BufferedReader breader;
		FileReader freader;
		String text = new String();
		String jarName = fid + "_" + ver + ".jar";
		String feature = "<feature url=\"" +
			"features/" + jarName + 
			"\" id=\"" + fid + 
			"\" version=\"" + ver+"\">";
		try {
			freader = new FileReader(site);
			breader = new BufferedReader(freader);
		} catch (FileNotFoundException e) {
			// would have been caught by assert above
			return false;
		}
		try {
			while ((text = breader.readLine()) != null) {
				text = text.trim();
				if (text.equals(feature)){
					breader.close();
					freader.close();
					return true;
				}
			}

			breader.close();
			freader.close();
			return false;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
	}

	public void checkSiteXML(String url) throws Exception {
		File mirror = new File(url);
		File site = new File(url + "/site.xml");
		assertTrue(mirror.isDirectory());
		assertTrue(mirror.exists());
		assertTrue(site.exists());
	}

	public void checkPolicyXML(String url) throws Exception {
		File mirror = new File(url);
		File site = new File(url + "/policy.xml");
		assertTrue(mirror.isDirectory());
		assertTrue(mirror.exists());
		assertTrue(site.exists());
	}
	public boolean checkPolicyURL(String url, String mirrorUrl){
		File site = new File(url + "/policy.xml");
		assertTrue(site.exists());
		BufferedReader breader;
		FileReader freader;
		String text = new String();

		try {
			freader = new FileReader(site);
			breader = new BufferedReader(freader);
		} catch (FileNotFoundException e) {
			// would have been caught by assert above
			return false;
		}

		try {
			while ((text = breader.readLine()) != null) {
				if (text.indexOf(mirrorUrl)!=-1){
					breader.close();
					freader.close();	
					return true;
				}
			}

			breader.close();
			freader.close();
			return false;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
	}

	public boolean doesCategoryDefinitionExist(String url) {
		File site = new File(url + "/site.xml");
		assertTrue(site.exists());
		BufferedReader breader;
		FileReader freader;
		String text = new String();

		try {
			freader = new FileReader(site);
			breader = new BufferedReader(freader);
		} catch (FileNotFoundException e) {
			// would have been caught by assert above
			return false;
		}

		try {
			while ((text = breader.readLine()) != null) {
				if (text.indexOf("category-def")!=-1)
					return true;
			}

			breader.close();
			freader.close();
			return false;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}

	}
	
	public String getEclipseRoot() {
		return ConfiguratorUtils.getInstallURL().toExternalForm().replaceFirst(
			"file:",
			"");
	}
	
	public FeatureCategory[] getFeatureCategories(String url){
		File site = new File(url + "/site.xml");
		assertTrue(site.exists());
		BufferedReader breader;
		FileReader freader;
		String text = new String();
		ArrayList featureCategories = new ArrayList();
		
		try {
			freader = new FileReader(site);
			breader = new BufferedReader(freader);
		} catch (FileNotFoundException e) {
			// would have been caught by assert above
			return new FeatureCategory[0];
		}

		try {
			FeatureCategory currTok = new FeatureCategory();
			boolean add = false;
			while((text =breader.readLine())!=null){
				StringTokenizer strTok = new StringTokenizer(text);
				while (strTok.hasMoreTokens()){
					String temp = strTok.nextToken();
					if (temp.equals("</feature>")){
						add = true;
					} else if (temp.startsWith("id")){
						currTok.setFeatureID(temp.split("\"")[1]);
					} else if (temp.startsWith("name")){
						currTok.addCategory(temp.split("\"")[1]);
					}
				}
				if (add){
					featureCategories.add(currTok);
					currTok = new FeatureCategory();
					add = false;
				}
			}

			breader.close();
			freader.close();
			return (FeatureCategory[])featureCategories.toArray(new FeatureCategory[featureCategories.size()]);
		} catch (IOException e) {
			System.err.println(e);
			return new FeatureCategory[0];
		}
	}
	
	public String getJavaVMPath() {
		// Create command string for launching the process
		String vm = System.getProperty("java.vm.name");
		String executable = "J9".equals(vm) ? "j9" : "java";
		if (org.eclipse.osgi.service.environment.Constants.OS_WIN32.equals(Platform.getOS()))
			executable += "w.exe";

		String javaInstallDir =
			System.getProperty("java.home") + File.separator + "bin";
		return javaInstallDir + File.separator + executable;
	}
	
	public CategoryDefinition[] getCategoryDefinitions(String url) {
		File site = new File(url + "/site.xml");
		assertTrue(site.exists());
		BufferedReader breader;
		FileReader freader;
		String text = new String();
		ArrayList catDef = new ArrayList();

		try {
			freader = new FileReader(site);
			breader = new BufferedReader(freader);
		} catch (FileNotFoundException e) {
			// would have been caught by assert above
			return new CategoryDefinition[0];
		}

		try {
			boolean add = false;
			boolean isDesc = false;
			CategoryDefinition temp = new CategoryDefinition();
			while ((text = breader.readLine()) != null) {
				if (text.trim().startsWith("<category-def")
					&& text.indexOf("name") != -1) {
					temp.setName(text.split("\"")[1]);
					add = false;
				} else if (text.trim().equals("<description>")) {
					isDesc = true;
				} else if (text.trim().equals("</description>")) {
					isDesc = false;
				} else if (isDesc) {
					temp.setDesc(text.trim());
				} else if (text.trim().equals("</category-def>")) {
					add = true;
				}
				if (add) {
					catDef.add(temp);
					add = false;
					temp = new CategoryDefinition();
				}
			}

			breader.close();
			freader.close();
			return (CategoryDefinition[])catDef.toArray(new CategoryDefinition[catDef.size()]);
		} catch (IOException e) {
			System.err.println(e);
			return new CategoryDefinition[0];
		}

	}
	
	public int performMirror(String[] cmd_mirror) {
		File file = new File(getEclipseRoot());
		try {
			System.out.println("Launching:");
			for(int i=0; i<cmd_mirror.length; i++){
				System.out.print(cmd_mirror[i]+" ");
			}
			System.out.println();
			Process proc =
				Runtime.getRuntime().exec(cmd_mirror, (String[]) null, file);

			StreamConsumer outputs = new StreamConsumer(proc.getInputStream());
			outputs.start();
			StreamConsumer errors = new StreamConsumer(proc.getErrorStream());
			errors.start();
			Timer timer = new Timer(proc);
			timer.start();

			return proc.waitFor();
		} catch (IOException e) {
			System.err.println(e);
		} catch (InterruptedException e) {
			System.err.println(e);
		} catch (Exception e) {
			System.err.println(e);
		}
		return -1;
	}

	// ensure exit without problems
	public void testExitValue() throws Exception {
		assertEquals(exitValue, 0);
	}
	
	// ensure output string buffer ends with "Mirror command completed
	// successfully."
	// note: output may instead by "Command completed successfully."
	public void testMirrorSuccess() throws Exception {
		StringTokenizer tokenizer =
			new StringTokenizer(
				errOutput.toString(),
				"\n");
		String lastLine = new String();
		while (tokenizer.hasMoreTokens()){
			lastLine = tokenizer.nextToken();
		}
		assertTrue(
			lastLine.equals("Mirror command completed successfully.")
				|| lastLine.equals("Command completed successfully."));
	}
}
