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 @ 3483

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
public class WCSConnector  {
66
        private WCSClient                         client;
67
        private Hashtable<String, WCSLayerNode>   coverages;
68
    private WCSLayerNode[]                    layerList;
69
    
70
    public WCSConnector(URL url) throws ConnectException, IOException {
71
            client = new WCSClient(url.toString());
72
    }
73

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

    
82
        /**
83
         * Sets the server that we want to connect to.
84
         *
85
         * @param host
86
         * @throws IOException
87
         */
88
        public void setHost(String host) throws IOException{
89
                client = new WCSClient(host);
90
        }
91

    
92

    
93
        /**
94
         * Returns a human-readable string containing the server's name.
95
         *
96
         * @return String
97
         */
98
        public String getLabel() {
99
                return client.getServiceTitle();
100
        }
101

    
102
        /**
103
         * Returns a string containing the server's WCS version number.
104
         *
105
         * @return String
106
         */
107
        public String getVersion(){
108
                return client.getVersion();
109
        }
110

    
111
        /**
112
         * <p>
113
         * Returns name and description of the server. It is supposed to be used
114
         * as the source of the abstract field in your application's interface.
115
         * </p>
116
         * <p>
117
         * Devuelve nombre y descripci?n (abstract) del servidor.
118
         * </p>
119
         * @return String
120
         */
121
        public String getDescription(){
122
                return client.getDescription();
123
        }
124

    
125
        /**
126
         * Returns the layer descriptor for a given coverage name.
127
         * @param layerName
128
         * @return WCSLayer
129
         */
130
        public WCSLayerNode getLayer(String layerName) {
131
                getLayerList();
132
                return (WCSLayerNode) getCoverages().get(layerName);
133
        }
134
        
135
        private Hashtable<String, WCSLayerNode> getCoverages() {
136
                if(coverages == null || coverages.isEmpty()) {
137
                        getLayerList();
138
                }
139
                return coverages;
140
        }
141

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

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

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

    
170
                                // title
171
                                lyr.setTitle(cov.getTitle());
172

    
173
                                // description
174
                                lyr.setDescription(cov.getAbstract());
175

    
176
                                // srs
177
                                lyr.addAllSrs(cov.getAllSrs());
178

    
179
                                // native srs
180
                                lyr.setNativeSRS(cov.getNativeSRS());
181

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

    
199
                                // formats
200
                                lyr.setFormats(cov.getFormats());
201

    
202
                                // time positions
203
                                lyr.setTimePositions(cov.getTimePositions());
204
                                
205
                                RectifiedGrid rf = cov.getRectifiedGrid();
206
                                if(rf != null){
207
                                        int w = rf.getHighGridEnvelopLimits()[0][0] - rf.getLowGridEnvelopLimits()[0][0];
208
                                        int h = rf.getHighGridEnvelopLimits()[0][1] - rf.getLowGridEnvelopLimits()[0][1];
209
                                        
210
                                        lyr.setWidth(w);
211
                                        lyr.setHeight(h);
212
                                }
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 (getCoverages().containsKey(coverageName)) {
297
                        return ((WCSLayerNode) getCoverages().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 (getCoverages().containsKey(coverageName)) {
309
                        return ((WCSLayerNode) getCoverages().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 (getCoverages().containsKey(coverageName)) {
321
                        return ((WCSLayerNode) getCoverages().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 (getCoverages().containsKey(coverageName)) {
333
                        return ((WCSLayerNode) getCoverages().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 (getCoverages().containsKey(coverageName)) {
345
                        return ((WCSLayerNode) getCoverages().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 (getCoverages().containsKey(coverageName)) {
358
                        return ((WCSLayerNode) getCoverages().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("WCS: error downloading the file. File:" + file.getAbsolutePath() + "...." + e.getMessage(),e);
394
                } catch (ServerErrorException e) {
395
                        throw new RemoteServiceException("WCS Unexpected server error."+e.getMessage(),e);
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
}