/**
* Copyright 2007-2008 University Of Southern California
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package edu.isi.pegasus.planner.namespace;
import edu.isi.pegasus.planner.catalog.classes.Profiles;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.LinkedHashMap;
import edu.isi.pegasus.planner.classes.Profile;
import edu.isi.pegasus.planner.common.PegasusProperties;
/**
* The environment namespace, that puts in the environment variables for the
* transformation that is being run, through Condor. At present on the occurence
* of a clash between the values of an environment variable the values are
* overwritten with the order of preference in decreasing order being users
* local properties, transformation catalog, pool file and the dax (vdl).
* Later on operations like append , prepend would also be supported.
*
* @author Karan Vahi
* @author Gaurang Mehta
* @version $Revision$
*/
public class ENV extends Namespace {
/**
* The name of the namespace that this class implements.
*/
public static final String NAMESPACE_NAME = Profile.ENV;
/**
* The name of the environment variable that specifies the path to the
* proxy.
*/
public static final String X509_USER_PROXY_KEY = "X509_USER_PROXY";
/**
* The name of the environment variable that specifies the Gridstart PREJOB.
*/
public static final String GRIDSTART_PREJOB = "GRIDSTART_PREJOB";
/**
* the env variable containing the workflow uuid assigned by pegasus
*/
public static final String PEGASUS_WF_ID_ENV_KEY = "PEGASUS_WF_UUID";
/**
* the env variable containing the job id of a job in the executable workflow
*/
public static final String PEGASUS_JOB_ID_ENV_KEY = "PEGASUS_DAG_JOB_ID";
/**
* the env variable containing the workflow label assigned by pegasus
*/
public static final String PEGASUS_WF_LABEL_ENV_KEY = "PEGASUS_WF_LABEL";
/**
* site which the job was mapped to
*/
public static final String PEGASUS_SITE_ID_ENV_KEY = "PEGASUS_SITE";
/**
* The env variable pointing to the scratch directory a job will be executed
* in , in a shared fs configuration
*/
public static final String PEGASUS_SCRATCH_DIR_KEY = "PEGASUS_SCRATCH_DIR";
/**
* The environment variable that indicates where Pegasus executables are installed
*/
public static String PEGASUS_BIN_DIR_ENV_KEY = "PEGASUS_BIN_DIR";
/**
* The name of the environment variable that specifies the s3cfg path
*/
public static final String S3CFG = "S3CFG";
/**
* The name of the implementing namespace. It should be one of the valid
* namespaces always.
*
* @see Namespace#isNamespaceValid(String)
*/
protected String mNamespace;
/**
* The default constructor.
* Note that the map is not allocated memory at this stage. It is done so
* in the overloaded construct function.
*/
public ENV() {
mProfileMap = null;
mNamespace = NAMESPACE_NAME;
}
/**
* The overloaded constructor.
*
* @param mp map (possibly empty).
*/
public ENV(Map mp) {
mProfileMap = new LinkedHashMap(mp);
mNamespace = NAMESPACE_NAME;
}
/**
* Returns the value to which this namespace maps the specified key.
* Returns null if the map contains no mapping for this key. A return value
* of null does not necessarily indicate that the map contains no mapping for
* the key; it's also possible that the map explicitly maps the key to null.
* The containsKey operation may be used to distinguish these two cases.
*
* @param key The key whose value you want.
*
*/
public Object get(Object key){
return ( mProfileMap == null )? null : mProfileMap.get(key);
}
/**
* Returns the name of the namespace associated with the profile implementations.
*
* @return the namespace name.
* @see #NAMESPACE_NAME
*/
public String namespaceName(){
return mNamespace;
}
/**
* Constructs a new element of the format (key=value). It first checks if
* the map has been initialised or not. If not then allocates memory first.
*
* @param key is the left-hand-side
* @param value is the right hand side
*/
public void construct(String key, String value) {
if(mProfileMap == null)
mProfileMap = new LinkedHashMap();
mProfileMap.put(key, value);
}
/**
* This checks whether the key passed by the user is valid in the current
* namespace or not. At present, for this namespace all the keys are
* construed as valid as long as the value passed is not null.
*
* @param key (left hand side)
* @param value (right hand side)
*
* @return Namespace.VALID_KEY
* @return Namespace.NOT_PERMITTED_KEY
*
*/
public int checkKey(String key, String value) {
if(key == null || value == null)
return Namespace.NOT_PERMITTED_KEY;
return Namespace.VALID_KEY;
}
/**
* Converts the contents of the map into the string that can be put in the
* Condor file for printing.
*
* @return String .
*/
public String toCondor() {
StringBuffer st = new StringBuffer();
String key = null;
String value = null;
Iterator it = (mProfileMap == null) ? null: mProfileMap.keySet().iterator();
if(it == null)
return null;
st.append("environment = ");
while(it.hasNext()){
key = (String)it.next();
value = (String)mProfileMap.get(key);
st.append(key).append("=").append(value).append(";");
}
st.append("\n");
return st.toString();
}
/**
* It puts in the namespace specific information specified in the properties
* file into the namespace. The name of the pool is also passed, as many of
* the properties specified in the properties file are on a per pool basis.
*
* @param properties the <code>PegasusProperties</code> object containing
* all the properties that the user specified at various
* places (like .chimerarc, properties file, command line).
* @param pool the pool name where the job is scheduled to run.
*/
public void checkKeyInNS(PegasusProperties properties, String pool){
/*
//get from the properties for pool local
String prop = pool.equalsIgnoreCase("local") ?
//check if property in props file
properties.getLocalPoolEnvVar() :
null;
if (prop != null) {
checkKeyInNS(prop);
}
*/
//retrieve the relevant profiles from properties
//and merge them into the existing.
this.assimilate( properties , Profiles.NAMESPACES.env );
}
/**
* It takes in key=value pairs separated by a ; and puts them into the
* namespace after checking if they are valid or not.
*
* @param envString the String containing the environment variables and
* their values separated by a semi colon.
*/
public void checkKeyInNS(String envString){
//sanity check
if(envString == null)
return;
StringTokenizer st = new StringTokenizer(envString,";");
String name;
String value;
String keyValPair;
while(st.hasMoreTokens()){
keyValPair = (String)st.nextToken(";");
if(keyValPair.trim().equalsIgnoreCase("null")){
return;
}
StringTokenizer st1 = new StringTokenizer(keyValPair);
name = st1.nextToken("=");
value= st1.nextToken();
checkKeyInNS(name,value);
}
}
/**
* Merge the profiles in the namespace in a controlled manner.
* In case of intersection, the new profile value overrides, the existing
* profile value.
*
* @param profiles the <code>Namespace</code> object containing the profiles.
*/
public void merge( Namespace profiles ){
//check if we are merging profiles of same type
if (!(profiles instanceof ENV )){
//throw an error
throw new IllegalArgumentException( "Profiles mismatch while merging" );
}
String key;
for ( Iterator it = profiles.getProfileKeyIterator(); it.hasNext(); ){
//construct directly. bypassing the checks!
key = (String)it.next();
this.construct( key, (String)profiles.get( key ) );
}
}
/**
* Returns a copy of the current namespace object.
*
* @return the Cloned object
*/
public Object clone() {
return ( mProfileMap == null ? new ENV() : new ENV(this.mProfileMap) );
}
}