/*
* This file or a portion of this file is licensed under the terms of
* the Globus Toolkit Public License, found in file GTPL, or at
* http://www.globus.org/toolkit/download/license.html. This notice must
* appear in redistributions of this file, with or without modification.
*
* Redistributions of this Software, with or without modification, must
* reproduce the GTPL in: (1) the Software, or (2) the Documentation or
* some other similar material which is provided with the Software (if
* any).
*
* Copyright 1999-2004 University of Chicago and The University of
* Southern California. All rights reserved.
*/
package edu.isi.pegasus.planner.invocation;
import java.util.*;
import java.io.Writer;
import java.io.IOException;
/**
* This class maintains the application that was run, and the
* arguments to the commandline that were actually passed on to
* the application.
*
* @author Jens-S. Vöckler
* @author Yong Zhao
* @version $Revision$
* @see Job
*/
public class ArgVector extends Arguments
{
/**
* This is the (new) alternative explicit argument vector. The reason
* for using a map is that I cannot random access an ArrayList.
*/
private Map m_argv;
/**
* Default c'tor: Construct a hollow shell and allow further
* information to be added later.
*/
public ArgVector()
{
super();
m_argv = new TreeMap();
}
/**
* Constructs an applications without arguments.
* @param executable is the name of the application.
*/
public ArgVector( String executable )
{
super(executable);
m_argv = new TreeMap();
}
/**
* Returns the full argument vector as one single string.
*
* @return a single string joining all arguments with a single space.
* @see #setValue(int,String)
*/
public String getValue()
{
StringBuffer result = new StringBuffer(128);
if ( m_argv.size() > 0 ) {
boolean flag = false;
for ( Iterator i=m_argv.keySet().iterator(); i.hasNext(); ) {
Integer key = (Integer) i.next();
String value = (String) m_argv.get(key);
if ( value != null ) {
if ( flag ) result.append(' ');
else flag = true;
// FIXME: Use single quotes around value, if it contains ws.
// FIXME: escape contained apostrophes and esc characters.
result.append( value );
}
}
}
return result.toString();
}
/**
* Sets the argument vector at the specified location.
* @param position is the position at which to set the entry.
* @param entry is the argument vector position
* Setting <code>null</code> is a noop.
*/
public void setValue( int position, String entry )
{
if ( position >= 0 ) {
if ( entry == null ) {
m_argv.put( new Integer(position), new String() );
} else {
m_argv.put( new Integer(position), entry );
}
}
}
/**
* Dumps the state of the current element as XML output. This function
* can return the necessary data more efficiently, thus overwriting
* the inherited method.
*
* @param indent is a <code>String</code> of spaces used for pretty
* printing. The initial amount of spaces should be an empty string.
* The parameter is used internally for the recursive traversal.
*
* @return a String which contains the state of the current class and
* its siblings using XML. Note that these strings might become large.
*/
public String toXML( String indent )
{
StringBuffer result = new StringBuffer(64);
String newline = System.getProperty( "line.separator", "\r\n" );
result.append( "<argument-vector" );
if ( m_executable != null ) {
result.append( " executable=\"" );
result.append( quote(m_executable,true) );
result.append( '"' );
}
if ( m_argv.size() == 0 ) {
// no content
result.append( "/>" );
} else {
// yes, content
String newindent = indent == null ? null : indent + " ";
result.append( '>' );
if ( indent != null ) result.append( newline );
for ( Iterator i=m_argv.keySet().iterator(); i.hasNext(); ) {
Integer key = (Integer) i.next();
String entry = (String) m_argv.get(key);
if ( entry != null ) {
if ( newindent != null ) result.append( newindent );
result.append( "<arg nr=\"" ).append(key).append("\">" );
result.append( quote(entry,false) );
result.append( "</arg>" );
if ( newindent != null ) result.append( newline );
}
}
result.append( "</argument-vector>" );
}
return result.toString();
}
/**
* Dump the state of the current element as XML output. This function
* traverses all sibling classes as necessary, and converts the data
* into pretty-printed XML output. The stream interface should be able
* to handle large output efficiently.
*
* @param stream is a stream opened and ready for writing. This can also
* be a string stream for efficient output.
* @param indent is a <code>String</code> of spaces used for pretty
* printing. The initial amount of spaces should be an empty string.
* The parameter is used internally for the recursive traversal.
* If a <code>null</code> value is specified, no indentation nor
* linefeeds will be generated.
* @param namespace is the XML schema namespace prefix. If neither
* empty nor null, each element will be prefixed with this prefix,
* and the root element will map the XML namespace.
* @exception IOException if something fishy happens to the stream.
*/
public void toXML( Writer stream, String indent, String namespace )
throws IOException
{
String newline = System.getProperty( "line.separator", "\r\n" );
String tag = ( namespace != null && namespace.length() > 0 ) ?
namespace + ":argument-vector" : "argument-vector";
// open tag
if ( indent != null && indent.length() > 0 ) stream.write( indent );
stream.write( '<' );
stream.write( tag );
if ( m_executable != null )
writeAttribute( stream, " executable=\"", m_executable );
if ( m_argv.size() > 0 ) {
// yes, new content
String newindent = indent == null ? null : indent + " ";
String newtag = ( namespace != null && namespace.length() > 0 ) ?
namespace + ":arg" : "arg";
stream.write( '>' );
if ( indent != null ) stream.write( newline );
for ( Iterator i=m_argv.keySet().iterator(); i.hasNext(); ) {
String key = (String) i.next();
String entry = (String) m_argv.get(key);
if ( entry != null ) {
if ( newindent != null && newindent.length() > 0 )
stream.write(newindent);
stream.write( '<' );
stream.write( newtag );
writeAttribute( stream, " nr=\"", key );
stream.write( '>' );
stream.write( quote(entry,false) );
stream.write( "</" );
stream.write( newtag );
stream.write( '>' );
if ( indent != null ) stream.write( newline );
}
}
if ( indent != null && indent.length() > 0 ) stream.write( indent );
stream.write( "</" );
stream.write( tag );
stream.write( '>' );
} else {
// no content
stream.write( "/>" );
}
if ( indent != null ) stream.write( newline );
}
}