Statistics
| Revision:

gvsig-raster / org.gvsig.raster.wms / trunk / org.gvsig.raster.wms / org.gvsig.raster.wms.io / src / main / java / org / gvsig / raster / wms / io / WMSConnector.java @ 1430

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

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

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

    
48
import org.cresques.cts.ICoordTrans;
49
import org.cresques.cts.IProjection;
50
import org.gvsig.compat.net.ICancellable;
51
import org.gvsig.fmap.crs.CRSFactory;
52
import org.gvsig.fmap.dal.coverage.exception.RemoteServiceException;
53
import org.gvsig.remoteclient.exceptions.ServerErrorException;
54
import org.gvsig.remoteclient.utils.BoundaryBox;
55
import org.gvsig.remoteclient.wms.WMSClient;
56
import org.gvsig.remoteclient.wms.WMSDimension;
57
import org.gvsig.remoteclient.wms.WMSLayer;
58
import org.gvsig.remoteclient.wms.WMSStatus;
59
import org.gvsig.remoteclient.wms.WMSStyle;
60

    
61

    
62
public class WMSConnector  {
63
        private WMSClient                     client;
64
    private WMSLayerNode                  fmapRootLayer;
65
    private TreeMap<String, WMSLayerNode> layers = new TreeMap<String, WMSLayerNode>();
66

    
67
    public WMSConnector(URL url) throws ConnectException, IOException {
68
            client = new WMSClient(url.toString());
69
    }
70

    
71
    public String[] getLayerNames(){
72
            return client.getLayerNames();
73
    }
74
    public String[] getLayerTitles(){
75
            return client.getLayerTitles();
76
    }
77
    /*
78
     *  (non-Javadoc)
79
     * @see com.iver.cit.gvsig.fmap.drivers.WMSDriver#getCapabilities(java.net.URL)
80
     */
81
        public void getCapabilities(URL server)
82
                throws RemoteServiceException {
83
//                try {
84
//                        client.connect();
85
//                } catch (Exception e) {
86
//                        throw new WMSException(e);
87
//                }
88
        }
89

    
90
    public File getMap(WMSStatus status, ICancellable cancel) throws RemoteServiceException {
91
        try {
92
                        return client.getMap(status, cancel);
93
        } catch (org.gvsig.remoteclient.exceptions.WMSException e) {
94
            throw new RemoteServiceException(e.getMessage());
95
        } catch (ServerErrorException e) {
96
            throw new RemoteServiceException("WMS Unexpected server error." + e.getMessage(), e);
97
        }
98
    }
99
    
100
    /**
101
     * 
102
     * @param status
103
     * @param cancel
104
     * @param file
105
     * @throws RemoteServiceException
106
     */
107
    public void getMap(WMSStatus status, ICancellable cancel, File file) throws RemoteServiceException {
108
        try {
109
                        URL url = client.getGetMapURL(status, cancel);
110
                        downloadFile(url, file, cancel);
111
                        String exceptionMessage = client.getExceptionMessage(file);
112
                        if(exceptionMessage != null)
113
                                throw new RemoteServiceException(exceptionMessage);
114
                } catch(IOException e) {
115
                        throw new RemoteServiceException("WMS: error downloading the file. File:" + file.getAbsolutePath() + "...." + e.getMessage());
116
                } catch (ServerErrorException e) {
117
            throw new RemoteServiceException("WMS Unexpected server error."+e.getMessage());
118
        }  catch (org.gvsig.remoteclient.exceptions.WMSException e) {
119
            throw new RemoteServiceException(e.getMessage());
120
        }
121
    }
122

    
123
    
124
    public void downloadFile(URL url, File dstFile, ICancellable cancel) throws IOException {
125
                Preferences prefs = Preferences.userRoot().node( "gvsig.downloader" );
126
                // by default 1 minute (60000 milliseconds.
127
                int timeout = prefs.getInt("timeout", 60000);
128

    
129
                DataOutputStream dos;
130
                DataInputStream is;
131
                OutputStreamWriter os = null;
132
                HttpURLConnection connection = null;
133
                //If the used protocol is HTTPS
134
                if (url.getProtocol().equals("https")) {
135
                        try {
136
                                disableHttsValidation();
137
                        } catch (KeyManagementException e) {
138
                                e.printStackTrace();
139
                        } catch (NoSuchAlgorithmException e) {
140
                                e.printStackTrace();
141
                        }
142
                }
143
                connection = (HttpURLConnection)url.openConnection();
144
                connection.setConnectTimeout(timeout);
145
                is = new DataInputStream(url.openStream());
146

    
147
                dos = new DataOutputStream( new BufferedOutputStream(new FileOutputStream(dstFile)));
148
                byte[] buffer = new byte[1024 * 4];
149

    
150

    
151
                long readed = 0;
152
                for (int i = is.read(buffer); i > 0; i = is.read(buffer)){
153
                        dos.write(buffer, 0, i);
154
                        readed += i;
155
                        if(cancel != null && cancel.isCanceled())
156
                                return;
157
                }
158
                if(os != null) {
159
                        os.close();
160
                }
161
                dos.close();
162
                is.close();
163
                is = null;
164
                dos = null;
165
        }
166

    
167
        /**
168
         * This method disables the Https certificate validation.
169
         * @throws KeyManagementException
170
         * @throws NoSuchAlgorithmException
171
         */
172
        private void disableHttsValidation() throws KeyManagementException, NoSuchAlgorithmException{
173
                // Create a trust manager that does not validate certificate chains
174
                TrustManager[] trustAllCerts = new TrustManager[] {
175
                                new X509TrustManager() {
176
                                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
177
                                                return null;
178
                                        }
179
                                        public void checkClientTrusted(
180
                                                        java.security.cert.X509Certificate[] certs, String authType) {
181
                                        }
182
                                        public void checkServerTrusted(
183
                                                        java.security.cert.X509Certificate[] certs, String authType) {
184
                                        }
185
                                }
186
                };
187

    
188
                // Install the all-trusting trust manager
189
                SSLContext sc = SSLContext.getInstance("SSL");
190
                sc.init(null, trustAllCerts, new java.security.SecureRandom());
191
                HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
192
        }
