001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/ogcwebservices/wmps/GetMapServiceInvokerForUL.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003    
004     This file is part of deegree.
005     Copyright (C) 2001-2008 by:
006     EXSE, Department of Geography, University of Bonn
007     http://www.giub.uni-bonn.de/deegree/
008     lat/lon GmbH
009     http://www.lat-lon.de
010    
011     This library is free software; you can redistribute it and/or
012     modify it under the terms of the GNU Lesser General Public
013     License as published by the Free Software Foundation; either
014     version 2.1 of the License, or (at your option) any later version.
015    
016     This library is distributed in the hope that it will be useful,
017     but WITHOUT ANY WARRANTY; without even the implied warranty of
018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
019     Lesser General Public License for more details.
020    
021     You should have received a copy of the GNU Lesser General Public
022     License along with this library; if not, write to the Free Software
023     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
024    
025     Contact:
026    
027     Andreas Poth
028     lat/lon GmbH
029     Aennchenstr. 19
030     53115 Bonn
031     Germany
032     E-Mail: poth@lat-lon.de
033    
034     Prof. Dr. Klaus Greve
035     Department of Geography
036     University of Bonn
037     Meckenheimer Allee 166
038     53115 Bonn
039     Germany
040     E-Mail: greve@giub.uni-bonn.de
041    
042     ---------------------------------------------------------------------------*/
043    package org.deegree.ogcwebservices.wmps;
044    
045    import java.io.ByteArrayOutputStream;
046    import java.io.InputStreamReader;
047    import java.io.StringReader;
048    import java.net.URL;
049    
050    import org.deegree.framework.log.ILogger;
051    import org.deegree.framework.log.LoggerFactory;
052    import org.deegree.framework.util.CharsetUtils;
053    import org.deegree.framework.util.IDGenerator;
054    import org.deegree.framework.util.NetWorker;
055    import org.deegree.framework.util.StringTools;
056    import org.deegree.framework.xml.XMLFragment;
057    import org.deegree.graphics.MapFactory;
058    import org.deegree.graphics.sld.AbstractStyle;
059    import org.deegree.graphics.sld.FeatureTypeConstraint;
060    import org.deegree.graphics.sld.LayerFeatureConstraints;
061    import org.deegree.graphics.sld.RemoteOWS;
062    import org.deegree.graphics.sld.UserLayer;
063    import org.deegree.graphics.sld.UserStyle;
064    import org.deegree.model.feature.FeatureCollection;
065    import org.deegree.model.feature.GMLFeatureCollectionDocument;
066    import org.deegree.model.filterencoding.Filter;
067    import org.deegree.ogcwebservices.OGCWebServiceException;
068    import org.deegree.ogcwebservices.wfs.WFService;
069    import org.deegree.ogcwebservices.wfs.operation.FeatureResult;
070    import org.deegree.ogcwebservices.wfs.operation.GetFeature;
071    import org.deegree.ogcwebservices.wms.capabilities.Layer;
072    import org.deegree.ogcwebservices.wms.configuration.AbstractDataSource;
073    import org.w3c.dom.Element;
074    
075    /**
076     * This a copy of the WMS package.
077     * 
078     * class for accessing the data of one user layer and creating <tt>DisplayElement</tt>s and a
079     * <tt>Thrme</tt> from it. The class extends <tt>Thread</tt> and implements the run method, so
080     * that a parallel data accessing from several layers is possible.
081     * 
082     * @version $Revision: 9348 $
083     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
084     * @author last edited by: $Author: apoth $
085     * 
086     * @version 1.0. $Revision: 9348 $, $Date: 2007-12-27 17:59:14 +0100 (Do, 27 Dez 2007) $
087     * 
088     * @since 2.0
089     */
090    class GetMapServiceInvokerForUL extends Thread {
091    
092        private static final ILogger LOG = LoggerFactory.getLogger( GetMapServiceInvokerForUL.class );
093    
094        private final DefaultGetMapHandler handler;
095    
096        private UserLayer layer = null;
097    
098        private UserStyle[] styles = null;
099    
100        private int index = 0;
101    
102        GetMapServiceInvokerForUL( DefaultGetMapHandler handler, UserLayer layer, int index ) {
103            this.layer = layer;
104            this.handler = handler;
105            AbstractStyle[] tmp = layer.getStyles();
106            this.styles = new UserStyle[tmp.length];
107            for ( int i = 0; i < tmp.length; i++ ) {
108                this.styles[i] = (UserStyle) tmp[i];
109            }
110    
111            this.index = index;
112        }
113    
114        /**
115         * overrides/implements the run-method of <tt>Thread</tt>
116         */
117        @Override
118        public void run() {
119            
120    
121            try {
122                if ( this.layer.getRemoteOWS() == null || this.layer.getRemoteOWS().getService().equals( RemoteOWS.WFS ) ) {
123                    handleWFS();
124                } else if ( this.layer.getRemoteOWS().getService().equals( RemoteOWS.WCS ) ) {
125                    handleWCS();
126                }
127            } catch ( Exception e ) {
128                LOG.logError( "", e );
129                OGCWebServiceException exce = new OGCWebServiceException(
130                                                                          "ServiceInvokerForUL: " + this.layer.getName(),
131                                                                          "Couldn't perform query!"
132                                                                                                  + StringTools.stackTraceToString( e ) );
133                this.handler.putTheme( this.index, exce );
134                this.handler.increaseCounter();
135                
136                return;
137            }
138    
139            
140        }
141    
142        /**
143         * handles requests against a WFS
144         * 
145         * @throws Exception
146         */
147        private void handleWFS()
148                                throws Exception {
149    
150            
151    
152            FeatureCollection fc = null;
153            String request = createGetFeatureRequest();
154    
155            if ( this.layer.getRemoteOWS() != null ) {
156                // handle request against a remote WFS
157                RemoteOWS remoteOWS = this.layer.getRemoteOWS();
158                URL url = remoteOWS.getOnlineResource();
159                NetWorker nw = new NetWorker( CharsetUtils.getSystemCharset(), url, request );
160                InputStreamReader isr = new InputStreamReader( nw.getInputStream(), CharsetUtils.getSystemCharset() );
161                GMLFeatureCollectionDocument doc = new GMLFeatureCollectionDocument();
162                doc.load( isr, url.toString() );
163                Element root = doc.getRootElement();
164    
165                if ( root.getNodeName().indexOf( "Exception" ) > -1 ) {
166                    ByteArrayOutputStream bos = new ByteArrayOutputStream( 1000 );
167                    doc.write( bos );
168                    throw new Exception( new String( bos.toByteArray() ) );
169                }
170                fc = doc.parse();
171            } else {
172                // handle request agaist a local WFS; this is bit problematic
173                // because deegree WMS is able to handle more than one
174                // local WFS. At the moment the WFS will be used that will
175                // returned by the WFServiceFactory as default
176                XMLFragment xml = new XMLFragment( new StringReader( request ), XMLFragment.DEFAULT_URL );
177                Element root = xml.getRootElement();
178                // create OGCWebServiceEvent object
179                IDGenerator idg = IDGenerator.getInstance();
180                GetFeature gfr = GetFeature.create( "" + idg.generateUniqueID(), root );
181    
182                // returns the WFS responsible for handling current feature type
183                WFService wfs = getResponsibleService();
184                FeatureResult fr = (FeatureResult) wfs.doService( gfr );
185                fc = (FeatureCollection) fr.getResponse();
186            }
187            org.deegree.graphics.Layer fl = MapFactory.createFeatureLayer( this.layer.getName(), this.handler.reqCRS, fc );
188            this.handler.putTheme( this.index, MapFactory.createTheme( this.layer.getName(), fl, this.styles ) );
189            this.handler.increaseCounter();
190            
191        }
192    
193        /**
194         * Returns the responsible service.
195         * 
196         * @return Exception
197         * @throws OGCWebServiceException
198         */
199        private WFService getResponsibleService()
200                                throws OGCWebServiceException {
201    
202            LayerFeatureConstraints lfc = this.layer.getLayerFeatureConstraints();
203            FeatureTypeConstraint[] ftc = lfc.getFeatureTypeConstraint();
204            Layer root = this.handler.getConfiguration().getLayer();
205            WFService wfs = findService( root, ftc[0].getFeatureTypeName().getPrefixedName() );
206            if ( wfs == null ) {
207                throw new OGCWebServiceException( this.getName(), "feature type: " + ftc[0].getFeatureTypeName()
208                                                                  + " is not serverd by this WMS/WFS" );
209            }
210            return wfs;
211    
212        }
213    
214        /**
215         * searches/findes the WFService that is resposible for handling the feature types of the
216         * current request. If no WFService instance can be found <code>null</code> will be returned
217         * to indicated that the current feature type is not served by the internal WFS of a WMS
218         * 
219         * @param currentlayer
220         * @param featureType
221         * @return WFService
222         * @throws OGCWebServiceException
223         */
224        private WFService findService( Layer currentlayer, String featureType )
225                                throws OGCWebServiceException {
226            Layer[] layers = currentlayer.getLayer();
227            for ( int i = 0; i < layers.length; i++ ) {
228                AbstractDataSource[] ad = layers[i].getDataSource();
229                if ( ad != null ) {
230                    for ( int j = 0; j < ad.length; j++ ) {
231                        if ( ad[j].getName().getPrefixedName().equals( featureType ) ) {
232                            return (WFService) ad[j].getOGCWebService();
233                        }
234                    }
235                }
236                // recursion
237                WFService wfs = findService( layers[i], featureType );
238                if ( wfs != null ) {
239                    return wfs;
240                }
241            }
242    
243            return null;
244        }
245    
246        /**
247         * creates a GetFeature request related to the UserLayer encapsulated in this object
248         * 
249         * @return String
250         * @throws Exception
251         */
252        private String createGetFeatureRequest()
253                                throws Exception {
254    
255            LayerFeatureConstraints lfc = this.layer.getLayerFeatureConstraints();
256            FeatureTypeConstraint[] ftc = lfc.getFeatureTypeConstraint();
257    
258            // no filter condition has been defined
259            StringBuffer sb = new StringBuffer( 5000 );
260            sb.append( "<?xml version='1.0' encoding='UTF-8'?>" );
261            sb.append( "<GetFeature xmlns='http://www.opengis.net/wfs' " );
262            sb.append( "xmlns:ogc='http://www.opengis.net/ogc' " );
263            sb.append( "xmlns:gml='http://www.opengis.net/gml' " );
264            sb.append( "xmlns:app=\"http://www.deegree.org/app\" " );
265            sb.append( "service='WFS' version='1.1.0' " );
266            sb.append( "outputFormat='text/xml; subtype=gml/3.1.1'>" );
267            for ( int i = 0; i < ftc.length; i++ ) {
268                sb.append( "<Query typeName='" + ftc[i].getFeatureTypeName() + "'>" );
269                Filter filter = ftc[i].getFilter();
270                if ( filter != null ) {
271                    sb.append( filter.toXML() );
272                }
273                sb.append( "</Query>" );
274            }
275            sb.append( "</GetFeature>" );
276    
277            return sb.toString();
278        }
279    
280        /**
281         * handles requests against a WCS
282         * 
283         * @throws Exception
284         */
285        private void handleWCS()
286                                throws Exception {
287            throw new UnsupportedOperationException( "The WCS support has not been implemented as of now. "
288                                                     + "Please bear with us." );
289            /*
290             * TODO RemoteOWS remoteOWS = layer.getRemoteOWS(); URL url = remoteOWS.getOnlineResource();
291             * 
292             * NetWorker nw = new NetWorker( url ); MemoryCacheSeekableStream mcss = new
293             * MemoryCacheSeekableStream( nw.getInputStream() );
294             * 
295             * RenderedOp rop = JAI.create("stream", mcss);
296             * 
297             * GC_GridCoverage gc = new ImageGridCoverage(rop.getAsBufferedImage(),
298             * request.getBoundingBox(), reqCRS, false); mcss.close();
299             * 
300             * org.deegree.graphics.Layer rl = MapFactory.createRasterLayer(layer.getName(), gc);
301             * 
302             * putTheme(index, MapFactory.createTheme(layer.getName(), rl)); mcss.close();
303             * increaseCounter();
304             */
305    
306        }
307    }