Statistics
| Revision:

gvsig-raster / org.gvsig.raster.wcs / trunk / org.gvsig.raster.wcs / org.gvsig.raster.wcs.io / src / main / java / org / gvsig / raster / wcs / io / WCSConnector.java @ 1355

History | View | Annotate | Download (13.4 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.wcs.io;
23

    
24
import java.awt.geom.Point2D;
25
import java.awt.geom.Rectangle2D;
26
import java.io.BufferedOutputStream;
27
import java.io.DataInputStream;
28
import java.io.DataOutputStream;
29
import java.io.File;
30
import java.io.FileOutputStream;
31
import java.io.IOException;
32
import java.io.OutputStreamWriter;
33
import java.net.ConnectException;
34
import java.net.HttpURLConnection;
35
import java.net.URL;
36
import java.security.KeyManagementException;
37
import java.security.NoSuchAlgorithmException;
38
import java.util.ArrayList;
39
import java.util.Hashtable;
40
import java.util.Iterator;
41
import java.util.Set;
42
import java.util.prefs.Preferences;
43

    
44
import javax.net.ssl.HttpsURLConnection;
45
import javax.net.ssl.SSLContext;
46
import javax.net.ssl.TrustManager;
47
import javax.net.ssl.X509TrustManager;
48

    
49
import org.gvsig.compat.net.ICancellable;
50
import org.gvsig.fmap.dal.coverage.exception.RemoteServiceException;
51
import org.gvsig.remoteclient.exceptions.ServerErrorException;
52
import org.gvsig.remoteclient.exceptions.WCSException;
53
import org.gvsig.remoteclient.utils.BoundaryBox;
54
import org.gvsig.remoteclient.wcs.WCSClient;
55
import org.gvsig.remoteclient.wcs.WCSCoverage;
56
import org.gvsig.remoteclient.wcs.WCSStatus;
57
import org.gvsig.remoteclient.wcs.WCSCoverage.AxisDescription;
58
import org.gvsig.remoteclient.wcs.WCSCoverage.RectifiedGrid;
59

    
60
/**
61
 * Connector between a WCS data provider and a WCSClient. 
62
 *
63
 * @author Nacho Brodin (nachobrodin@gmail.com)
64
 */
65
@SuppressWarnings("unchecked")
66
public class WCSConnector  {
67
        private WCSClient                     client;
68
        private Hashtable                     coverages;
69
    private WCSLayerNode[]                layerList;
70
    
71
    public WCSConnector(URL url) throws ConnectException, IOException {
72
            client = new WCSClient(url.toString());
73
    }
74

    
75
        /**
76
         * Returns the string "WCSDriver", which is the driver's name.
77
         *
78
         * Devuelve "WCSDriver", el nombre del driver.
79
         * @return String
80
         */
81
        public String getName() { 
82
                return "WCSDriver"; 
83
        }
84

    
85
        /**
86
         * Sets the server that we want to connect to.
87
         *
88
         * Establece el servidor al que se quiere conectar.
89
         *
90
         * @param host
91
         * @throws IOException
92
         */
93
        public void setHost(String host) throws IOException{
94
                client = new WCSClient(host);
95
        }
96

    
97

    
98
        /**
99
         * Returns a human-readable string containing the server's name.
100
         *
101
         * Devuelve el nombre legible del servidor devuelto por ?ste.
102
         *
103
         * @return String
104
         */
105
        public String getLabel() {
106
                return client.getServiceTitle();
107
        }
108

    
109
        /**
110
         * Returns a string containing the server's WCS version number.
111
         *
112
         * Devuelve el n?mero de versi?n WCS del servidor
113
         *
114
         * @return String
115
         */
116
        public String getVersion(){
117
                return client.getVersion();
118
        }
119

    
120
        /**
121
         * <p>
122
         * Returns name and description of the server. It is supposed to be used
123
         * as the source of the abstract field in your application's interface.
124
         * </p>
125
         * <p>
126
         * Devuelve nombre y descripci?n (abstract) del servidor.
127
         * </p>
128
         * @return String
129
         */
130
        public String getDescription(){
131
                return client.getDescription();
132
        }
133

    
134
        /**
135
         * Returns the layer descriptor for a given coverage name.
136
         * @param layerName
137
         * @return WCSLayer
138
         */
139
        public WCSLayerNode getLayer(String layerName) {
140
                getLayerList();
141
                return (WCSLayerNode) coverages.get(layerName);
142
        }
143

    
144
        /**
145
         * Returns an array of WCSLayer's with the descriptors of all coverages
146
         * @return WCSLayer[]
147
         */
148
        public WCSLayerNode[] getLayerList() {
149
                if (coverages == null || coverages.isEmpty()) {
150
                        // the WCSLayer collection will be built
151
                        coverages = new Hashtable();
152
                        Hashtable wcsCoverages  = client.getCoverageList();
153
                        int sz = wcsCoverages.size();
154

    
155
                        // Create an array with the WCSCoverages
156
                        WCSCoverage[] coverageList = new WCSCoverage[sz];
157
                        Iterator it = wcsCoverages.keySet().iterator();
158
                        int i = 0;
159
                        while (it.hasNext()) {
160
                                coverageList[i] = (WCSCoverage) wcsCoverages.get(it.next());
161
                                i++;
162
                        }
163

    
164
                        // Create a WCSLayer array from the previous WCSCoverage array
165
                        layerList = new WCSLayerNode[sz];
166
                        for (int j = 0; j < layerList.length; j++) {
167
                                WCSLayerNode lyr = new WCSLayerNode();
168
                                WCSCoverage cov = coverageList[j];
169
                                // name
170
                                lyr.setName(cov.getName());
171

    
172
                                // title
173
                                lyr.setTitle(cov.getTitle());
174

    
175
                                // description
176
                                lyr.setDescription(cov.getAbstract());
177

    
178
                                // srs
179
                                lyr.addAllSrs(cov.getAllSrs());
180

    
181
                                // native srs
182
                                lyr.setNativeSRS(cov.getNativeSRS());
183

    
184
                                // extents
185
                                Set k = cov.getBBoxes().keySet();
186
                                if (!k.isEmpty()) {
187
                                        it = k.iterator();
188
                                        while (it.hasNext()) {
189
                                                String srs = (String) it.next();
190
                                                BoundaryBox bBox = cov.getBbox(srs);
191
                                                Rectangle2D r = new Rectangle2D.Double(
192
                                                                bBox.getXmin(),
193
                                                                bBox.getYmin(),
194
                                                                bBox.getXmax() - bBox.getXmin(),
195
                                                                bBox.getYmax() - bBox.getYmin()
196
                                                );
197
                                                lyr.addExtent(srs, r);
198
                                        }
199
                                }
200

    
201
                                // formats
202
                                lyr.setFormats(cov.getFormats());
203

    
204
                                // time positions
205
                                lyr.setTimePositions(cov.getTimePositions());
206
                                
207
                                RectifiedGrid rf = cov.getRectifiedGrid();
208
                                int w = rf.getHighGridEnvelopLimits()[0][0] - rf.getLowGridEnvelopLimits()[0][0];
209
                                int h = rf.getHighGridEnvelopLimits()[0][1] - rf.getLowGridEnvelopLimits()[0][1]; 
210
                                
211
                                lyr.setWidth(w);
212
                                lyr.setHeight(h);
213
                                
214
                                // max res
215
                                lyr.setMaxRes(new Point2D.Double(cov.getResX(), cov.getResY()));
216

    
217
                                // interpolations
218
                                lyr.setInterpolationMethods(cov.getInterpolationMethods());
219

    
220
                                // parameters
221
                                k = cov.axisPool.keySet();
222
                                if (!k.isEmpty()) {
223
                                        it = k.iterator();
224
                                        while (it.hasNext()) {
225
                                                AxisDescription ad = (AxisDescription) cov.axisPool.get(it.next());
226
                                                FMapWCSParameter p = new FMapWCSParameter();
227
                                                p.setName(ad.getName());
228
                                                p.setLabel(ad.getLabel());
229
                                                p.setType(ad.getInterval() == null ? FMapWCSParameter.VALUE_LIST : FMapWCSParameter.INTERVAL);
230
                                                if (p.getType() == FMapWCSParameter.VALUE_LIST) {
231
                                                        p.setValueList(ad.getSingleValues());
232
                                                } /*else {
233
                                                        p.setInterval(ad.getInterval());
234
                                                }*/
235
                                                lyr.addParameter(p);
236
                                        }
237
                                }
238
                                layerList[j] = lyr;
239
                                coverages.put(lyr.getName(), lyr);
240
                        }
241
                }
242
                return layerList;
243
        }
244

    
245
        /**
246
         * Establishes the connection to the WCS server. Connecting to a WCS is
247
         * an abstraction.<br>
248
         * <p>
249
         * Actually, it sends a GetCapabilities and a general DescribeCoverage
250
         * request (not a coverage-specific DescribeCoverage request) to read the
251
         * necessary data for building further GetCoverage requests.
252
         * </p>
253
         * @param override
254
         * @throws IOException.
255
         */
256
        public boolean connect(boolean override, ICancellable cancel)
257
                        throws IOException {
258
                coverages = null;
259
                setHost(client.getHost());
260
                return client.connect(override, cancel);
261
        }
262

    
263
        /**
264
         * No close operation is needed since WCS service it is a non-session based
265
         * protocol. So, this does nothing and you can omit it.<br>
266
         */
267
        public void close() {
268
//                connected = false;
269
        }
270

    
271
        /**
272
         * Returns the label of an specific coverage given by the coverage name
273
         * @param coverage name (string)
274
         * @return string
275
         */
276
        public String getLabel(String coverageName) {
277
                return client.getLabel(coverageName);
278
        }
279

    
280
        /**
281
         * Returns the coverage's MAX extent from the server.
282
         * @return Rectangle2D
283
         * @throws IOException
284
         */
285
        public Rectangle2D getFullExtent(String coverageName, String srs)
286
                        throws IOException {
287
                return client.getExtent(coverageName, srs);
288
        }
289

    
290
        /**
291
         * Returns the max resolution of a specific coverage given by the coverage's name.
292
         * @param coverage name (string)
293
         * @return double
294
         */
295
        public Point2D getMaxResolution(String coverageName) {
296
                if (coverages.containsKey(coverageName)) {
297
                        return ((WCSLayerNode) coverages.get(coverageName)).getMaxRes();
298
                }
299
                return null;
300
        }
301
        
302
        /**
303
         * Gets the maximum width in pixels of this coverage
304
         * @param coverageName
305
         * @return
306
         */
307
        public int getWidth(String coverageName) {
308
                if (coverages.containsKey(coverageName)) {
309
                        return ((WCSLayerNode) coverages.get(coverageName)).getWidth();
310
                }
311
                return 0;
312
        }
313

    
314
        /**
315
         * Gets the maximum height in pixels of this coverage
316
         * @param coverageName
317
         * @return
318
         */
319
        public int getHeight(String coverageName) {
320
                if (coverages.containsKey(coverageName)) {
321
                        return ((WCSLayerNode) coverages.get(coverageName)).getHeight();
322
                }
323
                return 0;
324
        }
325

    
326
        /**
327
         * Returns an ArrayList containing a set of Strings with the coverage's SRSs.
328
         * @param coverage name (string)
329
         * @return ArrayList
330
         */
331
        public ArrayList getSRSs(String coverageName) {
332
                if (coverages.containsKey(coverageName)) {
333
                        return ((WCSLayerNode) coverages.get(coverageName)).getSRSs();
334
                }
335
                return null;
336
        }
337

    
338
        /**
339
         * Returns a String containing a description of an specific coverage.
340
         * @param coverage name (string)
341
         * @return string
342
         */
343
        public String getCoverageDescription(String coverageName) {
344
                if (coverages.containsKey(coverageName)) {
345
                        return ((WCSLayerNode) coverages.get(coverageName)).getDescription();
346
                }
347
                return null;
348
        }
349

    
350
        /**
351
         * Returns an ArrayList containing strings for the time positions of an
352
         * specific coverage given by the coverage's name.
353
         * @param coverage name (string)
354
         * @return ArrayList
355
         */
356
        public ArrayList getTimes(String coverageName) {
357
                if (coverages.containsKey(coverageName)) {
358
                        return ((WCSLayerNode) coverages.get(coverageName)).getTimePositions();
359
                }
360
                return null;
361
        }
362

    
363
        /**
364
         * Sends a GetCoverage request to the client.
365
         * @param status
366
         * @return
367
         * @throws WCSException
368
         */
369
        public File getCoverage(WCSStatus status, ICancellable cancel) throws RemoteServiceException {
370
                try {
371
                        return client.getCoverage(status, cancel);
372
                } catch (ServerErrorException e) {
373
                        throw new RemoteServiceException(getName(), e);
374
                } catch (org.gvsig.remoteclient.exceptions.WCSException e) {
375
                        throw new RemoteServiceException(e.getMessage(), e);
376
                }
377
        }
378
        
379
        /**
380
         * Sends a GetCoverage request to the client.
381
         * @param status
382
         * @return
383
         * @throws WCSException
384
         */
385
        public void getCoverageURL(WCSStatus status, ICancellable cancel, File file) throws RemoteServiceException {
386
                try {
387
                        URL url = client.getCoverageURL(status, cancel);
388
                        downloadFile(url, file, cancel);
389
                        String exceptionMessage = client.getExceptionMessage(file);
390
                        if(exceptionMessage != null)
391
                                throw new RemoteServiceException(exceptionMessage);
392
                } catch(IOException e) {
393
                        throw new RemoteServiceException("WMS: error downloading the file. File:" + file.getAbsolutePath() + "...." + e.getMessage());
394
                } catch (ServerErrorException e) {
395
                        throw new RemoteServiceException("WMS Unexpected server error."+e.getMessage());
396
                }  catch (org.gvsig.remoteclient.exceptions.WMSException e) {
397
                        throw new RemoteServiceException(e.getMessage());
398
                }
399
        }
400
        
401
        public void downloadFile(URL url, File dstFile, ICancellable cancel) throws IOException {
402
                Preferences prefs = Preferences.userRoot().node( "gvsig.downloader" );
403
                // by default 1 minute (60000 milliseconds.
404
                int timeout = prefs.getInt("timeout", 60000);
405

    
406
                DataOutputStream dos;
407
                DataInputStream is;
408
                OutputStreamWriter os = null;
409
                HttpURLConnection connection = null;
410
                //If the used protocol is HTTPS
411
                if (url.getProtocol().equals("https")) {
412
                        try {
413
                                disableHttsValidation();
414
                        } catch (KeyManagementException e) {
415
                                e.printStackTrace();
416
                        } catch (NoSuchAlgorithmException e) {
417
                                e.printStackTrace();
418
                        }
419
                }
420
                connection = (HttpURLConnection)url.openConnection();
421
                connection.setConnectTimeout(timeout);
422
                is = new DataInputStream(url.openStream());
423

    
424
                dos = new DataOutputStream( new BufferedOutputStream(new FileOutputStream(dstFile)));
425
                byte[] buffer = new byte[1024 * 4];
426

    
427

    
428
                long readed = 0;
429
                for (int i = is.read(buffer); i > 0; i = is.read(buffer)){
430
                        dos.write(buffer, 0, i);
431
                        readed += i;
432
                        if(cancel != null && cancel.isCanceled())
433
                                return;
434
                }
435
                if(os != null) {
436
                        os.close();
437
                }
438
                dos.close();
439
                is.close();
440
                is = null;
441
                dos = null;
442
        }
443

    
444
        /**
445
         * This method disables the Https certificate validation.
446
         * @throws KeyManagementException
447
         * @throws NoSuchAlgorithmException
448
         */
449
        private void disableHttsValidation() throws KeyManagementException, NoSuchAlgorithmException{
450
                // Create a trust manager that does not validate certificate chains
451
                TrustManager[] trustAllCerts = new TrustManager[] {
452
                                new X509TrustManager() {
453
                                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
454
                                                return null;
455
                                        }
456
                                        public void checkClientTrusted(
457
                                                        java.security.cert.X509Certificate[] certs, String authType) {
458
                                        }
459
                                        public void checkServerTrusted(
460
                                                        java.security.cert.X509Certificate[] certs, String authType) {
461
                                        }
462
                                }
463
                };
464

    
465
                // Install the all-trusting trust manager
466
                SSLContext sc = SSLContext.getInstance("SSL");
467
                sc.init(null, trustAllCerts, new java.security.SecureRandom());
468
                HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
469
        }
470
   
471
}