    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    }