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 }