Skip to content
Snippets Groups Projects
UWSUrl.java 22 KiB
Newer Older
  • Learn to ignore specific revisions
  • package uws.service;
    
    /*
     * This file is part of UWSLibrary.
     * 
     * UWSLibrary is free software: you can redistribute it and/or modify
     * it under the terms of the GNU Lesser General Public License as published by
     * the Free Software Foundation, either version 3 of the License, or
     * (at your option) any later version.
     * 
     * UWSLibrary 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 Lesser General Public License for more details.
     * 
     * You should have received a copy of the GNU Lesser General Public License
     * along with UWSLibrary.  If not, see <http://www.gnu.org/licenses/>.
     * 
    
     * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
    
     *                       Astronomisches Rechen Institut (ARI)
    
     */
    
    import java.io.Serializable;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.util.Map;
    
    import javax.servlet.http.HttpServletRequest;
    
    import uws.UWSToolBox;
    import uws.job.UWSJob;
    
    /**
     * This class helps managing with UWS URLs and URIs.
     * 
    
     * @author Gr&eacute;gory Mantelet (CDS;ARI)
    
     */
    public class UWSUrl implements Serializable {
    	private static final long serialVersionUID = 1L;
    
    	/** The whole request URL (i.e. http://foo.org/mySite/uws/jobList/job1/results/report). */
    	protected String requestURL = null;									// http://cds-dev-gm:8080/uwstuto/basic/timers/job1/results/report
    
    	/** The URL prefix (i.e. http://foo.org/mySite). */
    	protected String urlHeader = null;									// http://cds-dev-gm:8080/uwstuto
    
    	/** The request URI (i.e. /uws/jobList/job1/results/report) */
    	protected String requestURI = null;									// /basic/timers/job1/results/report
    
    	/** Base UWS URI (i.e. /uws). */
    	protected final String baseURI;										// /basic
    
    	/** The URI from the base UWS URI (i.e. /jobList/job1/results/report). */
    	protected String uwsURI = null;										// /timers/job1/results/report
    
    	/** Name of a jobs list found in uwsURI (i.e. jobList). */
    	protected String jobListName = null;								// timers
    
    	/** The JobID found in uwsURI (i.e. job1). */
    	protected String jobId = null;										// job1
    
    	/** Name of the job attribute found in uwsURI (i.e. {results, report}). */
    	protected String[] attributes = new String[0];						// {results, report}
    
    	/* ************ */
    	/* CONSTRUCTORS */
    	/* ************ */
    	/**
    	 * Builds a copy of the given UWSUrl.
    	 * 
    	 * @param toCopy	The UWSUrl to copy.
    	 */
    	public UWSUrl(UWSUrl toCopy){
    		requestURL = toCopy.requestURL;
    		urlHeader = toCopy.urlHeader;
    		requestURI = toCopy.requestURI;
    		baseURI = toCopy.baseURI;
    		uwsURI = toCopy.uwsURI;
    		jobListName = toCopy.jobListName;
    		jobId = toCopy.jobId;
    		attributes = new String[toCopy.attributes.length];
    		System.arraycopy(toCopy.attributes, 0, attributes, 0, attributes.length);
    	}
    
    	/**
    	 * Builds a UWSUrl with a fixed baseURI.
    	 * 
    	 * @param baseURI			The baseURI to consider in all URL or request parsing.
    	 * 
    
    	 * @throws NullPointerException		If the given baseURI is <i>null</i> or is an empty string.
    
    	public UWSUrl(String baseURI) throws NullPointerException{
    
    			throw new NullPointerException("The given base UWS URI is NULL!");
    
    
    		this.baseURI = normalizeURI(baseURI);
    
    		if (baseURI.length() == 0)
    
    			throw new NullPointerException("The given base UWS URI is empty!");
    
    	}
    
    	/**
    	 * Builds a UWSUrl considering the given request to set the baseURI.
    	 * 
    	 * @param request		The request to parse to get the baseURI.
    	 * 
    
    	 * @throws NullPointerException	If the given request is <i>null</i> or if the extracted baseURI is <i>null</i> or is an empty string.
    
    	 * 
    	 * @see #extractBaseURI(HttpServletRequest)
    	 */
    
    	public UWSUrl(HttpServletRequest request) throws NullPointerException{
    
    		String uri = extractBaseURI(request);
    		if (uri == null)
    
    			throw new NullPointerException("The extracted base UWS URI is NULL!");
    
    		// Load the rest of the request:
    		load(request);
    
    	}
    
    	/**
    	 * Extracts the base UWS URI from the given request.
    	 * 
    	 * @param request	The request from which the base UWS URI must be extracted.
    	 * 
    	 * @return			The extracted URI (may be <i>null</i>).
    	 */
    	protected String extractBaseURI(HttpServletRequest request){
    		if (request == null)
    			return null;
    
    		return request.getServletPath();
    	}
    
    	/**
    	 * <p>Normalizes the given URI.</p>
    	 * 
    	 * <p><i><u>Note:</u> A normalized URI always starts with a / and ends with no /.</i></p>
    	 * 
    	 * @param uri	The URI to normalize.
    	 * 
    	 * @return		The normalized URI.
    	 */
    	protected static final String normalizeURI(String uri){
    		uri = uri.trim();
    		if (uri.length() > 0 && uri.charAt(0) != '/')
    
    			uri = "/" + uri;
    		while(uri.length() >= 1 && uri.charAt(uri.length() - 1) == '/')
    			uri = uri.substring(0, uri.length() - 1).trim();
    
    		return uri.trim();
    	}
    
    	/* ************ */
    	/* LOAD METHODS */
    	/* ************ */
    	/**
    	 * <p>Parses and loads the given request.</p>
    	 * 
    	 * <p>
    	 * 	Before all, {@link #extractBaseURI(HttpServletRequest)} is called so that extracting the base URI from the request.
    	 * 	If this URI is different from the URI stored in this UWSUrl, {@link #load(URL)} is called so that parsing only the request URL
    	 * 	and then this method ends immediately.
    	 * </p>
    	 * 
    	 * <p>
    	 * 	Otherwise this method sets its fields as following:
    	 * 	<ul>
    	 * 		<li>requestURL = {@link HttpServletRequest#getRequestURL()}</li>
    	 * 		<li>urlHeader = {@link HttpServletRequest#getScheme()}+"://"+{@link HttpServletRequest#getServerName()}+":"+{@link HttpServletRequest#getServerPort()}+{@link HttpServletRequest#getContextPath()}</li>
    	 * 		<li>requestURI = {@link HttpServletRequest#getRequestURI()}</li>
    	 * 		<li>uwsURI = {@link HttpServletRequest#getPathInfo()}</li>
    	 * 		<li>for jobListName, jobId and attributes, see {@link #loadUwsURI()}</li>
    	 * 	</ul>
    	 * </p>
    	 * 
    	 * <p><i><u>Note:</u> If the given request is NULL, all fields are set to NULL.</i></p>
    	 * 
    	 * @param request	The request to parse and to load.
    	 * 
    	 * @see #extractBaseURI(HttpServletRequest)
    	 * @see #load(URL)
    	 * @see #loadUwsURI()
    	 */
    	public void load(HttpServletRequest request){
    		if (request == null){
    			urlHeader = null;
    			requestURL = null;
    			requestURI = null;
    			uwsURI = null;
    		}else{
    			if (extractBaseURI(request).equalsIgnoreCase(baseURI)){
    				requestURL = request.getRequestURL().toString();
    				urlHeader = (new StringBuffer(request.getScheme())).append("://").append(request.getServerName()).append(":").append(request.getServerPort()).append(request.getContextPath()).toString();
    				requestURI = request.getRequestURI().substring(request.getRequestURI().indexOf(baseURI));
    				uwsURI = request.getPathInfo();
    			}else{
    				URL url = null;
    				try{
    					url = new URL(request.getRequestURL().toString());
    
    				load(url);
    				return;
    			}
    		}
    
    		loadUwsURI();
    	}
    
    	/**
    	 * <p>Parses and loads the given request URL.</p>
    	 * 
    	 * <p>
    	 * 	All the fields are set as following:
    	 * 	<ul>
    	 * 		<li>requestURL = requestUrl.substring(0, requestUrl.indexOf("?")</li>
    	 * 		<li>urlHeader = requestURL.substring(0, requestURL.indexOf(baseURI))</li>
    	 * 		<li>requestURI = requestURL.substring(requestURL.indexOf(baseURI))</li>
    	 * 		<li>uwsURI = requestURI.substring(baseURI.length())</li>
    	 * 		<li>for jobListName, jobId and attributes, see {@link #loadUwsURI()}</li>
    	 * 	</ul>
    	 * </p>
    	 * 
    	 * <p><i><u>Note:</u> If the given URL is NULL, all fields are set to NULL.</i></p>
    	 * 
    	 * @param requestUrl	The URL to parse and to load.
    	 * 
    	 * @see #loadUwsURI()
    	 */
    	public void load(URL requestUrl){
    		if (requestUrl == null){
    			urlHeader = null;
    			requestURL = null;
    			requestURI = null;
    			uwsURI = null;
    		}else{
    			requestURL = requestUrl.toString();
    			if (requestURL.indexOf("?") > 0)
    				requestURL = requestURL.substring(0, requestURL.indexOf("?"));
    
    			int indBaseURI = requestURL.indexOf(baseURI);
    			if (indBaseURI >= 0){
    				urlHeader = requestURL.substring(0, indBaseURI);
    				requestURI = requestURL.substring(indBaseURI);
    				uwsURI = requestURI.substring(baseURI.length());
    			}else{
    				urlHeader = null;
    				requestURI = null;
    				uwsURI = null;
    			}
    		}
    
    		loadUwsURI();
    	}
    
    	/**
    	 * <p>Loads and parses the URI stored in the member {@link #uwsURI}.</p>
    	 * 
    	 * <p>
    	 * 	The URI is split by the / character. The items of the resulting array corresponds to:
    	 * 	<ul>
    	 * 		<li>item 0 = empty (the empty string before the first / of a URI)</li>
    	 * 		<li>item 1 = jobListName</li>
    	 * 		<li>item 2 = jobId</li>
    	 * 		<li>item 3 and more = attributes</li>
    	 * 	</ul>
    	 * </p>
    	 * 
    	 * <p><i><u>Note:</u> If {@link #uwsURI} is NULL, jobListName and jobId are set to null while attributes is set to an empty array.</i></p>
    	 */
    	protected void loadUwsURI(){
    		jobListName = null;
    		jobId = null;
    		attributes = new String[0];
    
    		if (uwsURI != null){
    			// URI normalization: it must always begin with a / but never ends with a / !
    			uwsURI = normalizeURI(uwsURI);
    
    			String[] uriParts = uwsURI.split("/");
    
    			// uwsURI begins always with a / so uriParts[0] is always null !
    
    			if (uriParts.length >= 2){
    				jobListName = uriParts[1].trim();
    				if (jobListName.length() == 0)
    					jobListName = null;
    			}
    
    			if (uriParts.length >= 3){
    				jobId = uriParts[2].trim();
    				if (jobId.length() == 0)
    					jobId = null;
    			}
    
    			if (uriParts.length >= 4){
    
    				attributes = new String[uriParts.length - 3];
    				for(int i = 3; i < uriParts.length; i++)
    					attributes[i - 3] = uriParts[i].trim();
    
    			}
    		}
    	}
    
    	/* ******* */
    	/* GETTERS */
    	/* ******* */
    	/**
    	 * Gets the base UWS URI given at the initialization of this instance of {@link UWSUrl}.
    	 * 
    	 * @return The baseUri.
    	 */
    
    		return baseURI;
    	}
    
    	/**
    	 * Gets the <b>SUPPOSED</b> name of the UWS from its baseURI.
    	 * 
    	 * @return	The presumed UWS name.
    	 */
    	public final String getUWSName(){
    
    		return baseURI.substring(baseURI.lastIndexOf('/') + 1);
    
    	}
    
    	/**
    	 * Gets the request URL.
    	 * 
    	 * @return	The last loaded request URL.
    	 */
    	public final String getRequestURL(){
    		return requestURL;
    	}
    
    	/**
    	 * <p>Gets the URL header of the request URL.</p>
    	 * 
    	 * <p>
    	 * 	<i><u>Example:</u>
    	 * 		If the base URI is "/uws" and the request URL is "http://foo.org/mySite/uws/jobList/job1/results/report", then the URL header will be:
    	 * 		"http://foo.org/mySite".
    	 * 	</i>
    	 * </p>
    	 * 
    	 * @return	The last loaded URL header.
    	 */
    	public final String getUrlHeader(){
    		return urlHeader;
    	}
    
    	/**
    	 * <p>Gets the request URI.</p>
    	 * 
    	 * <p>
    	 * 	<i><u>Example:</u>
    	 * 		If the base URI is "/uws" and the request URL is "http://foo.org/mySite/uws/jobList/job1/results/report", then the request URI will be:
    	 * 		"/uws/jobList/jobId/results/report".
    	 * 	</i>
    	 * </p>
    	 * 
    	 * @return The last loaded request URI.
    	 */
    	public final String getRequestURI(){
    		return requestURI;
    	}
    
    	/**
    	 * <p>Gets the UWS URI.</p>
    	 * 
    	 * <p>
    	 * 	<i><u>Example:</u>
    	 * 		If the base URI is "/uws" and the request URL is "http://foo.org/mySite/uws/jobList/job1/results/report", then the request URI will be:
    	 * 		"/jobList/jobId/results/report".
    	 * 	</i>
    	 * </p>
    	 * 
    	 * @return	The extracted UWS URI.
    	 */
    	public final String getUwsURI(){
    		return uwsURI;
    	}
    
    	/**
    	 * Tells whether the last loaded request or request URL contains a jobs list name.
    	 * 
    	 * @return	<i>true</i> if a jobs list name has been extracted, <i>false</i> otherwise.
    	 */
    	public final boolean hasJobList(){
    		return jobListName != null;
    	}
    
    	/**
    	 * Gets the jobs list name extracted from the last parsed request or request URL.
    	 * 
    	 * @return The extracted jobs list name.
    	 */
    
    		return jobListName;
    	}
    
    	/**
    	 * Tells whether the last loaded request or request URL contains a job ID.
    	 * 
    	 * @return	<i>true</i> if a job ID has been extracted, <i>false</i> otherwise.
    	 */
    	public final boolean hasJob(){
    		return jobId != null;
    	}
    
    	/**
    	 * Gets the job ID extracted from the last parsed request or request URL.
    	 * 
    	 * @return The extracted job ID.
    	 */
    
    		return jobId;
    	}
    
    	/**
    	 * Tells whether the last loaded request or request URL contains at least one job attribute.
    	 * 
    	 * @return	<i>true</i> if at least one job attribute has been extracted, <i>false</i> otherwise.
    	 */
    	public final boolean hasAttribute(){
    		return attributes != null && attributes.length > 0;
    	}
    
    	/**
    	 * Tells whether the last loaded request or request URL contains a job attribute with the given name.
    	 * 
    	 * @param attributeName	The name of the job attribute expected in the last request or request URL.
    	 * 
    	 * @return				<i>true</i> if the specified job attribute has been extracted, <i>false</i> otherwise.
    	 */
    	public final boolean hasAttribute(String attributeName){
    		for(String att : attributes){
    			if (att.equalsIgnoreCase(attributeName))
    				return true;
    		}
    		return false;
    	}
    
    	/**
    	 * Gets all the job attributes extracted from the last request or request URL.
    	 * 
    	 * @return	The extracted job attributes.
    	 */
    	public final String[] getAttributes(){
    		return attributes;
    	}
    
    	/* ******* */
    	/* SETTERS */
    	/* ******* */
    	/**
    	 * <p>Updates the field {@link #uwsURI} in function of {@link #jobListName}, {@link #jobId} and {@link #attributes} as following:
    	 * uwsURI = "/"+jobListName+"/"+jobId+"/"+attributes.</p>
    	 * 
    	 * <p>Once {@link #uwsURI} updated the request URL and URI are also updated.</p>
    	 * 
    	 * @see #updateRequestURL()
    	 */
    	protected void updateUwsURI(){
    		uwsURI = null;
    		if (hasJobList()){
    			StringBuffer uri = new StringBuffer("/");
    			uri.append(jobListName);
    			if (hasJob()){
    				uri.append("/").append(jobId);
    				if (hasAttribute()){
    					for(String att : attributes)
    						uri.append("/").append(att);
    				}
    			}
    			uwsURI = uri.toString();
    		}
    
    		updateRequestURL();
    	}
    
    	/**
    	 * <p>
    	 * 	Updates the fields {@link #requestURI} and {@link #requestURL} as following:
    	 * 	<ul>
    	 * 		<li>requestURI = baseURI+uwsURI</li>
    	 * 		<li>requestURL = urlHeader+requestURI (or <i>null</i> if urlHeader is <i>null</i>)</li>
    	 * 	</ul>
    	 * </p>
    	 */
    	protected void updateRequestURL(){
    
    		requestURI = baseURI + ((uwsURI != null) ? uwsURI : "");
    		requestURL = (urlHeader == null) ? null : (urlHeader + requestURI);
    
    	}
    
    	/**
    	 * Sets the whole UWS URI (that is to say a URI starting with the jobs list name).
    	 * Once done all the other fields of this UWS URL are updated.
    	 * 
    	 * @param uwsURI	The UWS URI to set.
    	 * 
    	 * @see #loadUwsURI()
    	 * @see #updateRequestURL()
    	 */
    	public final void setUwsURI(String uwsURI){
    		if (uwsURI == null || uwsURI.trim().length() == 0)
    			this.uwsURI = null;
    
    			this.uwsURI = uwsURI.trim();
    
    		loadUwsURI();
    		updateRequestURL();
    	}
    
    	/**
    	 * Sets the jobs list name.
    	 * Once done all the other fields of this UWS URL are updated.
    	 * 
    	 * @param jobListName A jobs list name.
    	 * 
    	 * @see #updateUwsURI()
    	 */
    
    	public final void setJobListName(String jobListName){
    
    		this.jobListName = jobListName;
    		updateUwsURI();
    	}
    
    	/**
    	 * Sets the job ID.
    	 * Once done all the other fields of this UWS URL are updated.
    	 * 
    	 * @param jobId	A job ID.
    	 * 
    	 * @see #updateUwsURI()
    	 */
    
    		this.jobId = jobId;
    		updateUwsURI();
    	}
    
    	/**
    	 * <p>Sets all the job attributes.
    	 * Once done all the other fields of this UWS URL are updated.</p>
    	 * 
    	 * <p><i><u>Note:</u> The given array is entirely copied.</i></p>
    	 * 
    	 * @param newAttributes	The new job attributes.
    	 * 
    	 * @see #updateUwsURI()
    	 */
    	public final void setAttributes(String[] newAttributes){
    		if (newAttributes == null)
    			attributes = new String[0];
    
    		attributes = new String[newAttributes.length];
    		System.arraycopy(newAttributes, 0, attributes, 0, attributes.length);
    
    		updateUwsURI();
    	}
    
    	/* ******************** */
    	/* URL BUILDING METHODS */
    	/* ******************** */
    	/** Gets the base UWS URI = UWS home page. */
    
    		UWSUrl url = new UWSUrl(this);
    		url.setUwsURI(null);
    		return url;
    	}
    
    	/** Gets the UWS URL to get the specified <b>jobs list</b>. */
    
    	public final UWSUrl listJobs(String jobListName){
    		UWSUrl url = homePage();
    		url.setJobListName(jobListName);
    		return url;
    	}
    
    
    	/** Gets the UWS URL to get the <b>summary</b>. */
    
    	public final UWSUrl jobSummary(String jobListName, String jobId){
    		UWSUrl url = listJobs(jobListName);
    		url.setJobId(jobId);
    		return url;
    	}
    
    
    	/** Gets the UWS URL to get the <b>runID</b>. */
    
    	public final UWSUrl jobName(String jobListName, String jobId){
    		UWSUrl url = jobSummary(jobListName, jobId);
    		url.setAttributes(new String[]{UWSJob.PARAM_RUN_ID});
    		return url;
    	}
    
    
    	/** Gets the UWS URL to get the <b>phase</b>. */
    
    	public final UWSUrl jobPhase(String jobListName, String jobId){
    		UWSUrl url = jobSummary(jobListName, jobId);
    		url.setAttributes(new String[]{UWSJob.PARAM_PHASE});
    		return url;
    	}
    
    
    	/** Gets the UWS URL to get the <b>execution duration</b>. */
    
    	public final UWSUrl jobExecDuration(String jobListName, String jobId){
    		UWSUrl url = jobSummary(jobListName, jobId);
    		url.setAttributes(new String[]{UWSJob.PARAM_EXECUTION_DURATION});
    		return url;
    	}
    
    
    	/** Gets the UWS URL to get the <b>destruction time</b>. */
    
    	public final UWSUrl jobDestruction(String jobListName, String jobId){
    		UWSUrl url = jobSummary(jobListName, jobId);
    		url.setAttributes(new String[]{UWSJob.PARAM_DESTRUCTION_TIME});
    		return url;
    	}
    
    
    	/** Gets the UWS URL to get the <b>error summary</b>. */
    
    	public final UWSUrl jobError(String jobListName, String jobId){
    		UWSUrl url = jobSummary(jobListName, jobId);
    		url.setAttributes(new String[]{UWSJob.PARAM_ERROR_SUMMARY});
    		return url;
    	}
    
    
    	/** Gets the UWS URL to get the <b>quote</b>. */
    
    	public final UWSUrl jobQuote(String jobListName, String jobId){
    		UWSUrl url = jobSummary(jobListName, jobId);
    		url.setAttributes(new String[]{UWSJob.PARAM_QUOTE});
    		return url;
    	}
    
    
    	/** Gets the UWS URL to get the <b>results</b>. */
    
    	public final UWSUrl jobResults(String jobListName, String jobId){
    		UWSUrl url = jobSummary(jobListName, jobId);
    		url.setAttributes(new String[]{UWSJob.PARAM_RESULTS});
    		return url;
    	}
    
    
    	/** Gets the UWS URL to get the <b>specified result</b>. */
    
    	public final UWSUrl jobResult(String jobListName, String jobId, String resultId){
    		UWSUrl url = jobSummary(jobListName, jobId);
    		url.setAttributes(new String[]{UWSJob.PARAM_RESULTS,resultId});
    		return url;
    	}
    
    
    	/** Gets the UWS URL to get the <b>parameters</b>. */
    
    	public final UWSUrl jobParameters(String jobListName, String jobId){
    		UWSUrl url = jobSummary(jobListName, jobId);
    		url.setAttributes(new String[]{UWSJob.PARAM_PARAMETERS});
    		return url;
    	}
    
    
    	/** Gets the UWS URL to get the <b>parameters/parameter</b>. */
    
    	public final UWSUrl jobParameter(String jobListName, String jobId, String paramName){
    		UWSUrl url = jobSummary(jobListName, jobId);
    		url.setAttributes(new String[]{UWSJob.PARAM_PARAMETERS,paramName});
    		return url;
    	}
    
    
    	/** Gets the UWS URL to get the <b>owner ID</b>. */
    
    	public final UWSUrl jobOwner(String jobListName, String jobId){
    		UWSUrl url = jobSummary(jobListName, jobId);
    		url.setAttributes(new String[]{UWSJob.PARAM_OWNER});
    		return url;
    	}
    
    
    	/* ******************************* */
    	/* URL BUILDING METHODS (HTTP GET) */
    	/* ******************************* */
    	/** Gets the UWS URL <b>(HTTP-GET ONLY)</b> to <b>create</b> a job with the given parameters. */
    
    	public final String createJob(String jobListName, Map<String,String> parameters){
    		return listJobs(jobListName) + "?" + UWSToolBox.getQueryPart(parameters);
    	}
    
    
    	/** Gets the UWS URL <b>(HTTP-GET ONLY)</b> to <b>delete</b> the specified job. */
    
    	public final String deleteJob(String jobListName, String jobId){
    		return jobSummary(jobListName, jobId) + "?" + UWSJob.PARAM_ACTION + "=" + UWSJob.ACTION_DELETE;
    	}
    
    
    	/** Gets the UWS URL <b>(HTTP-GET ONLY)</b> to <b>start</b> the specified job. */
    
    	public final String startJob(String jobListName, String jobId){
    		return jobPhase(jobListName, jobId) + "?" + UWSJob.PARAM_PHASE.toUpperCase() + "=" + UWSJob.PHASE_RUN;
    	}
    
    
    	/** Gets the UWS URL <b>(HTTP-GET ONLY)</b> to <b>abort</b> the specified job. */
    
    	public final String abortJob(String jobListName, String jobId){
    		return jobPhase(jobListName, jobId) + "?" + UWSJob.PARAM_PHASE.toUpperCase() + "=" + UWSJob.PHASE_ABORT;
    	}
    
    
    	/** Gets the UWS URL <b>(HTTP-GET ONLY)</b> to change the run ID. */
    
    	public final String changeJobName(String jobListName, String jobId, String newName){
    		return jobName(jobListName, jobId) + "?" + UWSJob.PARAM_RUN_ID.toUpperCase() + "=" + newName;
    	}
    
    
    	/** Gets the UWS URL <b>(HTTP-GET ONLY)</b> to change the destruction time. */
    
    	public final String changeDestructionTime(String jobListName, String jobId, String newDestructionTime){
    		return jobDestruction(jobListName, jobId) + "?" + UWSJob.PARAM_DESTRUCTION_TIME.toUpperCase() + "=" + newDestructionTime;
    	}
    
    
    	/** Gets the UWS URL <b>(HTTP-GET ONLY)</b> to change the execution duration. */
    
    	public final String changeExecDuration(String jobListName, String jobId, String newExecDuration){
    		return jobExecDuration(jobListName, jobId) + "?" + UWSJob.PARAM_EXECUTION_DURATION.toUpperCase() + "=" + newExecDuration;
    	}
    
    
    	/** Gets the UWS URL <b>(HTTP-GET ONLY)</b> to change the specified parameter. */
    
    	public final String changeJobParam(String jobListName, String jobId, String paramName, String paramValue){
    		return jobParameters(jobListName, jobId) + "?" + paramName.toUpperCase() + "=" + paramValue;
    	}
    
    
    	/**
    	 * Gets the full request URL corresponding to this UWSUrl.
    	 * 
    	 * @return	The corresponding request URL.
    	 * 
    	 * @throws MalformedURLException If there is an error while building the URL object from the {@link #requestURL} field.
    	 * 
    	 * @see #getRequestURL()
    	 */
    
    	public URL toURL() throws MalformedURLException{
    
    		String url = getRequestURL();
    		return (url != null) ? (new URL(url)) : null;
    	}
    
    	/**
    	 * Gets the full request URI corresponding to this UWSUrl.
    	 * 
    	 * @return	The corresponding request URI.
    	 * 
    	 * @see #getRequestURI()
    	 */
    	public String toURI(){
    		return getRequestURI();
    	}
    
    	/**
    	 * Gets the corresponding request URL.
    	 * 
    	 * @see #getRequestURL()
    	 * @see java.lang.Object#toString()
    	 */
    	@Override
    	public String toString(){
    		return getRequestURL();
    	}
    
    }