193

    
194
    /**
195
     * Gets the legend graphic of one layer
196
     */
197
    public File getLegendGraphic(WMSStatus status, String layerName, ICancellable cancel) throws RemoteServiceException {
198
        try {
199
                File f = client.getLegendGraphic(status, layerName, cancel);
200
                        return f;
201
        } catch (org.gvsig.remoteclient.exceptions.WMSException e) {
202
            //throw new RemoteServiceException(e.getMessage());
203
        } catch (ServerErrorException e) {
204
            throw new RemoteServiceException("WMS Unexpected server error."+e.getMessage());
205
        }
206
        return null;
207
    }
208

    
209
        /**
210
         * Devuelve WMSClient a partir de su URL.
211
         *
212
         * @param url URL.
213
         *
214
         * @return WMSClient.
215
         * @throws IOException
216
         * @throws ConnectException
217
         *
218
         * @throws UnsupportedVersionException
219
         * @throws IOException
220
         */
221

    
222

    
223
    /**
224
     * Establishes the connection.
225
     * @param override, if true the previous downloaded data will be overridden
226
     * @return <b>true</b> if the connection was successful, or <b>false</b> if it was no possible
227
     * to establish the connection for any reason such as version negotiation.
228
     */
229
    public boolean connect(boolean override, ICancellable cancel) {
230
            if (override) {
231
                    fmapRootLayer = null;
232
                    layers.clear();
233
            }
234
                return client.connect(override, cancel);
235
    }
236

    
237
    public boolean connect(ICancellable cancel) {
238
            return client.connect(false, cancel);
239
    }
240

    
241
    /**
242
     * @return the version of this client.
243
     */
