Statistics
| Revision:

gvsig-3d / 1.10 / trunk / libraries / lib3DMap / src / org / gvsig / gvsig3d / cacheservices / FLayerCacheService.java @ 12

History | View | Annotate | Download (18.1 KB)

1
package org.gvsig.gvsig3d.cacheservices;
2

    
3
import java.awt.Color;
4
import java.awt.Dimension;
5
import java.awt.Graphics2D;
6
import java.awt.Image;
7
import java.awt.geom.AffineTransform;
8
import java.awt.geom.Rectangle2D;
9
import java.awt.image.BufferedImage;
10
import java.io.File;
11
import java.io.IOException;
12
import java.net.URL;
13
import java.util.ArrayList;
14
import java.util.HashMap;
15
import java.util.Hashtable;
16
import java.util.Iterator;
17
import java.util.PriorityQueue;
18
import java.util.Vector;
19

    
20
import org.apache.log4j.Logger;
21
import org.cresques.cts.IProjection;
22
import org.exolab.castor.xml.ValidationException;
23
import org.gvsig.cacheservice.CacheService;
24
import org.gvsig.cacheservice.CacheServiceException;
25
import org.gvsig.cacheservice.RasterCacheService;
26
import org.gvsig.cacheservice.TileNum;
27
import org.gvsig.fmap.raster.layers.FLyrRasterSE;
28
import org.gvsig.osgvp.terrain.Terrain;
29
import org.gvsig.raster.buffer.BufferFactory;
30
import org.gvsig.raster.buffer.RasterBuffer;
31
import org.gvsig.raster.buffer.WriterBufferServer;
32
import org.gvsig.raster.dataset.GeoRasterWriter;
33
import org.gvsig.raster.dataset.InvalidSetViewException;
34
import org.gvsig.raster.dataset.NotSupportedExtensionException;
35
import org.gvsig.raster.dataset.Params;
36
import org.gvsig.raster.dataset.io.RasterDriverException;
37
import org.gvsig.remoteClient.utils.Utilities;
38
import org.gvsig.remoteClient.wcs.WCSStatus;
39
import org.gvsig.remoteClient.wms.ICancellable;
40
import org.gvsig.remoteClient.wms.WMSStatus;
41

    
42
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
43
import com.iver.ai2.gvsig3d.map3d.layers.Layer3DProps;
44
import com.iver.cit.gvsig.exceptions.expansionfile.ExpansionFileReadException;
45
import com.iver.cit.gvsig.exceptions.layers.LoadLayerException;
46
import com.iver.cit.gvsig.fmap.ViewPort;
47
import com.iver.cit.gvsig.fmap.drivers.wcs.FMapWCSDriver;
48
import com.iver.cit.gvsig.fmap.drivers.wcs.FMapWCSDriverFactory;
49
import com.iver.cit.gvsig.fmap.drivers.wms.FMapWMSDriver;
50
import com.iver.cit.gvsig.fmap.drivers.wms.FMapWMSDriverFactory;
51
import com.iver.cit.gvsig.fmap.drivers.wms.WMSException;
52
import com.iver.cit.gvsig.fmap.layers.FLayer;
53
import com.iver.cit.gvsig.fmap.layers.FLyrDefault;
54
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
55
import com.iver.cit.gvsig.fmap.layers.FLyrWCS;
56
import com.iver.cit.gvsig.fmap.layers.FLyrWMS;
57
import com.iver.utiles.FileUtils;
58
import com.iver.utiles.swing.threads.Cancellable;
59

    
60
public class FLayerCacheService extends RasterCacheService {
61
        private boolean _loadFailed = true;
62
        private Rectangle2D _lyrExtentRect;
63
        private FLayer _layer;
64
        private IProjection _viewProj;
65
        private int _dataType;
66
        private Object cacheMutex = new Object();
67

    
68
        // WMS terrain
69
        FMapWMSDriver _wmsDriver = null;
70
        FMapWCSDriver _wcsDriver = null;
71

    
72
        WMSStatus _wmsStatus = null;
73
        WCSStatus _wcsStatus = null;
74

    
75
        Thread _requestThead = null;
76
        private RequestTileFromLayerThread _requestTileFromLayerThread;
77

    
78
        private static Logger _logger = Logger.getLogger(FLayerCacheService.class
79
                        .getName());
80

    
81
        public FLayerCacheService(Terrain terrain, String name, FLayer layer,
82
                        IProjection viewProj) {
83
                super(terrain.getTerrainName(), name);
84

    
85
                _layer = layer;
86
                _viewProj = viewProj;
87
                _loadFailed = true;
88

    
89
                int cacheType = CacheService.GLOBAL;
90
                if (terrain.getCoordinateSystemType() == Terrain.CoordinateSystemType.GEOCENTRIC)
91
                        cacheType += SPHERIC;
92
                else
93
                        cacheType += PLANE;
94
                setCacheType(cacheType);
95

    
96
                try {
97
                        _lyrExtentRect = _layer.getFullExtent();
98
                } catch (ExpansionFileReadException e) {
99
                        e.printStackTrace();
100
                } catch (ReadDriverException e) {
101
                        e.printStackTrace();
102
                }
103

    
104
                Layer3DProps props3D = Layer3DProps.getLayer3DProps(layer);
105
                _dataType = props3D.getType();
106
                if (_dataType == Layer3DProps.layer3DImage)
107
                        setFileExtension(".png");
108
                else
109
                        setFileExtension(".tif");
110

    
111
                _loadFailed = false;
112

    
113
        }
114

    
115
        protected class MyCancel implements Cancellable, ICancellable {
116

    
117
                public boolean isCanceled() {
118
                        return false;
119
                }
120

    
121
                public void setCanceled(boolean canceled) {
122

    
123
                }
124

    
125
                /* if you don�t put and ID the wms donwload will be fail */
126
                public Object getID() {
127
                        return this;
128
                }
129

    
130
        }
131

    
132
        protected class RequestTileFromLayerThread implements Runnable {
133

    
134
                private class Request implements Comparable<Request> {
135
                        public Request(long timeStamp, String fName, Rectangle2D tileExtent) {
136
                                _timeStamp = timeStamp;
137
                                _fName = fName;
138
                                _tileExtent = tileExtent;
139
                        }
140
                        long _timeStamp;
141
                        String _fName;
142
                        Rectangle2D _tileExtent;
143
                        public int compareTo(Request o) {
144
                                if(_timeStamp > o._timeStamp) return -1;
145
                                else if(_timeStamp < o._timeStamp) return 1;
146
                                else return 0;
147
                        }
148
                }
149

    
150
                private HashMap<String, Request> _requestList = new HashMap<String, Request>();
151
                private PriorityQueue<Request> _priorityRequestList = new PriorityQueue<Request>();
152
                private volatile boolean _done = false;
153

    
154
                protected synchronized void purgeOldRequests() {
155
                        int max_elements = 100;
156
                        if(_requestList.size() > max_elements) {
157
                                //_logger.debug("max elements reached from request list thread...");
158
                                Iterator<Request> iterator = _requestList.values().iterator();
159
                                ArrayList<Request> removeRequests = new ArrayList<Request>();
160
                                int index = 0;
161
                                while(iterator.hasNext()) {
162
                                        Request request = iterator.next();
163
                                        if(index>max_elements) {
164
                                                removeRequests.add(request);
165
                                        }
166
                                        index++;
167
                                }
168
                                for(int i=0;i<removeRequests.size();i++) {
169
                                        //_logger.debug("Removing old elements from request list thread...");
170
                                        _priorityRequestList.remove(removeRequests.get(i));
171
                                        _requestList.remove(removeRequests.get(i)._fName);
172
                                }
173
                        }
174
                }
175

    
176
                public synchronized void requestTile(String fName, Rectangle2D tileExtent) {
177
                        Request request = _requestList.get(fName);
178
                        if(request == null) {
179
                                Request req = new Request(System.currentTimeMillis(),fName,tileExtent);
180
                                _requestList.put(fName,req);
181
                                _priorityRequestList.add(req);
182
                        } else {
183
                                request._timeStamp = System.currentTimeMillis();
184
                        }
185
                        purgeOldRequests();
186
                }
187

    
188
                public void run() {
189
                        while(!_done) {
190
                                Request request = null;
191
                                synchronized (this) {
192
                                        request = _priorityRequestList.poll();
193
                                }
194
                                if(request != null) {
195
                                        _requestList.remove(request._fName);
196
                                        getTileFromLayer(request._fName, request._tileExtent);
197
                                }
198
                                else {
199
                                        try {
200
                                                Thread.sleep(1);
201
                                        } catch (InterruptedException e) {
202
                                                e.printStackTrace();
203
                                        }
204
                                }
205
                        }
206

    
207
                }
208

    
209
                public void setDone(boolean value) { _done = value; }
210

    
211
        }
212

    
213
        private void requestTileFromLayer(String fName, Rectangle2D tileExtent) {
214
                if(_requestThead == null) {
215
                        _requestTileFromLayerThread = new RequestTileFromLayerThread();
216
                        _requestThead = new Thread(_requestTileFromLayerThread);
217
                        _requestThead.start();
218
                }
219
                _requestTileFromLayerThread.requestTile(fName, tileExtent);
220

    
221
        }
222

    
223
        private void getTileFromLayer(String fName, Rectangle2D tileExtent) {
224
                BufferedImage image;
225

    
226
                // Check if the file exists, because some files are in request queue
227
                // while the request is processing.
228
                boolean fileExists = new File(fName).exists();
229
                if(!fileExists)
230
                {
231
                        if (_dataType == Layer3DProps.layer3DImage) {
232
                                // Workaround to avoid too many System.gc() calls on layer.draw. which makes
233
                                // rendering stall when rendering the tile.
234
                                if (_layer instanceof FLyrWMS) { // WMS Elevation
235
                                        try {
236
                                                FLyrWMS wmsLayer = (FLyrWMS) _layer;
237
                                                if (_wmsDriver == null) {
238

    
239
                                                        URL host = wmsLayer.getHost();
240
                                                        _wmsDriver = FMapWMSDriverFactory
241
                                                        .getFMapDriverForURL(host);
242
                                                }
243
                                                if (_wmsStatus == null) {
244
                                                        _wmsStatus = new WMSStatus();
245
                                                        _wmsStatus.setFormat(wmsLayer.getFormat());
246
                                                        _wmsStatus.setHeight(512);
247
                                                        _wmsStatus.setWidth(512);
248
                                                        _wmsStatus.setLayerNames(Utilities.createVector(
249
                                                                        wmsLayer.getLayerQuery(), ","));
250
                                                        _wmsStatus.setSrs(wmsLayer.getSRS());
251

    
252
                                                        HashMap props = wmsLayer.getProperties();
253
                                                        Vector styles;
254
                                                        Vector dimensions;
255
                                                        styles = (Vector) (props.get("styles"));
256
                                                        dimensions = (Vector) (props.get("dimensions"));
257
                                                        _wmsStatus.setStyles(styles);
258
                                                        _wmsStatus.setDimensions(dimensions);
259
                                                        _wmsStatus.setTransparency((Boolean)props.get("wmsTransparency"));
260
                                                        String getMapStr = wmsLayer.getOnlineResource("GetMap");
261
                                                        _wmsStatus.setOnlineResource(getMapStr);
262
                                                }
263
                                                _wmsStatus.setExtent(tileExtent);
264
                                                File f = _wmsDriver.getMap(_wmsStatus, new MyCancel());
265
                                                if (f == null)
266
                                                        return;
267
                                                synchronized (cacheMutex) {
268
                                                        FileUtils.copy(f, new File(fName));
269
                                                }
270
//                                                wmsLayer.setName(f.getName());
271
//                                                wmsLayer.setLoadParams(f);
272
//                                                wmsLayer.load();
273
                                                //wmsLayer.init();
274
                                        } catch (Exception e) {
275
                                                return;
276
                                        }
277
                                } else {
278
                                        int size = getTileSize();
279
                                        image = new BufferedImage(size, size,
280
                                                        BufferedImage.TYPE_INT_ARGB);
281

    
282
                                        ViewPort vp = new ViewPort(_viewProj);
283
                                        vp.setExtent(tileExtent); // the real extent of the tile
284
                                        // NotificationManager.addInfo("Extent solicitado--> "
285
                                        // + tileExtent.getMinX() + " " + tileExtent.getMinY() + " "
286
                                        // + tileExtent.getMaxX() + " " + tileExtent.getMaxY());
287
                                        vp.setAdjustable(false);
288
                                        vp.setImageSize(new Dimension(size, size));
289
                                        // vp.setDist1pixel(1 / 150000);
290
                                        vp.setDist1pixel(0.000000001);
291

    
292
                                        Graphics2D graphics = image.createGraphics();
293
                                        Color backgColor = new Color(255, 255, 255, 0); // transparent
294
                                        // background
295
                                        graphics.setColor(backgColor);
296
                                        graphics.fillRect(0, 0, size, size);
297

    
298
                                        // CancelDraw canceldraw = new MapControl.CancelDraw();
299
                                        // canceldraw.setCanceled(false);
300
                                        // For now we'll use a trick to make sure the layer is drawn
301
                                        // even if it has scale dependency
302
                                        // In the future, a scale corresponding to the tile should be
303
                                        // passed
304
                                        double scale = 0.5 * (_layer.getMaxScale() + _layer
305
                                                        .getMinScale());
306
                                        int trans = 255;
307

    
308
                                        // The layers of remote services don�t have transparency.
309
                                        if (_layer.getClass().equals(FLyrVect.class)) {
310
                                                // Generate layers 3D properties
311
                                                Layer3DProps props3D = Layer3DProps.getLayer3DProps(_layer);
312
                                                // fix opaque the layer to save in disk
313
                                                ((FLyrDefault) _layer).setTransparency((int) (props3D
314
                                                                .getOpacity() * 255));
315

    
316
                                        }
317

    
318
                                        if (_layer instanceof FLyrRasterSE) {
319
                                                // fix opaque the layer to save in disk
320
                                                ((FLyrRasterSE) _layer).setTransparency(255);
321
                                        }
322

    
323
                                        try {
324
                                                _layer.draw(image, graphics, vp, new MyCancel(), scale);
325
                                                if ((_layer.getClass().equals(FLyrVect.class))&& ((FLyrVect)_layer).isLabeled())
326
                                                        ((FLyrVect)_layer).drawLabels(image, graphics, vp, new MyCancel(), scale,72);
327

    
328
                                        } catch (Exception e) {
329
                                                return;
330
                                        }
331
                                        // Restoring the real value of transparency
332
                                        if (_layer.getClass().equals(FLyrVect.class)) {
333
                                                // fix the real transparency to the layer
334
                                                ((FLyrDefault) _layer).setTransparency(trans);
335
                                        }
336

    
337
                                        try {
338
                                                File file = new File(fName);
339
                                                String format = getFileExtension().substring(1);
340
                                                synchronized (cacheMutex) {
341
                                                        saveCachedFile(image, format, file);
342
                                                }
343
                                        } catch (IOException e1) {
344
                                                e1.printStackTrace();
345
                                                return;
346
                                        }
347
                                }
348
                        } else { // Elevation data
349
                                if (_layer instanceof FLyrWMS) { // WMS Elevation
350
                                        try {
351
                                                FLyrWMS wmsLayer = (FLyrWMS) _layer;
352
                                                if (_wmsDriver == null) {
353

    
354
                                                        URL host = wmsLayer.getHost();
355
                                                        _wmsDriver = FMapWMSDriverFactory
356
                                                        .getFMapDriverForURL(host);
357
                                                }
358
                                                if (_wmsStatus == null) {
359
                                                        _wmsStatus = new WMSStatus();
360
                                                        _wmsStatus.setFormat(wmsLayer.getFormat());
361
                                                        _wmsStatus.setHeight(32);
362
                                                        _wmsStatus.setWidth(32);
363
                                                        _wmsStatus.setLayerNames(Utilities.createVector(
364
                                                                        wmsLayer.getLayerQuery(), ","));
365
                                                        _wmsStatus.setSrs(wmsLayer.getSRS());
366

    
367
                                                        HashMap props = wmsLayer.getProperties();
368
                                                        Vector styles;
369
                                                        Vector dimensions;
370
                                                        styles = (Vector) (props.get("styles"));
371
                                                        dimensions = (Vector) (props.get("dimensions"));
372
                                                        _wmsStatus.setStyles(styles);
373
                                                        _wmsStatus.setDimensions(dimensions);
374
                                                        _wmsStatus.setTransparency(false);
375
                                                        String getMapStr = wmsLayer.getOnlineResource("GetMap");
376
                                                        _wmsStatus.setOnlineResource(getMapStr);
377
                                                }
378
                                                _wmsStatus.setExtent(tileExtent);
379
                                                File f = _wmsDriver.getMap(_wmsStatus, new MyCancel());
380
                                                if (f == null)
381
                                                        return;
382

    
383
                                                synchronized (cacheMutex) {
384
                                                        FileUtils.copy(f, new File(fName));
385
                                                }
386

    
387
                                        } catch (Exception e) {
388
                                                return;
389
                                        }
390
                                } else if (_layer instanceof FLyrWCS) { // WCS Elevation
391
                                        try {
392
                                                FLyrWCS wcsLayer = (FLyrWCS) _layer;
393
                                                if (_wcsDriver == null) {
394

    
395
                                                        URL host = wcsLayer.getHost();
396
                                                        _wcsDriver = FMapWCSDriverFactory
397
                                                        .getFMapDriverForURL(host);
398
                                                }
399
                                                if (_wcsStatus == null) {
400
                                                        _wcsStatus = new WCSStatus();
401

    
402
                                                        Hashtable props = wcsLayer.getProperties();
403

    
404
                                                        _wcsStatus.setCoveraName((String) props.get("name"));
405
                                                        _wcsStatus.setFormat((String) props.get("format"));
406
                                                        _wcsStatus.setHeight(32);
407
                                                        _wcsStatus.setWidth(32);
408
                                                        _wcsStatus.setSrs((String) props.get("crs"));
409
                                                        _wcsStatus.setParameters((String) props
410
                                                                        .get("parameter"));
411
                                                        String time = (String) props.get("time");
412
                                                        if (time.length() > 0)
413
                                                                _wcsStatus.setTime(time);
414
                                                }
415
                                                _wcsStatus.setExtent(tileExtent);
416

    
417
                                                File f = _wcsDriver.getCoverage(_wcsStatus, new MyCancel());
418
                                                if (f == null)
419
                                                        return;
420
                                                synchronized (cacheMutex) {
421
                                                        FileUtils.copy(f, new File(fName));
422
                                                }
423
                                        } catch (Exception e) {
424
                                                return;
425
                                        }
426
                                } else
427
                                        // RASTER_GRID
428
                                        if (_layer instanceof FLyrRasterSE) {
429

    
430
                                                FLyrRasterSE rasterLayer = (FLyrRasterSE) _layer;
431
                                                BufferFactory bufferFactory = rasterLayer.getBufferFactory();
432

    
433
                                                //int bands[] = { 0 };
434
                                                bufferFactory.setAllDrawableBands();
435
                                                bufferFactory.setAdjustToExtent(false);
436
                                                bufferFactory.setNoDataToFill(0.0);
437

    
438
                                                // The y max and min are mixed because there are some problems 
439
                                                // computing the adjustedDataExtent.
440
                                                try {
441
                                                        bufferFactory.setAreaOfInterest(tileExtent.getMinX(),
442
                                                                        tileExtent.getMaxY(), tileExtent.getMaxX(),
443
                                                                        tileExtent.getMinY(), 32, 32);
444
                                                } catch (RasterDriverException e) {
445
                                                        // TODO Auto-generated catch block
446
                                                        e.printStackTrace();
447
                                                } catch (InvalidSetViewException e) {
448
                                                        // TODO Auto-generated catch block
449
                                                        e.printStackTrace();
450
                                                } catch (InterruptedException e) {
451
                                                        // TODO Auto-generated catch block
452
                                                        e.printStackTrace();
453
                                                } catch (Exception e) {
454
                                                        return;
455
                                                }
456

    
457
                                                RasterBuffer raster = (RasterBuffer) bufferFactory
458
                                                .getRasterBuf();
459
                                                raster.setNoDataValue(0.0);
460
                                                raster.setNotValidValue(0.0);
461
                                                try {
462
                                                        WriterBufferServer bufferServer = new WriterBufferServer(
463
                                                                        raster);
464
                                                        Params p = GeoRasterWriter.getWriter(fName).getParams();
465
                                                        AffineTransform at = new AffineTransform(tileExtent
466
                                                                        .getWidth() / 32, 0, 0,
467
                                                                        -(tileExtent.getHeight() / 32), tileExtent
468
                                                                        .getMinX(), tileExtent.getMaxY());
469
                                                        GeoRasterWriter grw = GeoRasterWriter.getWriter(
470
                                                                        bufferServer, fName, 1, at, raster.getWidth(),
471
                                                                        raster.getHeight(), raster.getDataType(), p, null);
472
                                                        synchronized (cacheMutex) {
473
                                                                try {
474
                                                                        grw.dataWrite();
475
                                                                } catch (InterruptedException e) {
476
                                                                        e.printStackTrace();
477
                                                                }
478
                                                                grw.writeClose();
479
                                                        }
480

    
481
                                                } catch (NotSupportedExtensionException e) {
482
                                                        // e.printStackTrace();
483
                                                        return;
484
                                                } catch (RasterDriverException e) {
485
                                                        // e.printStackTrace();
486
                                                        return;
487
                                                } catch (IOException e) {
488
                                                        // e.printStackTrace();
489
                                                        return;
490
                                                }
491

    
492
                                        }
493
                        }
494
                }                
495

    
496
                //The method cant return a image because ImageIO crashes with tiff images.
497
                /*try {
498
                        synchronized (cacheMutex) {
499
                                image = ImageIO.read(new File(fName));
500
                        }
501
                } catch (IOException e) {
502
                        return null;
503
                }
504
                return image;*/
505
        }
506

    
507
        public String getTileAsFName(TileNum t, Rectangle2D extent)
508
        throws CacheServiceException {
509
                if (_loadFailed) {
510
                        throw new CacheServiceException(new Exception());
511
                }
512

    
513
                String fName = getTileFileName(t);
514
                boolean fileExists = false;
515
                synchronized (cacheMutex) {
516
                        fileExists = new File(fName).exists();
517
                }
518
                if (!fileExists) {
519
                        Rectangle2D tileExtent = extent;
520
                        requestTileFromLayer(fName,tileExtent);
521
                        //if (getTileFromLayer(fName, tileExtent) == null)
522
                        fName = null;
523
                }
524
                
525
                return fName;
526
        }
527

    
528
        /**
529
         * @TODO: This method crashes with tiff images use getTileAsFileName instead
530
         */
531
        public Image getTileAsImage(TileNum tileNum, Rectangle2D extent)
532
        throws CacheServiceException {
533

    
534
                if (_loadFailed) {
535
                        throw new CacheServiceException(new Exception());
536
                }
537
                String fName = getTileFileName(tileNum);
538
                Image image = null;
539
                boolean fileExists = false;
540
                synchronized (cacheMutex) {
541
                        fileExists = new File(fName).exists();
542
                }
543
                if (!fileExists) {
544
                        Rectangle2D tileExtent = extent;
545
                        requestTileFromLayer(fName,tileExtent);
546
                        //image = getTileFromLayer(fName, tileExtent);
547
                } else {
548
                        //ImageIO cant read tiff images. Change in the next version.
549
                        /*try {
550
                                //image = ImageIO.read(new File(fName));
551
                        } catch (IOException e) {
552
                                return null;
553
                        }*/
554
                }
555
                return image;
556
        }
557

    
558
        public boolean intersectsLayer(Rectangle2D extent) {
559
                return _lyrExtentRect.intersects(extent);
560
        }
561

    
562
        public void free() throws Throwable {
563
                _logger.info("finalizing cache service and thread");
564
                _requestTileFromLayerThread.setDone(true);
565
                _requestThead.join();
566
        }
567

    
568
        public WMSStatus getWMSStatus(){
569
                
570
                return _wmsStatus; 
571
                
572
        }
573
        /*@Override
574
        protected void finalize() throws Throwable {
575
                _logger.info("finalizing cache service and thread");
576
                _requestTileFromLayerThread.setDone(true);
577
                _requestThead.join();
578
                super.finalize();
579
        }*/
580

    
581
}