D. How to customize a UWS ?
5. UWS URL Interpretation
In this library there is one very usefull and important class: UWSUrl. Indeed it is used each time a URL of a UWS must be interpreted and/or generated. So you should be very carefull if you want to customize it ! So that helping you in the customization, you will find below some explanations about the way a UWS URL is represented by this kind of object.
URL splitting
As said in the IVOA Recommendation all UWS URIs must be built in a hierarchical manner, according to REST. UWSUrl splits and generates URLs in the same way. Below are two schemas: the left schema describes the way UWS URLs are split by UWSUrl ; the right schema shows the splitting of a UWS URL example:
The base URI (in bold and red in the example) is used as separator between the URL header and the UWS URI. It is the key of the URL splitting in this class. It is required for any URL interpretation or generation !
Thus you can create a UWSUrl directly with the base URI (or a URL) or by copying another UWSUrl. Besides it can also be extracted automatically from a HttpServletRequest object thanks to the function getServletPath(). This path is set in the web.xml file of your servlet:
By default, the UWS URL interpreter of an AbstractUWS is initialized with the first received request. No interpreter exists before that ! However you can set one at any moment with the method setUrlInterpreter(UWSUrl).
URL interpretation
Once the base URI is known, you can use load(URL) or load(HttpServletRequest) to load and to interpret respectively a URL or a request. The two functions return always the same result except for the URL header which may be more complete with a request.
Note:
In load(HttpServletRequest), the base URI is always extracted from the given request and is then compared to the one stored in this class. If they are different nothing is done except calling load(URL).
Each part of the URL can be retrieved individually thanks to its corresponding getter function (i.e. getUwsURI(), getJobListName(), getJobId(), ...). Besides you can also know if some parts are valued or not: hasJobList() tells whether the UWS URL indicates at least a job list name, hasJob() tells the same thing but about a job ID, ...
getUWSName() returns the presumed name of the UWS. This "name" is the last item of the base URI. However it may not be the real name of the UWS which can be set at any moment with AbstractUWS.setName(String). Actually getUWSName() is only used by AbstractUWS.getName() to returns a default value.
URL generation
UWS URLs can be generated in two ways: by modifying the current instance of a UWSUrl or by using it as a base for a new UWSUrl.
a. With modification
A UWSUrl object can be updated thanks to its setter methods. But contrary to the getters, setters exist only for the UWS URI part (part of the request URL which starts just after the base URI).
Lets take an example ! Supposing we have created a UWSUrl object named uwsUrl with /basic as base URI. It has been initialized with a UWS URL which lets getting the additional parameter time of the job 1298904240779A. Then only the job ID of the UWS URL is modified thanks to setJobId(String). Here is the corresponding code:
UWSUrl uwsUrl = new UWSUrl("/basic"); uwsUrl.load(new URL("http://saada.u-strasbg.fr/uwstuto/basic/timers/1298904240779A/parameters/time")); System.out.println("BEFORE MODIFICATION:"); UWSToolBox.printURL(uwsUrl); uwsUrl.setJobId("1298971587132A"); System.out.println("AFTER MODIFICATION:"); UWSToolBox.printURL(uwsUrl);
And the result is:
BEFORE MODIFICATION: ***** UWS_URL (/basic) ***** Request URL: http://saada.u-strasbg.fr/uwstuto/basic/timers/1298904240779A/parameters/time Request URI: /basic/timers/1298904240779A/parameters/time UWS URI: /timers/1298904240779A/parameters/time Job List: timers Job ID: 1298904240779A Attributes (2): parameters time AFTER MODIFICATION: ***** UWS_URL (/basic) ***** Request URL: http://saada.u-strasbg.fr/uwstuto/basic/timers/1298971587132A/parameters/time Request URI: /basic/timers/1298971587132A/parameters/time UWS URI: /timers/1298971587132A/parameters/time Job List: timers Job ID: 1298971587132A Attributes (2): parameters time
As you can notice only the job ID has been changed. Indeed when using a such function all the other parts of the main request URL are automatically updated.
Notes:
- As shown in the above example, you can use the function UWSToolBox.printURL(UWSUrl) to display the content of a UWSUrl.
- Rather than setting individually each part of a UWS URI you can set the whole URI thanks to the method setUwsURI(String) !
b. Without modification
To avoid modifying a UWSUrl object you have three solutions:
- To create a new UWSUrl() and to initialize it with a base URI and any request URL you want. (warning: the base URI must be contained in the URL !)
- To make a copy of an existing UWSUrl() object (thanks to the constructor UWSUrl(UWSUrl)) and to use the methods described above, directly on the copy.
- To use one of the following methods which return a modified copy of the current
UWSUrl() instance:
- homePage()
- listJobs(String jobListName)
- jobSummary(String jobListName, String jobId)
- jobName(String jobListName, String jobId)
- jobPhase(String jobListName, String jobId)
- jobExecDuration(String jobListName, String jobId)
- jobDestruction(String jobListName, String jobId)
- jobError(String jobListName, String jobId)
- jobQuote(String jobListName, String jobId)
- jobResults(String jobListName, String jobId)
- jobResult(String jobListName, String jobId, String resultId)
- jobParameters(String jobListName, String jobId)
- jobParameters(String jobListName, String jobId, String paramName)
- jobOwner(String jobListName, String jobId)
Warning:
The following methods lets generating a URL corresponding to an action on a JobList or a Job:
- createJob(String jobList, Map params)
- deleteJob(String jobList, String jobId)
- startJob(String jobList, String jobId)
- abortJob(String jobList, String jobId)
- changeJobName(String jobList, String jobId, String newName)
- changeDestructionTime(String jobList, String jobId, String newDate)
- changeExecDuration(String jobList, String jobId, String newDuration)
- changeJobParam(String jobList, String jobId, String paramName, String paramValue)
Since these actions needs to add some HTTP parameters, all these methods return a String which corresponds to the final request URL.
Besides they are designed for a HTTP-GET request rather than HTTP-POST. But you can use these functions and then call UWSToolBox.getParameters(String queryPart) to extract the HTTP-GET parameters into a Map. Then you can use the URL and the parameters map to send a HTTP-POST request through a servlet.
How to customize ?
By default the base URI is extracted from a HttpServletRequest by extractBaseURI(HttpServletRequest). This function only calls HttpServletRequest.getServletPath(). Consequently if you want to change the extraction of this URI, you just have to override extractBaseURI(HttpServletRequest).
However if you intend to change the URL splitting or the whole UWS URL structure, you will have to override all the other functions:
-
load(HttpServletRequest)
and load(URL):
They both fetch the request URI and the UWS URI. Then they call loadUwsURI().
-
loadUwsURI():
extracts all parts (jobListName, jobId and attributes) of the stored UWS URI.
-
updateUwsURI():
updates the UWS URI with the stored job list name, job ID and attributes. At the end, updateRequestURL() is called.
-
updateRequestURL():
updates the request URL and URI with the stored UWS URI, base URI and URL header.
One more time, this class is very important and you should take care of any of your modifications ! By the way I hope the UML class diagram opposite will help you to better understand this class and to extend it if needed.