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