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

History | View | Annotate | Download (15.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.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.List;
40
import java.util.TreeMap;
41
import java.util.Vector;
42
import java.util.prefs.Preferences;
43

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

    
50
import org.cresques.cts.ICoordTrans;
51
import org.cresques.cts.IProjection;
52
import org.gvsig.compat.net.ICancellable;
53
import org.gvsig.fmap.crs.CRSFactory;
54
import org.gvsig.fmap.dal.DataParameters;
55
import org.gvsig.fmap.dal.DataServerExplorerParameters;
56
import org.gvsig.fmap.dal.DataStoreParameters;
57
import org.gvsig.fmap.dal.coverage.exception.RemoteServiceException;
58
import org.gvsig.remoteclient.exceptions.ServerErrorException;
59
import org.gvsig.remoteclient.utils.BoundaryBox;
60
import org.gvsig.remoteclient.utils.Utilities;
61
import org.gvsig.remoteclient.wms.WMSClient;
62
import org.gvsig.remoteclient.wms.WMSDimension;
63
import org.gvsig.remoteclient.wms.WMSLayer;
64
import org.gvsig.remoteclient.wms.WMSStatus;
65
import org.gvsig.remoteclient.wms.WMSStyle;
66
import org.slf4j.Logger;
67
import org.slf4j.LoggerFactory;
68

    
69

    
70
public class WMSConnector  {
71
        private WMSClient                     client;
72
    private WMSLayerNode                  fmapRootLayer;
73
    private TreeMap<String, WMSLayerNode> layers = new TreeMap<String, WMSLayerNode>();
74
    private Logger                        log    = LoggerFactory.getLogger(WMSConnector.class);
75

    
76
    public WMSConnector(URL url) throws ConnectException, IOException {
77
            client = new WMSClient(url.toString());
78
    }
79

    
80
    public String[] getLayerNames() {
81
            return client.getLayerNames();
82
    }
83
    
84
    public String[] getLayerTitles() {
85
            return client.getLayerTitles();
86
    }
87
    
88
        public void getCapabilities(URL server) throws RemoteServiceException {
89
//                try {
90
//                        client.connect();
91
//                } catch (Exception e) {
92
//                        throw new WMSException(e);
93
//                }
94
        }
95

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

    
129
    
130
    public void downloadFile(URL url, File dstFile, ICancellable cancel) throws IOException {
131
                Preferences prefs = Preferences.userRoot().node( "gvsig.downloader" );
132
                // by default 1 minute (60000 milliseconds.
133
                int timeout = prefs.getInt("timeout", 60000);
134

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

    
153
                dos = new DataOutputStream( new BufferedOutputStream(new FileOutputStream(dstFile)));
154
                byte[] buffer = new byte[1024 * 4];
155

    
156

    
157
                long readed = 0;
158
                for (int i = is.read(buffer); i > 0; i = is.read(buffer)){
159
                        dos.write(buffer, 0, i);
160
                        readed += i;
161
                        if(cancel != null && cancel.isCanceled())
162
                                return;
163
                }
164
                if(os != null) {
165
                        os.close();
166
                }
167
                dos.close();
168
                is.close();
169
                is = null;
170
                dos = null;
171
        }
172

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

    
194
                // Install the all-trusting trust manager
195
                SSLContext sc = SSLContext.getInstance("SSL");
196
                sc.init(null, trustAllCerts, new java.security.SecureRandom());
197
                HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
198
        }
199

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

    
215
        /**
216
         * Devuelve WMSClient a partir de su URL.
217
         *
218
         * @param url URL.
219
         *
220
         * @return WMSClient.
221
         * @throws IOException
222
         * @throws ConnectException
223
         *
224
         * @throws UnsupportedVersionException
225
         * @throws IOException
226
         */
227

    
228

    
229
    /**
230
     * Establishes the connection.
231
     * @param override, if true the previous downloaded data will be overridden
232
     * @return <b>true</b> if the connection was successful, or <b>false</b> if it was no possible
233
     * to establish the connection for any reason such as version negotiation.
234
     */
235
    public boolean connect(boolean override, ICancellable cancel) {
236
            if (override) {
237
                    fmapRootLayer = null;
238
                    layers.clear();
239
            }
240
                return client.connect(override, cancel);
241
    }
242
    
243
    /**
244
     * Establishes the connection.
245
     * @param override, if true the previous downloaded data will be overridden
246
     * @return <b>true</b> if the connection was successful, or <b>false</b> if it was no possible
247
     * to establish the connection for any reason such as version negotiation.
248
     */
249
    public boolean connect(DataServerExplorerParameters p, boolean override, ICancellable cancel) {
250
            if (override) {
251
                    fmapRootLayer = null;
252
                    layers.clear();
253
            }
254
            WMSStatus status = new WMSStatus();
255
            if (p!=null && p instanceof WMSServerExplorerParameters) {
256
                    status.setXyAxisOrder(((WMSServerExplorerParameters) p).isXyAxisOrder());
257
            }
258

    
259
                return client.connect(status, override, cancel);
260
    }
261

    
262
    /**
263
     * 
264
     * @param cancel
265
     * @return
266
     * @deprecated Use {@link #connect(WMSServerExplorerParameters, boolean, ICancellable)}
267
     * instead
268
     */
269
    public boolean connect(ICancellable cancel) {
270
            return client.connect(false, cancel);
271
    }
272

    
273
    /**
274
     * @return the version of this client.
275
     */
276
    public String getVersion() {
277
            return client.getVersion();
278
    }
279

    
280
    /**
281
     * @return The title of the service offered by the WMS server.
282
     */
283
    public String getServiceTitle() {
284
                return client.getServiceInformation().title;
285
    }
286

    
287
    /**
288
     * Returns a Hash table containing the values for each online resource.
289
     * Using as key a String with name of the WMS request and the value returned
290
     * by the hash is another string containing the corresponding Url
291
     * @return HashTable
292
     */
293
        public Hashtable getOnlineResources() {
294
            return client.getServiceInformation().getSupportedOperationsByName();
295
    }
296

    
297
    /**
298
     * @return <b>Vector</b> containing strings with the formats supported by this server.
299
     */
300
    public Vector getFormats() {
301
            return client.getFormats();
302
    }
303
    
304
    /**
305
     * @return <b>Vector</b> containing strings with the information formats supported by this server.
306
     */
307
    public Vector getInfoFormats() {
308
            return client.getInfoFormats();
309
    }
310

    
311
    /**
312
     * @return <b>Boolean</b> returns if the WMS is queryable (suppports GetFeatureInfo)
313
     */
314
    public boolean isQueryable() {
315
        return client.isQueryable();
316
    }
317
    /**
318
     * @return <b>Boolean</b> returns if the WMS supports getLegendGraphic operation (suppports GetFeatureInfo)
319
     */
320
    public boolean hasLegendGraphic() {
321
        return client.hasLegendGraphic();
322
    }
323
    /**
324
     * @return A tree containing the info of all layers available on this server.
325
     */
326
    public WMSLayerNode getLayersTree() {
327
        if (fmapRootLayer == null){
328
            WMSLayer clientRoot;
329
            if (client.getLayersRoot() == null) {
330
                    client.connect(false, null);
331
            }
332
            clientRoot = client.getLayersRoot();
333

    
334

    
335
            fmapRootLayer = parseTree(clientRoot, null);
336
        }
337
        return fmapRootLayer;
338
    }
339

    
340
    /**
341
     * Parses the client's layer node and translates it to a fmap's layer node
342
     * @param WMSLayer
343
     * @return WMSLayerNode
344
     */
345
    @SuppressWarnings("unchecked")
346
        private WMSLayerNode parseTree(WMSLayer node, WMSLayerNode parentNode) {
347

    
348
        WMSLayerNode myNode = new WMSLayerNode();
349

    
350
        // Name
351
        myNode.setName(node.getName());
352

    
353
        // Title
354
        myNode.setTitle(node.getTitle());
355

    
356
        // Transparency
357
        myNode.setTransparency(node.hasTransparency());
358

    
359
        // CRS
360

    
361
//        for (int i = 0; i < node.getAllSrs().size(); i++) {
362
//                String srs = (String)node.getAllSrs().get(i);
363
//                if(node.getBbox(srs) == null) {
364
//                        IProjection projSrc = CRSFactory.getCRS("EPSG:4326");
365
//                        try {
366
//                                IProjection projDst = CRSFactory.getCRS(srs);
367
//                                if(projDst != null) {
368
//                                        try {
369
//                                                ICoordTrans t = projSrc.getCT(projDst);
370
//                                                Rectangle2D r = t.convert(getRectangleFromBoundaryBox(node.getLatLonBox()));
371
//                                                BoundaryBox bbox = getBoundaryBoxFromRectangle(r);
372
//                                                bbox.setSrs(srs);
373
//                                                node.addBBox(bbox);
374
//                                        } catch (Exception e) {
375
//                                                log.info("I cannot get the transformation between EPSG:4326 and " + srs, e);
376
//                                        }
377
//                                }
378
//                        } catch (Exception e1) {
379
//                                log.info("I cannot get " + srs, e1);
380
//                                node.removeSrs(srs);
381
//                        }
382
//                }
383
//                }
384
        myNode.setSrs(node.getAllSrs());
385

    
386
        // Queryable
387

    
388
        myNode.setQueryable(node.isQueryable() && client.getServiceInformation().isQueryable());
389

    
390
        // Parent layer
391
        myNode.setParent(parentNode);
392

    
393
        // Abstract
394
        myNode.setAbstract(node.getAbstract());
395

    
396
        // Fixed Size
397
        myNode.setFixedSize(node.getfixedWidth(), node.getfixedHeight());
398

    
399
        // LatLonBox
400
        if (node.getLatLonBox()!=null)
401
            myNode.setLatLonBox(node.getLatLonBox().toString());
402

    
403
        // Keywords
404
        ArrayList keywords = node.getKeywords();
405
        for (int i = 0; i < keywords.size(); i++) {
406
                myNode.addKeyword((String) keywords.get(i));
407
                }
408

    
409
        // Styles
410
        ArrayList styles = node.getStyles();
411
        for (int i = 0; i < styles.size(); i++) {
412
            WMSStyle style = (WMSStyle) styles.get(i);
413
            myNode.addStyle(style);
414
        }
415

    
416
        // Dimensions
417
        ArrayList dimensions = node.getDimensions();
418
        for (int i = 0; i < dimensions.size(); i++) {
419
            WMSDimension d = (WMSDimension) dimensions.get(i);
420
            myNode.addDimension(d.getName(), d.getUnits(), d.getUnitSymbol(), d.getDimensionExpression());
421
        }
422

    
423
        // Children
424
        int children = node.getChildren().size();
425
        myNode.setChildren(new ArrayList());
426
        for (int i = 0; i < children; i++) {
427
            myNode.getChildren().add(parseTree((WMSLayer)node.getChildren().get(i), myNode));
428
        }
429

    
430
        if (myNode.getName()!=null)
431
            layers.put(myNode.getName(), myNode);
432

    
433
        return myNode;
434
    }
435
    
436
    public Rectangle2D getRectangleFromBoundaryBox(BoundaryBox bbox) {
437
            return new Rectangle2D.Double(bbox.getXmin(),
438
                            bbox.getYmin(),
439
                            Math.abs(bbox.getXmax() - bbox.getXmin()),
440
                            Math.abs(bbox.getYmax() - bbox.getYmin()));
441
    }
442
    
443
    public BoundaryBox getBoundaryBoxFromRectangle(Rectangle2D r) {
444
            BoundaryBox bbox = new BoundaryBox();
445
            bbox.setXmin(r.getMinX());
446
            bbox.setXmax(r.getMaxX());
447
            bbox.setYmin(r.getMinY());
448
            bbox.setYmax(r.getMaxY());
449
            return bbox;
450
    }
451

    
452
    public String getAbstract() {
453
            return client.getServiceInformation().abstr;
454
    }
455

    
456
    public Rectangle2D getLayersExtent(String[] layerName, String srs) {
457
            return client.getLayersExtent(layerName, srs);
458
    }
459

    
460
    public WMSLayerNode getLayer(String layerName) {
461
        if (getLayers().get(layerName) != null) {
462
            return (WMSLayerNode)layers.get(layerName);
463
        }
464
        return null;
465
    }
466

    
467
        private TreeMap getLayers() {
468
        if (fmapRootLayer == null){
469
            fmapRootLayer = getLayersTree();
470
        }
471
        return layers;
472
    }
473

    
474
    public String getFeatureInfo(WMSStatus _wmsStatus, int i, int j, int max_value, ICancellable cancellable) throws RemoteServiceException {
475
        try {
476
            return client.getFeatureInfo(_wmsStatus, i, j, max_value, cancellable);
477
        } catch (org.gvsig.remoteclient.exceptions.WMSException e) {
478
            throw new RemoteServiceException();
479
                }
480
    }
481

    
482
    public String getHost(){
483
            return client.getHost();
484
    }
485
   
486
}