/*
 * $Id$
 *
 * Copyright 1996-2008 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */
package com.sun.javatest.tool;

import java.util.HashMap;
import java.util.ListIterator;
import java.util.Map;
import java.lang.SecurityManager;

import com.sun.javatest.JavaTestSecurityManager;
import com.sun.javatest.TestEnvironment;
import com.sun.javatest.util.HelpTree;
import com.sun.javatest.util.I18NResourceBundle;

/**
 * A command manager to handle the command line options for adding
 * default values into every test environment.
 * The supported options are:
 * <ul>
 * <li><code>-EsysProps</code>: add all the system properties into every
 *  environment
 * <li><code>-E</code><i>name</i><code>=</code><i>value</i>: set <i>name</i>
 * to <i>value</i> in every environment
 * </ul>
 */
public class EnvironmentManager extends CommandManager 
{
    EnvironmentManager() {
	// flush any prior tables
	TestEnvironment.clearDefaultPropTables();

	// set basic defaults
	String[] stdSysProps = {"user.dir", "user.home"};
	Map m = new HashMap();
	for (int i = 0; i < stdSysProps.length; i++) {
	    String name = stdSysProps[i];
	    m.put(name, System.getProperty(name));
	}
	TestEnvironment.addDefaultPropTable(i18n.getString("env.def.sysProps"), m);
    }
    

    public HelpTree.Node getHelp() {
	String[] opts = { "EsysProps", "EnameVar" };
	return new HelpTree.Node(i18n, "env", opts);
    }

    public boolean parseCommand(String cmd, ListIterator argIter, CommandContext ctx)
	throws Command.Fault
    {
	if (cmd.equalsIgnoreCase("EsysProps")) {
	    ctx.addCommand(new ESysPropsCommand());
	    return true;
	}
	
	if (cmd.startsWith("E") && (cmd.indexOf('=') > 0)) {
	    int sep = cmd.indexOf('=');
	    String name = cmd.substring(1, sep).trim();
	    String value = cmd.substring(sep + 1).trim();
	    ctx.addCommand(new ENameValueCommand(name, value));
	    return true;
	}

	return false;
    }

    private static I18NResourceBundle i18n = I18NResourceBundle.getBundleForClass(ConfigManager.class);

    //--------------------------------------------------------------------------

    private class ENameValueCommand extends Command {
	ENameValueCommand(String name, String value) {
	    super("E" + name + "=" + value);
	    this.name = name;
	    this.value = value;
	}

	public void run(CommandContext ctx) throws Fault {
	    Map m = new HashMap(1);  // would be nice to have a singleton map
	    m.put(name, value);
	    TestEnvironment.addDefaultPropTable(i18n.getString("env.def.cmdLine"), m);
	}

	private String name;
	private String value;
    }

    //--------------------------------------------------------------------------

    private class ESysPropsCommand extends Command {
	ESysPropsCommand() {
	    super("EsysProps");
	}

	public void run(CommandContext ctx) throws Fault {
	    try {
		Map sysProps;
		SecurityManager sc = System.getSecurityManager();
		if (sc instanceof JavaTestSecurityManager) {
		    // open up the properties access permission to get system props.
		    boolean prev = ((JavaTestSecurityManager) sc).setAllowPropertiesAccess(true);
		    try {
			sysProps = System.getProperties();
		    }
		    finally {
			((JavaTestSecurityManager) sc).setAllowPropertiesAccess(prev);
		    }
		}
		else {
		    // if not JTSecurityManager, try to get properties anyway
		    // and handle the exception if we can't get them
		    sysProps = System.getProperties();
		}
		TestEnvironment.addDefaultPropTable(i18n.getString("env.def.sysProps"), sysProps);
	    }
	    catch (SecurityException e) {
		throw new Fault(i18n, "env.cantAccessSysProps", e);
	    }
	}
    }
}
