/*******************************************************************************
 * 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.boot.BootLoader;
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 BootLoader.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 (BootLoader.OS_WIN32.equals(BootLoader.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 {

			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."));
	}
}