244
    public String getVersion() {
245
            return client.getVersion();
246
    }
247

    
248
    /**
249
     * @return The title of the service offered by the WMS server.
250
     */
251
    public String getServiceTitle() {
252
                return client.getServiceInformation().title;
253
    }
254

    
255
    /**
256
     * Returns a Hash table containing the values for each online resource.
257
     * Using as key a String with name of the WMS request and the value returned
258
     * by the hash is another string containing the corresponding Url
259
     * @return HashTable
260
     */
261
    @SuppressWarnings("unchecked")
262
        public Hashtable getOnlineResources() {
263
            return client.getServiceInformation().getSupportedOperationsByName();
264
    }
265

    
266
    /**
267
     * @return <b>Vector</b> containing strings with the formats supported by this server.
268
     */
269
    @SuppressWarnings("unchecked")
270
    public Vector getFormats() {
271
            return client.getFormats();
272
    }
273
    
274
    /**
275
     * @return <b>Vector</b> containing strings with the information formats supported by this server.
276
     */
277
    @SuppressWarnings("unchecked")
278
    public Vector getInfoFormats() {
279
            return client.getInfoFormats();
280
    }
281

    
282
    /**
283
     * @return <b>Boolean</b> returns if the WMS is queryable (suppports GetFeatureInfo)
284
     */
285
    public boolean isQueryable() {
286
        return client.isQueryable();
287
    }
288
    /**
289
     * @return <b>Boolean</b> returns if the WMS supports getLegendGraphic operation (suppports GetFeatureInfo)
290
     */
291
    public boolean hasLegendGraphic() {
292
        return client.hasLegendGraphic();
293
    }
294
    /**
295
     * @return A tree containing the info of all layers available on this server.
296
     */
297
    public WMSLayerNode getLayersTree() {
298
        if (fmapRootLayer == null){
299
            WMSLayer clientRoot;
300
            if (client.getLayersRoot() == null) {
301
                    client.connect(false, null);
302
            }
303
            clientRoot = client.getLayersRoot();
304

    
305

    
306
            fmapRootLayer = parseTree(clientRoot, null);
307
        }
308
        return fmapRootLayer;
309
    }
310

    
311
    /**
312
     * Parses the client's layer node and translates it to a fmap's layer node
313
     * @param WMSLayer
314
     * @return WMSLayerNode
315
     */
316
    @SuppressWarnings("unchecked")
317
        private WMSLayerNode parseTree(WMSLayer node, WMSLayerNode parentNode) {
318

    
319
        WMSLayerNode myNode = new WMSLayerNode();
320

    
321
        // Name
322
        myNode.setName(node.getName());
323

    
324
        // Title
325
        myNode.setTitle(node.getTitle());
326

    
327
        // Transparency
328
        myNode.setTransparency(node.hasTransparency());
329

    
330
        for (int i = 0; i < node.getAllSrs().size(); i++) {
331
                String srs = (String)node.getAllSrs().get(i);
332
                        if(node.getBbox(srs) == null) {
333
                                IProjection projSrc = CRSFactory.getCRS("EPSG:4326");
334
                                IProjection projDst = CRSFactory.getCRS(srs);
335
                                ICoordTrans t = projSrc.getCT(projDst);
336
                                Rectangle2D r = t.convert(getRectangleFromBoundaryBox(node.getLatLonBox()));
337
                                BoundaryBox bbox = getBoundaryBoxFromRectangle(r);
338
                                bbox.setSrs(srs);
339
                                node.addBBox(bbox);
340
                        }
341
                }
342
        myNode.setSrs(node.getAllSrs());
343

    
344
        // Queryable
345

    
346
        myNode.setQueryable(node.isQueryable() && client.getServiceInformation().isQueryable());
347

    
348
        // Parent layer
349
        myNode.setParent(parentNode);
350

    
351
        // Abstract
352
        myNode.setAbstract(node.getAbstract());
353

    
354
        // Fixed Size
355
        myNode.setFixedSize(node.getfixedWidth(), node.getfixedHeight());
356

    
357
        // LatLonBox
358
        if (node.getLatLonBox()!=null)
359
            myNode.setLatLonBox(node.getLatLonBox().toString());
360

    
361
        // Keywords
362
        ArrayList keywords = node.getKeywords();
363
        for (int i = 0; i < keywords.size(); i++) {
364
                myNode.addKeyword((String) keywords.get(i));
365
                }
366

    
367
        // Styles
368
        ArrayList styles = node.getStyles();
369
        for (int i = 0; i < styles.size(); i++) {
370
            WMSStyle style = (WMSStyle) styles.get(i);
371
            myNode.addStyle(style);
372
        }
373

    
374
        // Dimensions
375
        ArrayList dimensions = node.getDimensions();
376
        for (int i = 0; i < dimensions.size(); i++) {
377
            WMSDimension d = (WMSDimension) dimensions.get(i);
378
            myNode.addDimension(d.getName(), d.getUnits(), d.getUnitSymbol(), d.getDimensionExpression());
379
        }
380

    
381
        // Children
382
        int children = node.getChildren().size();
383
        myNode.setChildren(new ArrayList());
384
        for (int i = 0; i < children; i++) {
385
            myNode.getChildren().add(parseTree((WMSLayer)node.getChildren().get(i), myNode));
386
        }
387

    
388
        if (myNode.getName()!=null)
389
            layers.put(myNode.getName(), myNode);
390

    
391
        return myNode;
392
    }
