Statistics
| Revision:

gvsig-raster / org.gvsig.raster.wcs / branches / org.gvsig.raster.wcs_dataaccess_refactoring / org.gvsig.raster.wcs.io / src / main / java / org / gvsig / raster / wcs / io / WCSConnector.java @ 2340

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
                                int w = rf.getHighGridEnvelopLimits()[0][0] - rf.getLowGridEnvelopLimits()[0][0];
207
                                int h = rf.getHighGridEnvelopLimits()[0][1] - rf.getLowGridEnvelopLimits()[0][1]; 
208
                                
209
                                lyr.setWidth(w);
210
                                lyr.setHeight(h);
211
                                
212
                                // max res
213
                                lyr.setMaxRes(new Point2D.Double(cov.getResX(), cov.getResY()));
214

    
215
                                // interpolations
216
                                lyr.setInterpolationMethods(cov.getInterpolationMethods());
217

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

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

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

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

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

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

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

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

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

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

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

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

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

    
425

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

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

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