001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/ogcwebservices/wms/GetMapServiceInvokerForUL.java $
002 /*---------------- FILE HEADER ------------------------------------------
003
004 This file is part of deegree.
005 Copyright (C) 2001-2007 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 53177 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.wms;
044
045 import java.io.ByteArrayOutputStream;
046 import java.io.InputStreamReader;
047 import java.io.StringReader;
048 import java.net.URI;
049 import java.net.URL;
050 import java.util.Arrays;
051 import java.util.Iterator;
052 import java.util.List;
053 import java.util.Map;
054
055 import org.deegree.datatypes.QualifiedName;
056 import org.deegree.framework.log.ILogger;
057 import org.deegree.framework.log.LoggerFactory;
058 import org.deegree.framework.util.CharsetUtils;
059 import org.deegree.framework.util.IDGenerator;
060 import org.deegree.framework.util.NetWorker;
061 import org.deegree.framework.xml.XMLFragment;
062 import org.deegree.graphics.MapFactory;
063 import org.deegree.graphics.sld.AbstractStyle;
064 import org.deegree.graphics.sld.FeatureTypeConstraint;
065 import org.deegree.graphics.sld.LayerFeatureConstraints;
066 import org.deegree.graphics.sld.RemoteOWS;
067 import org.deegree.graphics.sld.StyleUtils;
068 import org.deegree.graphics.sld.UserLayer;
069 import org.deegree.graphics.sld.UserStyle;
070 import org.deegree.model.feature.FeatureCollection;
071 import org.deegree.model.feature.GMLFeatureCollectionDocument;
072 import org.deegree.model.filterencoding.Filter;
073 import org.deegree.ogcbase.PropertyPath;
074 import org.deegree.ogcwebservices.OGCWebServiceException;
075 import org.deegree.ogcwebservices.wfs.WFService;
076 import org.deegree.ogcwebservices.wfs.operation.FeatureResult;
077 import org.deegree.ogcwebservices.wfs.operation.GetFeature;
078 import org.w3c.dom.Element;
079
080 /**
081 * class for accessing the data of one user layer and creating <tt>DisplayElement</tt>s and a
082 * <tt>Thrme</tt> from it. The class extends <tt>Thread</tt> and implements the run method, so
083 * that a parallel data accessing from several layers is possible.
084 *
085 * @version $Revision: 6891 $
086 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
087 * @author last edited by: $Author: aschmitz $
088 *
089 * @version 1.0. $Revision: 6891 $, $Date: 2007-05-08 14:02:55 +0200 (Di, 08 Mai 2007) $
090 *
091 * @since 2.0
092 */
093 class GetMapServiceInvokerForUL extends GetMapServiceInvoker implements Runnable {
094
095 private static final ILogger LOG = LoggerFactory.getLogger( GetMapServiceInvokerForUL.class );
096
097 private UserLayer layer = null;
098
099 private UserStyle[] styles = null;
100
101 /**
102 *
103 * @param handler
104 * @param layer
105 * @param scale
106 * current mapscale denominator
107 * @param index
108 */
109 GetMapServiceInvokerForUL( DefaultGetMapHandler handler, UserLayer layer, double scale, int index ) {
110 super( handler, index, scale );
111
112 this.layer = layer;
113 AbstractStyle[] tmp = layer.getStyles();
114 styles = new UserStyle[tmp.length];
115 for ( int i = 0; i < tmp.length; i++ ) {
116 styles[i] = (UserStyle) tmp[i];
117 }
118
119 }
120
121 /**
122 * overrides/implements the run-method of <tt>Thread</tt>
123 */
124 public void run() {
125
126 try {
127 if ( layer.getRemoteOWS() == null || layer.getRemoteOWS().getService().equals( RemoteOWS.WFS ) ) {
128 handleWFS();
129 } else if ( layer.getRemoteOWS().getService().equals( RemoteOWS.WCS ) ) {
130 handleWCS();
131 }
132 } catch ( Exception e ) {
133 LOG.logError( e.getMessage(), e );
134 OGCWebServiceException exce = new OGCWebServiceException( "ServiceInvokerForUL: " + layer.getName(),
135 "Couldn't perform query!" );
136 this.handler.putTheme( index, exce );
137 this.handler.increaseCounter();
138 LOG.exiting();
139 return;
140 }
141
142 }
143
144 /**
145 * handles requests against a WFS
146 */
147 private void handleWFS()
148 throws Exception {
149
150 FeatureCollection fc = null;
151 String request = createGetFeatureRequest();
152 LOG.logDebug( request );
153 if ( layer.getRemoteOWS() != null ) {
154 // handle request against a remote WFS
155 RemoteOWS remoteOWS = layer.getRemoteOWS();
156 URL url = remoteOWS.getOnlineResource();
157
158 NetWorker nw = new NetWorker( CharsetUtils.getSystemCharset(), url, request );
159 InputStreamReader isr = new InputStreamReader( nw.getInputStream(), CharsetUtils.getSystemCharset() );
160 GMLFeatureCollectionDocument doc = new GMLFeatureCollectionDocument();
161 doc.load( isr, url.toString() );
162 Element root = doc.getRootElement();
163
164 if ( root.getNodeName().indexOf( "Exception" ) > -1 ) {
165 ByteArrayOutputStream bos = new ByteArrayOutputStream( 1000 );
166 doc.write( bos );
167 throw new Exception( new String( bos.toByteArray() ) );
168 }
169 fc = doc.parse();
170 } else {
171 // handle request agaist a local WFS; this is bit problematic
172 // because deegree WMS is able to handle more than one
173 // local WFS. At the moment the WFS will be used that will
174 // returned by the WFServiceFactory as default
175 XMLFragment xml = new XMLFragment( new StringReader( request ), XMLFragment.DEFAULT_URL );
176 Element root = xml.getRootElement();
177 // create OGCWebServiceEvent object
178 IDGenerator idg = IDGenerator.getInstance();
179 GetFeature gfr = GetFeature.create( "" + idg.generateUniqueID(), root );
180
181 // returns the WFS responsible for handling current feature type
182 WFService wfs = getResponsibleService( layer );
183 FeatureResult fr = (FeatureResult) wfs.doService( gfr );
184 fc = (FeatureCollection) fr.getResponse();
185 }
186 org.deegree.graphics.Layer fl = MapFactory.createFeatureLayer( layer.getName(), this.handler.getRequestCRS(),
187 fc );
188 this.handler.putTheme( index, MapFactory.createTheme( layer.getName(), fl, styles ) );
189 this.handler.increaseCounter();
190
191 }
192
193 /**
194 * creates a GetFeature request related to the UserLayer encapsulated in this object
195 */
196 private String createGetFeatureRequest()
197 throws Exception {
198
199 LayerFeatureConstraints lfc = layer.getLayerFeatureConstraints();
200 FeatureTypeConstraint[] ftc = lfc.getFeatureTypeConstraint();
201
202 List<UserStyle> styleList = Arrays.asList( styles );
203 List<PropertyPath> pp = StyleUtils.extractRequiredProperties( styleList, scaleDen );
204 LOG.logDebug( "required properties: ", pp );
205 pp = findGeoProperties( layer, ftc, pp );
206 Map<String, URI> namesp = extractNameSpaceDef( pp );
207 for ( int i = 0; i < ftc.length; i++ ) {
208 QualifiedName qn = ftc[i].getFeatureTypeName();
209 namesp.put( qn.getPrefix(), qn.getNamespace() );
210 }
211
212 StringBuffer sb = new StringBuffer( 5000 );
213 sb.append( "<?xml version='1.0' encoding='" + CharsetUtils.getSystemCharset() + "'?>" );
214 sb.append( "<GetFeature xmlns='http://www.opengis.net/wfs' " );
215 sb.append( "xmlns:ogc='http://www.opengis.net/ogc' " );
216 sb.append( "xmlns:gml='http://www.opengis.net/gml' " );
217
218 Iterator<String> iter = namesp.keySet().iterator();
219 while ( iter.hasNext() ) {
220 String pre = iter.next();
221 URI nsp = namesp.get( pre );
222 if ( !pre.equals( "xmlns" ) ) {
223 sb.append( "xmlns:" ).append( pre ).append( "='" );
224 sb.append( nsp.toASCIIString() ).append( "' " );
225 }
226 }
227
228 sb.append( "service='WFS' version='1.1.0' " );
229 sb.append( "outputFormat='text/xml; subtype=gml/3.1.1'>" );
230 for ( int i = 0; i < ftc.length; i++ ) {
231 QualifiedName qn = ftc[i].getFeatureTypeName();
232 sb.append( "<Query typeName='" ).append( qn.getPrefixedName() ).append( "'>" );
233
234 for ( int j = 0; j < pp.size(); j++ ) {
235 if ( !pp.get( j ).getAsString().endsWith( "$SCALE" ) ) {
236 // $SCALE is a dynamicly created property of each feature
237 // and can not be requested
238 sb.append( "<PropertyName>" ).append( pp.get( j ).getAsString() );
239 sb.append( "</PropertyName>" );
240 }
241 }
242
243 Filter filter = ftc[i].getFilter();
244 if ( filter != null ) {
245 sb.append( filter.toXML() );
246 }
247 sb.append( "</Query>" );
248 }
249 sb.append( "</GetFeature>" );
250
251 LOG.logDebug( sb.toString() );
252
253 return sb.toString();
254 }
255
256 /**
257 * handles requests against a WCS
258 */
259 private void handleWCS()
260 throws Exception {
261
262 /*
263 * TODO RemoteOWS remoteOWS = layer.getRemoteOWS(); URL url = remoteOWS.getOnlineResource();
264 *
265 * NetWorker nw = new NetWorker( url ); MemoryCacheSeekableStream mcss = new
266 * MemoryCacheSeekableStream( nw.getInputStream() );
267 *
268 * RenderedOp rop = JAI.create("stream", mcss);
269 *
270 * GC_GridCoverage gc = new ImageGridCoverage(rop.getAsBufferedImage(),
271 * request.getBoundingBox(), reqCRS, false); mcss.close();
272 *
273 * org.deegree.graphics.Layer rl = MapFactory.createRasterLayer(layer.getName(), gc);
274 *
275 * putTheme(index, MapFactory.createTheme(layer.getName(), rl)); mcss.close();
276 * increaseCounter();
277 */
278
279 }
280
281 }