svn-gvsig-desktop / tags / v2_0_0_Build_2020 / libraries / libRemoteServices / src / org / gvsig / remoteclient / wcs / WCSProtocolHandler.java @ 33910
History | View | Annotate | Download (10.7 KB)
1 | 3483 | jaume | /* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
|
---|---|---|---|
2 | *
|
||
3 | * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
|
||
4 | *
|
||
5 | * This program is free software; you can redistribute it and/or
|
||
6 | * modify it under the terms of the GNU General Public License
|
||
7 | * as published by the Free Software Foundation; either version 2
|
||
8 | * of the License, or (at your option) any later version.
|
||
9 | *
|
||
10 | * This program is distributed in the hope that it will be useful,
|
||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
13 | * GNU General Public License for more details.
|
||
14 | *
|
||
15 | * You should have received a copy of the GNU General Public License
|
||
16 | * along with this program; if not, write to the Free Software
|
||
17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA.
|
||
18 | *
|
||
19 | * For more information, contact:
|
||
20 | *
|
||
21 | * Generalitat Valenciana
|
||
22 | * Conselleria d'Infraestructures i Transport
|
||
23 | * Av. Blasco Ib??ez, 50
|
||
24 | * 46010 VALENCIA
|
||
25 | * SPAIN
|
||
26 | *
|
||
27 | * +34 963862235
|
||
28 | * gvsig@gva.es
|
||
29 | * www.gvsig.gva.es
|
||
30 | *
|
||
31 | * or
|
||
32 | *
|
||
33 | * IVER T.I. S.A
|
||
34 | * Salamanca 50
|
||
35 | * 46005 Valencia
|
||
36 | * Spain
|
||
37 | *
|
||
38 | * +34 963163400
|
||
39 | * dac@iver.es
|
||
40 | */
|
||
41 | 29649 | jpiera | package org.gvsig.remoteclient.wcs; |
42 | 3483 | jaume | |
43 | 4924 | jaume | import java.io.ByteArrayInputStream; |
44 | 3483 | jaume | import java.io.File; |
45 | 4493 | jaume | import java.io.IOException; |
46 | 17849 | jmvivo | import java.net.MalformedURLException; |
47 | 3483 | jaume | import java.net.URL; |
48 | 4427 | jaume | import java.util.ArrayList; |
49 | import java.util.Hashtable; |
||
50 | 17849 | jmvivo | import java.util.StringTokenizer; |
51 | 3483 | jaume | |
52 | 33738 | jpiera | import org.kxml2.io.KXmlParser; |
53 | import org.xmlpull.v1.XmlPullParserException; |
||
54 | |||
55 | import org.gvsig.compat.CompatLocator; |
||
56 | import org.gvsig.compat.lang.StringUtils; |
||
57 | import org.gvsig.compat.net.ICancellable; |
||
58 | 29649 | jpiera | import org.gvsig.remoteclient.exceptions.ServerErrorException; |
59 | import org.gvsig.remoteclient.exceptions.WCSException; |
||
60 | import org.gvsig.remoteclient.ogc.OGCProtocolHandler; |
||
61 | 31834 | jpiera | import org.gvsig.remoteclient.ogc.OGCServiceInformation; |
62 | 29649 | jpiera | import org.gvsig.remoteclient.utils.ExceptionTags; |
63 | import org.gvsig.remoteclient.utils.Utilities; |
||
64 | import org.gvsig.remoteclient.wcs.request.WCSDescribeCoverageRequest; |
||
65 | import org.gvsig.remoteclient.wcs.request.WCSGetCoverageRequest; |
||
66 | 3483 | jaume | /**
|
67 | 7010 | jaume | *
|
68 | 3483 | jaume | * @author jaume
|
69 | *
|
||
70 | */
|
||
71 | 17849 | jmvivo | public abstract class WCSProtocolHandler extends OGCProtocolHandler { |
72 | 4500 | jaume | /**
|
73 | * Encoding used to parse different xml documents.
|
||
74 | */
|
||
75 | protected String encoding = "UTF-8"; |
||
76 | 4427 | jaume | protected Hashtable layerPool = new Hashtable(); |
77 | 7010 | jaume | |
78 | 4924 | jaume | /**
|
79 | 3483 | jaume | * WCS metadata
|
80 | */
|
||
81 | 31834 | jpiera | protected WCSServiceInformation serviceInfo = new WCSServiceInformation(); |
82 | 33738 | jpiera | |
83 | private static final StringUtils stringUtils = CompatLocator.getStringUtils(); |
||
84 | 7010 | jaume | |
85 | 17849 | jmvivo | /*
|
86 | * (non-Javadoc)
|
||
87 | * @see org.gvsig.remoteClient.OGCProtocolHandler#setHost(java.lang.String)
|
||
88 | */
|
||
89 | public void setHost(String host) { |
||
90 | try {
|
||
91 | // Validates the URL if doesn't produces an exception
|
||
92 | new URL(host); |
||
93 | |||
94 | int index = host.indexOf("?"); |
||
95 | |||
96 | if (index == -1) |
||
97 | super.setHost(host);
|
||
98 | else
|
||
99 | super.setHost(host.substring(0, index)); |
||
100 | } |
||
101 | catch (MalformedURLException m) { |
||
102 | // Bad URL -> hold it
|
||
103 | super.setHost(host);
|
||
104 | } |
||
105 | } |
||
106 | |||
107 | /**
|
||
108 | 4924 | jaume | * <p>
|
109 | * Builds a GetCapabilities request that is sent to the WCS
|
||
110 | 3483 | jaume | * the response will be parse to extract the data needed by the
|
111 | 4924 | jaume | * WCS client.
|
112 | * </p>
|
||
113 | 9003 | jaume | * @param override, if true the cache is ignored
|
114 | 3483 | jaume | */
|
115 | 9003 | jaume | public void getCapabilities(WCSStatus status, boolean override, ICancellable cancel) { |
116 | 3483 | jaume | URL request = null; |
117 | 4427 | jaume | try {
|
118 | request = new URL(buildCapabilitiesRequest(status)); |
||
119 | 3483 | jaume | } |
120 | 4427 | jaume | catch(Exception e) { |
121 | 3483 | jaume | e.printStackTrace(); |
122 | } |
||
123 | 4427 | jaume | try {
|
124 | 9003 | jaume | if (override)
|
125 | 33738 | jpiera | downloader.removeURL(request); |
126 | File f = downloader.downloadFile(request,"wcs_capabilities.xml", cancel); |
||
127 | 5409 | jaume | if (f!=null) |
128 | parseCapabilities(f); |
||
129 | 4427 | jaume | } catch(Exception e) { |
130 | e.printStackTrace(); |
||
131 | 3483 | jaume | } |
132 | } |
||
133 | 7010 | jaume | |
134 | 3483 | jaume | /**
|
135 | 4924 | jaume | * Builds a complete URL-string that can be used to send a GetCapabilities request.
|
136 | * @return String
|
||
137 | 3483 | jaume | */
|
138 | 4427 | jaume | private String buildCapabilitiesRequest(WCSStatus status) { |
139 | StringBuffer req = new StringBuffer(); |
||
140 | String symbol = null; |
||
141 | 7010 | jaume | |
142 | 4427 | jaume | String onlineResource;
|
143 | if (status == null || status.getOnlineResource() == null) |
||
144 | onlineResource = getHost(); |
||
145 | 7010 | jaume | else
|
146 | 4427 | jaume | onlineResource = status.getOnlineResource(); |
147 | symbol = getSymbol(onlineResource); |
||
148 | 7010 | jaume | |
149 | 4427 | jaume | req.append(onlineResource).append(symbol).append("REQUEST=GetCapabilities&SERVICE=WCS&");
|
150 | req.append("VERSION=").append(getVersion()).append("&EXCEPTIONS=XML"); |
||
151 | return req.toString();
|
||
152 | 3483 | jaume | } |
153 | 4427 | jaume | |
154 | 7010 | jaume | |
155 | |||
156 | 3483 | jaume | /**
|
157 | * parses the data retrieved by the DescribeCoverage XML document
|
||
158 | */
|
||
159 | 4222 | jaume | public abstract boolean parseDescribeCoverage(File f); |
160 | 7010 | jaume | |
161 | 4924 | jaume | /**
|
162 | * Send a DescribeCoverage request using the settings passed in the status argument.
|
||
163 | * If status is null, then default settings are used.
|
||
164 | 9003 | jaume | * @param override
|
165 | 4924 | jaume | * @return String
|
166 | */
|
||
167 | 9003 | jaume | public void describeCoverage(WCSStatus status, boolean override, ICancellable cancel) { |
168 | 27881 | jpiera | try {
|
169 | WCSDescribeCoverageRequest request = createDescribeCoverageRequest(status); |
||
170 | File f = request.sendRequest();
|
||
171 | 5409 | jaume | if (f!=null) |
172 | parseDescribeCoverage(f); |
||
173 | 4427 | jaume | } catch(Exception e) { |
174 | e.printStackTrace(); |
||
175 | } |
||
176 | 3483 | jaume | } |
177 | 7010 | jaume | |
178 | 4924 | jaume | /**
|
179 | * Send a GetCoverage request using the settings passed in the status.
|
||
180 | * @return String
|
||
181 | */
|
||
182 | 5409 | jaume | public File getCoverage(WCSStatus status, ICancellable cancel) throws ServerErrorException, WCSException { |
183 | 27881 | jpiera | try
|
184 | 4493 | jaume | { |
185 | //TODO:
|
||
186 | //pass this buildXXXRequest to the WCSProtocolHandlerXXX: The request can depend on the WCS version.
|
||
187 | 27881 | jpiera | WCSGetCoverageRequest request = createGetCoverageRequest(status); |
188 | File f = request.sendRequest();
|
||
189 | 7010 | jaume | |
190 | 5409 | jaume | if (f!=null && Utilities.isTextFile(f)) { |
191 | 33738 | jpiera | byte[] data = fileToBytes(f); |
192 | 7010 | jaume | |
193 | 4493 | jaume | WCSException wcsEx = null;
|
194 | 7010 | jaume | |
195 | 4493 | jaume | String exceptionMessage = parseException(data);
|
196 | if (exceptionMessage==null) |
||
197 | { |
||
198 | String error = new String(data); |
||
199 | int pos = error.indexOf("<?xml"); |
||
200 | if (pos!= -1) |
||
201 | { |
||
202 | String xml = error.substring(pos,error.length());
|
||
203 | exceptionMessage = parseException(xml.getBytes()); |
||
204 | 7010 | jaume | } |
205 | 4493 | jaume | if (exceptionMessage == null) |
206 | exceptionMessage = new String(data); |
||
207 | 7010 | jaume | |
208 | 4493 | jaume | } |
209 | wcsEx = new WCSException(exceptionMessage);
|
||
210 | wcsEx.setWCSMessage(new String(data)); |
||
211 | 7010 | jaume | |
212 | 4493 | jaume | // Since it is an error file, It must be deleted from the cache
|
213 | 33738 | jpiera | downloader.removeURL(request); |
214 | 4493 | jaume | throw wcsEx;
|
215 | } |
||
216 | 7010 | jaume | return f;
|
217 | 4493 | jaume | } |
218 | catch(IOException e) |
||
219 | { |
||
220 | e.printStackTrace(); |
||
221 | throw new ServerErrorException(); |
||
222 | } |
||
223 | 7010 | jaume | } |
224 | |||
225 | |||
226 | 4924 | jaume | /**
|
227 | * Parses the WCS Exception document.
|
||
228 | * @param bytes, byte[]
|
||
229 | * @return
|
||
230 | */
|
||
231 | private String parseException(byte[] data) { |
||
232 | // TODO: a?? est? fusilat del WMS, comprovar que funciona.
|
||
233 | ArrayList errors = new ArrayList(); |
||
234 | KXmlParser kxmlParser = new KXmlParser();
|
||
235 | try
|
||
236 | { |
||
237 | 7010 | jaume | kxmlParser.setInput(new ByteArrayInputStream(data), encoding); |
238 | 4924 | jaume | kxmlParser.nextTag(); |
239 | int tag;
|
||
240 | 7010 | jaume | if ( kxmlParser.getEventType() != KXmlParser.END_DOCUMENT )
|
241 | { |
||
242 | kxmlParser.require(KXmlParser.START_TAG, null, ExceptionTags.EXCEPTION_ROOT);
|
||
243 | 4924 | jaume | tag = kxmlParser.nextTag(); |
244 | while(tag != KXmlParser.END_DOCUMENT)
|
||
245 | { |
||
246 | switch(tag)
|
||
247 | { |
||
248 | case KXmlParser.START_TAG:
|
||
249 | if (kxmlParser.getName().compareTo(ExceptionTags.SERVICE_EXCEPTION)==0){ |
||
250 | String errorCode = kxmlParser.getAttributeValue("", ExceptionTags.CODE); |
||
251 | errorCode = (errorCode != null) ? "["+errorCode+"] " : ""; |
||
252 | String errorMessage = kxmlParser.nextText();
|
||
253 | errors.add(errorCode+errorMessage); |
||
254 | } |
||
255 | break;
|
||
256 | 7010 | jaume | case KXmlParser.END_TAG:
|
257 | 4924 | jaume | break;
|
258 | 7010 | jaume | |
259 | 4924 | jaume | } |
260 | tag = kxmlParser.nextTag(); |
||
261 | } |
||
262 | //kxmlParser.require(KXmlParser.END_DOCUMENT, null, null);
|
||
263 | } |
||
264 | } |
||
265 | 7010 | jaume | catch(XmlPullParserException parser_ex){
|
266 | 4924 | jaume | parser_ex.printStackTrace(); |
267 | } |
||
268 | 7010 | jaume | catch (IOException ioe) { |
269 | ioe.printStackTrace(); |
||
270 | 4924 | jaume | } |
271 | String message = errors.size()>0? "" : null; |
||
272 | for (int i = 0; i < errors.size(); i++) { |
||
273 | message += (String) errors.get(i)+"\n"; |
||
274 | } |
||
275 | return message;
|
||
276 | 27881 | jpiera | } |
277 | 4493 | jaume | |
278 | 4293 | jaume | /**
|
279 | 4427 | jaume | * Builds the GetCapabilitiesRequest according to the OGC WCS Specifications
|
280 | * without a VERSION, to get the highest version than a WCS supports.
|
||
281 | 4293 | jaume | */
|
282 | public static String buildCapabilitiesSuitableVersionRequest(String _host, String _version) { |
||
283 | 17849 | jmvivo | int index = _host.indexOf('?'); |
284 | |||
285 | if (index > -1) { |
||
286 | String host = _host.substring(0, index + 1); |
||
287 | String query = _host.substring(index + 1, _host.length()); |
||
288 | |||
289 | StringTokenizer tokens = new StringTokenizer(query, "&"); |
||
290 | String newQuery = "", token; |
||
291 | |||
292 | // If there is a field or a value with spaces, (and then it's on different tokens) -> unify them
|
||
293 | while (tokens.hasMoreTokens()) {
|
||
294 | token = tokens.nextToken().trim(); |
||
295 | |||
296 | if (token.toUpperCase().compareTo("REQUEST=GETCAPABILITIES") == 0) |
||
297 | continue;
|
||
298 | |||
299 | if (token.toUpperCase().compareTo("SERVICE=WCS") == 0) |
||
300 | continue;
|
||
301 | |||
302 | if ((_version != null) && (_version.length() > 0)) { |
||
303 | if (token.toUpperCase().compareTo("VERSION=" + _version) == 0) |
||
304 | continue;
|
||
305 | } |
||
306 | |||
307 | if (token.toUpperCase().compareTo("EXCEPTIONS=XML") == 0) |
||
308 | continue;
|
||
309 | |||
310 | newQuery += token + "&";
|
||
311 | } |
||
312 | |||
313 | _host = host + newQuery; |
||
314 | } |
||
315 | else {
|
||
316 | _host += "?";
|
||
317 | } |
||
318 | |||
319 | if ((_version != null) && (_version.compareTo("") != 0)) |
||
320 | _host += "REQUEST=GetCapabilities&SERVICE=WCS&VERSION=" + _version + "&EXCEPTIONS=XML"; |
||
321 | else
|
||
322 | _host += "REQUEST=GetCapabilities&SERVICE=WCS&EXCEPTIONS=XML";
|
||
323 | |||
324 | 33738 | jpiera | return stringUtils.replaceAll(_host, " ", "%20"); |
325 | 4293 | jaume | } |
326 | 7010 | jaume | |
327 | 4931 | jaume | public ArrayList getFormats() { |
328 | return new ArrayList(serviceInfo.formats); |
||
329 | 31834 | jpiera | } |
330 | 4931 | jaume | |
331 | 4427 | jaume | public Hashtable getLayers() { |
332 | return layerPool;
|
||
333 | 7010 | jaume | } |
334 | 27881 | jpiera | |
335 | public abstract WCSDescribeCoverageRequest createDescribeCoverageRequest(WCSStatus status); |
||
336 | |||
337 | public abstract WCSGetCoverageRequest createGetCoverageRequest(WCSStatus status); |
||
338 | 31834 | jpiera | |
339 | /* (non-Javadoc)
|
||
340 | * @see org.gvsig.remoteclient.ogc.OGCProtocolHandler#getServiceInformation()
|
||
341 | 33738 | jpiera | */
|
342 | 31834 | jpiera | public OGCServiceInformation getServiceInformation() {
|
343 | return serviceInfo;
|
||
344 | } |
||
345 | 27881 | jpiera | |
346 | 3483 | jaume | } |