001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_testing/src/org/deegree/portal/standard/csw/control/DisplayMapListener.java $
002 /*----------------------------------------------------------------------------
003 This file is part of deegree, http://deegree.org/
004 Copyright (C) 2001-2009 by:
005 Department of Geography, University of Bonn
006 and
007 lat/lon GmbH
008
009 This library is free software; you can redistribute it and/or modify it under
010 the terms of the GNU Lesser General Public License as published by the Free
011 Software Foundation; either version 2.1 of the License, or (at your option)
012 any later version.
013 This library is distributed in the hope that it will be useful, but WITHOUT
014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
016 details.
017 You should have received a copy of the GNU Lesser General Public License
018 along with this library; if not, write to the Free Software Foundation, Inc.,
019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020
021 Contact information:
022
023 lat/lon GmbH
024 Aennchenstr. 19, 53177 Bonn
025 Germany
026 http://lat-lon.de/
027
028 Department of Geography, University of Bonn
029 Prof. Dr. Klaus Greve
030 Postfach 1147, 53001 Bonn
031 Germany
032 http://www.geographie.uni-bonn.de/deegree/
033
034 e-mail: info@deegree.org
035 ----------------------------------------------------------------------------*/
036
037 package org.deegree.portal.standard.csw.control;
038
039 import java.io.File;
040 import java.io.FileOutputStream;
041 import java.io.IOException;
042 import java.io.InputStreamReader;
043 import java.io.Reader;
044 import java.net.MalformedURLException;
045 import java.net.URL;
046 import java.util.ArrayList;
047 import java.util.HashMap;
048 import java.util.Iterator;
049 import java.util.List;
050
051 import javax.servlet.http.HttpServletRequest;
052 import javax.servlet.http.HttpSession;
053 import javax.xml.transform.TransformerFactoryConfigurationError;
054
055 import org.deegree.enterprise.control.FormEvent;
056 import org.deegree.enterprise.control.RPCParameter;
057 import org.deegree.enterprise.control.RPCStruct;
058 import org.deegree.enterprise.control.RPCWebEvent;
059 import org.deegree.framework.log.ILogger;
060 import org.deegree.framework.log.LoggerFactory;
061 import org.deegree.framework.util.CharsetUtils;
062 import org.deegree.framework.util.NetWorker;
063 import org.deegree.framework.xml.XMLFragment;
064 import org.deegree.framework.xml.XMLParsingException;
065 import org.deegree.framework.xml.XMLTools;
066 import org.deegree.i18n.Messages;
067 import org.deegree.model.crs.CRSFactory;
068 import org.deegree.model.crs.CoordinateSystem;
069 import org.deegree.model.crs.UnknownCRSException;
070 import org.deegree.model.spatialschema.Envelope;
071 import org.deegree.model.spatialschema.GeometryFactory;
072 import org.deegree.model.spatialschema.Point;
073 import org.deegree.ogcbase.BaseURL;
074 import org.deegree.ogcbase.ImageURL;
075 import org.deegree.ogcwebservices.getcapabilities.InvalidCapabilitiesException;
076 import org.deegree.ogcwebservices.wms.capabilities.Layer;
077 import org.deegree.ogcwebservices.wms.capabilities.LegendURL;
078 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilities;
079 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocument;
080 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocumentFactory;
081 import org.deegree.portal.PortalException;
082 import org.deegree.portal.context.ContextException;
083 import org.deegree.portal.context.Format;
084 import org.deegree.portal.context.FormatList;
085 import org.deegree.portal.context.General;
086 import org.deegree.portal.context.GeneralExtension;
087 import org.deegree.portal.context.LayerList;
088 import org.deegree.portal.context.Server;
089 import org.deegree.portal.context.Style;
090 import org.deegree.portal.context.StyleList;
091 import org.deegree.portal.context.ViewContext;
092 import org.deegree.portal.context.WebMapContextFactory;
093 import org.deegree.portal.context.XMLFactory;
094 import org.deegree.portal.standard.csw.CatalogClientException;
095 import org.deegree.portal.standard.csw.configuration.CSWClientConfiguration;
096 import org.deegree.portal.standard.csw.model.DataSessionRecord;
097 import org.deegree.portal.standard.csw.model.ServiceSessionRecord;
098 import org.deegree.portal.standard.csw.model.ShoppingCart;
099 import org.w3c.dom.Document;
100 import org.xml.sax.SAXException;
101
102 /**
103 * A <code>${type_name}</code> class.<br/>
104 *
105 * This listener is called when one or more items of the shopping cart shall be displayed in a map. For all chosen items
106 * of the cart the wms layers are collected and a new mapcontext containing these layers is created/saved in the users
107 * folder (user must be logged in). Then, the contextname is passed to the follow up page to be loaded in the portal.
108 *
109 * @author <a href="mailto:mays@lat-lon.de">Judit Mays</a>
110 * @author last edited by: $Author: mschneider $
111 *
112 * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
113 *
114 * @deprecated Shopping cart will not be supported at the moment. update: new changes in deegree1_fork will not be
115 * carried here, since this class is still not used. Remove when this status changes
116 */
117 @Deprecated
118 public class DisplayMapListener extends AddToShoppingCartListener {
119 // extends AddToShoppingCartListener --> SimpleSearchListener --> AbstractListener.
120
121 private static final ILogger LOG = LoggerFactory.getLogger( DisplayMapListener.class );
122
123 private String userDir = "WEB-INF/conf/igeoportal/users/";
124
125 /*
126 * (non-Javadoc)
127 *
128 * @see org.deegree.enterprise.control.WebListener#actionPerformed(org.deegree.enterprise.control.FormEvent)
129 */
130 @Override
131 public void actionPerformed( FormEvent event ) {
132
133 RPCWebEvent rpcEvent = (RPCWebEvent) event;
134 HttpSession session = ( (HttpServletRequest) this.getRequest() ).getSession( true );
135 ShoppingCart cart = (ShoppingCart) session.getAttribute( Constants.SESSION_SHOPPINGCART );
136 config = (CSWClientConfiguration) session.getAttribute( Constants.CSW_CLIENT_CONFIGURATION );
137
138 try {
139 validateRequest( rpcEvent );
140 } catch ( Exception e ) {
141 gotoErrorPage( Messages.getMessage( "IGEO_STD_CSW_INVALID_RPC_EVENT", e.getMessage() ) );
142 LOG.logError( e.getMessage(), e );
143 return;
144 }
145
146 List rpcDataSessionRecords = null;
147
148 try {
149 rpcDataSessionRecords = getDataSessionRecordsFromList( cart.getContents(), rpcEvent );
150 } catch ( Exception e ) {
151 gotoErrorPage( Messages.getMessage( "IGEO_STD_CSW_INVALID_RPC_EVENT", e.getMessage() ) );
152 LOG.logError( e.getMessage(), e );
153 return;
154 }
155
156 try {
157 validateWMSAbility( rpcDataSessionRecords );
158 } catch ( Exception e ) {
159 gotoErrorPage( Messages.getMessage( "IGEO_STD_CSW_ERROR_NOT_WMSABLE", e.getMessage() ) );
160 LOG.logError( e.getMessage(), e );
161 return;
162 }
163
164 // GetCapabilities block
165
166 // addressTitlesMap(k=address, v=titleList)
167 HashMap wmsAddressTitlesMap = createWMSAddressToTitlesMapping( rpcDataSessionRecords );
168
169 // addressRequestMap(k=address, v=request)
170 HashMap wmsAddressRequestMap = createCapabilitiesRequests( wmsAddressTitlesMap );
171
172 // addressCapabilitiesMap(k=address, v=WMSCapabilities)
173 HashMap wmsAddressCapabilityMap = null;
174 try {
175 wmsAddressCapabilityMap = createAddressToWMSCapabilitiesMapping( wmsAddressRequestMap );
176 } catch ( Exception e ) {
177 gotoErrorPage( Messages.getMessage( "IGEO_STD_CSW_ERROR_CREATE_WMSCAPS", e.getMessage() ) );
178 LOG.logError( e.getMessage(), e );
179 return;
180 }
181
182 // HashMap titleCSWAddressMap = createTitleToCswAddressMap( rpcDataSessionRecords );
183 // HashMap titleIdentifierMap = createTitleToIdentiferMap( rpcDataSessionRecords );
184
185 ViewContext vc = null;
186 try {
187 vc = setContextLayers( wmsAddressTitlesMap, wmsAddressCapabilityMap, rpcDataSessionRecords );
188 } catch ( Exception e ) {
189 gotoErrorPage( Messages.getMessage( "IGEO_STD_CSW_ERROR_CREATE_CNTXT_LAYERS", e.getMessage() ) );
190 LOG.logError( e.getMessage(), e );
191 return;
192 }
193
194 // identify user block
195
196 String contextName = "newContext";
197 try {
198 contextName = extractContextName( rpcEvent );
199 } catch ( Exception e ) {
200 gotoErrorPage( Messages.getMessage( "IGEO_STD_CSW_MISSING_PARAM", "CONTEXT_NAME" ) );
201 LOG.logError( e.getMessage(), e );
202 return;
203 }
204
205 String sessionId;
206 try {
207 sessionId = extractSessionId( rpcEvent );
208 } catch ( Exception e ) {
209 gotoErrorPage( Messages.getMessage( "IGEO_STD_CSW_MISSING_PARAM", "SESSION_ID" ) );
210 LOG.logError( e.getMessage(), e );
211 return;
212 }
213
214 String userName = null;
215 try {
216 userName = getUserNameForId( sessionId );
217 } catch ( Exception e ) {
218 gotoErrorPage( Messages.getMessage( "IGEO_STD_CSW_ERROR_DETERMIN_USERNAME", e.getMessage() ) );
219 LOG.logError( e.getMessage(), e );
220 return;
221 }
222
223 // create WebMapContext Document block
224
225 try {
226 vc.getGeneral().setTitle( contextName );
227 } catch ( Exception e ) {
228 gotoErrorPage( Messages.getMessage( "IGEO_STD_CSW_ERROR_SET_CNTXT_TITLE", e.getMessage() ) );
229 LOG.logError( e.getMessage(), e );
230 return;
231 }
232
233 Envelope bbox = null;
234 String msg = null;
235 try {
236 msg = Messages.getMessage( "IGEO_STD_CSW_ERROR_DETERMIN_BBOX" );
237 bbox = determinCombiningBBox( rpcDataSessionRecords );
238 if ( bbox != null ) {
239 msg = Messages.getMessage( "IGEO_STD_CSW_ERROR_CHANGE_BBOX" );
240 changeBBox( vc, bbox );
241 }
242 } catch ( Exception e ) {
243 gotoErrorPage( msg + e.getMessage() );
244 LOG.logError( e.getMessage(), e );
245 return;
246 }
247
248 try {
249 storeContext( userName, contextName, vc );
250 } catch ( Exception e ) {
251 gotoErrorPage( Messages.getMessage( "IGEO_STD_CSW_ERROR_STORE_CNTXT", e.getMessage() ) );
252 LOG.logError( e.getMessage(), e );
253 return;
254 }
255
256 // write contextname to request
257 StringBuffer path2Dir = new StringBuffer( "users/" );
258 path2Dir.append( userName ).append( "/" ).append( contextName ).append( ".xml" );
259 this.getRequest().setAttribute( "CONTEXTNAME", path2Dir.toString() );
260
261 return;
262 }
263
264 /*
265 * (non-Javadoc)
266 *
267 * @see org.deegree.portal.standard.csw.control.SimpleSearchListener#validateRequest(org.deegree.enterprise.control.RPCWebEvent)
268 */
269 @Override
270 protected void validateRequest( RPCWebEvent rpcEvent )
271 throws CatalogClientException {
272
273 try {
274 extractSessionId( rpcEvent );
275 } catch ( CatalogClientException e ) {
276 throw new CatalogClientException( Messages.getMessage( "IGEO_STD_CSW_MISSING_PARAM", "SESSION_ID" ) );
277 }
278 String contextName = null;
279 try {
280 contextName = extractContextName( rpcEvent );
281 } catch ( CatalogClientException e ) {
282 throw new CatalogClientException( Messages.getMessage( "IGEO_STD_CSW_MISSING_PARAM", "CONTEXT_NAME" ) );
283 }
284 if ( contextName == null || "null".equals( contextName ) ) {
285 throw new CatalogClientException( Messages.getMessage( "IGEO_STD_CSW_ERROR_CNTXT_NAME_IS_NULL" ) );
286 }
287
288 RPCParameter[] params = extractRPCParameters( rpcEvent );
289 for ( int i = 1; i < params.length; i++ ) {
290
291 RPCStruct struct = extractRPCStruct( rpcEvent, 0 );
292 struct = extractRPCStruct( rpcEvent, i );
293 Object o = extractRPCMember( struct, Constants.RPC_IDENTIFIER );
294 if ( o == null ) {
295 throw new CatalogClientException( Messages.getMessage( "IGEO_STD_CSW_MISSING_PARAM",
296 Constants.RPC_IDENTIFIER ) );
297 }
298 o = extractRPCMember( struct, RPC_CATALOG );
299 if ( o == null ) {
300 throw new CatalogClientException( Messages.getMessage( "IGEO_STD_CSW_MISSING_PARAM", RPC_CATALOG ) );
301 }
302 o = extractRPCMember( struct, RPC_TITLE );
303 if ( o == null ) {
304 throw new CatalogClientException( Messages.getMessage( "IGEO_STD_CSW_MISSING_PARAM", RPC_TITLE ) );
305 }
306
307 RPCStruct bboxStruct = null;
308 if ( struct.getMember( Constants.RPC_BBOX ) != null ) {
309 bboxStruct = (RPCStruct) struct.getMember( Constants.RPC_BBOX ).getValue();
310 }
311 if ( bboxStruct != null ) {
312 Double member = (Double) extractRPCMember( bboxStruct, Constants.RPC_BBOXMINX );
313 if ( member == null ) {
314 throw new CatalogClientException( Messages.getMessage( "IGEO_STD_CSW_INVALID_BBOX_VALUE",
315 Constants.RPC_BBOXMINX ) );
316 }
317 member = (Double) extractRPCMember( bboxStruct, Constants.RPC_BBOXMINY );
318 if ( member == null ) {
319 throw new CatalogClientException( Messages.getMessage( "IGEO_STD_CSW_INVALID_BBOX_VALUE",
320 Constants.RPC_BBOXMINY ) );
321 }
322 member = (Double) extractRPCMember( bboxStruct, Constants.RPC_BBOXMAXX );
323 if ( member == null ) {
324 throw new CatalogClientException( Messages.getMessage( "IGEO_STD_CSW_INVALID_BBOX_VALUE",
325 Constants.RPC_BBOXMAXX ) );
326 }
327 member = (Double) extractRPCMember( bboxStruct, Constants.RPC_BBOXMAXY );
328 if ( member == null ) {
329 throw new CatalogClientException( Messages.getMessage( "IGEO_STD_CSW_INVALID_BBOX_VALUE",
330 Constants.RPC_BBOXMAXY ) );
331 }
332 }
333 }
334
335 return;
336 }
337
338 /**
339 * @param contents
340 * The List of DataSessionRecords to get DataSessionRecords from.
341 * @param rpcEvent
342 * The RpcWebEvent contains the parameters defining the DataSessionRecords to get from the passed List.
343 * @return Returns a sublist of the passed contents, where each of the contained DataSessionRecords is defined by
344 * the parameters of the passed rpcEvent OR null, if no matches were found in the passed List.
345 * @throws CatalogClientException
346 * @throws IllegalArgumentException,
347 * if if at least one record defined by the passed rpcEvent is not part of the passed List.
348 */
349 private List getDataSessionRecordsFromList( List contents, RPCWebEvent rpcEvent )
350 throws CatalogClientException {
351
352 RPCParameter[] params = extractRPCParameters( rpcEvent );
353 List<DataSessionRecord> dsrList = new ArrayList<DataSessionRecord>( params.length );
354 boolean matches = false;
355
356 for ( int i = 1; i < params.length; i++ ) {
357 RPCStruct struct = extractRPCStruct( rpcEvent, i );
358 String id = (String) struct.getMember( Constants.RPC_IDENTIFIER ).getValue();
359 String catalog = (String) struct.getMember( RPC_CATALOG ).getValue();
360 String title = (String) struct.getMember( RPC_TITLE ).getValue();
361
362 DataSessionRecord dsr = getDataSessionRecordFromList( contents, id, catalog, title );
363 if ( dsr == null ) {
364 throw new IllegalArgumentException( Messages.getMessage( "IGEO_STD_CSW_ILLEGAL_ARGS", id ) );
365 }
366 dsrList.add( dsr );
367 matches = true;
368 }
369
370 if ( matches ) {
371 return dsrList;
372 }
373 return null;
374 }
375
376 /**
377 * Checks, if each DataSessionRecord in the passed List contains at least one "OGC:WMS" serviceType.
378 *
379 * @param dataSessionRecords
380 * List of DataSessionRecords in the ShoppingCart.
381 * @throws CatalogClientException,
382 * if at least one record in the passed List has no WMS ability.
383 */
384 private void validateWMSAbility( List dataSessionRecords )
385 throws CatalogClientException {
386
387 for ( int i = 0; i < dataSessionRecords.size(); i++ ) {
388 boolean wmsAble = false;
389 DataSessionRecord dsr = (DataSessionRecord) dataSessionRecords.get( i );
390 for ( int j = 0; j < dsr.getServices().length; j++ ) {
391 if ( "OGC:WMS".equals( dsr.getServices()[j].getServiceType() ) ) {
392 wmsAble = true;
393 break;
394 }
395 }
396 if ( !wmsAble ) {
397 throw new CatalogClientException( Messages.getMessage( "IGEO_STD_CSW_ERROR_NO_WMSABLE_ID",
398 dsr.getIdentifier() ) );
399 }
400 }
401
402 return;
403 }
404
405 /**
406 * Creates a HashMap with the WebMapService address as key and a List of titles of the resources as value. Both
407 * titles and addresses are taken from the passed List of DataSessionRecords. For each DataSessionRecord only the
408 * first WMS address is used.
409 *
410 * @param dataSessionRecords
411 * @return Returns a HashMap containing the wmsAddress (as key) and the title (as value).
412 */
413 private HashMap<String, List<String>> createWMSAddressToTitlesMapping( List dataSessionRecords ) {
414
415 HashMap<String, List<String>> wmsAddressToTitlesMap = new HashMap<String, List<String>>(
416 dataSessionRecords.size() );
417
418 for ( int i = 0; i < dataSessionRecords.size(); i++ ) {
419 String title = ( (DataSessionRecord) dataSessionRecords.get( i ) ).getTitle();
420 ServiceSessionRecord[] ssrs = ( (DataSessionRecord) dataSessionRecords.get( i ) ).getServices();
421 for ( int j = 0; j < ssrs.length; j++ ) {
422 if ( "OGC:WMS".equals( ssrs[j].getServiceType() ) ) {
423 String addr = ssrs[j].getServiceAddress();
424
425 // since a WMS address might be used by more than one DataSessionRecord,
426 // a List of titles for one address is needed.
427 ArrayList<String> titleList = null;
428 if ( wmsAddressToTitlesMap.get( addr ) != null ) {
429 titleList = (ArrayList<String>) wmsAddressToTitlesMap.get( addr );
430 if ( !titleList.contains( title ) ) {
431 titleList.add( title );
432 }
433 } else {
434 titleList = new ArrayList<String>( 10 );
435 titleList.add( title );
436 }
437 wmsAddressToTitlesMap.put( addr, titleList );
438 break; // only use the first WMS address for each DataSessionRecord.
439 }
440 }
441 }
442
443 return wmsAddressToTitlesMap;
444 }
445
446 /**
447 * @param addressTitlesMap
448 * Map from which the WMS addresses are taken.
449 * @return Returns a HashMap containing the WMS address as key and the GetCapabilities request as value.
450 */
451 private HashMap<String, String> createCapabilitiesRequests( HashMap addressTitlesMap ) {
452
453 HashMap<String, String> addressRequestMap = new HashMap<String, String>( addressTitlesMap.size() );
454
455 for ( Iterator it = addressTitlesMap.keySet().iterator(); it.hasNext(); ) {
456 String address = (String) it.next();
457 String request = null;
458 if ( address.endsWith( "?" ) ) {
459 request = address + "request=GetCapabilities&service=WMS";
460 } else {
461 request = address + "?request=GetCapabilities&service=WMS";
462 }
463 addressRequestMap.put( address, request );
464 }
465
466 return addressRequestMap;
467 }
468
469 /**
470 * Creates a HashMap with the WebMapService address as key and a WMSCapabilities object as value.
471 *
472 * @param addressRequestMap
473 * The Map containing the address as key for the Map to be returned, and the request as String, with
474 * which to create the Capability object.
475 * @return Returns a HashMap containing the WMS address as key and a WMSCapabilities object as value.
476 * @throws MalformedURLException
477 * @throws SAXException
478 * @throws IOException
479 * @throws MalformedURLException
480 * @throws InvalidCapabilitiesException
481 * @throws XMLParsingException
482 */
483 private HashMap<String, WMSCapabilities> createAddressToWMSCapabilitiesMapping( HashMap addressRequestMap )
484 throws MalformedURLException, IOException, SAXException, InvalidCapabilitiesException,
485 XMLParsingException {
486
487 HashMap<String, WMSCapabilities> addressCapabilitiesMap = new HashMap<String, WMSCapabilities>(
488 addressRequestMap.size() );
489
490 for ( Iterator it = addressRequestMap.keySet().iterator(); it.hasNext(); ) {
491 String address = (String) it.next();
492 String request = (String) addressRequestMap.get( address );
493
494 WMSCapabilitiesDocument capsDoc = WMSCapabilitiesDocumentFactory.getWMSCapabilitiesDocument( new URL(
495 request ) );
496 WMSCapabilities capabilities = (WMSCapabilities) capsDoc.parseCapabilities();
497
498 addressCapabilitiesMap.put( address, capabilities );
499
500 }
501
502 return addressCapabilitiesMap;
503 }
504
505 /**
506 * Creates a new ViewContext and sets the context Layers from the passed WMSCapabilities objects that match the
507 * corresponding titles of the passed addressTitlesMap.
508 *
509 * @param wmsAddressTitlesMap
510 * The Map contains the titles for which to search the matching layers.
511 * @param wmsAddressCapabilitiesMap
512 * The Map contains the WMSCapabilities for each address.
513 * @param dataSessionRecords
514 * The List contains the DataSessionRecords.
515 * @return Returns a new ViewContext with the ContextLayers set.
516 * @throws ContextException
517 * @throws SAXException
518 * @throws IOException
519 * @throws XMLParsingException
520 * @throws UnknownCRSException
521 */
522 private ViewContext setContextLayers( HashMap wmsAddressTitlesMap, HashMap wmsAddressCapabilitiesMap,
523 List dataSessionRecords )
524 throws ContextException, IOException, SAXException, XMLParsingException,
525 UnknownCRSException {
526
527 List<org.deegree.portal.context.Layer> contextLayerList = new ArrayList<org.deegree.portal.context.Layer>( 10 );
528
529 File file = new File( getHomePath() + config.getMapContextTemplatePath() );
530 ViewContext vc = WebMapContextFactory.createViewContext( file.toURL(), null, null );
531 Point[] env = vc.getGeneral().getBoundingBox();
532 String[] srs = new String[] { env[0].getCoordinateSystem().getIdentifier() };
533
534 Format[] formats = new Format[1];
535 formats[0] = new Format( "image/jpeg", true );
536 FormatList formatList = new FormatList( formats );
537
538 for ( Iterator it = wmsAddressTitlesMap.keySet().iterator(); it.hasNext(); ) {
539 String address = (String) it.next();
540 List titles = (List) wmsAddressTitlesMap.get( address );
541
542 for ( int i = 0; i < titles.size(); i++ ) {
543 String title = (String) titles.get( i );
544
545 WMSCapabilities capabilities = (WMSCapabilities) wmsAddressCapabilitiesMap.get( address );
546 Layer layer = getLayer( capabilities, title );
547
548 BaseURL metadataURL = createMetadataURL( dataSessionRecords, title );
549
550 ImageURL imageURL = getLegendURL( address, capabilities, layer );
551 Style[] styles = new Style[1];
552 styles[0] = new Style( "default", "default", "", imageURL, true );
553 StyleList styleList = new StyleList( styles );
554
555 Server server = new Server( capabilities.getServiceIdentification().getTitle(),
556 capabilities.getVersion(), "OGC:WMS", new URL( address ), capabilities );
557
558 org.deegree.portal.context.Layer contextLayer = new org.deegree.portal.context.Layer(
559 server,
560 layer.getName(),
561 layer.getTitle(),
562 layer.getAbstract(),
563 srs,
564 null,
565 metadataURL,
566 formatList,
567 styleList,
568 layer.isQueryable(),
569 false, null );
570 contextLayerList.add( contextLayer );
571 }
572 }
573
574 org.deegree.portal.context.Layer[] contextLayers = new org.deegree.portal.context.Layer[contextLayerList.size()];
575 contextLayers = contextLayerList.toArray( contextLayers );
576
577 vc.setLayerList( new LayerList( contextLayers ) );
578
579 return vc;
580 }
581
582 /**
583 * Creates a MetadataURL for a layer of the passed title.
584 *
585 * @param dataSessionRecords
586 * The List contains information necessary for creating the URL.
587 * @param title
588 * The layer's title.
589 * @return Returns the MetadataURL for the passed title.
590 * @throws MalformedURLException
591 */
592 private BaseURL createMetadataURL( List dataSessionRecords, String title )
593 throws MalformedURLException {
594
595 String catalogAddress = getCatalogAddressToTitle( dataSessionRecords, title );
596 String identifier = getIdentifierToTitel( dataSessionRecords, title );
597
598 StringBuffer sb = new StringBuffer( catalogAddress );
599 if ( sb.lastIndexOf( "?" ) != sb.length() - 1 ) {
600 sb.append( "?" );
601 }
602 sb.append( "request=GetRecordById&version=2.0.0&elementsetname=full&id=" );
603 sb.append( identifier );
604
605 URL onlineResource = new URL( sb.toString() );
606 String format = "text/xml";
607
608 BaseURL metadataURL = new BaseURL( format, onlineResource );
609
610 return metadataURL;
611 }
612
613 /**
614 * Gets the catalog address from the configuration file for the catalog that is part of the same DataSessionRecord
615 * in the passed list as the passed title.
616 *
617 * @param dataSessionRecords
618 * List of DataSessionRecords
619 * @param title
620 * @return Returns the catalog address for the passed title.
621 */
622 private String getCatalogAddressToTitle( List dataSessionRecords, String title ) {
623 String catalogAddress = null;
624 String catalogName;
625 for ( int i = 0; i < dataSessionRecords.size(); i++ ) {
626 String dsrTitle = ( (DataSessionRecord) dataSessionRecords.get( i ) ).getTitle();
627 if ( title.equals( dsrTitle ) ) {
628 catalogName = ( (DataSessionRecord) dataSessionRecords.get( i ) ).getCatalogName();
629 catalogAddress = config.getCatalogServerAddress( catalogName );
630 break;
631 }
632 }
633 return catalogAddress;
634 }
635
636 /**
637 * Gets the identifier that is part of the same DataSessionRecord in the passed list as the passed title.
638 *
639 * @param dataSessionRecords
640 * List of DataSessionRecords
641 * @param title
642 * @return Returns the catalog address for the passed title.
643 */
644 private String getIdentifierToTitel( List dataSessionRecords, String title ) {
645 String identifier = null;
646 for ( int i = 0; i < dataSessionRecords.size(); i++ ) {
647 String dsrTitle = ( (DataSessionRecord) dataSessionRecords.get( i ) ).getTitle();
648 if ( title.equals( dsrTitle ) ) {
649 identifier = ( (DataSessionRecord) dataSessionRecords.get( i ) ).getIdentifier();
650 break;
651 }
652 }
653 return identifier;
654 }
655
656 /**
657 * @param address
658 * @param capabilities
659 * @param layer
660 * @return Returns the getLegendGraphic request url.
661 * @throws MalformedURLException
662 */
663 private ImageURL getLegendURL( String address, WMSCapabilities capabilities, Layer layer )
664 throws MalformedURLException {
665
666 org.deegree.ogcwebservices.wms.capabilities.Style style = layer.getStyleResource( "default:" + layer.getName() );
667 if ( style == null ) {
668 style = layer.getStyleResource( "default" );
669 }
670
671 ImageURL imageURL = null;
672 if ( style != null && style.getLegendURL() != null && style.getLegendURL().length > 0 ) {
673 LegendURL lu = style.getLegendURL()[0];
674 imageURL = new ImageURL( lu.getWidth(), lu.getHeight(), lu.getFormat(), lu.getOnlineResource() );
675 } else {
676 StringBuffer sb = new StringBuffer( 5000 );
677 sb.append( address ).append( "?VERSION=" ).append( capabilities.getVersion() );
678 sb.append( "&STYLE=&REQUEST=GetLegendGraphic&FORMAT=image/jpeg&WIDTH=50&HEIGHT=50" );
679 sb.append( "&EXCEPTIONS=application/vnd.ogc.se_inimage" );
680 sb.append( "&LAYER=" ).append( layer.getName() );
681 imageURL = new ImageURL( 50, 50, "image/jpeg", new URL( sb.toString() ) );
682 }
683
684 return imageURL;
685 }
686
687 /**
688 * Returns the Layer identified by the submitted name. If no Layer matches the title <tt>null</tt> will be
689 * returned.
690 *
691 * @param capabilities
692 * @param title
693 * The title of the requested layer.
694 * @return Returns a layer object or <tt>null</tt>
695 */
696 private Layer getLayer( WMSCapabilities capabilities, String title ) {
697 Layer layer = capabilities.getLayer();
698 Layer lay = null;
699
700 if ( layer.getTitle() != null && title.equals( layer.getTitle() ) ) {
701 lay = layer;
702 } else {
703 lay = getLayer( title, layer.getLayer() );
704 }
705 return lay;
706 }
707
708 /**
709 * Recursion over all layers to find the layer that matches the submitted title. If no layer can be found that
710 * fullfills the condition <tt>null</tt> will be returned.
711 *
712 * @param title
713 * The title of the layer to be found
714 * @param layers
715 * An array of layers to be searched.
716 * @return Returns a layer object or <tt>null</tt>
717 */
718 private Layer getLayer( String title, Layer[] layers ) {
719 Layer lay = null;
720
721 if ( layers != null ) {
722 for ( int i = 0; i < layers.length; i++ ) {
723 // TODO
724 // remove break statements
725 if ( layers[i].getTitle() != null && title.equals( layers[i].getTitle() ) ) {
726 lay = layers[i];
727 break;
728 }
729 lay = getLayer( title, layers[i].getLayer() );
730 if ( lay != null )
731 break;
732 }
733 }
734 return lay;
735 }
736
737 /**
738 * Extracts the context name from the RPCStruct of the first parameter in the passed RPCWebEvent.
739 *
740 * @param rpcEvent
741 * @return Returns the context (file) name from the rpcEvent.
742 * @throws CatalogClientException
743 */
744 private String extractContextName( RPCWebEvent rpcEvent )
745 throws CatalogClientException {
746 RPCStruct struct = extractRPCStruct( rpcEvent, 0 );
747 return (String) extractRPCMember( struct, "CONTEXT_NAME" );
748 }
749
750 /**
751 * Extracts the sessionId from the RPCStruct of the first parameter in the passed RPCWebEvent.
752 *
753 * @param rpcEvent
754 * @return Returns the sessionId from the rpcEvent.
755 * @throws CatalogClientException
756 */
757 private String extractSessionId( RPCWebEvent rpcEvent )
758 throws CatalogClientException {
759 RPCStruct struct = extractRPCStruct( rpcEvent, 0 );
760 return (String) extractRPCMember( struct, "SESSION_ID" );
761 }
762
763 /**
764 * Gets the user name assigned to the passed session ID from an authentication service.
765 *
766 * If the session ID equals "null", then the default user name is returned. If no user is assigned to the session ID
767 * a CatalogClientException will be returned. If the session is closed or expired an exception will be thrown.
768 *
769 * @param sessionId
770 * @return Returns the user name for the passed session id.
771 * @throws IOException
772 * @throws SAXException
773 * @throws CatalogClientException
774 * @throws XMLParsingException
775 */
776 private String getUserNameForId( String sessionId )
777 throws IOException, SAXException, CatalogClientException, XMLParsingException {
778
779 if ( "null".equals( sessionId ) ) {
780 LOG.logDebug( "sessionId is 'null' => user is 'default'\n" );
781 return "default";
782 }
783
784 HttpSession session = ( (HttpServletRequest) getRequest() ).getSession( true );
785 ViewContext vc = (ViewContext) session.getAttribute( Constants.CURRENTMAPCONTEXT );
786 GeneralExtension ge = vc.getGeneral().getExtension();
787
788 BaseURL baseUrl = ge.getAuthentificationSettings().getAuthentificationURL();
789 StringBuffer sb = new StringBuffer( NetWorker.url2String( baseUrl.getOnlineResource() ) );
790 sb.append( "?request=GetUser&SESSIONID=" ).append( sessionId );
791
792 NetWorker nw = new NetWorker( CharsetUtils.getSystemCharset(), new URL( sb.toString() ) );
793 Reader reader = new InputStreamReader( nw.getInputStream() );
794 Document doc = XMLTools.parse( reader );
795 // Node nsNode = XMLTools.getNamespaceNode(new HashMap());
796
797 String tmp = null;
798 tmp = XMLTools.getNodeAsString( doc.getDocumentElement(), "/User/Name", nsContext, null );
799 if ( tmp == null ) {
800 throw new CatalogClientException( Messages.getMessage( "IGEO_STD_CSW_ERROR_GET_USERNAME", sessionId ) );
801 }
802
803 return tmp;
804 }
805
806 /**
807 * Determins the minimum and maximum values for x and y for the bounding box of each DataSessionRecord in the passed
808 * <code>List</code> and uses these values to determin an all combining bounding box. If none of the passed
809 * records has a bounding box, then null is returned.
810 *
811 * @param rpcDataSessionRecords
812 * List of DataSessionRecords for which to determin a combining bounding box.
813 * @return Returns a new GM_Envelope for a combining bounding box, OR null, if no bounding box was set in any of the
814 * passed DataSessionRecords.
815 * @throws UnknownCRSException
816 */
817 private Envelope determinCombiningBBox( List rpcDataSessionRecords )
818 throws UnknownCRSException {
819
820 Envelope bbox = null;
821
822 // upper left corner of combining bounding box
823 double minx = Double.MAX_VALUE;
824 double maxy = Double.MIN_VALUE;
825 // lower right corner of combining bounding box
826 double maxx = Double.MIN_VALUE;
827 double miny = Double.MAX_VALUE;
828
829 int count = 0;
830 for ( int i = 0; i < rpcDataSessionRecords.size(); i++ ) {
831 DataSessionRecord dsr = (DataSessionRecord) rpcDataSessionRecords.get( i );
832 if ( dsr.getBoundingBox() != null ) {
833 count++;
834 double tempMinx, tempMiny, tempMaxx, tempMaxy;
835 tempMinx = dsr.getBoundingBox().getMin().getX();
836 tempMiny = dsr.getBoundingBox().getMin().getY();
837 tempMaxx = dsr.getBoundingBox().getMax().getX();
838 tempMaxy = dsr.getBoundingBox().getMax().getY();
839
840 // find min for x and y
841 minx = Math.min( tempMinx, minx );
842 miny = Math.min( tempMiny, miny );
843 // find max for x and y
844 maxx = Math.max( tempMaxx, maxx );
845 maxy = Math.max( tempMaxy, maxy );
846 }
847 }
848 if ( count > 0 ) {
849 CoordinateSystem srs = CRSFactory.create( config.getSrs() );
850 bbox = GeometryFactory.createEnvelope( minx, miny, maxx, maxy, srs );
851 }
852
853 return bbox;
854 }
855
856 /**
857 * Changes the bounding box of a given view context.
858 *
859 * @param vc
860 * The view context to be changed
861 * @param bbox
862 * The new bounding box
863 * @throws ContextException
864 */
865 private void changeBBox( ViewContext vc, Envelope bbox )
866 throws ContextException {
867 General general = vc.getGeneral();
868 CoordinateSystem cs = general.getBoundingBox()[0].getCoordinateSystem();
869 Point[] p = new Point[] { GeometryFactory.createPoint( bbox.getMin(), cs ),
870 GeometryFactory.createPoint( bbox.getMax(), cs ) };
871 general.setBoundingBox( p );
872 }
873
874 /**
875 * @param userName
876 * @param contextName
877 * @param vc
878 * @throws TransformerFactoryConfigurationError
879 * @throws PortalException
880 */
881 private void storeContext( String userName, String contextName, ViewContext vc )
882 throws PortalException, TransformerFactoryConfigurationError {
883
884 // save new context
885 StringBuffer path2Dir = new StringBuffer( getHomePath() );
886 path2Dir.append( userDir );
887 path2Dir.append( userName );
888 File file = new File( path2Dir.toString() );
889 if ( !file.exists() ) {
890 // create directory if not existent
891 file.mkdir();
892 }
893 path2Dir.append( "/" ).append( contextName ).append( ".xml" );
894
895 // Document doc = XMLFactory.export( vc );
896 // FileOutputStream fos = new FileOutputStream( path2Dir.toString() );
897 // internalSave( new StreamResult(fos), doc );
898 // fos.close();
899 saveDocument( vc, path2Dir.toString() );
900
901 return;
902 }
903
904 // /**
905 // * common method to save xml
906 // *
907 // * @param result
908 // * @param doc
909 // * @throws TransformerFactoryConfigurationError
910 // * @throws TransformerException
911 // */
912 // protected static void internalSave(Result result, Document doc)
913 // throws TransformerFactoryConfigurationError, TransformerException {
914 // Source source = new DOMSource(doc);
915 // Transformer transformer =
916 // TransformerFactory.newInstance().newTransformer();
917 // transformer.transform(source, result);
918 // }
919
920 /**
921 * saves the new context as xml
922 *
923 * @param vc
924 * @param filename
925 * @throws PortalException
926 */
927 public static final void saveDocument( ViewContext vc, String filename )
928 throws PortalException {
929 try {
930 XMLFragment xml = XMLFactory.export( vc );
931 FileOutputStream fos = new FileOutputStream( filename );
932 xml.write( fos );
933 fos.close();
934 } catch ( Exception e ) {
935 throw new PortalException( Messages.getMessage( "IGEO_STD_CSW_ERROR_SAVE_FILE", filename ) );
936 }
937 }
938
939 }