393
    
394
    public Rectangle2D getRectangleFromBoundaryBox(BoundaryBox bbox) {
395
            return new Rectangle2D.Double(bbox.getXmin(),
396
                            bbox.getYmin(),
397
                            Math.abs(bbox.getXmax() - bbox.getXmin()),
398
                            Math.abs(bbox.getYmax() - bbox.getYmin()));
399
    }
400
    
401
    public BoundaryBox getBoundaryBoxFromRectangle(Rectangle2D r) {
402
            BoundaryBox bbox = new BoundaryBox();
403
            bbox.setXmin(r.getMinX());
404
            bbox.setXmax(r.getMaxX());
405
            bbox.setYmin(r.getMinY());
406
            bbox.setYmax(r.getMaxY());
407
            return bbox;
408
    }
409

    
410
    /**
411
     * @return
412
     */
413
    public String getAbstract() {
414
            return client.getServiceInformation().abstr;
415
    }
416

    
417
    /**
418
     * @param layerName
419
     * @param srs
420
     * @return
421
     */
422
    public Rectangle2D getLayersExtent(String[] layerName, String srs) {
423
            return client.getLayersExtent(layerName, srs);
424
    }
425

    
426
    /**
427
     * @param string
428
     * @return
429
     */
430
    public WMSLayerNode getLayer(String layerName) {
431
        if (getLayers().get(layerName) != null) {
432
            return (WMSLayerNode)layers.get(layerName);
433
        }
434
        return null;
435
    }
436

    
437
    /**
438
     * @return
439
     */
440
    @SuppressWarnings("unchecked")
441
        private TreeMap getLayers() {
442
        if (fmapRootLayer == null){
443
            fmapRootLayer = getLayersTree();
444
        }
445
        return layers;
446
    }
447

    
448
    /**
449
     * @param wmsStatus
450
     * @param i
451
     * @param j
452
     * @param max_value
453
     * @return
454
     * @throws RemoteServiceException
455
     */
456
    public String getFeatureInfo(WMSStatus _wmsStatus, int i, int j, int max_value, ICancellable cancellable) throws RemoteServiceException {
457
        try {
458
            return client.getFeatureInfo(_wmsStatus, i, j, max_value, cancellable);
459
        } catch (org.gvsig.remoteclient.exceptions.WMSException e) {
460
            throw new RemoteServiceException();
461
                }
462
    }
463

    
464
    public String getHost(){
465
            return client.getHost();
466
    }
467
   
468
}