/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Common Public License (CPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/cpl1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.mmtk.utility.options; import org.mmtk.utility.Log; import org.mmtk.utility.statistics.Xml; import org.mmtk.vm.VM; /** * The abstract base class for all options. This class also has * the static interfaces to access the options system to set * option values. * * All options within the system should have a unique name. No * two options shall have a name that is the same when a case * insensitive comparison between the names with spaces removed * is performed. Only basic alphanumeric characters and spaces * are allowed. * * The VM is required to provide a one way mapping function that * takes the name and creates a VM style name, such as mapping * "No Finalizer" to noFinalizer. The VM may not remove any letters * when performing this mapping but may remove spaces and change * the case of any character. */ public abstract class Option { // options registry private static Option head; private static Option tail; /** * Initialize the options system so that options can be created. * This also creates the first option that can be used to echo * the setting of options to the console to assist debugging. */ static { head = tail = null; } // Option types public static final int BOOLEAN_OPTION = 1; public static final int STRING_OPTION = 2; public static final int ENUM_OPTION = 3; public static final int INT_OPTION = 4; public static final int PAGES_OPTION = 6; public static final int MICROSECONDS_OPTION = 7; public static final int FLOAT_OPTION = 8; public static final int ADDRESS_OPTION = 9; /** * The possible output formats */ public static final int READABLE = 0; public static final int RAW = 1; public static final int XML = 2; /** * Using the VM determined key, look up the corresponding option, * or return null if an option can not be found. * * @param key The (unique) option key. * @return The option, or null. */ public static Option getOption(String key) { Option o = getFirst(); while (o != null) { if (o.key.equals(key)) { return o; } o = o.getNext(); } return null; } /** * Return the first option. This can be used with the getNext method to * iterate through the options. * * @return The first option, or null if no options exist. */ public static Option getFirst() { return head; } // Per option values private int type; private String name; private String description; private String key; private Option next; /** * Construct a new option. This also calls the VM to map the option's * name into a unique option key and links it onto the option list. * * @param type The option type as defined in this class. * @param name The unique name of the option. * @param description A short description of the option and purpose. */ protected Option(int type, String name, String description) { this.type = type; this.name = name; this.description = description; this.key = VM.options.getKey(name); if (tail == null) { tail = head = this; } else { tail.next = this; tail = this; } } /** * Return the VM determined key for an option * * @return The key. */ public String getKey() { return this.key; } /** * Return the next option in the linked list. * * @return The next option or null if this is the last option. */ public Option getNext() { return this.next; } /** * Return the name for the option. * * @return The option name. */ public String getName() { return this.name; } /** * Return the option description. * * @return The option description. */ public String getDescription() { return this.description; } /** * Return the type of the option. * * @return The option type. */ public int getType() { return this.type; } /** * Log the option value in one of several formats * * @param format Output format (see Option.java for possible values) */ void log(int format) { switch (format) { case READABLE: Log.write("Option '"); Log.write(getKey()); Log.write(" = "); log(RAW); Log.writeln(); break; case XML: Xml.openMinorTag("option"); Xml.attribute("name",getKey()); Xml.openAttribute("value"); log(RAW); Xml.closeAttribute(); Xml.closeMinorTag(); break; case RAW: VM.assertions.fail("Subtypes of Option must implement log(RAW)"); break; } } /** * This is a validation method that can be implemented by leaf option * classes to provide additional validation. This should not be implemented * at other levels within the heirarchy to avoid confusion. The validate * method works against the current value of the option (post-set). */ protected void validate() {} /** * A fatal error occurred during the setting of an option. This method * calls into the VM and is required to cause the system to stop. * * @param message The error message associated with the failure. */ protected void fail(String message) { VM.options.fail(this, message); } /** * Fail if a specified condition is met. * * @param condition The condition that indicates failure. * @param message The error message associated with the failure. */ protected void failIf(boolean condition, String message) { if (condition) VM.options.fail(this, message); } /** * A non-fatal error occurred during the setting of an option. This method * calls into the VM and shall not cause the system to stop. * * @param message The message associated with the warning. */ protected void warn(String message) { VM.options.warn(this, message); } /** * Warn if a specified condition is met. * * @param condition The condition that indicates warning. * @param message The message associated with the warning. */ protected void warnIf(boolean condition, String message) { if (condition) VM.options.warn(this, message); } }