gvsig-raster / org.gvsig.raster.wmts / trunk / org.gvsig.raster.wmts / org.gvsig.raster.wmts.ogc / org.gvsig.raster.wmts.ogc.impl / src / main / java / org / gvsig / raster / wmts / ogc / impl / base / WMTSProtocolHandler.java @ 4175
History | View | Annotate | Download (24.3 KB)
1 |
/* gvSIG. Geographic Information System of the Valencian Government
|
---|---|
2 |
*
|
3 |
* Copyright (C) 2007-2008 Infrastructures and Transports Department
|
4 |
* of the Valencian Government (CIT)
|
5 |
*
|
6 |
* This program is free software; you can redistribute it and/or
|
7 |
* modify it under the terms of the GNU General Public License
|
8 |
* as published by the Free Software Foundation; either version 2
|
9 |
* of the License, or (at your option) any later version.
|
10 |
*
|
11 |
* This program is distributed in the hope that it will be useful,
|
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14 |
* GNU General Public License for more details.
|
15 |
*
|
16 |
* You should have received a copy of the GNU General Public License
|
17 |
* along with this program; if not, write to the Free Software
|
18 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
19 |
* MA 02110-1301, USA.
|
20 |
*
|
21 |
*/
|
22 |
package org.gvsig.raster.wmts.ogc.impl.base; |
23 |
|
24 |
import java.io.BufferedOutputStream; |
25 |
import java.io.ByteArrayInputStream; |
26 |
import java.io.DataInputStream; |
27 |
import java.io.DataOutputStream; |
28 |
import java.io.File; |
29 |
import java.io.FileInputStream; |
30 |
import java.io.FileOutputStream; |
31 |
import java.io.FileReader; |
32 |
import java.io.IOException; |
33 |
import java.net.HttpURLConnection; |
34 |
import java.net.MalformedURLException; |
35 |
import java.net.URL; |
36 |
import java.nio.ByteBuffer; |
37 |
import java.nio.channels.FileChannel; |
38 |
import java.security.KeyManagementException; |
39 |
import java.security.NoSuchAlgorithmException; |
40 |
import java.util.ArrayList; |
41 |
import java.util.Hashtable; |
42 |
import java.util.List; |
43 |
import java.util.StringTokenizer; |
44 |
import java.util.prefs.Preferences; |
45 |
|
46 |
import javax.net.ssl.HttpsURLConnection; |
47 |
import javax.net.ssl.SSLContext; |
48 |
import javax.net.ssl.TrustManager; |
49 |
import javax.net.ssl.X509TrustManager; |
50 |
|
51 |
import org.gvsig.compat.CompatLocator; |
52 |
import org.gvsig.compat.net.Downloader; |
53 |
import org.gvsig.compat.net.ICancellable; |
54 |
import org.gvsig.gui.beans.incrementabletask.IncrementableProcess; |
55 |
import org.gvsig.raster.wmts.ogc.WMTSStatus; |
56 |
import org.gvsig.raster.wmts.ogc.exception.DownloadException; |
57 |
import org.gvsig.raster.wmts.ogc.exception.ServerErrorException; |
58 |
import org.gvsig.raster.wmts.ogc.exception.WMTSException; |
59 |
import org.gvsig.raster.wmts.ogc.impl.Tags; |
60 |
import org.gvsig.raster.wmts.ogc.impl.Utilities; |
61 |
import org.gvsig.raster.wmts.ogc.impl.request.WMTSGetCapabilitiesRequest; |
62 |
import org.gvsig.raster.wmts.ogc.impl.request.WMTSGetFeatureInfoRequest; |
63 |
import org.gvsig.raster.wmts.ogc.impl.request.WMTSGetTileRequest; |
64 |
import org.gvsig.raster.wmts.ogc.struct.WMTSLayer; |
65 |
import org.gvsig.raster.wmts.ogc.struct.WMTSOperationsMetadata; |
66 |
import org.gvsig.raster.wmts.ogc.struct.WMTSStyle; |
67 |
import org.kxml2.io.KXmlParser; |
68 |
import org.slf4j.Logger; |
69 |
import org.slf4j.LoggerFactory; |
70 |
import org.xmlpull.v1.XmlPullParserException; |
71 |
|
72 |
/**
|
73 |
* <p> Abstract class that represents handlers to comunicate via WMS protocol.</p>
|
74 |
*
|
75 |
* @author Nacho Brodin (nachobrodin@gmail.com)
|
76 |
*/
|
77 |
public abstract class WMTSProtocolHandler { |
78 |
private static final Logger logger = LoggerFactory |
79 |
.getLogger(WMTSProtocolHandler.class); |
80 |
|
81 |
protected static final Downloader downloader = CompatLocator.getDownloader(); |
82 |
/**
|
83 |
* Encoding used to parse different xml documents.
|
84 |
*/
|
85 |
protected String encoding = "UTF-8"; |
86 |
private static int count = 0; |
87 |
final String tempDirectoryPath = System.getProperty("java.io.tmpdir")+"/tmp-andami"; |
88 |
protected boolean forceChangeAxisOrder = false; |
89 |
protected String name; |
90 |
protected String version; |
91 |
protected String host; |
92 |
protected String port; |
93 |
private WMTSServerDescription serverDescription = null; |
94 |
|
95 |
protected abstract WMTSGetFeatureInfoRequest createGetFeatureInfoRequest(WMTSStatusImpl status, int x, int y); |
96 |
|
97 |
protected abstract WMTSGetTileRequest createGetTileRequest(WMTSStatusImpl status); |
98 |
|
99 |
protected abstract WMTSGetCapabilitiesRequest createGetCapabilitiesRequest(); |
100 |
|
101 |
/**
|
102 |
* parses the data retrieved by the Capabilities XML document
|
103 |
*/
|
104 |
public abstract boolean parseCapabilities(File f); |
105 |
|
106 |
public WMTSServerDescription getServerDescription() {
|
107 |
if(serverDescription == null) { |
108 |
serverDescription = new WMTSServerDescription(getVersion());
|
109 |
} |
110 |
return this.serverDescription; |
111 |
} |
112 |
|
113 |
/**
|
114 |
* @return Returns the host.
|
115 |
*/
|
116 |
public String getHost() { |
117 |
return host;
|
118 |
} |
119 |
/**
|
120 |
* @param host The host to set.
|
121 |
*/
|
122 |
public void setHost(String host) { |
123 |
this.host = host;
|
124 |
} |
125 |
/**
|
126 |
* @return Returns the name.
|
127 |
*/
|
128 |
public String getName() { |
129 |
return name;
|
130 |
} |
131 |
/**
|
132 |
* @param name The name to set.
|
133 |
*/
|
134 |
public void setName(String name) { |
135 |
this.name = name;
|
136 |
} |
137 |
/**
|
138 |
* @return Returns the port.
|
139 |
*/
|
140 |
public String getPort() { |
141 |
return port;
|
142 |
} |
143 |
/**
|
144 |
* @param port The port to set.
|
145 |
*/
|
146 |
public void setPort(String port) { |
147 |
this.port = port;
|
148 |
} |
149 |
/**
|
150 |
* @return Returns the version.
|
151 |
*/
|
152 |
public String getVersion() { |
153 |
return version;
|
154 |
} |
155 |
/**
|
156 |
* @param version The version to set.
|
157 |
*/
|
158 |
public void setVersion(String version) { |
159 |
this.version = version;
|
160 |
} |
161 |
|
162 |
/**
|
163 |
* Just for not repeat code. Gets the correct separator according
|
164 |
* to the server URL
|
165 |
* @param h
|
166 |
* @return
|
167 |
*/
|
168 |
public String getSymbol(String h) { |
169 |
String symbol;
|
170 |
if (h.indexOf("?")==-1) |
171 |
symbol = "?";
|
172 |
else if (h.indexOf("?")!=h.length()-1) |
173 |
symbol = "&";
|
174 |
else
|
175 |
symbol = "";
|
176 |
return symbol;
|
177 |
} |
178 |
|
179 |
/**
|
180 |
* Copy the file in a byte array
|
181 |
* @param file
|
182 |
* The file to copy
|
183 |
* @return
|
184 |
* An array of bytes
|
185 |
* @throws IOException
|
186 |
*/
|
187 |
protected byte[] fileToBytes(File file) throws IOException { |
188 |
FileInputStream fis = null; |
189 |
byte[] bytes = null; |
190 |
try{
|
191 |
fis = new FileInputStream(file); |
192 |
|
193 |
//long length = file.length();
|
194 |
bytes = new byte[(int)file.length()]; |
195 |
|
196 |
int offset = 0; |
197 |
int numRead = 0; |
198 |
while (offset < bytes.length &&
|
199 |
(numRead = fis.read(bytes, offset, bytes.length-offset)) >= 0) {
|
200 |
offset += numRead; |
201 |
} |
202 |
} catch (IOException e) { |
203 |
throw e;
|
204 |
} finally {
|
205 |
if (fis != null) { |
206 |
fis.close(); |
207 |
} |
208 |
} |
209 |
return bytes;
|
210 |
} |
211 |
|
212 |
/**
|
213 |
* Sets longitude first in the axis order read from the capabilities file
|
214 |
* @param force
|
215 |
*/
|
216 |
public void setForceChangeAxisOrder(boolean force) { |
217 |
this.forceChangeAxisOrder = force;
|
218 |
} |
219 |
|
220 |
//**************************************************************
|
221 |
//Esto es temporal hasta que est? la cach?
|
222 |
|
223 |
private Hashtable<URL, String> downloadedFiles; |
224 |
/**
|
225 |
* Returns the content of a URL as a file from the file system.<br>
|
226 |
* <p>
|
227 |
* If the URL has been already downloaded in this session and notified
|
228 |
* to the system using the static <b>Utilities.addDownloadedURL(URL)</b>
|
229 |
* method, it can be restored faster from the file system avoiding to
|
230 |
* download it again.
|
231 |
* </p>
|
232 |
* @param url
|
233 |
* @return File containing this URL's content or null if no file was found.
|
234 |
*/
|
235 |
private File getPreviousDownloaded(Object object) { |
236 |
File f = null; |
237 |
if (downloadedFiles != null && downloadedFiles.containsKey(object)) { |
238 |
String filePath = (String) downloadedFiles.get(object); |
239 |
f = new File(filePath); |
240 |
if (!f.exists())
|
241 |
return null; |
242 |
} |
243 |
return f;
|
244 |
} |
245 |
|
246 |
/**
|
247 |
* Adds an URL to the table of downloaded files for further uses. If the URL
|
248 |
* already exists in the table its filePath value is updated to the new one and
|
249 |
* the old file itself is removed from the file system.
|
250 |
*
|
251 |
* @param url
|
252 |
* @param filePath
|
253 |
*/
|
254 |
void addDownloadedURL(URL url, String filePath) { |
255 |
if (downloadedFiles == null) |
256 |
downloadedFiles = new Hashtable<URL, String>(); |
257 |
downloadedFiles.put(url, filePath); |
258 |
} |
259 |
|
260 |
//Fin del c?digo temporal hasta que est? la cach?
|
261 |
//**************************************************************
|
262 |
|
263 |
public synchronized File getTile(WMTSStatusImpl status, ICancellable cancel, File file) throws ServerErrorException, WMTSException { |
264 |
try {
|
265 |
WMTSGetTileRequest request = createGetTileRequest(status); |
266 |
request.sendRequest(cancel, file); |
267 |
try {
|
268 |
checkFileError(file); |
269 |
} catch(WMTSException e) {
|
270 |
file.delete(); |
271 |
throw new WMTSException("This tile is not available:" + file.getAbsoluteFile().toString(), e); |
272 |
} catch(IOException e) { |
273 |
file.delete(); |
274 |
throw new WMTSException("This tile is not available:" + file.getAbsoluteFile().toString(), e); |
275 |
} |
276 |
return file;
|
277 |
} catch(IOException e) { |
278 |
throw new WMTSException(e); |
279 |
} |
280 |
} |
281 |
|
282 |
public synchronized File getTile(WMTSStatus status, ICancellable cancel) throws ServerErrorException, WMTSException { |
283 |
try {
|
284 |
WMTSGetTileRequest request = createGetTileRequest((WMTSStatusImpl)status); |
285 |
File f = request.sendRequest(cancel);
|
286 |
try {
|
287 |
checkFileError(f); |
288 |
} catch(WMTSException e) {
|
289 |
downloader.removeURL(request); |
290 |
throw new ServerErrorException(); |
291 |
} |
292 |
return f;
|
293 |
} catch(IOException e) { |
294 |
e.printStackTrace(); |
295 |
throw new ServerErrorException(); |
296 |
} |
297 |
} |
298 |
|
299 |
public synchronized File getTile(String url, ICancellable cancel, File file) throws ServerErrorException, WMTSException { |
300 |
try {
|
301 |
downloadFile(new URL(url), cancel, file); |
302 |
try {
|
303 |
checkFileError(file); |
304 |
} catch(WMTSException e) {
|
305 |
file.delete(); |
306 |
throw new WMTSException("This tile is not available:" + file.getAbsoluteFile().toString(), e); |
307 |
} catch(IOException e) { |
308 |
file.delete(); |
309 |
throw new WMTSException("This tile is not available:" + file.getAbsoluteFile().toString(), e); |
310 |
} |
311 |
return file;
|
312 |
} catch(IOException e) { |
313 |
throw new WMTSException(e); |
314 |
} catch (DownloadException e1) {
|
315 |
throw new WMTSException(e1); |
316 |
} |
317 |
} |
318 |
|
319 |
/**
|
320 |
* Checks if the file downloaded is correct or doesn't
|
321 |
* @param f
|
322 |
* @throws WMTSException
|
323 |
* @throws IOException
|
324 |
*/
|
325 |
private void checkFileError(File f) throws WMTSException, IOException { |
326 |
if (f == null) |
327 |
return;
|
328 |
if (Utilities.isTextFile(f)) { |
329 |
byte[] data = fileToBytes(f); |
330 |
|
331 |
String exceptionMessage = parseException(data);
|
332 |
if (exceptionMessage == null) { |
333 |
String error = new String(data); |
334 |
int pos = error.indexOf("<?xml"); |
335 |
if (pos!= -1) { |
336 |
String xml = error.substring(pos,error.length());
|
337 |
exceptionMessage = parseException(xml.getBytes()); |
338 |
} |
339 |
if (exceptionMessage == null) |
340 |
exceptionMessage = new String(data); |
341 |
|
342 |
} |
343 |
throw new WMTSException(exceptionMessage); |
344 |
} |
345 |
} |
346 |
|
347 |
public synchronized URL getTileURL(WMTSStatusImpl status) throws MalformedURLException { |
348 |
String onlineResource = getBaseURL(Tags.GETTILE);
|
349 |
|
350 |
StringBuffer req = new StringBuffer(); |
351 |
req.append(onlineResource) |
352 |
.append("REQUEST=GetTile&SERVICE=WMTS&VERSION=").append(getVersion()).append("&") |
353 |
.append("Layer=" + status.getLayer())
|
354 |
.append("&Style=" + status.getStyle())
|
355 |
.append("&Format=" + status.getFormat())
|
356 |
.append("&TileMatrixSet=" + status.getTileMatrixSet())
|
357 |
.append("&TileMatrix=" + status.getTileMatrix())
|
358 |
.append("&TileRow=" + status. getTileRow())
|
359 |
.append("&TileCol=" + status.getTileCol());
|
360 |
|
361 |
return new URL(req.toString()); |
362 |
} |
363 |
|
364 |
/**
|
365 |
* Gets the URL base for a operation (GetCapabilities, GetTile, ...)
|
366 |
* @param operation
|
367 |
* @return the base URL for the GET protocol or the host passed by the user
|
368 |
* if it does not exists.
|
369 |
*/
|
370 |
public String getBaseURL(String operation) { |
371 |
String onlineResource = null; |
372 |
WMTSServerDescription svDescription = getServerDescription(); |
373 |
if(svDescription != null) { |
374 |
WMTSOperationsMetadata opMetadata = svDescription.getOperationsMetadata(); |
375 |
if(opMetadata != null) |
376 |
onlineResource = opMetadata.getOnlineResource(operation); |
377 |
} |
378 |
if(onlineResource == null) |
379 |
onlineResource = getHost(); |
380 |
String symbol = getSymbol(onlineResource);
|
381 |
onlineResource = onlineResource + symbol; |
382 |
return onlineResource;
|
383 |
} |
384 |
|
385 |
/**
|
386 |
* Gets the URL base for a operation (GetCapabilities, GetTile, ...) and
|
387 |
* a protocol GET or POST
|
388 |
* @param operation
|
389 |
* @return the base URL for this protocol or null if it does not exists.
|
390 |
*/
|
391 |
public String getBaseURL(String operation, int protocol) { |
392 |
String onlineResource = null; |
393 |
WMTSServerDescription svDescription = getServerDescription(); |
394 |
if(svDescription != null) { |
395 |
WMTSOperationsMetadata opMetadata = svDescription.getOperationsMetadata(); |
396 |
if(opMetadata != null) { |
397 |
onlineResource = opMetadata.getOnlineResource(operation, protocol); |
398 |
if(onlineResource != null) { |
399 |
String symbol = getSymbol(onlineResource);
|
400 |
return onlineResource + symbol;
|
401 |
} |
402 |
} |
403 |
} |
404 |
return null; |
405 |
} |
406 |
|
407 |
/**
|
408 |
* Gets a file name to download. I
|
409 |
* @param url
|
410 |
* @return
|
411 |
*/
|
412 |
private File getFile() { |
413 |
count ++; |
414 |
int index = name.lastIndexOf("."); |
415 |
if (index > 0){ |
416 |
return new File(tempDirectoryPath + "/" + name.substring(0,index) + System.currentTimeMillis() + count + |
417 |
name.substring(index, name.length())); |
418 |
} |
419 |
return new File(tempDirectoryPath + "/" + name + System.currentTimeMillis() + count); |
420 |
} |
421 |
|
422 |
public synchronized File downloadFile(URL url, ICancellable cancel, File forceFile) throws DownloadException { |
423 |
if(forceFile == null) { |
424 |
File f = null; |
425 |
if((f = getPreviousDownloaded(url)) != null) |
426 |
return f;
|
427 |
} |
428 |
|
429 |
Preferences prefs = Preferences.userRoot().node( "gvsig.downloader" ); |
430 |
int IO_BUFFER_SIZE = 8 * 1024; |
431 |
int timeout = prefs.getInt("timeout", 60000); |
432 |
|
433 |
File dstFile = forceFile;
|
434 |
if(dstFile == null) |
435 |
dstFile = getFile(); |
436 |
|
437 |
DataOutputStream dos;
|
438 |
try {
|
439 |
DataInputStream is;
|
440 |
//OutputStreamWriter os = null;
|
441 |
HttpURLConnection connection = null; |
442 |
|
443 |
if (url.getProtocol().equals("https")) { |
444 |
disableHttsValidation(); |
445 |
} |
446 |
connection = (HttpURLConnection)url.openConnection();
|
447 |
connection.setConnectTimeout(timeout); |
448 |
|
449 |
is = new DataInputStream(url.openStream()); |
450 |
|
451 |
dos = new DataOutputStream( new BufferedOutputStream(new FileOutputStream(dstFile))); |
452 |
byte[] buffer = new byte[IO_BUFFER_SIZE]; |
453 |
|
454 |
int read;
|
455 |
while ((read = is.read(buffer)) != -1) { |
456 |
dos.write(buffer, 0, read);
|
457 |
} |
458 |
|
459 |
/*if(os != null) {
|
460 |
os.close();
|
461 |
}*/
|
462 |
dos.close(); |
463 |
is.close(); |
464 |
is = null;
|
465 |
dos = null;
|
466 |
if (cancel != null && cancel.isCanceled()) { |
467 |
dstFile.delete(); |
468 |
dstFile = null;
|
469 |
return null; |
470 |
} |
471 |
} catch (Exception e) { |
472 |
logger.error("[WMTSProtocolHandler.java:473] " + e);
|
473 |
throw new DownloadException(e); |
474 |
} |
475 |
addDownloadedURL(url, dstFile.getAbsolutePath()); |
476 |
return dstFile;
|
477 |
} |
478 |
|
479 |
/**
|
480 |
* This method disables the Https certificate validation.
|
481 |
* @throws KeyManagementException
|
482 |
* @throws NoSuchAlgorithmException
|
483 |
*/
|
484 |
private void disableHttsValidation() throws KeyManagementException, NoSuchAlgorithmException{ |
485 |
// Create a trust manager that does not validate certificate chains
|
486 |
TrustManager[] trustAllCerts = new TrustManager[] { |
487 |
new X509TrustManager() { |
488 |
public java.security.cert.X509Certificate[] getAcceptedIssuers() { |
489 |
return null; |
490 |
} |
491 |
public void checkClientTrusted( |
492 |
java.security.cert.X509Certificate[] certs, String authType) { |
493 |
} |
494 |
public void checkServerTrusted( |
495 |
java.security.cert.X509Certificate[] certs, String authType) { |
496 |
} |
497 |
} |
498 |
}; |
499 |
|
500 |
// Install the all-trusting trust manager
|
501 |
SSLContext sc = SSLContext.getInstance("SSL"); |
502 |
sc.init(null, trustAllCerts, new java.security.SecureRandom()); |
503 |
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
|
504 |
} |
505 |
|
506 |
/**
|
507 |
* @return string that represents the url for getting the wms legend
|
508 |
* If the layer has the object layer-->style-->legendurl that url will be returned
|
509 |
* otherwise builds the getLegendGraphic according to the OGC WMS Specifications
|
510 |
*
|
511 |
*/
|
512 |
/*private String buildGetLegendGraphicRequest(WMTSLayer layer, WMTSStyle style) {
|
513 |
String onlineResource = style.getLegendURL().getHref();
|
514 |
String symbol = getSymbol(onlineResource);
|
515 |
String layerName = layer.getTitle();
|
516 |
|
517 |
if(onlineResource == null || onlineResource.equals(""))
|
518 |
return null;
|
519 |
|
520 |
StringBuffer req = new StringBuffer();
|
521 |
req.append(onlineResource + symbol + "REQUEST=GetLegendGraphic&SERVICE=WMS&VERSION=").append(getVersion());
|
522 |
req.append("&LAYER=" + layerName).append("&TRANSPARENT=TRUE").append("&FORMAT=image/png");
|
523 |
String aux = req.toString().replaceAll(" ", "%20");
|
524 |
System.out.println("GetLegendGraphic url:" + aux);
|
525 |
return aux;
|
526 |
}*/
|
527 |
|
528 |
public File getLegendGraphic(WMTSLayer layer, WMTSStyle style, ICancellable cancel) |
529 |
throws ServerErrorException, WMTSException, DownloadException {
|
530 |
URL request = null; |
531 |
try {
|
532 |
String requestStr = style.getLegendURL().getHref();
|
533 |
if(requestStr == null || requestStr.equals("")) |
534 |
return null; |
535 |
request = new URL(requestStr); |
536 |
System.out.println(requestStr);
|
537 |
|
538 |
File f = downloadFile(request, cancel, null); |
539 |
if (f== null) |
540 |
return null; |
541 |
if (Utilities.isTextFile(f)) { |
542 |
FileInputStream fis = new FileInputStream(f); |
543 |
FileChannel fc = fis.getChannel();
|
544 |
byte[] data = new byte[(int)fc.size()]; |
545 |
ByteBuffer bb = ByteBuffer.wrap(data); |
546 |
fc.read(bb); |
547 |
|
548 |
WMTSException wmsEx = null;
|
549 |
|
550 |
String exceptionMessage = parseException(data);
|
551 |
if (exceptionMessage == null) { |
552 |
String error = new String(data); |
553 |
int pos = error.indexOf("<?xml"); |
554 |
if (pos!= -1) { |
555 |
String xml = error.substring(pos,error.length());
|
556 |
exceptionMessage = parseException(xml.getBytes()); |
557 |
} |
558 |
if (exceptionMessage == null) |
559 |
exceptionMessage = new String(data); |
560 |
|
561 |
} |
562 |
wmsEx = new WMTSException(exceptionMessage);
|
563 |
wmsEx.setWMTSMessage(new String(data)); |
564 |
Utilities.removeURL(request);
|
565 |
fis.close(); |
566 |
throw wmsEx;
|
567 |
} |
568 |
return f;
|
569 |
} catch(IOException e) { |
570 |
e.printStackTrace(); |
571 |
throw new ServerErrorException(); |
572 |
} |
573 |
} |
574 |
|
575 |
/**
|
576 |
* <p>It will send a GetFeatureInfo request to the WMTS
|
577 |
* Parsing the response and redirecting the info to the WMTS client</p>
|
578 |
* TODO: return a stored file instead a String.
|
579 |
*/
|
580 |
public String getFeatureInfo(WMTSStatusImpl status, int x, int y, ICancellable cancel) { |
581 |
StringBuffer output = new StringBuffer(); |
582 |
String outputFormat = new String(); |
583 |
String ServiceException = "ServiceExceptionReport"; |
584 |
StringBuffer sb = new StringBuffer(); |
585 |
sb.append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
|
586 |
try {
|
587 |
WMTSGetFeatureInfoRequest request = createGetFeatureInfoRequest(status, x, y); |
588 |
URL url = request.getURL();
|
589 |
outputFormat = url.openConnection().getContentType(); |
590 |
File f = request.sendRequest(cancel);
|
591 |
if (f == null) { |
592 |
return ""; |
593 |
} |
594 |
|
595 |
FileReader fReader = new FileReader(f); |
596 |
char[] buffer = new char[1024*256]; |
597 |
for (int i = fReader.read(buffer);i > 0;i = fReader.read(buffer)) { |
598 |
String str = new String(buffer, 0, i); |
599 |
output.append(str); |
600 |
} |
601 |
fReader.close(); |
602 |
if ( (outputFormat == null) || (outputFormat.indexOf("xml") != -1) |
603 |
||output.toString().toLowerCase().startsWith("<?xml")
|
604 |
||(outputFormat.indexOf("gml") != -1)) { |
605 |
KXmlParser kxmlParser = null;
|
606 |
kxmlParser = new KXmlParser();
|
607 |
//kxmlParser.setInput(new StringReader(output.toString()));
|
608 |
kxmlParser.setInput(new FileReader(f)); |
609 |
|
610 |
kxmlParser.nextTag(); |
611 |
if (kxmlParser.getName().compareTo(ServiceException) == 0) { |
612 |
sb.append("<INFO>").append(parseException( output.toString().getBytes())).append("</INFO>"); |
613 |
return sb.toString();
|
614 |
} else if (kxmlParser.getName().compareToIgnoreCase("ERROR") == 0) { |
615 |
return output.toString();
|
616 |
} else {
|
617 |
return output.toString();
|
618 |
} |
619 |
} else {
|
620 |
return output.toString();
|
621 |
} |
622 |
} catch(XmlPullParserException parserEx) {
|
623 |
if (output.toString().toLowerCase().indexOf("xml") != -1) { |
624 |
return output.toString().trim();
|
625 |
} else {
|
626 |
sb.append("<INFO>").append("Info format not supported").append("</INFO>"); |
627 |
return sb.toString();
|
628 |
} |
629 |
} catch(Exception e) { |
630 |
e.printStackTrace(); |
631 |
sb.append("<INFO>").append("Info format not supported").append("</INFO>"); |
632 |
return sb.toString();
|
633 |
} |
634 |
} |
635 |
|
636 |
/**
|
637 |
* <p>Builds a GetCapabilities request that is sent to the WMS
|
638 |
* the response will be parse to extract the data needed by the
|
639 |
* WMS client</p>
|
640 |
* @param override, if true the previous downloaded data will be overridden
|
641 |
*/
|
642 |
public void getCapabilities(WMTSServerDescription status, boolean override, ICancellable cancel) { |
643 |
try {
|
644 |
serverDescription = status; |
645 |
WMTSGetCapabilitiesRequest request = createGetCapabilitiesRequest(); |
646 |
File f = request.sendRequest(cancel);
|
647 |
|
648 |
if (f == null) |
649 |
return;
|
650 |
parseCapabilities(f); |
651 |
} catch(Exception e) { |
652 |
e.printStackTrace(); |
653 |
} |
654 |
} |
655 |
|
656 |
|
657 |
/**
|
658 |
* Builds the GetCapabilitiesRequest according to the OGC WMS Specifications
|
659 |
* without a VERSION, to get the highest version than a WMS supports.
|
660 |
*/
|
661 |
public static String buildCapabilitiesSuitableVersionRequest(String _host, String _version) { |
662 |
int index = _host.indexOf('?'); |
663 |
|
664 |
if (index > -1) { |
665 |
String host = _host.substring(0, index + 1); |
666 |
String query = _host.substring(index + 1, _host.length()); |
667 |
|
668 |
StringTokenizer tokens = new StringTokenizer(query, "&"); |
669 |
String newQuery = "", token; |
670 |
|
671 |
// If there is a field or a value with spaces, (and then it's on different tokens) -> unify them
|
672 |
while (tokens.hasMoreTokens()) {
|
673 |
token = tokens.nextToken().trim(); |
674 |
|
675 |
if (token.toUpperCase().compareTo("REQUEST=GETCAPABILITIES") == 0) |
676 |
continue;
|
677 |
|
678 |
if (token.toUpperCase().compareTo("SERVICE=WMTS") == 0) |
679 |
continue;
|
680 |
|
681 |
if ((_version != null) && (_version.length() > 0)) { |
682 |
if (token.toUpperCase().compareTo("VERSION=" + _version) == 0) |
683 |
continue;
|
684 |
} |
685 |
|
686 |
if (token.toUpperCase().compareTo("EXCEPTIONS=XML") == 0) |
687 |
continue;
|
688 |
|
689 |
newQuery += token + "&";
|
690 |
} |
691 |
|
692 |
_host = host + newQuery; |
693 |
} |
694 |
else {
|
695 |
_host += "?";
|
696 |
} |
697 |
|
698 |
if ((_version != null) && (_version.compareTo("") != 0)) |
699 |
_host += "REQUEST=GetCapabilities&SERVICE=WMTS&VERSION=" + _version;
|
700 |
else
|
701 |
_host += "REQUEST=GetCapabilities&SERVICE=WMTS";
|
702 |
|
703 |
return _host;
|
704 |
} |
705 |
|
706 |
protected String parseException(byte[] data) throws IOException { |
707 |
List<String> errors = new ArrayList<String>(); |
708 |
KXmlParser kxmlParser = new KXmlParser();
|
709 |
try
|
710 |
{ |
711 |
kxmlParser.setInput(new ByteArrayInputStream(data), encoding); |
712 |
kxmlParser.nextTag(); |
713 |
int tag;
|
714 |
if ( kxmlParser.getEventType() != KXmlParser.END_DOCUMENT )
|
715 |
{ |
716 |
kxmlParser.require(KXmlParser.START_TAG, null, Tags.EXCEPTION_ROOT);
|
717 |
tag = kxmlParser.nextTag(); |
718 |
while(tag != KXmlParser.END_DOCUMENT)
|
719 |
{ |
720 |
switch(tag)
|
721 |
{ |
722 |
case KXmlParser.START_TAG:
|
723 |
if (kxmlParser.getName().compareTo(Tags.SERVICE_EXCEPTION)==0){ |
724 |
String errorCode = kxmlParser.getAttributeValue("", Tags.CODE); |
725 |
errorCode = (errorCode != null) ? "["+errorCode+"] " : ""; |
726 |
String errorMessage = kxmlParser.nextText();
|
727 |
errors.add(errorCode + errorMessage); |
728 |
} |
729 |
break;
|
730 |
case KXmlParser.END_TAG:
|
731 |
break;
|
732 |
|
733 |
} |
734 |
tag = kxmlParser.nextTag(); |
735 |
} |
736 |
//kxmlParser.require(KXmlParser.END_DOCUMENT, null, null);
|
737 |
} |
738 |
} |
739 |
catch(XmlPullParserException parser_ex){
|
740 |
throw new IOException(parser_ex.getMessage()); |
741 |
} |
742 |
|
743 |
String message = errors.size() > 0? "" : null; |
744 |
for (int i = 0; i < errors.size(); i++) { |
745 |
message += (String) errors.get(i)+"\n"; |
746 |
} |
747 |
return message;
|
748 |
} |
749 |
|
750 |
} |