Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package uws.job.serializer;
/*
* 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 - UDS/Centre de Données astronomiques de Strasbourg (CDS)
*/
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Iterator;
import uws.UWSException;
import uws.job.ErrorSummary;
import uws.job.JobList;
import uws.job.Result;
import uws.job.UWSJob;
import uws.job.user.JobOwner;
import uws.service.UWS;
import uws.service.UWSUrl;
/**
* Lets serializing any UWS resource in XML.
*
* @author Grégory Mantelet (CDS)
* @version 05/2012
*/
public class XMLSerializer extends UWSSerializer {
private static final long serialVersionUID = 1L;
/** Tab to add just before each next XML node. */
protected String tabPrefix = "";
/** The path of the XSLT style-sheet. */
protected String xsltPath = null;
/**
* Builds a XML serializer.
*/
gmantele
committed
public XMLSerializer(){
;
}
/**
* Builds a XML serializer with a XSLT link.
*
* @param xsltPath Path of a XSLT style-sheet.
*/
public XMLSerializer(final String xsltPath){
this.xsltPath = xsltPath;
}
/**
* Gets the path/URL of the XSLT style-sheet to use.
*
* @return XSLT path/url.
*/
public final String getXSLTPath(){
return xsltPath;
}
/**
* Sets the path/URL of the XSLT style-sheet to use.
*
* @param path The new XSLT path/URL.
*/
public final void setXSLTPath(final String path){
gmantele
committed
if (path == null)
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
xsltPath = null;
else{
xsltPath = path.trim();
if (xsltPath.isEmpty())
xsltPath = null;
}
}
/**
* <p>Gets the XML file header (xml version, encoding and the xslt style-sheet link if any).</p>
* <p>It is always called by the implementation of the UWSSerializer functions
* if their boolean parameter (<i>root</i>) is <i>true</i>.</p>
*
* @return The XML file header.
*/
public String getHeader(){
StringBuffer xmlHeader = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
if (xsltPath != null)
xmlHeader.append("<?xml-stylesheet type=\"text/xsl\" href=\"").append(escapeXMLAttribute(xsltPath)).append("\"?>\n");
return xmlHeader.toString();
}
/**
* Gets all UWS namespaces declarations needed for an XML representation of a UWS object.
*
* @return The UWS namespaces: <br /> (i.e. <i>= "xmlns:uws=[...] xmlns:xlink=[...] xmlns:xs=[...] xmlns:xsi=[...]"</i>).
*/
public String getUWSNamespace(){
return "xmlns:uws=\"http://www.ivoa.net/xml/UWS/v1.0\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"";
}
/**
* Gets the node attributes which declare the UWS namespace.
*
* @param root <i>false</i> if the attribute to serialize will be included
* in a top level serialization (for a job attribute: job), <i>true</i> otherwise.
*
* @return "" if <i>root</i> is <i>false</i>, " "+UWSNamespace otherwise.
*
* @see #getUWSNamespace()
*/
protected final String getUWSNamespace(boolean root){
if (root)
gmantele
committed
return " " + getUWSNamespace();
else
return "";
}
@Override
public final String getMimeType(){
return MIME_TYPE_XML;
}
@Override
gmantele
committed
public String getUWS(final UWS uws, final JobOwner user){
String name = uws.getName(), description = uws.getDescription();
StringBuffer xml = new StringBuffer(getHeader());
xml.append("<uws").append(getUWSNamespace(true));
gmantele
committed
if (name != null)
xml.append(" name=\"").append(escapeXMLAttribute(name)).append("\"");
xml.append(">\n");
if (description != null)
xml.append("\t<description>\n").append(escapeXMLData(description)).append("\n\t</description>\n");
xml.append("\t<jobLists>\n");
for(JobList jobList : uws){
UWSUrl jlUrl = jobList.getUrl();
xml.append("\t\t<jobListRef name=\"").append(escapeXMLAttribute(jobList.getName())).append("\" href=\"");
gmantele
committed
if (jlUrl != null && jlUrl.getRequestURL() != null)
gmantele
committed
xml.append(escapeURL(jlUrl.getRequestURL()));
xml.append("\" />\n");
}
xml.append("\t</jobLists>\n");
xml.append("</uws>\n");
return xml.toString();
}
@Override
gmantele
committed
public String getJobList(final JobList jobsList, final JobOwner owner, final boolean root) throws UWSException{
String name = jobsList.getName();
StringBuffer xml = new StringBuffer(getHeader());
xml.append("<uws:jobList").append(getUWSNamespace(true));
if (name != null)
xml.append(" name=\"").append(escapeXMLAttribute(name)).append("\"");
xml.append(">");
UWSUrl jobsListUrl = jobsList.getUrl();
Iterator<UWSJob> it = jobsList.getJobs(owner);
while(it.hasNext())
xml.append("\n\t").append(getJobRef(it.next(), jobsListUrl));
xml.append("\n</uws:jobList>");
return xml.toString();
}
@Override
gmantele
committed
public String getJob(final UWSJob job, final boolean root){
StringBuffer xml = new StringBuffer(root ? getHeader() : "");
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
String newLine = "\n\t";
// general information:
xml.append("<uws:job").append(getUWSNamespace(root)).append(">");
xml.append(newLine).append(getJobID(job, false));
xml.append(newLine).append(getRunID(job, false));
xml.append(newLine).append(getOwnerID(job, false));
xml.append(newLine).append(getPhase(job, false));
xml.append(newLine).append(getQuote(job, false));
xml.append(newLine).append(getStartTime(job, false));
xml.append(newLine).append(getEndTime(job, false));
xml.append(newLine).append(getExecutionDuration(job, false));
xml.append(newLine).append(getDestructionTime(job, false));
tabPrefix = "\t";
newLine = "\n";
// parameters:
xml.append(newLine).append(getAdditionalParameters(job, false));
// results:
xml.append(newLine).append(getResults(job, false));
// errorSummary:
xml.append(newLine).append(getErrorSummary(job.getErrorSummary(), false));
tabPrefix = "";
return xml.append("\n</uws:job>").toString();
}
@Override
public String getJobRef(final UWSJob job, final UWSUrl jobsListUrl){
String url = null;
if (jobsListUrl != null){
jobsListUrl.setJobId(job.getJobId());
url = jobsListUrl.getRequestURL();
}
StringBuffer xml = new StringBuffer("<uws:jobRef id=\"");
xml.append(escapeXMLAttribute(job.getJobId()));
if (job.getRunId() != null && job.getRunId().length() > 0)
xml.append("\" runId=\"").append(escapeXMLAttribute(job.getRunId()));
xml.append("\" xlink:href=\"");
gmantele
committed
if (url != null)
xml.append(escapeURL(url));
xml.append("\">").append(getPhase(job, false)).append("</uws:jobRef>");
return xml.toString();
}
@Override
gmantele
committed
public String getJobID(final UWSJob job, final boolean root){
return (new StringBuffer(root ? getHeader() : "")).append("<uws:jobId").append(getUWSNamespace(root)).append(">").append(escapeXMLData(job.getJobId())).append("</uws:jobId>").toString();
}
@Override
gmantele
committed
public String getRunID(final UWSJob job, final boolean root){
StringBuffer xml = new StringBuffer(root ? getHeader() : "");
xml.append("<uws:runId").append(getUWSNamespace(root));
if (job.getRunId() == null)
xml.append(" xsi:nil=\"true\" />");
else
xml.append(">").append(escapeXMLData(job.getRunId())).append("</uws:runId>");
return xml.toString();
}
@Override
gmantele
committed
public String getOwnerID(final UWSJob job, final boolean root){
StringBuffer xml = new StringBuffer(root ? getHeader() : "");
xml.append("<uws:ownerId").append(getUWSNamespace(root));
if (job.getOwner() == null)
xml.append(" xsi:nil=\"true\" />");
else
xml.append(">").append(escapeXMLData(job.getOwner().getPseudo())).append("</uws:ownerId>");
return xml.toString();
}
@Override
gmantele
committed
public String getPhase(final UWSJob job, final boolean root){
return (new StringBuffer(root ? getHeader() : "")).append("<uws:phase").append(getUWSNamespace(root)).append(">").append(job.getPhase()).append("</uws:phase>").toString();
}
@Override
gmantele
committed
public String getQuote(final UWSJob job, final boolean root){
StringBuffer xml = new StringBuffer(root ? getHeader() : "");
xml.append("<uws:quote").append(getUWSNamespace(root));
if (job.getQuote() <= 0)
xml.append(" xsi:nil=\"true\" />");
else
xml.append(">").append(job.getQuote()).append("</uws:quote>");
return xml.toString();
}
@Override
gmantele
committed
public String getStartTime(final UWSJob job, final boolean root){
StringBuffer xml = new StringBuffer(root ? getHeader() : "");
xml.append("<uws:startTime").append(getUWSNamespace(root));
if (job.getStartTime() == null)
xml.append(" xsi:nil=\"true\" />");
else
xml.append(">").append(UWSJob.dateFormat.format(job.getStartTime())).append("</uws:startTime>");
return xml.toString();
}
@Override
gmantele
committed
public String getEndTime(final UWSJob job, final boolean root){
StringBuffer xml = new StringBuffer(root ? getHeader() : "");
xml.append("<uws:endTime").append(getUWSNamespace(root));
if (job.getEndTime() == null)
xml.append(" xsi:nil=\"true\" />");
else
xml.append(">").append(UWSJob.dateFormat.format(job.getEndTime())).append("</uws:endTime>");
return xml.toString();
}
@Override
gmantele
committed
public String getDestructionTime(final UWSJob job, final boolean root){
StringBuffer xml = new StringBuffer(root ? getHeader() : "");
xml.append("<uws:destruction").append(getUWSNamespace(root));
if (job.getDestructionTime() == null)
xml.append(" xsi:nil=\"true\" />");
else
xml.append(">").append(UWSJob.dateFormat.format(job.getDestructionTime())).append("</uws:destruction>");
return xml.toString();
}
@Override
gmantele
committed
public String getExecutionDuration(final UWSJob job, final boolean root){
return (new StringBuffer(root ? getHeader() : "")).append("<uws:executionDuration").append(getUWSNamespace(root)).append(">").append(job.getExecutionDuration()).append("</uws:executionDuration>").toString();
}
@Override
gmantele
committed
public String getErrorSummary(final ErrorSummary error, final boolean root){
StringBuffer xml = new StringBuffer(root ? getHeader() : "");
xml.append(tabPrefix).append("<uws:errorSummary").append(getUWSNamespace(root));
if (error != null){
xml.append(" type=\"").append(error.getType()).append("\"").append(" hasDetail=\"").append(error.hasDetail()).append("\">");
xml.append("\n\t").append(tabPrefix).append("<uws:message>").append(escapeXMLData(error.getMessage())).append("</uws:message>");
xml.append("\n").append(tabPrefix).append("</uws:errorSummary>");
}else
xml.append(" xsi:nil=\"true\" />");
return xml.toString();
}
@Override
gmantele
committed
public String getAdditionalParameters(final UWSJob job, final boolean root){
StringBuffer xml = new StringBuffer(root ? getHeader() : "");
xml.append(tabPrefix).append("<uws:parameters").append(getUWSNamespace(root)).append(">");
gmantele
committed
String newLine = "\n\t" + tabPrefix;
for(String paramName : job.getAdditionalParameters())
xml.append(newLine).append(getAdditionalParameter(paramName, job.getAdditionalParameterValue(paramName), false));
xml.append("\n").append(tabPrefix).append("</uws:parameters>");
return xml.toString();
}
@Override
gmantele
committed
public String getAdditionalParameter(final String paramName, final Object paramValue, final boolean root){
if (paramName != null && paramValue != null){
if (root)
return paramValue.toString();
else
return (new StringBuffer("<uws:parameter")).append(getUWSNamespace(root)).append(" id=\"").append(escapeXMLAttribute(paramName)).append("\">").append(escapeXMLData(paramValue.toString())).append("</uws:parameter>").toString();
}else
return "";
}
@Override
gmantele
committed
public String getResults(final UWSJob job, final boolean root){
StringBuffer xml = new StringBuffer(root ? getHeader() : "");
xml.append(tabPrefix).append("<uws:results").append(getUWSNamespace(root)).append(">");
Iterator<Result> it = job.getResults();
gmantele
committed
String newLine = "\n\t" + tabPrefix;
while(it.hasNext())
xml.append(newLine).append(getResult(it.next(), false));
xml.append("\n").append(tabPrefix).append("</uws:results>");
return xml.toString();
}
@Override
gmantele
committed
public String getResult(final Result result, final boolean root){
StringBuffer xml = new StringBuffer(root ? getHeader() : "");
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
xml.append("<uws:result").append(getUWSNamespace(root)).append(" id=\"").append(escapeXMLAttribute(result.getId())).append("\"");
if (result.getHref() != null){
if (result.getType() != null)
xml.append(" xlink:type=\"").append(escapeXMLAttribute(result.getType())).append("\"");
xml.append(" xlink:href=\"").append(escapeURL(result.getHref())).append("\"");
}
if (result.getMimeType() != null)
xml.append(" mime=\"").append(escapeXMLAttribute(result.getMimeType())).append("\"");
if (result.getSize() >= 0)
xml.append(" size=\"").append(result.getSize()).append("\"");
return xml.append(" />").toString();
}
/* ************** */
/* ESCAPE METHODS */
/* ************** */
/**
* <p>Escapes the content of a node (data between the open and the close tags).</p>
*
* <p><i>By default: surrounds the given data by "<![CDATA[" and "]]>".</i></p>
*
* @param data Data to escape.
*
* @return Escaped data.
*/
public static String escapeXMLData(final String data){
gmantele
committed
return "<![CDATA[" + data + "]]>";
}
/**
* Escapes the given value of an XML attribute.
*
* @param value Value of an XML attribute.
*
* @return The escaped value.
*/
public static String escapeXMLAttribute(final String value){
StringBuffer encoded = new StringBuffer();
gmantele
committed
for(int i = 0; i < value.length(); i++){
char c = value.charAt(i);
switch(c){
gmantele
committed
case '&':
encoded.append("&");
break;
case '<':
encoded.append("<");
break;
case '>':
encoded.append(">");
break;
case '"':
encoded.append(""");
break;
case '\'':
encoded.append("'");
break;
default:
encoded.append(c);
}
}
return encoded.toString();
}
/**
* Escapes the given URL.
*
* @param url URL to escape.
*
* @return The escaped URL.
*
* @see URLEncoder
* @see #escapeXMLAttribute(String)
*/
public static String escapeURL(final String url){
gmantele
committed
try{
return URLEncoder.encode(url, "UTF-8");
gmantele
committed
}catch(UnsupportedEncodingException e){