001    //$HeadURL: http://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/portal/context/WebMapContextFactory.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    package org.deegree.portal.context;
037    
038    import java.awt.Rectangle;
039    import java.io.File;
040    import java.io.IOException;
041    import java.io.InputStreamReader;
042    import java.io.Reader;
043    import java.net.MalformedURLException;
044    import java.net.URL;
045    import java.util.HashMap;
046    import java.util.Map;
047    
048    import org.apache.commons.httpclient.HttpClient;
049    import org.apache.commons.httpclient.methods.GetMethod;
050    import org.deegree.datatypes.QualifiedName;
051    import org.deegree.enterprise.WebUtils;
052    import org.deegree.framework.log.ILogger;
053    import org.deegree.framework.log.LoggerFactory;
054    import org.deegree.framework.util.Parameter;
055    import org.deegree.framework.util.ParameterList;
056    import org.deegree.framework.util.StringTools;
057    import org.deegree.framework.xml.ElementList;
058    import org.deegree.framework.xml.NamespaceContext;
059    import org.deegree.framework.xml.XMLFragment;
060    import org.deegree.framework.xml.XMLParsingException;
061    import org.deegree.framework.xml.XMLTools;
062    import org.deegree.graphics.sld.FeatureTypeStyle;
063    import org.deegree.graphics.sld.SLDFactory;
064    import org.deegree.graphics.sld.StyledLayerDescriptor;
065    import org.deegree.model.crs.CRSFactory;
066    import org.deegree.model.crs.CoordinateSystem;
067    import org.deegree.model.crs.UnknownCRSException;
068    import org.deegree.model.metadata.iso19115.Address;
069    import org.deegree.model.metadata.iso19115.CitedResponsibleParty;
070    import org.deegree.model.metadata.iso19115.ContactInfo;
071    import org.deegree.model.metadata.iso19115.Phone;
072    import org.deegree.model.metadata.iso19115.RoleCode;
073    import org.deegree.model.spatialschema.GeometryFactory;
074    import org.deegree.model.spatialschema.Point;
075    import org.deegree.ogcbase.BaseURL;
076    import org.deegree.ogcbase.CommonNamespaces;
077    import org.deegree.ogcbase.ImageURL;
078    import org.deegree.ogcwebservices.OWSUtils;
079    import org.deegree.ogcwebservices.getcapabilities.MetadataURL;
080    import org.deegree.ogcwebservices.getcapabilities.OGCCapabilities;
081    import org.deegree.ogcwebservices.getcapabilities.OGCCapabilitiesDocument;
082    import org.deegree.ogcwebservices.wcs.getcapabilities.WCSCapabilities;
083    import org.deegree.ogcwebservices.wcs.getcapabilities.WCSCapabilitiesDocument;
084    import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilities;
085    import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilitiesDocument;
086    import org.deegree.ogcwebservices.wms.capabilities.LegendURL;
087    import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilities;
088    import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocument;
089    import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocumentFactory;
090    import org.deegree.ogcwebservices.wms.operation.GetLegendGraphic;
091    import org.deegree.owscommon_new.HTTP;
092    import org.deegree.owscommon_new.Operation;
093    import org.deegree.owscommon_new.OperationsMetadata;
094    import org.deegree.security.drm.model.User;
095    import org.w3c.dom.Attr;
096    import org.w3c.dom.Element;
097    import org.w3c.dom.Text;
098    import org.xml.sax.SAXException;
099    
100    /**
101     * Factory class for creating an instance of a web map Context (<tt>ViewContext</tt>). The factory is able to parse
102     * deegree specific extensions (General and Layer) as well as standard web map context documents.
103     * 
104     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
105     * @author last edited by: $Author: apoth $
106     * 
107     * @version $Revision: 31070 $, $Date: 2011-06-16 14:57:48 +0200 (Do, 16 Jun 2011) $
108     */
109    public class WebMapContextFactory {
110    
111        private static final ILogger LOG = LoggerFactory.getLogger( WebMapContextFactory.class );
112    
113        /**
114         * Caching the wms capabilities. Key is the wms address (URL), value is the WMSCapabilities.
115         */
116        private static Map<URL, WMSCapabilities> wmsCache = new HashMap<URL, WMSCapabilities>();
117    
118        private static Map<URL, WFSCapabilities> wfsCache = new HashMap<URL, WFSCapabilities>();
119    
120        private static Map<URL, WCSCapabilities> wcsCache = new HashMap<URL, WCSCapabilities>();
121    
122        /**
123         * creates an instance of a ViewContext from the web map context document read from the passed URL
124         * 
125         * @param url
126         * @param user
127         * @param sessionID
128         * @return new ViewContext for web map context document from <code>url</code>
129         * @throws IOException
130         * @throws XMLParsingException
131         * @throws ContextException
132         * @throws SAXException
133         * @throws UnknownCRSException
134         */
135        public synchronized static ViewContext createViewContext( URL url, User user, String sessionID )
136                                throws IOException, XMLParsingException, ContextException, SAXException,
137                                UnknownCRSException {
138            // cache have to be cleared because contained capabilities may has been
139            // requested with other user identification
140            wmsCache.clear();
141    
142            XMLFragment xml = new XMLFragment( url );
143    
144            return createViewContext( xml, user, sessionID );
145        }
146    
147        /**
148         * @param xml
149         * @param user
150         * @param sessionID
151         * @return new ViewContext for web map context document from <code>xml</code>
152         * @throws IOException
153         * @throws XMLParsingException
154         * @throws ContextException
155         * @throws UnknownCRSException
156         * @throws SAXException
157         */
158        public synchronized static ViewContext createViewContext( XMLFragment xml, User user, String sessionID )
159                                throws IOException, XMLParsingException, ContextException, UnknownCRSException,
160                                SAXException {
161    
162            // general section
163            Element element = XMLTools.getRequiredChildElement( "General", CommonNamespaces.CNTXTNS, xml.getRootElement() );
164            General general = createGeneral( element, xml );
165    
166            // Layer (List) section
167            element = XMLTools.getRequiredChildElement( "LayerList", CommonNamespaces.CNTXTNS, xml.getRootElement() );
168    
169            final LayerList layerList = createLayerList( element, user, sessionID );
170    
171            GeneralExtension ge = general.getExtension();
172            MapModel mapModel = ge.getMapModel();
173            if ( mapModel != null ) {
174                // WMC layers assigned to MapModel layers just can be set after WMC layer
175                // list has been parsed
176                try {
177                    mapModel.walkLayerTree( new MapModelVisitor() {
178    
179                        public void visit( LayerGroup layerGroup )
180                                                throws Exception {
181                        }
182    
183                        public void visit( MMLayer layer )
184                                                throws Exception {
185                            Layer[] layers = layerList.getLayers();
186                            for ( Layer layer2 : layers ) {
187                                if ( layer.getIdentifier().equals( layer2.getExtension().getIdentifier() ) ) {
188                                    layer.setLayer( layer2 );
189                                    break;
190                                }
191                            }
192                        }
193                    } );
194                } catch ( Exception e ) {
195                    e.printStackTrace();
196                }
197            }
198    
199            ViewContext vc = new ViewContext( general, layerList );
200    
201            return vc;
202        }
203    
204        /**
205         * creates an instance of a class encapsulating the general context informations
206         * 
207         * @param element
208         *            <General>
209         * @param xml
210         * 
211         * @return instance of <tt>General</tt>
212         * 
213         * @throws XMLParsingException
214         * @throws UnknownCRSException
215         * @throws SAXException
216         * @throws IOException
217         */
218        private static General createGeneral( Element element, XMLFragment xml )
219                                throws XMLParsingException, UnknownCRSException, IOException, SAXException {
220    
221            // <Window>
222            Element elem = XMLTools.getChildElement( "Window", CommonNamespaces.CNTXTNS, element );
223            Rectangle rect = createWindow( elem );
224    
225            // <BoundingBox>
226            elem = XMLTools.getRequiredChildElement( "BoundingBox", CommonNamespaces.CNTXTNS, element );
227            Point[] bbox = createBoundingBox( elem );
228    
229            // <Title>
230            String title = XMLTools.getRequiredStringValue( "Title", CommonNamespaces.CNTXTNS, element );
231    
232            // <KeywordList>
233            elem = XMLTools.getChildElement( "KeywordList", CommonNamespaces.CNTXTNS, element );
234            String[] keywords = createKeywords( elem );
235    
236            // <Abstract>
237            String abstract_ = XMLTools.getStringValue( "Abstract", CommonNamespaces.CNTXTNS, element, null );
238    
239            // <LogoURL>
240            elem = XMLTools.getChildElement( "LogoURL", CommonNamespaces.CNTXTNS, element );
241            ImageURL logoURL = createImageURL( elem );
242    
243            // <DescriptionURL>
244    
245            // elem = XMLTools.getChildElement( "DescriptionURL", CommonNamespaces.CNTXTNS, element );
246            elem = XMLTools.getRequiredElement( element, CommonNamespaces.CNTXT_PREFIX + ":DescriptionURL",
247                                                CommonNamespaces.getNamespaceContext() );
248    
249            BaseURL descriptionURL = createBaseURL( elem );
250    
251            // <ContactInformation>
252            elem = XMLTools.getChildElement( "ContactInformation", CommonNamespaces.CNTXTNS, element );
253            CitedResponsibleParty contact = createContactInformation( elem );
254    
255            // <Extension>
256            elem = XMLTools.getChildElement( "Extension", CommonNamespaces.CNTXTNS, element );
257            GeneralExtension extension = createGeneralExtension( elem, xml );
258    
259            General general = null;
260            try {
261                general = new General( title, abstract_, rect, contact, bbox, descriptionURL, logoURL, keywords, extension );
262            } catch ( Exception e ) {
263                throw new XMLParsingException( e.getMessage(), e );
264            }
265    
266            return general;
267        }
268    
269        /**
270         * creates a <tt>Rectangle<tt> (Window) instance from the passed Element.
271         * 
272         * @param element
273         *            <Window>
274         * 
275         * @return instance of <tt>Rectangle</tt>
276         * 
277         * @throws XMLParsingException
278         */
279        private static Rectangle createWindow( Element element )
280                                throws XMLParsingException {
281    
282            Rectangle rect = null;
283    
284            if ( element != null ) {
285                String tmp = XMLTools.getRequiredAttrValue( "width", null, element );
286                int width = Integer.parseInt( tmp );
287                tmp = XMLTools.getRequiredAttrValue( "height", null, element );
288    
289                int height = Integer.parseInt( tmp );
290                rect = new Rectangle( width, height );
291            }
292    
293            return rect;
294        }
295    
296        /**
297         * creates a <tt>Envelope </tt> from the passed Element
298         * 
299         * @param element
300         *            <BoundingBox>
301         * 
302         * @return instance of <tt>Envelope</tt>
303         * 
304         * @throws XMLParsingException
305         * @throws UnknownCRSException
306         */
307        private static Point[] createBoundingBox( Element element )
308                                throws XMLParsingException, UnknownCRSException {
309    
310            String srs = XMLTools.getRequiredAttrValue( "SRS", null, element );
311            CoordinateSystem crs = CRSFactory.create( srs );
312            String tmp = XMLTools.getRequiredAttrValue( "minx", null, element );
313            double minx = Double.parseDouble( tmp );
314            tmp = XMLTools.getRequiredAttrValue( "miny", null, element );
315    
316            double miny = Double.parseDouble( tmp );
317            tmp = XMLTools.getRequiredAttrValue( "maxx", null, element );
318    
319            double maxx = Double.parseDouble( tmp );
320            tmp = XMLTools.getRequiredAttrValue( "maxy", null, element );
321    
322            double maxy = Double.parseDouble( tmp );
323    
324            Point[] points = new Point[2];
325            points[0] = GeometryFactory.createPoint( minx, miny, crs );
326            points[1] = GeometryFactory.createPoint( maxx, maxy, crs );
327    
328            return points;
329        }
330    
331        /**
332         * creates an array of keywords (String) from the passed Keyword list
333         * 
334         * @param element
335         *            <KeywordList>
336         * 
337         * @return array of Strings
338         * 
339         */
340        private static String[] createKeywords( Element element ) {
341    
342            ElementList el = XMLTools.getChildElements( "Keyword", CommonNamespaces.CNTXTNS, element );
343            String[] keywords = new String[el.getLength()];
344    
345            for ( int i = 0; i < keywords.length; i++ ) {
346                keywords[i] = XMLTools.getStringValue( el.item( i ) );
347            }
348    
349            return keywords;
350        }
351    
352        /**
353         * creates an instance of an ImageURL that is used for <LogoURL> and LegendURL
354         * 
355         * @param element
356         *            <LogoURL> or <LegendURL>
357         * 
358         * @return instance of <tt>ImageURL</tt>
359         * 
360         * @throws XMLParsingException
361         */
362        private static ImageURL createImageURL( Element element )
363                                throws XMLParsingException {
364    
365            ImageURL imageURL = null;
366    
367            if ( element != null ) {
368                String tmp = XMLTools.getAttrValue( element, null, "width", null );
369                int width = -1;
370                if ( tmp != null ) {
371                    width = Integer.parseInt( tmp );
372                }
373                tmp = XMLTools.getAttrValue( element, null, "height", null );
374                int height = -1;
375                if ( tmp != null ) {
376                    height = Integer.parseInt( tmp );
377                }
378                String format = XMLTools.getAttrValue( element, null, "format", null );
379    
380                Element elem = XMLTools.getRequiredChildElement( "OnlineResource", CommonNamespaces.CNTXTNS, element );
381                URL onlineResource = createOnlineResource( elem );
382    
383                imageURL = new ImageURL( width, height, format, onlineResource );
384            }
385    
386            return imageURL;
387        }
388    
389        /**
390         * creates an instance of an URL described by a <OnlineResource> element
391         * 
392         * @param element
393         *            <OnlineResource>
394         * 
395         * @return instance of <tt>URL</tt>
396         * 
397         * @throws XMLParsingException
398         */
399        private static URL createOnlineResource( Element element )
400                                throws XMLParsingException {
401    
402            URL onlineResource = null;
403    
404            if ( element != null ) {
405                String type = element.getAttributeNS( CommonNamespaces.XLNNS.toASCIIString(), "type" );
406                if ( ( type != null ) && !"".equals( type ) && !type.equals( "simple" ) ) {
407                    throw new XMLParsingException( "unknown type of online resource: " + type );
408                }
409                String tmp = element.getAttributeNS( CommonNamespaces.XLNNS.toASCIIString(), "href" );
410                if ( !isImageURL( tmp ) ) {
411                    tmp = OWSUtils.validateHTTPGetBaseURL( tmp );
412                }
413    
414                try {
415                    onlineResource = new URL( tmp );
416                } catch ( Exception e ) {
417                    e.printStackTrace();
418                    throw new XMLParsingException( "couldn't create online resource", e );
419                }
420            }
421    
422            return onlineResource;
423        }
424    
425        /**
426         * @param tmp
427         * @return
428         */
429        private static boolean isImageURL( String tmp ) {
430            String s = tmp.toLowerCase();
431            return s.endsWith( ".gif" ) || s.endsWith( ".png" ) || s.endsWith( ".jpg" ) || s.endsWith( ".jpeg" )
432                   || s.endsWith( ".tif" ) || s.endsWith( ".tiff" ) || s.endsWith( ".bmp" );
433        }
434    
435        /**
436         * creates an instance of BaseURL that is used for <DescriptionURL>
437         * 
438         * @param element
439         *            <DescriptionURL>
440         * @return instance of <tt>BaseURL</tt>, or null, if the passed element is null
441         * @throws XMLParsingException
442         */
443        private static BaseURL createBaseURL( Element element )
444                                throws XMLParsingException {
445    
446            BaseURL baseURL = null;
447    
448            if ( element != null ) {
449                String format = XMLTools.getAttrValue( element, null, "format", null );
450    
451                Element elem = XMLTools.getElement( element, CommonNamespaces.CNTXT_PREFIX + ":OnlineResource",
452                                                    CommonNamespaces.getNamespaceContext() );
453                URL onlineResource = createOnlineResource( elem );
454    
455                baseURL = new BaseURL( format, onlineResource );
456            }
457    
458            return baseURL;
459        }
460    
461        /**
462         * Creates a <tt>ContactInformation</tt>-instance according to the contents of the DOM-subtree starting at the given
463         * 'ContactInformation'-<tt>Element</tt>.
464         * <p>
465         * 
466         * @param element
467         *            the 'ContactInformation'-<tt>Element</tt>
468         * @throws XMLParsingException
469         *             if a syntactic or semantic error in the DOM-subtree is encountered
470         * @return the constructed <tt>ContactInformation</tt>-instance
471         */
472        private static CitedResponsibleParty createContactInformation( Element element )
473                                throws XMLParsingException {
474    
475            CitedResponsibleParty contact = null;
476    
477            if ( element != null ) {
478                // optional: <ContactPersonPrimary>
479                Element contactPersonPrimaryElement = XMLTools.getChildElement( "ContactPersonPrimary",
480                                                                                CommonNamespaces.CNTXTNS, element );
481    
482                String contactPerson = null;
483                String contactOrganization = null;
484                if ( contactPersonPrimaryElement != null ) {
485                    // required: <ContactPerson>
486                    contactPerson = XMLTools.getRequiredStringValue( "ContactPerson", CommonNamespaces.CNTXTNS,
487                                                                     contactPersonPrimaryElement );
488    
489                    // required: <ContactOrganization>
490                    contactOrganization = XMLTools.getRequiredStringValue( "ContactOrganization", CommonNamespaces.CNTXTNS,
491                                                                           contactPersonPrimaryElement );
492                }
493    
494                // optional: <ContactPosition>
495                String contactPosition = XMLTools.getStringValue( "ContactPosition", CommonNamespaces.CNTXTNS, element,
496                                                                  null );
497    
498                // optional: <ContactAddress>
499                Address contactAddress = null;
500                Element contactAddressElement = XMLTools.getChildElement( "ContactAddress", CommonNamespaces.CNTXTNS,
501                                                                          element );
502    
503                if ( contactAddressElement != null ) {
504                    // optional: <ContactElectronicMailAddress>
505                    String eMailAddress = XMLTools.getStringValue( "ContactElectronicMailAddress",
506                                                                   CommonNamespaces.CNTXTNS, element, null );
507                    contactAddress = createContactAddress( eMailAddress, contactAddressElement );
508                }
509    
510                // optional: <ContactVoiceTelephone>
511                String voice = XMLTools.getStringValue( "ContactVoiceTelephone", CommonNamespaces.CNTXTNS, element, null );
512    
513                // optional: <ContactFacsimileTelephone>
514                String fax = XMLTools.getStringValue( "ContactFacsimileTelephone", CommonNamespaces.CNTXTNS, element, null );
515    
516                Phone phone = new Phone( new String[] { fax }, new String[] { voice } );
517                ContactInfo ci = new ContactInfo( contactAddress, null, null, null, phone );
518                contact = new CitedResponsibleParty( new ContactInfo[] { ci }, new String[] { contactPerson },
519                                                     new String[] { contactOrganization },
520                                                     new String[] { contactPosition }, new RoleCode[0] );
521            }
522    
523            return contact;
524        }
525    
526        /**
527         * Creates a <tt>ContactAddress</tt>-instance according to the contents of the DOM-subtree starting at the given
528         * 'ContactAddress'-<tt>Element</tt>.
529         * <p>
530         * 
531         * @param element
532         *            the 'ContactAddress'-<tt>Element</tt>
533         * @throws XMLParsingException
534         *             if a syntactic or semantic error in the DOM-subtree is encountered
535         * @return the constructed <tt>ContactAddress</tt>-instance
536         */
537        private static Address createContactAddress( String eMail, Element element )
538                                throws XMLParsingException {
539    
540            // required: <AddressType>
541            /*
542             * String addressType = XMLTools.getRequiredStringValue( "AddressType", CommonNamespaces.CNTXTNS, element );
543             */
544            // required: <Address>
545            String address = XMLTools.getRequiredStringValue( "Address", CommonNamespaces.CNTXTNS, element );
546    
547            // required: <City>
548            String city = XMLTools.getRequiredStringValue( "City", CommonNamespaces.CNTXTNS, element );
549    
550            // required: <StateOrProvince>
551            String stateOrProvince = XMLTools.getRequiredStringValue( "StateOrProvince", CommonNamespaces.CNTXTNS, element );
552    
553            // required: <PostCode>
554            String postCode = XMLTools.getRequiredStringValue( "PostCode", CommonNamespaces.CNTXTNS, element );
555    
556            // required: <Country>
557            String country = XMLTools.getRequiredStringValue( "Country", CommonNamespaces.CNTXTNS, element );
558    
559            return new Address( stateOrProvince, city, country, new String[] { address }, new String[] { eMail }, postCode );
560        }
561    
562        /**
563         * creates an instance of a class encapsulating the deegree specific extensions of the general section of a web map
564         * context document
565         * 
566         * @param element
567         *            <Extension>
568         * @param xml
569         * 
570         * @return instance of <tt>GeneralExtension</tt>
571         * 
572         * @throws XMLParsingException
573         * @throws SAXException
574         * @throws IOException
575         */
576        private static GeneralExtension createGeneralExtension( Element element, XMLFragment xml )
577                                throws XMLParsingException, IOException, SAXException {
578    
579            GeneralExtension ge = null;
580    
581            if ( element != null ) {
582    
583                // retunrs the current mode of a client using a WMC
584                String mode = XMLTools.getStringValue( "Mode", CommonNamespaces.DGCNTXTNS, element, "ZOOMIN" );
585    
586                // <AuthentificationSettings>
587                Element elem = XMLTools.getChildElement( "AuthentificationSettings", CommonNamespaces.DGCNTXTNS, element );
588                AuthentificationSettings authSettings = null;
589                if ( elem != null ) {
590                    authSettings = createAuthentificationSettings( elem );
591                }
592                // <IOSetiings>
593                elem = XMLTools.getChildElement( "IOSettings", CommonNamespaces.DGCNTXTNS, element );
594                IOSettings ioSettings = null;
595                if ( elem != null ) {
596                    ioSettings = createIOSettings( elem, xml );
597                }
598                // <Frontend>
599                elem = XMLTools.getChildElement( "Frontend", CommonNamespaces.DGCNTXTNS, element );
600                Frontend frontend = null;
601                if ( elem != null ) {
602                    frontend = createFrontend( elem, xml );
603                }
604                // <MapParameter>
605                elem = XMLTools.getRequiredChildElement( "MapParameter", CommonNamespaces.DGCNTXTNS, element );
606                MapParameter mapParameter = createMapParameter( elem );
607    
608                // <LayerTree> old version
609                elem = XMLTools.getChildElement( "LayerTree", CommonNamespaces.DGCNTXTNS, element );
610    
611                Node layerTreeRoot = null;
612                if ( elem != null ) {
613                    Element nodeElem = XMLTools.getRequiredChildElement( "Node", CommonNamespaces.DGCNTXTNS, elem );
614                    layerTreeRoot = createNode( nodeElem, null );
615                } else {
616                    try {
617                        layerTreeRoot = new Node( 0, null, "root", false, false );
618                        Node[] nodes = new Node[] { new Node( 1, layerTreeRoot, "deegree", false, false ) };
619                        layerTreeRoot.setNodes( nodes );
620                    } catch ( ContextException e ) {
621                        throw new XMLParsingException( "couldn't create layertree node", e );
622                    }
623                }
624    
625                elem = XMLTools.getChildElement( "MapModel", CommonNamespaces.DGCNTXTNS, element );
626                MapModel mapModel = null;
627                if ( elem != null ) {
628                    MapModelDocument doc = new MapModelDocument( elem );
629                    mapModel = doc.parseMapModel();
630                }
631    
632                String tmp = XMLTools.getStringValue( "XSLT", CommonNamespaces.DGCNTXTNS, element, "context2HTML.xsl" );
633                URL xslt = xml.resolve( tmp );
634                File file = new File( xslt.getFile() );
635                if ( !file.exists() ) {
636                    // address xslt script from WEB-INF/conf/igeoportal
637                    file = new File( file.getParentFile().getParentFile().getParent() + File.separatorChar + file.getName() );
638                    xslt = file.toURL();
639                }
640    
641                ge = new GeneralExtension( ioSettings, frontend, mapParameter, authSettings, mode, layerTreeRoot, mapModel,
642                                           xslt );
643            }
644    
645            return ge;
646        }
647    
648        /**
649         * creates a node in the layerTree
650         */
651        private static Node createNode( Element nodeElem, Node parent )
652                                throws XMLParsingException {
653    
654            int id = Integer.parseInt( XMLTools.getRequiredAttrValue( "id", null, nodeElem ) );
655            String title = XMLTools.getRequiredAttrValue( "title", null, nodeElem );
656            String s = XMLTools.getAttrValue( nodeElem, null, "selectable", null );
657            boolean selectable = "true".equals( s ) || "1".equals( s );
658            s = XMLTools.getAttrValue( nodeElem, null, "collapsed", null );
659            boolean collapsed = "true".equals( s ) || "1".equals( s );
660            Node node = null;
661            try {
662                node = new Node( id, parent, title, selectable, collapsed );
663            } catch ( Exception e ) {
664                throw new XMLParsingException( "couldn't create layertree node", e );
665            }
666    
667            // get Child nodes
668            ElementList nl = XMLTools.getChildElements( "Node", CommonNamespaces.DGCNTXTNS, nodeElem );
669            Node[] nodes = new Node[nl.getLength()];
670            for ( int i = 0; i < nodes.length; i++ ) {
671                nodes[i] = createNode( nl.item( i ), node );
672            }
673            // set child nodes
674            node.setNodes( nodes );
675    
676            return node;
677        }
678    
679        /**
680         * creates an instance of a class encapsulating access descrition to an authentification service for a deegree map
681         * client
682         * 
683         * @param element
684         *            <AuthentificationSettings>
685         * @return instance of <tt>AuthentificationSettings</tt>
686         * @throws XMLParsingException
687         */
688        private static AuthentificationSettings createAuthentificationSettings( Element element )
689                                throws XMLParsingException {
690    
691            Element elem = XMLTools.getRequiredChildElement( "AuthentificationService", CommonNamespaces.DGCNTXTNS, element );
692            elem = XMLTools.getRequiredChildElement( "OnlineResource", CommonNamespaces.CNTXTNS, elem );
693    
694            URL url = createOnlineResource( elem );
695            BaseURL bu = new BaseURL( "text/xml", url );
696    
697            return new AuthentificationSettings( bu );
698        }
699    
700        /**
701         * creates an instance of a class encapsulating the frontend (GUI) description of a deegree map client
702         * 
703         * @param element
704         * 
705         * @param xml
706         * 
707         * @return instance of <tt>Frontend</tt>
708         * 
709         * @throws XMLParsingException
710         * @throws SAXException
711         * @throws IOException
712         */
713        private static Frontend createFrontend( Element element, XMLFragment xml )
714                                throws XMLParsingException, IOException, SAXException {
715    
716            // <Controller>
717            String controller = XMLTools.getRequiredStringValue( "Controller", CommonNamespaces.DGCNTXTNS, element );
718            // <Style>
719            String style = XMLTools.getStringValue( "Style", CommonNamespaces.DGCNTXTNS, element, null );
720            // <Buttons>
721            String buttons = XMLTools.getStringValue( "Buttons", CommonNamespaces.DGCNTXTNS, element, null );
722            // <CommonJS>
723            Element elem = XMLTools.getChildElement( "CommonJS", CommonNamespaces.DGCNTXTNS, element );
724            String[] commonJS = createCommonJS( elem );
725            // <West>
726            elem = XMLTools.getChildElement( "West", CommonNamespaces.DGCNTXTNS, element );
727            GUIArea west = createGUIArea( elem, xml );
728            // <East>
729            elem = XMLTools.getChildElement( "East", CommonNamespaces.DGCNTXTNS, element );
730            GUIArea east = createGUIArea( elem, xml );
731            // <North>
732            elem = XMLTools.getChildElement( "North", CommonNamespaces.DGCNTXTNS, element );
733            GUIArea north = createGUIArea( elem, xml );
734            // <South>
735            elem = XMLTools.getChildElement( "South", CommonNamespaces.DGCNTXTNS, element );
736            GUIArea south = createGUIArea( elem, xml );
737            // <Center>
738            elem = XMLTools.getChildElement( "Center", CommonNamespaces.DGCNTXTNS, element );
739            GUIArea center = createGUIArea( elem, xml );
740            // <Header>
741            String header = XMLTools.getStringValue( "Header", CommonNamespaces.DGCNTXTNS, element, null );
742            // <Footer>
743            String footer = XMLTools.getStringValue( "Footer", CommonNamespaces.DGCNTXTNS, element, null );
744    
745            Frontend frontend = new JSPFrontend( controller, west, east, south, north, center, style, buttons, commonJS,
746                                                 header, footer );
747    
748            return frontend;
749        }
750    
751        /**
752         * creates a list of javascript pages (names) that contains javascript objects and methods that are used by more
753         * than one module
754         * 
755         * @param element
756         *            <CommonJS>
757         * 
758         * @return instance of <tt>String[]</tt>
759         * 
760         */
761        private static String[] createCommonJS( Element element ) {
762            String[] commonJS = null;
763            if ( element != null ) {
764                ElementList el = XMLTools.getChildElements( "Name", CommonNamespaces.DGCNTXTNS, element );
765                commonJS = new String[el.getLength()];
766                for ( int i = 0; i < commonJS.length; i++ ) {
767                    commonJS[i] = XMLTools.getStringValue( el.item( i ) );
768                }
769            }
770    
771            return commonJS;
772        }
773    
774        /**
775         * creates an instance of a class encapsulating the GUI description of one region of the GUI
776         * 
777         * @param element
778         *            <West>; <East>; <South>; <North> or <Center>
779         * 
780         * @return instance of <tt>GUIArea</tt>
781         * 
782         * @throws XMLParsingException
783         * @throws SAXException
784         * @throws IOException
785         */
786        private static GUIArea createGUIArea( Element element, XMLFragment xml )
787                                throws XMLParsingException, IOException, SAXException {
788    
789            GUIArea gui = null;
790            if ( element != null ) {
791                String tmp = element.getLocalName();
792                int area = 0;
793                if ( tmp.equals( "West" ) ) {
794                    area = GUIArea.WEST;
795                } else if ( tmp.equals( "East" ) ) {
796                    area = GUIArea.EAST;
797                } else if ( tmp.equals( "South" ) ) {
798                    area = GUIArea.SOUTH;
799                } else if ( tmp.equals( "North" ) ) {
800                    area = GUIArea.NORTH;
801                } else if ( tmp.equals( "Center" ) ) {
802                    area = GUIArea.CENTER;
803                }
804    
805                NamespaceContext nsContext = CommonNamespaces.getNamespaceContext();
806                int w = XMLTools.getNodeAsInt( element, "./@width", nsContext, -1 );
807                int h = XMLTools.getNodeAsInt( element, "./@height", nsContext, -1 );
808                int l = XMLTools.getNodeAsInt( element, "./@left", nsContext, -1 );
809                int t = XMLTools.getNodeAsInt( element, "./@top", nsContext, -1 );
810                int r = XMLTools.getNodeAsInt( element, "./@right", nsContext, -1 );
811                int b = XMLTools.getNodeAsInt( element, "./@bottom", nsContext, -1 );
812                boolean ov = XMLTools.getNodeAsBoolean( element, "./@overlay", nsContext, false );
813                boolean head = XMLTools.getNodeAsBoolean( element, "./@header", nsContext, false );
814                boolean close = XMLTools.getNodeAsBoolean( element, "./@closable", nsContext, false );
815    
816                // hidden
817                tmp = XMLTools.getAttrValue( element, null, "hidden", null );
818                boolean hidden = "1".equals( tmp ) || "true".equals( tmp );
819                // <Module>
820                ElementList el = XMLTools.getChildElements( "Module", CommonNamespaces.DGCNTXTNS, element );
821                Module[] modules = new Module[el.getLength()];
822                for ( int i = 0; i < modules.length; i++ ) {
823                    modules[i] = createModule( el.item( i ), xml );
824                }
825                gui = new GUIArea( area, hidden, w, h, l, t, r, b, ov, head, close, modules );
826            }
827    
828            return gui;
829        }
830    
831        /**
832         * creates an instance of a class encapsulating module informations
833         * 
834         * @param element
835         * @param xml
836         * 
837         * @return instance of <tt>Module</tt>
838         * 
839         * @throws XMLParsingException
840         * @throws SAXException
841         * @throws IOException
842         */
843        private static Module createModule( Element element, XMLFragment xml )
844                                throws XMLParsingException, IOException, SAXException {
845    
846            // width and height of a Module are optional
847            // if not set '0' will be used instead
848            NamespaceContext nsContext = CommonNamespaces.getNamespaceContext();
849            String w = XMLTools.getNodeAsString( element, "./@width", nsContext, "-1" );
850            String h = XMLTools.getNodeAsString( element, "./@height", nsContext, "-1" );
851            int l = XMLTools.getNodeAsInt( element, "./@left", nsContext, -1 );
852            int t = XMLTools.getNodeAsInt( element, "./@top", nsContext, -1 );
853            int b = XMLTools.getNodeAsInt( element, "./@bottom", nsContext, -1 );
854            int r = XMLTools.getNodeAsInt( element, "./@right", nsContext, -1 );
855            boolean ov = XMLTools.getNodeAsBoolean( element, "./@overlay", nsContext, false );
856            boolean head = XMLTools.getNodeAsBoolean( element, "./@header", nsContext, false );
857            boolean close = XMLTools.getNodeAsBoolean( element, "./@closable", nsContext, false );
858            boolean collapsed = XMLTools.getNodeAsBoolean( element, "./@collapsed", nsContext, false );
859            String scrollable = XMLTools.getAttrValue( element, null, "scrolling", null );
860    
861            String tmp = XMLTools.getAttrValue( element, null, "hidden", null );
862            boolean hidden = tmp.equals( "1" ) || tmp.equals( "true" );
863    
864            // <ModuleConfiguration>
865            Element elem = XMLTools.getElement( element, "dgcntxt:ModuleConfiguration", nsContext );
866            ModuleConfiguration mc = createModuleConfiguration( elem, xml );
867            if ( mc != null ) {
868                XMLFragment moduleXML = new XMLFragment( mc.getOnlineResource() );
869                element = moduleXML.getRootElement();
870            }
871    
872            // <Name>
873            String name = XMLTools.getRequiredStringValue( "Name", CommonNamespaces.DGCNTXTNS, element );
874            // <Title>
875            String title = XMLTools.getStringValue( "Title", CommonNamespaces.DGCNTXTNS, element, name );
876            // <Content>
877            String content = XMLTools.getRequiredStringValue( "Content", CommonNamespaces.DGCNTXTNS, element );
878    
879            // <ParameterList>
880            elem = XMLTools.getElement( element, "dgcntxt:ParameterList", nsContext );
881            ParameterList paramList = createParameterList( elem );
882    
883            String type = XMLTools.getAttrValue( element, null, "type", null );
884    
885            String[] moduleJS = createModuleJSList( element );
886            return new Module( name, title, content, hidden, type, l, t, r, b, w, h, ov, head, close, collapsed,
887                               scrollable, moduleJS, mc, paramList );
888        }
889    
890        /**
891         * creates an instance of a class encapsulating the access the configuration of Module
892         * 
893         * @param element
894         * @param xml
895         * 
896         * @return instance of <tt>ModuleConfiguration</tt>
897         * 
898         * @throws XMLParsingException
899         * @throws MalformedURLException
900         */
901        private static ModuleConfiguration createModuleConfiguration( Element element, XMLFragment xml )
902                                throws XMLParsingException, MalformedURLException {
903    
904            ModuleConfiguration mc = null;
905            if ( element != null ) {
906                Element elem = XMLTools.getRequiredElement( element, "cntxt:OnlineResource",
907                                                            CommonNamespaces.getNamespaceContext() );
908                Attr attr = elem.getAttributeNodeNS( CommonNamespaces.XLNNS.toASCIIString(), "href" );
909                String url = attr.getValue();
910                URL u = xml.resolve( url );
911                url = u.toExternalForm();
912                if ( url.endsWith( "?" ) ) {
913                    url = url.substring( 0, url.length() - 1 );
914                }
915                attr.setNodeValue( url );
916                URL onlineResource = createOnlineResource( elem );
917                mc = new ModuleConfiguration( onlineResource );
918            }
919    
920            return mc;
921        }
922    
923        /**
924         * creates an instance of a class encapsulating the layer list informations
925         * 
926         * @param element
927         *            <LayerList>
928         * 
929         * @return instance of <tt>LayerList</tt>
930         * 
931         * @throws XMLParsingException
932         */
933        private static ParameterList createParameterList( Element element )
934                                throws XMLParsingException {
935    
936            ParameterList parameterList = new ParameterList();
937            if ( element != null ) {
938                ElementList el = XMLTools.getChildElements( "Parameter", CommonNamespaces.DGCNTXTNS, element );
939                for ( int i = 0; i < el.getLength(); i++ ) {
940                    Parameter parameter = createParameter( el.item( i ) );
941                    parameterList.addParameter( parameter );
942                }
943            }
944    
945            return parameterList;
946        }
947    
948        /**
949         * creates an instance of a class encapsulating a parameter that shall be passed to a module
950         * 
951         * @param element
952         *            <Parameter>
953         * 
954         * @return instance of <tt>Parameter</tt>
955         * 
956         * @throws XMLParsingException
957         */
958        private static Parameter createParameter( Element element )
959                                throws XMLParsingException {
960    
961            String name = XMLTools.getRequiredStringValue( "Name", CommonNamespaces.DGCNTXTNS, element );
962            String value = XMLTools.getRequiredStringValue( "Value", CommonNamespaces.DGCNTXTNS, element );
963            // Parameter param = new Parameter_Impl( name+":"+value, value );
964            Parameter param = new Parameter( name, value );
965    
966            return param;
967        }
968    
969        /**
970         * creates an instance of a class encapsulating informations about controlling options for a map presented to the
971         * user
972         * 
973         * @param element
974         *            <MapParameter>
975         * 
976         * @return instance of <tt>MapParameter</tt>
977         * 
978         * @throws XMLParsingException
979         */
980        private static MapParameter createMapParameter( Element element )
981                                throws XMLParsingException {
982    
983            // <OfferedInfoFormats>
984            Element elem = XMLTools.getChildElement( "OfferedInfoFormats", CommonNamespaces.DGCNTXTNS, element );
985            Format[] infoFormats = null;
986            if ( elem != null ) {
987                infoFormats = createOfferedInfoFormats( elem );
988            }
989            // <OfferedZoomFactor>
990            elem = XMLTools.getChildElement( "OfferedZoomFactor", CommonNamespaces.DGCNTXTNS, element );
991            MapOperationFactor[] zoomFactors = null;
992            if ( elem != null ) {
993                zoomFactors = createOfferedMapOperationFactors( elem );
994            }
995            // <OfferedPanFactor>
996            elem = XMLTools.getChildElement( "OfferedPanFactor", CommonNamespaces.DGCNTXTNS, element );
997            MapOperationFactor[] panFactors = null;
998            if ( elem != null ) {
999                panFactors = createOfferedMapOperationFactors( elem );
1000            }
1001            // <MinScale>
1002            String tmp = XMLTools.getStringValue( "MinScale", CommonNamespaces.DGCNTXTNS, element, "0" );
1003            double minScale = Double.parseDouble( tmp );
1004            // <MaxScale>
1005            tmp = XMLTools.getStringValue( "MaxScale", CommonNamespaces.DGCNTXTNS, element, "9999999999" );
1006            double maxScale = Double.parseDouble( tmp );
1007    
1008            MapParameter mp = new MapParameter( infoFormats, panFactors, zoomFactors, minScale, maxScale );
1009    
1010            return mp;
1011        }
1012    
1013        /**
1014         * Creates a list of the feature info formats offered by the client.
1015         * 
1016         * @param element
1017         *            <OfferedInfoFormats> element of the configuration
1018         * 
1019         * @return list of offered feature info formats
1020         * 
1021         * @throws XMLParsingException
1022         */
1023        private static Format[] createOfferedInfoFormats( Element element )
1024                                throws XMLParsingException {
1025    
1026            Format[] format = null;
1027    
1028            // get list of offered feature info formats
1029            ElementList el = XMLTools.getChildElements( "Format", CommonNamespaces.DGCNTXTNS, element );
1030    
1031            format = new Format[el.getLength()];
1032    
1033            for ( int i = 0; i < el.getLength(); i++ ) {
1034                String name = XMLTools.getStringValue( el.item( i ) );
1035                String sel = XMLTools.getAttrValue( el.item( i ), null, "selected", null );
1036    
1037                boolean selected = "1".equals( sel ) || "true".equals( sel );
1038                try {
1039                    format[i] = new Format( name, selected );
1040                } catch ( ContextException e ) {
1041                    throw new XMLParsingException( "", e );
1042                }
1043            }
1044    
1045            return format;
1046        }
1047    
1048        /**
1049         * returns a list of offered numerical map operation factors that can be used to determine zoom or pan levels
1050         * 
1051         * @param element
1052         *            a <tt>Element</tt> that contains <Factor> elements as children
1053         * 
1054         * @return list of <tt>MapOperationFactor</tt>s
1055         * 
1056         */
1057        private static MapOperationFactor[] createOfferedMapOperationFactors( Element element ) {
1058    
1059            // get list of offered factors
1060            ElementList el = XMLTools.getChildElements( "Factor", CommonNamespaces.DGCNTXTNS, element );
1061    
1062            MapOperationFactor[] mof = new MapOperationFactor[el.getLength()];
1063    
1064            for ( int i = 0; i < el.getLength(); i++ ) {
1065                boolean free = true;
1066                String tmp = XMLTools.getStringValue( el.item( i ) );
1067                double fac = -99;
1068    
1069                if ( !tmp.equals( "*" ) ) {
1070                    free = false;
1071                    fac = Double.parseDouble( tmp );
1072                }
1073    
1074                String sel = XMLTools.getAttrValue( el.item( i ), null, "selected", null );
1075                boolean selected = "1".equals( sel ) || "true".equals( sel );
1076                mof[i] = new MapOperationFactor( fac, selected, free );
1077            }
1078    
1079            return mof;
1080        }
1081    
1082        /**
1083         * creates an instance of a class encapsulating the IO setting informations
1084         * 
1085         * @param element
1086         * @param xml
1087         * @return the iosettings.
1088         * @throws XMLParsingException
1089         */
1090        private static IOSettings createIOSettings( Element element, XMLFragment xml )
1091                                throws XMLParsingException, MalformedURLException {
1092    
1093            // temp directory
1094            Element elem = XMLTools.getChildElement( "TempDirectory", CommonNamespaces.DGCNTXTNS, element );
1095            DirectoryAccess temp = null;
1096            if ( elem != null ) {
1097                temp = createDirectoryAccess( elem, null, xml );
1098            }
1099            // download directory
1100            elem = XMLTools.getChildElement( "DownloadDirectory", CommonNamespaces.DGCNTXTNS, element );
1101            DirectoryAccess download = null;
1102            if ( elem != null ) {
1103                download = createDirectoryAccess( elem, temp, xml );
1104            }
1105            if ( temp == null && elem == null ) {
1106                throw new XMLParsingException( "If <TempDirectory> isn't set, " + "downloaddirectory must be set!" );
1107            }
1108            // SLD directory
1109            elem = XMLTools.getChildElement( "SLDDirectory", CommonNamespaces.DGCNTXTNS, element );
1110            DirectoryAccess sld = null;
1111            if ( elem != null ) {
1112                sld = createDirectoryAccess( elem, temp, xml );
1113            }
1114            if ( temp == null && elem == null ) {
1115                throw new XMLParsingException( "If <TempDirectory> isn't set, " + "slddirectory must be set!" );
1116            }
1117            // Print directory
1118            elem = XMLTools.getChildElement( "PrintDirectory", CommonNamespaces.DGCNTXTNS, element );
1119            DirectoryAccess print = null;
1120            if ( elem != null ) {
1121                print = createDirectoryAccess( elem, temp, xml );
1122            }
1123            if ( temp == null && elem == null ) {
1124                throw new XMLParsingException( "If <TempDirectory> isn't set, " + "printdirectory must be set!" );
1125            }
1126    
1127            IOSettings ioSettings = new IOSettings( download, sld, print, temp );
1128    
1129            return ioSettings;
1130        }
1131    
1132        /**
1133         * @param element
1134         * @param tempDir
1135         * @return the directory access.
1136         * @throws XMLParsingException
1137         */
1138        private static DirectoryAccess createDirectoryAccess( Element element, DirectoryAccess tempDir, XMLFragment xml )
1139                                throws XMLParsingException, MalformedURLException {
1140    
1141            // directory name
1142            String name = XMLTools.getStringValue( "Name", CommonNamespaces.DGCNTXTNS, element, null );
1143            name = xml.resolve( name ).toExternalForm();
1144    
1145            URL url = null;
1146            Element elem = XMLTools.getChildElement( "Access", CommonNamespaces.DGCNTXTNS, element );
1147            if ( elem != null ) {
1148                elem = XMLTools.getRequiredChildElement( "OnlineResource", CommonNamespaces.CNTXTNS, elem );
1149                url = createOnlineResource( elem );
1150            }
1151    
1152            DirectoryAccess da = null;
1153            if ( name == null || url == null ) {
1154                da = tempDir;
1155            } else {
1156                da = new DirectoryAccess( xml.resolve( name ).toExternalForm(), url );
1157            }
1158    
1159            return da;
1160    
1161        }
1162    
1163        /**
1164         * creates an instance of a class encapsulating the layer list informations
1165         * 
1166         * @param element
1167         *            <LayerList>
1168         * @param user
1169         * @param sessionID
1170         * 
1171         * @return instance of <tt>LayerList</tt>
1172         * 
1173         * @throws XMLParsingException
1174         */
1175        private static LayerList createLayerList( Element element, User user, String sessionID )
1176                                throws XMLParsingException {
1177    
1178            ElementList el = XMLTools.getChildElements( "Layer", CommonNamespaces.CNTXTNS, element );
1179            Layer[] layers = new Layer[el.getLength()];
1180            for ( int i = 0; i < layers.length; i++ ) {
1181                Layer layer = createLayer( el.item( i ), user, sessionID );
1182                layers[i] = layer;
1183    
1184            }
1185            LayerList list = new LayerList( layers );
1186    
1187            return list;
1188        }
1189    
1190        /**
1191         * creates an instance of a class encapsulating a web map context layer's attributes
1192         * 
1193         * @param element
1194         *            <Layer>
1195         * @param user
1196         * @param sessionID
1197         * 
1198         * @return instance of <tt>Layer</tt>
1199         * 
1200         * @throws XMLParsingException
1201         */
1202        private static Layer createLayer( Element element, User user, String sessionID )
1203                                throws XMLParsingException {
1204    
1205            String tmp = XMLTools.getRequiredAttrValue( "queryable", null, element );
1206            boolean queryable = "1".equals( tmp ) || "true".equals( tmp );
1207            tmp = XMLTools.getRequiredAttrValue( "hidden", null, element );
1208            boolean hidden = "1".equals( tmp ) || "true".equals( tmp );
1209    
1210            // <Name>
1211            String name = XMLTools.getRequiredStringValue( "Name", CommonNamespaces.CNTXTNS, element );
1212            // <Title>
1213            String title = XMLTools.getRequiredStringValue( "Title", CommonNamespaces.CNTXTNS, element );
1214            // <Abstract>
1215            String abstract_ = XMLTools.getStringValue( "Abstract", CommonNamespaces.CNTXTNS, element, null );
1216            // <DataURL>
1217            Element elem = XMLTools.getChildElement( "DataURL", CommonNamespaces.CNTXTNS, element );
1218            BaseURL dataURL = createBaseURL( elem );
1219            // <MetaDataURL>
1220            elem = XMLTools.getChildElement( "MetadataURL", CommonNamespaces.CNTXTNS, element );
1221            BaseURL metadataURL = createBaseURL( elem );
1222            // <SRS>
1223            tmp = XMLTools.getStringValue( "SRS", CommonNamespaces.CNTXTNS, element, null );
1224            String[] srs = StringTools.toArray( tmp, ",; ", true );
1225            // <FormatList>
1226            elem = XMLTools.getChildElement( "FormatList", CommonNamespaces.CNTXTNS, element );
1227            FormatList formatList = createFormatList( elem );
1228            // <Extension>
1229            Element extElem = XMLTools.getChildElement( "Extension", CommonNamespaces.CNTXTNS, element );
1230            LayerExtension extension = createLayerExtension( extElem, user, sessionID );
1231            // <Server>
1232            elem = XMLTools.getRequiredChildElement( "Server", CommonNamespaces.CNTXTNS, element );
1233            Server server = createServer( elem, user, sessionID, extension.getAuthentication() );
1234    
1235            // try setting metadataURl again. this time from server.
1236            if ( metadataURL == null ) {
1237                metadataURL = createMetadataURL( name, server );
1238            }
1239    
1240            // TODO must be removed, if reading capabilities from remote WMS is too slow
1241            setScaleHint( extElem, name, extension, server, user, sessionID, extension.getAuthentication() );
1242    
1243            // <StyleList>
1244            elem = XMLTools.getChildElement( "StyleList", CommonNamespaces.CNTXTNS, element );
1245            StyleList styleList = createStyleList( elem, name, server );
1246    
1247            Layer layer = null;
1248            try {
1249                layer = new Layer( server, name, title, abstract_, srs, dataURL, metadataURL, formatList, styleList,
1250                                   queryable, hidden, extension );
1251            } catch ( Exception e ) {
1252                throw new XMLParsingException( "couldn't create map context layer", e );
1253            }
1254    
1255            if ( layer.getServer().getCapabilities() == null ) {
1256                LOG.logInfo( "set status of  layer: " + name + " to not valid because capabilities could be read." );
1257                layer.getExtension().setValid( false );
1258            }
1259            return layer;
1260        }
1261    
1262        /**
1263         * @param layerName
1264         *            the layer name from which to take the MetadataURL information
1265         * @param server
1266         *            the WMS server from which to read the layer information (WMS capabilities document)
1267         * @return only the first MetadataURL from the WMS capabilities for the given layer
1268         * @throws XMLParsingException
1269         */
1270        private static BaseURL createMetadataURL( String layerName, Server server )
1271                                throws XMLParsingException {
1272    
1273            WMSCapabilities capa = (WMSCapabilities) server.getCapabilities();
1274            BaseURL metaURL = null;
1275    
1276            if ( capa != null ) {
1277                org.deegree.ogcwebservices.wms.capabilities.Layer layer = capa.getLayer( layerName );
1278                if ( layer != null ) {
1279                    MetadataURL[] urls = layer.getMetadataURL();
1280                    if ( urls != null && urls.length > 0 ) {
1281                        metaURL = urls[0];
1282                    }
1283                } else {
1284                    if ( LOG.getLevel() == ILogger.LOG_DEBUG ) {
1285                        String msg = StringTools.concat( 500, "LayerName '", layerName,
1286                                                         "' does not exist in the WMSCapabilities of server ",
1287                                                         server.getOnlineResource() );
1288                        LOG.logDebug( msg );
1289                    }
1290                }
1291            }
1292            return metaURL;
1293        }
1294    
1295        /**
1296         * creates an instance of a class encapsulating informations about the server (service) a layer based on
1297         * 
1298         * @param element
1299         *            <Server>
1300         * @param user
1301         * @param sessionID
1302         * @param useAuthentication
1303         * 
1304         * @return instance of <tt>Server</tt>
1305         * 
1306         * @throws XMLParsingException
1307         */
1308        private static Server createServer( Element element, User user, String sessionID, int useAuthentication )
1309                                throws XMLParsingException {
1310    
1311            String service = XMLTools.getRequiredAttrValue( "service", null, element );
1312            String version = XMLTools.getRequiredAttrValue( "version", null, element );
1313            String title = XMLTools.getRequiredAttrValue( "title", null, element );
1314    
1315            // <OnlineResource>
1316            Element elem = XMLTools.getRequiredChildElement( "OnlineResource", CommonNamespaces.CNTXTNS, element );
1317            URL onlineResource = createOnlineResource( elem );
1318    
1319            OGCCapabilities capabilities = getCapabilities( onlineResource, service, version, user, sessionID,
1320                                                            useAuthentication );
1321    
1322            Server server = null;
1323            try {
1324                server = new Server( title, version, service, onlineResource, capabilities );
1325            } catch ( Exception e ) {
1326                LOG.logError( e.getMessage(), e );
1327                throw new XMLParsingException( "could not create context server", e );
1328            }
1329    
1330            return server;
1331        }
1332    
1333        /**
1334         * creates an instance of a class encapsulating a list of image formats a layer offers
1335         * 
1336         * @param element
1337         *            <FormatList>
1338         * 
1339         * @return instance of <tt>FormatList</tt>
1340         * 
1341         * @throws XMLParsingException
1342         */
1343        private static FormatList createFormatList( Element element )
1344                                throws XMLParsingException {
1345    
1346            ElementList el = XMLTools.getChildElements( "Format", CommonNamespaces.CNTXTNS, element );
1347            Format[] formats = new Format[el.getLength()];
1348            for ( int i = 0; i < formats.length; i++ ) {
1349                String name = XMLTools.getStringValue( el.item( i ) );
1350                String tmp = XMLTools.getAttrValue( el.item( i ), null, "current", null );
1351                boolean current = "1".equals( tmp ) || "true".equals( tmp ) || formats.length == 1;
1352                try {
1353                    formats[i] = new Format( name, current );
1354                } catch ( Exception e ) {
1355                    throw new XMLParsingException( "could not create context format", e );
1356                }
1357            }
1358    
1359            FormatList formatList = null;
1360            try {
1361                formatList = new FormatList( formats );
1362            } catch ( Exception e ) {
1363                LOG.logDebug( e.getMessage(), e );
1364                throw new XMLParsingException( "could not create context formatList", e );
1365            }
1366    
1367            return formatList;
1368        }
1369    
1370        /**
1371         * creates an instance of a class encapsulating a list of styles available for a layer
1372         * 
1373         * @param element
1374         *            <StyleList>
1375         * @param layerName
1376         * @param server
1377         * 
1378         * @return instance of <tt>StyleList</tt>
1379         * 
1380         * @throws XMLParsingException
1381         */
1382        private static StyleList createStyleList( Element element, String layerName, Server server )
1383                                throws XMLParsingException {
1384    
1385            ElementList el = XMLTools.getChildElements( "Style", CommonNamespaces.CNTXTNS, element );
1386            Style[] styles = new Style[el.getLength()];
1387            boolean current = false;
1388            for ( int i = 0; i < styles.length; i++ ) {
1389                styles[i] = createStyle( el.item( i ), layerName, server );
1390                if ( styles[i].isCurrent() ) {
1391                    current = true;
1392                }
1393            }
1394            if ( !current ) {
1395                styles[0].setCurrent( true );
1396                LOG.logWarning( "not style for layer: " + layerName
1397                                + " has been defined as current -> first style has been marked as current" );
1398            }
1399            StyleList styleList = null;
1400            try {
1401                styleList = new StyleList( styles );
1402            } catch ( Exception e ) {
1403                LOG.logDebug( e.getMessage(), e );
1404                throw new XMLParsingException( "could not create context stylelist", e );
1405            }
1406    
1407            return styleList;
1408        }
1409    
1410        /**
1411         * creates an instance of a class encapsulating a description of a Style
1412         * 
1413         * @param element
1414         *            <Style>
1415         * 
1416         * @return instance of <tt>Style</tt>
1417         * 
1418         * @throws XMLParsingException
1419         */
1420        private static Style createStyle( Element element, String layerName, Server server )
1421                                throws XMLParsingException {
1422    
1423            Style style = null;
1424    
1425            String tmp = XMLTools.getAttrValue( element, null, "current", null );
1426            boolean current = "1".equals( tmp ) || "true".equals( tmp );
1427    
1428            Element elem = XMLTools.getChildElement( "SLD", CommonNamespaces.CNTXTNS, element );
1429            if ( elem != null ) {
1430                SLD sld = createSLD( elem );
1431                try {
1432                    style = new Style( sld, current );
1433                } catch ( Exception e ) {
1434                    throw new XMLParsingException( "could not create context style", e );
1435                }
1436            } else {
1437                String name = XMLTools.getRequiredStringValue( "Name", CommonNamespaces.CNTXTNS, element );
1438                String title = XMLTools.getRequiredStringValue( "Title", CommonNamespaces.CNTXTNS, element );
1439                String abstract_ = XMLTools.getStringValue( "Abstract", CommonNamespaces.CNTXTNS, element, null );
1440                // <LegendURL>
1441                elem = XMLTools.getChildElement( "LegendURL", CommonNamespaces.CNTXTNS, element );
1442                ImageURL legendURL = null;
1443                if ( elem != null ) {
1444                    legendURL = createImageURL( elem );
1445                } else {
1446                    try {
1447                        legendURL = createLegendURL( name, layerName, server );
1448                    } catch ( Exception e ) {
1449                        throw new XMLParsingException( "could not create context style", e );
1450                    }
1451                }
1452                try {
1453                    style = new Style( name, title, abstract_, legendURL, current );
1454                } catch ( Exception e ) {
1455                    LOG.logDebug( e.getMessage(), e );
1456                    throw new XMLParsingException( "could not create context style", e );
1457                }
1458            }
1459    
1460            return style;
1461        }
1462    
1463        /**
1464         * creates a legendURL for a style/layer by evaluating the servers capabilities the layer is servered by.
1465         * 
1466         * @return the image url.
1467         * @throws XMLParsingException
1468         */
1469        private static ImageURL createLegendURL( String styleName, String layerName, Server server )
1470                                throws XMLParsingException {
1471    
1472            WMSCapabilities capa = (WMSCapabilities) server.getCapabilities();
1473            ImageURL legendURL = null;
1474            if ( capa != null ) {
1475                org.deegree.ogcwebservices.wms.capabilities.Layer layer = capa.getLayer( layerName );
1476                // null layer will produce NullPointerException@layer.getStyles()
1477                if ( layer == null ) {
1478                    LOG.logDebug( "LayerName: " + layerName + " does not exist in the WMSCapabilities" );
1479                }
1480                // if layer is null, no legend is needed!
1481                if ( layer != null ) {
1482                    org.deegree.ogcwebservices.wms.capabilities.Style[] styles = layer.getStyles();
1483                    org.deegree.ogcwebservices.wms.capabilities.Style style = null;
1484                    for ( int i = 0; i < styles.length; i++ ) {
1485                        // find responsible style definition
1486                        style = styles[i];
1487                        if ( style.getName().equals( styleName ) ) {
1488                            break;
1489                        }
1490                    }
1491    
1492                    LegendURL[] urls = null;
1493    
1494                    if ( style != null ) {
1495                        urls = style.getLegendURL();
1496                    }
1497    
1498                    if ( urls != null && urls.length > 0 && urls[0] != null ) {
1499                        // if style has defined LegendURL(s) take the first
1500                        legendURL = new ImageURL( urls[0].getWidth(), urls[0].getHeight(), urls[0].getFormat(),
1501                                                  urls[0].getOnlineResource() );
1502                    } else {
1503                        // create a GetLegendGraphic request as style URL if the server
1504                        // supports GetLegendGraphic operation
1505                        OperationsMetadata om = capa.getOperationMetadata();
1506                        Operation operation = om.getOperation( new QualifiedName( "GetLegendGraphic" ) );
1507                        if ( operation != null ) {
1508                            HTTP http = (HTTP) operation.getDCP().get( 0 );
1509                            URL url = http.getGetOnlineResources().get( 0 );
1510                            StringBuffer sb = new StringBuffer( 500 );
1511                            sb.append( OWSUtils.validateHTTPGetBaseURL( url.toExternalForm() ) );
1512                            GetLegendGraphic glg = GetLegendGraphic.create( "12", capa.getVersion(), layerName, styleName,
1513                                                                            null, null, 1, null, null, "image/jpeg", 20,
1514                                                                            20, null, null );
1515                            try {
1516                                sb.append( glg.getRequestParameter() );
1517                                url = new URL( sb.toString() );
1518                                legendURL = new ImageURL( 20, 20, "image/jpeg", url );
1519                            } catch ( Exception shouldNeverHappen ) {
1520                                shouldNeverHappen.printStackTrace();
1521                            }
1522                        }
1523                    }
1524                }
1525            }
1526    
1527            return legendURL;
1528        }
1529    
1530        /**
1531         * creates an instance of a class encapsulating a description of a Style based on a SLD
1532         * 
1533         * @param element
1534         *            <SLD>
1535         * 
1536         * @return instance of <tt>SLD</tt>
1537         * 
1538         * @throws XMLParsingException
1539         */
1540        private static SLD createSLD( Element element )
1541                                throws XMLParsingException {
1542    
1543            SLD sld = null;
1544    
1545            String name = XMLTools.getRequiredStringValue( "Name", CommonNamespaces.CNTXTNS, element );
1546            String title = XMLTools.getStringValue( "Title", CommonNamespaces.CNTXTNS, element, null );
1547    
1548            Element elem = XMLTools.getChildElement( "OnlineResource", CommonNamespaces.CNTXTNS, element );
1549            try {
1550                if ( elem != null ) {
1551                    URL onlineResource = createOnlineResource( elem );
1552                    sld = new SLD( name, title, onlineResource );
1553                } else {
1554                    elem = XMLTools.getChildElement( "StyledLayerDescriptor", CommonNamespaces.SLDNS, element );
1555                    if ( elem != null ) {
1556                        XMLFragment xml = new XMLFragment();
1557                        xml.setRootElement( elem );
1558                        StyledLayerDescriptor styledLayerDescriptor = SLDFactory.createSLD( xml );
1559                        sld = new SLD( name, title, styledLayerDescriptor );
1560                    } else {
1561                        FeatureTypeStyle fts = SLDFactory.createFeatureTypeStyle( elem );
1562                        sld = new SLD( name, title, fts );
1563                    }
1564                }
1565            } catch ( Exception e ) {
1566                LOG.logDebug( e.getMessage(), e );
1567                throw new XMLParsingException( "couldn't create map context SLD", e );
1568            }
1569    
1570            return sld;
1571        }
1572    
1573        /**
1574         * creates an instance of a class encapsulating the deegree specific extensions of a Layer.
1575         * 
1576         * Extensions are: DataService, MasterLayer, SelectedForQuery, parentNodeId, showLegendGraphic, identifier,
1577         * ScaleHint.
1578         * 
1579         * @param element
1580         *            Extension
1581         * @param user
1582         * @param sessionID
1583         * 
1584         * @return instance of <tt>LayerExtension</tt>
1585         * 
1586         * @throws XMLParsingException
1587         */
1588        private static LayerExtension createLayerExtension( Element element, User user, String sessionID )
1589                                throws XMLParsingException {
1590    
1591            LayerExtension le = null;
1592            if ( element != null ) {
1593    
1594                String tmp = XMLTools.getNodeAsString( element, "./dgcntxt:UseAuthentication/text()",
1595                                                       CommonNamespaces.getNamespaceContext(), "NONE" );
1596                int ua = LayerExtension.NONE;
1597                if ( "sessionID".equalsIgnoreCase( tmp ) ) {
1598                    ua = LayerExtension.SESSIONID;
1599                } else if ( "user/password".equalsIgnoreCase( tmp ) ) {
1600                    ua = LayerExtension.USERPASSWORD;
1601                }
1602    
1603                // standard edition: download WFS data
1604                DataService dataService = null;
1605                Element elem = XMLTools.getChildElement( "DataService", CommonNamespaces.DGCNTXTNS, element );
1606                if ( elem != null ) {
1607                    Element el = XMLTools.getRequiredChildElement( "Server", CommonNamespaces.CNTXTNS, elem );
1608                    Server server = createServer( el, user, sessionID, ua );
1609                    String geoType = XMLTools.getStringValue( "GeometryType", CommonNamespaces.DGCNTXTNS, elem, null );
1610                    String featureType = XMLTools.getStringValue( "FeatureType", CommonNamespaces.DGCNTXTNS, elem, null );
1611                    dataService = new DataService( server, featureType, geoType );
1612                }
1613    
1614                // project specific
1615                boolean masterLayer = false;
1616                elem = XMLTools.getChildElement( "MasterLayer", CommonNamespaces.DGCNTXTNS, element );
1617                if ( elem != null ) {
1618                    String s = XMLTools.getStringValue( elem );
1619                    masterLayer = "true".equals( s ) || "1".equals( s );
1620                }
1621    
1622                // project specific
1623                boolean selectedForFI = false;
1624                elem = XMLTools.getChildElement( "SelectedForQuery", CommonNamespaces.DGCNTXTNS, element );
1625                if ( elem != null ) {
1626                    String s = XMLTools.getStringValue( elem );
1627                    selectedForFI = "true".equalsIgnoreCase( s ) || "1".equals( s );
1628                }
1629    
1630                // portlet edition: LayerTree
1631                int parentNodeId = 1;
1632                elem = XMLTools.getChildElement( "parentNodeId", CommonNamespaces.DGCNTXTNS, element );
1633                if ( elem != null ) {
1634                    parentNodeId = Integer.parseInt( XMLTools.getStringValue( elem ) );
1635                }
1636    
1637                // 
1638                boolean showLegendGraphic = false;
1639                elem = XMLTools.getChildElement( "showLegendGraphic", CommonNamespaces.DGCNTXTNS, element );
1640                if ( elem != null ) {
1641                    String s = XMLTools.getStringValue( elem );
1642                    showLegendGraphic = "true".equalsIgnoreCase( s ) || "1".equals( s );
1643                }
1644    
1645                boolean tiled = false;
1646                elem = XMLTools.getChildElement( "tiled", CommonNamespaces.DGCNTXTNS, element );
1647                if ( elem != null ) {
1648                    String s = XMLTools.getStringValue( elem );
1649                    tiled = "true".equalsIgnoreCase( s ) || "1".equals( s );
1650                }
1651    
1652                // standard edition: LayerTree
1653                String identifier = null;
1654                elem = XMLTools.getChildElement( "identifier", CommonNamespaces.DGCNTXTNS, element );
1655                if ( elem != null ) {
1656                    identifier = XMLTools.getStringValue( elem );
1657                }
1658    
1659                // standard edition: ScaleHint
1660                String scaleHint = null;
1661                elem = XMLTools.getChildElement( "ScaleHint", CommonNamespaces.DGCNTXTNS, element );
1662                double minScale = 0;
1663                double maxScale = Double.MAX_VALUE;
1664                if ( elem != null ) {
1665                    minScale = Double.valueOf( XMLTools.getRequiredAttrValue( "min", null, elem ) );
1666                    maxScale = Double.valueOf( XMLTools.getRequiredAttrValue( "max", null, elem ) );
1667                }
1668    
1669                le = new LayerExtension( dataService, masterLayer, minScale, maxScale, selectedForFI, ua, parentNodeId,
1670                                         showLegendGraphic, identifier, tiled );
1671    
1672            } else {
1673                le = new LayerExtension();
1674            }
1675    
1676            return le;
1677        }
1678    
1679        /**
1680         * Use information form extension and server elements of a layer to set a scaleHint.
1681         * 
1682         * If layer extension contains scale hints (min, max), then these values are used. Otherwise, the information is
1683         * taken from the WMS capabilities by using {@link #getScaleHintFromCapabilities(Server, String, User, String, int)}
1684         * 
1685         * @param extElem
1686         * @param name
1687         * @param extension
1688         * @param server
1689         * @param user
1690         * @param sessionID
1691         * @param useAuthentication
1692         * @throws XMLParsingException
1693         */
1694        private static void setScaleHint( Element extElem, String name, LayerExtension extension, Server server, User user,
1695                                          String sessionID, int useAuthentication )
1696                                throws XMLParsingException {
1697    
1698            // <deegree:ScaleHint min="0.0" max="41.0"/>
1699            Element elem = null;
1700            if ( extElem != null ) {
1701                elem = XMLTools.getChildElement( "ScaleHint", CommonNamespaces.DGCNTXTNS, extElem );
1702            }
1703    
1704            if ( elem == null ) {
1705                // reade scaleHint from WMS Capabilities
1706                double[] sc = getScaleHintFromCapabilities( server, name, user, sessionID, useAuthentication );
1707                extension.setMinScaleHint( sc[0] );
1708                extension.setMaxScaleHint( sc[1] );
1709            } else {
1710                // do nothing. Values have already been read from layer extension when creating the LayerExtension object.
1711            }
1712        }
1713    
1714        /**
1715         * taken from d1 and adjusted for d2.
1716         * 
1717         * TODO: check if inconsistencies arise regarding user-dependant scaleHint, because of using {@link #wmsCache}.
1718         * 
1719         * @param server
1720         * @param layerName
1721         * @param user
1722         * @param sessionID
1723         * @param useAuthentication
1724         * @return
1725         */
1726        private static double[] getScaleHintFromCapabilities( Server server, String layerName, User user, String sessionID,
1727                                                              int useAuthentication ) {
1728    
1729            double[] sc = new double[] { 0, Double.MAX_VALUE };
1730            WMSCapabilities capa = null;
1731    
1732            // capabilities have not been stored in cache before. getting the capabilities for the specified user
1733            if ( wmsCache.get( server.getOnlineResource() ) == null ) {
1734                capa = (WMSCapabilities) getCapabilities( server.getOnlineResource(), server.getService(),
1735                                                          server.getVersion(), user, sessionID, useAuthentication );
1736            } else {
1737                // get capabilities from cache.
1738                // May cause an inconsistency problem, if cache contains capabilities of a different but the specified user.
1739                // Could be handled with different caches for different users, but this would cause performance problems.
1740                capa = (WMSCapabilities) wmsCache.get( server.getOnlineResource() );
1741            }
1742            if ( capa != null ) {
1743                wmsCache.put( server.getOnlineResource(), capa );
1744                org.deegree.ogcwebservices.wms.capabilities.Layer lay = capa.getLayer( layerName );
1745                if ( lay != null ) {
1746                    try {
1747                        sc[0] = lay.getScaleHint().getMin();
1748                        sc[1] = lay.getScaleHint().getMax();
1749                    } catch ( Exception e ) {
1750                    }
1751                }
1752            }
1753            return sc;
1754        }
1755    
1756        /**
1757         * returns the capabilities for the passed server. The capabilities are read directly from the server or from the
1758         * loacal cache.
1759         * 
1760         * @param url
1761         * @param service
1762         * @param version
1763         * @param user
1764         * @param sessionID
1765         * @param useAuthentication
1766         * @return he capabilities for the passed server. The capabilities are read directly from the server or from the
1767         *         loacal cache.
1768         */
1769        private static OGCCapabilities getCapabilities( URL url, String service, String version, User user,
1770                                                        String sessionID, int useAuthentication ) {
1771    
1772            OGCCapabilities capa = null;
1773    
1774            String href = OWSUtils.validateHTTPGetBaseURL( url.toExternalForm() );
1775            if ( href.toLowerCase().startsWith( "http://" ) || href.toLowerCase().startsWith( "https://" ) ) {
1776                if ( "OGC:WMS".equals( service ) ) {
1777                    // is a HTTP URL so GetCapabilities request must be constructed
1778                    if ( "1.0.0".equals( version ) ) {
1779                        href = StringTools.concat( 1000, href, "request=capabilities&service=WMS", "&WMTVER=", version );
1780                    } else {
1781                        href = StringTools.concat( 1000, href, "request=GetCapabilities&service=WMS", "&version=", version );
1782                    }
1783    
1784                } else if ( "OGC:WFS".equals( service ) ) {
1785                    // is a HTTP URL so GetCapabilities request must be constructed
1786                    href = StringTools.concat( 1000, href, "request=GetCapabilities&service=WFS", "&version=", version );
1787    
1788                } else if ( "OGC:WCS".equals( service ) ) {
1789                    // is a HTTP URL so GetCapabilities request must be constructed
1790                    href = StringTools.concat( 1000, href, "request=GetCapabilities&service=WCS", "&version=", version );
1791    
1792                }
1793    
1794                if ( useAuthentication == LayerExtension.SESSIONID ) {
1795                    href = StringTools.concat( 1000, href, "&sessionID=", sessionID );
1796                } else if ( useAuthentication == LayerExtension.USERPASSWORD ) {
1797                    href = StringTools.concat( 1000, href, "&user=", user.getName(), "&password=", user.getPassword() );
1798                }
1799            }
1800    
1801            if ( wmsCache.get( url ) == null && "OGC:WMS".equals( service ) ) {
1802                LOG.logDebug( "get " + service + " capabilities from GetCapabilities request" );
1803                capa = parseCapabilities( href, service );
1804                if ( capa != null ) {
1805                    // write capabilities into local cache
1806                    wmsCache.put( url, (WMSCapabilities) capa );
1807                }
1808            } else if ( "OGC:WMS".equals( service ) ) {
1809                LOG.logDebug( "get WMS capabilities from cache" );
1810                capa = wmsCache.get( url );
1811            } else if ( wfsCache.get( url ) == null && "OGC:WFS".equals( service ) ) {
1812                LOG.logDebug( "get " + service + " capabilities from GetCapabilities request" );
1813                capa = parseCapabilities( href, service );
1814                if ( capa != null ) {
1815                    // write capabilities into local cache
1816                    wfsCache.put( url, (WFSCapabilities) capa );
1817                }
1818            } else if ( "OGC:WFS".equals( service ) ) {
1819                LOG.logDebug( "get WFS capabilities from cache" );
1820                capa = wfsCache.get( url );
1821            } else if ( wcsCache.get( url ) == null && "OGC:WCS".equals( service ) ) {
1822                LOG.logDebug( "get " + service + " capabilities from GetCapabilities request" );
1823                capa = parseCapabilities( href, service );
1824                if ( capa != null ) {
1825                    // write capabilities into local cache
1826                    wcsCache.put( url, (WCSCapabilities) capa );
1827                }
1828            } else if ( "OGC:WFS".equals( service ) ) {
1829                LOG.logDebug( "get WCS capabilities from cache" );
1830                capa = wcsCache.get( url );
1831            }
1832    
1833            return capa;
1834        }
1835    
1836        /**
1837         * 
1838         * @param href
1839         * @param service
1840         * @return the capabilities bean.
1841         */
1842        private static OGCCapabilities parseCapabilities( String href, String service ) {
1843    
1844            OGCCapabilities capa = null;
1845            try {
1846                URL url = null;
1847                Reader reader = null;
1848    
1849                // consider that the reference to the capabilities may has been
1850                // made by a file URL to a local copy
1851                if ( href.toLowerCase().startsWith( "http://" ) || href.toLowerCase().startsWith( "https://" ) ) {
1852                    HttpClient httpclient = new HttpClient();
1853                    httpclient = WebUtils.enableProxyUsage( httpclient, new URL( href ) );
1854                    int timeout = Integer.parseInt( Messages.getString( "WebMapContextFactory.timeout" ) );
1855                    httpclient.getHttpConnectionManager().getParams().setSoTimeout( timeout );
1856    
1857                    GetMethod httpget = new GetMethod( href );
1858                    LOG.logDebug( "GetCapabilities: ", href );
1859    
1860                    httpclient.executeMethod( httpget );
1861                    reader = new InputStreamReader( httpget.getResponseBodyAsStream() );
1862                } else {
1863                    if ( href.endsWith( "?" ) ) {
1864                        url = new URL( href.substring( 0, href.length() - 1 ) );
1865                    }
1866                    reader = new InputStreamReader( url.openStream() );
1867                }
1868    
1869                OGCCapabilitiesDocument doc = null;
1870                if ( "OGC:WMS".equals( service ) ) {
1871                    doc = new WMSCapabilitiesDocument();
1872                    doc.load( reader, XMLFragment.DEFAULT_URL );
1873                    doc = WMSCapabilitiesDocumentFactory.getWMSCapabilitiesDocument( doc.getRootElement() );
1874                } else if ( "OGC:WFS".equals( service ) ) {
1875                    doc = new WFSCapabilitiesDocument();
1876                    doc.load( reader, XMLFragment.DEFAULT_URL );
1877                } else if ( "OGC:WCS".equals( service ) ) {
1878                    doc = new WCSCapabilitiesDocument();
1879                    doc.load( reader, XMLFragment.DEFAULT_URL );
1880                } else {
1881                    throw new XMLParsingException( "not supported service type: " + service );
1882                }
1883    
1884                capa = doc.parseCapabilities();
1885            } catch ( Exception e ) {
1886                LOG.logWarning( "could not read capabilities: " + href );
1887                // LOG.logError( e.getMessage(), e );
1888                return null;
1889            }
1890            return capa;
1891        }
1892    
1893        // /**
1894        // * @param mapServer
1895        // * @param layer
1896        // * @return ScaleHint
1897        // */
1898        // private static double[] getScaleHintFromCapabilities( Server mapServer, String layer ) {
1899        //
1900        // double[] sc = new double[] { 0, 9999999 };
1901        // WMSCapabilities capa = (WMSCapabilities) mapServer.getCapabilities();
1902        // if ( capa != null ) {
1903        // org.deegree.ogcwebservices.wms.capabilities.Layer lay = capa.getLayer( layer );
1904        // if ( lay != null ) {
1905        // sc[0] = lay.getScaleHint().getMin();
1906        // sc[1] = lay.getScaleHint().getMax();
1907        // }
1908        // }
1909        // return sc;
1910        // }
1911    
1912        /**
1913         * creates a list (String[]) containing the name of the JavaScript files used by the moudle
1914         * 
1915         * @param element
1916         *            <Module>
1917         * 
1918         * @return instance of <tt>String[]</tt>
1919         * 
1920         */
1921        private static String[] createModuleJSList( Element element ) {
1922            String[] moduleJS = null;
1923            if ( element != null ) {
1924                ElementList el = XMLTools.getChildElements( "ModuleJS", CommonNamespaces.DGCNTXTNS, element );
1925                moduleJS = new String[el.getLength()];
1926                for ( int i = 0; i < el.getLength(); i++ ) {
1927                    moduleJS[i] = ( (Text) el.item( i ).getFirstChild() ).getData();
1928                }
1929            }
1930    
1931            return moduleJS;
1932        }
1933    }