/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at * trunk/opends/resource/legal-notices/OpenDS.LICENSE * or https://OpenDS.dev.java.net/OpenDS.LICENSE. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, * add the following below this CDDL HEADER, with the fields enclosed * by brackets "[]" replaced with your own identifying information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Copyright 2006-2008 Sun Microsystems, Inc. */ package com.sun.opends.sdk.tools; import static com.sun.opends.sdk.messages.Messages.*; import static com.sun.opends.sdk.util.StaticUtils.*; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.util.LinkedHashMap; import org.opends.sdk.LocalizableMessage; import org.opends.sdk.LocalizableMessageBuilder; /** * This class defines an argument whose value will be read from a file * rather than actually specified on the command-line. When a value is * specified on the command line, it will be treated as the path to the * file containing the actual value rather than the value itself.
*
* Note that if if no filename is provided on the command line but a * default value is specified programatically or if the default value is * read from a specified property, then that default value will be taken * as the actual value rather than a filename.
*
* Also note that this argument type assumes that the entire value for * the argument is on a single line in the specified file. If the file * contains multiple lines, then only the first line will be read. */ final class FileBasedArgument extends Argument { // The mapping between filenames specified and the first lines read // from those // files. private LinkedHashMap namesToValues; /** * Creates a new file-based argument with the provided information. * * @param name * The generic name that should be used to refer to this * argument. * @param shortIdentifier * The single-character identifier for this argument, or * null if there is none. * @param longIdentifier * The long identifier for this argument, or * null if there is none. * @param isRequired * Indicates whether this argument must be specified on the * command line. * @param valuePlaceholder * The placeholder for the argument value that will be * displayed in usage information, or null if * this argument does not require a value. * @param description * LocalizableMessage for the description of this argument. * @throws ArgumentException * If there is a problem with any of the parameters used to * create this argument. */ public FileBasedArgument(String name, Character shortIdentifier, String longIdentifier, boolean isRequired, LocalizableMessage valuePlaceholder, LocalizableMessage description) throws ArgumentException { super(name, shortIdentifier, longIdentifier, isRequired, false, true, valuePlaceholder, null, null, description); namesToValues = new LinkedHashMap(); } /** * Creates a new file-based argument with the provided information. * * @param name * The generic name that should be used to refer to this * argument. * @param shortIdentifier * The single-character identifier for this argument, or * null if there is none. * @param longIdentifier * The long identifier for this argument, or * null if there is none. * @param isRequired * Indicates whether this argument must be specified on the * command line. * @param isMultiValued * Indicates whether this argument may be specified more than * once to provide multiple values. * @param valuePlaceholder * The placeholder for the argument value that will be * displayed in usage information, or null if * this argument does not require a value. * @param defaultValue * The default value that should be used for this argument if * none is provided in a properties file or on the command * line. This may be null if there is no generic * default. * @param propertyName * The name of the property in a property file that may be * used to override the default value but will be overridden * by a command-line argument. * @param description * LocalizableMessage for the description of this argument. * @throws ArgumentException * If there is a problem with any of the parameters used to * create this argument. */ public FileBasedArgument(String name, Character shortIdentifier, String longIdentifier, boolean isRequired, boolean isMultiValued, LocalizableMessage valuePlaceholder, String defaultValue, String propertyName, LocalizableMessage description) throws ArgumentException { super(name, shortIdentifier, longIdentifier, isRequired, isMultiValued, true, valuePlaceholder, defaultValue, propertyName, description); namesToValues = new LinkedHashMap(); } /** * Retrieves a map between the filenames specified on the command line * and the first lines read from those files. * * @return A map between the filenames specified on the command line * and the first lines read from those files. */ public LinkedHashMap getNameToValueMap() { return namesToValues; } /** * Indicates whether the provided value is acceptable for use in this * argument. * * @param valueString * The value for which to make the determination. * @param invalidReason * A buffer into which the invalid reason may be written if * the value is not acceptable. * @return true if the value is acceptable, or * false if it is not. */ public boolean valueIsAcceptable(String valueString, LocalizableMessageBuilder invalidReason) { // First, make sure that the specified file exists. File valueFile; try { valueFile = new File(valueString); if (!valueFile.exists()) { invalidReason.append(ERR_FILEARG_NO_SUCH_FILE.get(valueString, getName())); return false; } } catch (Exception e) { invalidReason.append(ERR_FILEARG_CANNOT_VERIFY_FILE_EXISTENCE .get(valueString, getName(), getExceptionMessage(e))); return false; } // Open the file for reading. BufferedReader reader; try { reader = new BufferedReader(new FileReader(valueFile)); } catch (Exception e) { invalidReason.append(ERR_FILEARG_CANNOT_OPEN_FILE.get( valueString, getName(), getExceptionMessage(e))); return false; } // Read the first line and close the file. String line; try { line = reader.readLine(); } catch (Exception e) { invalidReason.append(ERR_FILEARG_CANNOT_READ_FILE.get( valueString, getName(), getExceptionMessage(e))); return false; } finally { try { reader.close(); } catch (Exception e) { } } // If the line read is null, then that means the file was empty. if (line == null) { invalidReason.append(ERR_FILEARG_EMPTY_FILE.get(valueString, getName())); return false; } // Store the value in the hash so it will be available for addValue. // We // won't do any validation on the value itself, so anything that we // read // will be considered acceptable. namesToValues.put(valueString, line); return true; } /** * Adds a value to the set of values for this argument. This should * only be called if the value is allowed by the * valueIsAcceptable method. Note that in this case, * correct behavior depends on a previous successful call to * valueIsAcceptable so that the value read from the file * may be stored in the name-to-value hash and used in place of the * filename here. * * @param valueString * The string representation of the value to add to this * argument. */ public void addValue(String valueString) { String actualValue = namesToValues.get(valueString); if (actualValue != null) { super.addValue(actualValue); } } }