Source Code Cross Referenced for GetMapKvpReader.java in  » GIS » GeoServer » org » vfny » geoserver » wms » requests » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » GIS » GeoServer » org.vfny.geoserver.wms.requests 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* Copyright (c) 2001 - 2007 TOPP - www.openplans.org.  All rights reserved.
0002:         * This code is licensed under the GPL 2.0 license, availible at the root
0003:         * application directory.
0004:         */
0005:        package org.vfny.geoserver.wms.requests;
0006:
0007:        import java.awt.Color;
0008:        import java.awt.geom.Point2D;
0009:        import java.io.IOException;
0010:        import java.io.InputStream;
0011:        import java.io.Reader;
0012:        import java.io.StringReader;
0013:        import java.net.HttpURLConnection;
0014:        import java.net.MalformedURLException;
0015:        import java.net.URL;
0016:        import java.net.URLConnection;
0017:        import java.util.ArrayList;
0018:        import java.util.Collections;
0019:        import java.util.Iterator;
0020:        import java.util.List;
0021:        import java.util.Map;
0022:        import java.util.logging.Level;
0023:        import java.util.logging.Logger;
0024:        import java.util.zip.GZIPInputStream;
0025:        import java.util.zip.Inflater;
0026:        import java.util.zip.InflaterInputStream;
0027:
0028:        import javax.servlet.http.HttpServletRequest;
0029:
0030:        import org.geotools.data.DefaultQuery;
0031:        import org.geotools.data.FeatureReader;
0032:        import org.geotools.data.Query;
0033:        import org.geotools.data.Transaction;
0034:        import org.geotools.data.crs.ForceCoordinateSystemFeatureReader;
0035:        import org.geotools.data.memory.MemoryDataStore;
0036:        import org.geotools.factory.CommonFactoryFinder;
0037:        import org.geotools.feature.FeatureType;
0038:        import org.geotools.referencing.CRS;
0039:        import org.geotools.referencing.crs.DefaultGeographicCRS;
0040:        import org.geotools.styling.FeatureTypeConstraint;
0041:        import org.geotools.styling.NamedLayer;
0042:        import org.geotools.styling.NamedStyle;
0043:        import org.geotools.styling.SLDParser;
0044:        import org.geotools.styling.Style;
0045:        import org.geotools.styling.StyleAttributeExtractor;
0046:        import org.geotools.styling.StyleFactory;
0047:        import org.geotools.styling.StyledLayer;
0048:        import org.geotools.styling.StyledLayerDescriptor;
0049:        import org.geotools.styling.UserLayer;
0050:        import org.opengis.filter.Filter;
0051:        import org.opengis.referencing.crs.CoordinateReferenceSystem;
0052:        import org.vfny.geoserver.Request;
0053:        import org.vfny.geoserver.ServiceException;
0054:        import org.vfny.geoserver.config.PaletteManager;
0055:        import org.vfny.geoserver.global.CoverageInfo;
0056:        import org.vfny.geoserver.global.Data;
0057:        import org.vfny.geoserver.global.FeatureTypeInfo;
0058:        import org.vfny.geoserver.global.MapLayerInfo;
0059:        import org.vfny.geoserver.global.TemporaryFeatureTypeInfo;
0060:        import org.vfny.geoserver.global.WMS;
0061:        import org.vfny.geoserver.util.SLDValidator;
0062:        import org.vfny.geoserver.wms.WmsException;
0063:        import org.vfny.geoserver.wms.responses.palette.InverseColorMapOp;
0064:        import org.vfny.geoserver.wms.servlets.WMService;
0065:        import org.xml.sax.InputSource;
0066:
0067:        import com.vividsolutions.jts.geom.Envelope;
0068:
0069:        /**
0070:         * Builds a GetMapRequest object given by a set of CGI parameters supplied in
0071:         * the constructor.
0072:         * 
0073:         * <p>
0074:         * Mandatory parameters:
0075:         * 
0076:         * <ul>
0077:         * <li> LAYERS layer names, as exposed by the capabilities document, to compose
0078:         * a map with, in the order they may appear, being the first layer the one at
0079:         * the bottom of the layer stack and the last one the one at the top. </li>
0080:         * <li> STYLES list of named styles known by this server and applicable to the
0081:         * requested layers. It can be empty or contain exactly as many style names as
0082:         * layers was requested, in which case empty strings could be used to denote
0083:         * that the default layer style should be used. (exaple:
0084:         * <code>LAYERS=buildings,roads,railroads&STYLES=,centerline,</code>. This
0085:         * example says create a map with roads layer using its default style, roads
0086:         * with "centerline" style, and railroads with its default style. </li>
0087:         * <li> BBOX Area of interest for which to contruct the map image, in the
0088:         * Coordinate Reference System given by the SRS parameter. </li>
0089:         * <li> FORMAT MIME type of the resulting map, must be one of the advertised in
0090:         * the capabilities document. </li>
0091:         * <li> WIDTH desired map witdth in output units (pixels). UNITS support should
0092:         * be added to the spec, and UNITS and DPI parameters added. </li>
0093:         * <li> HEIGHT desired map height in output units (pixels). UNITS support should
0094:         * be added to the spec, and UNITS and DPI parameters added. </li>
0095:         * </ul>
0096:         * </p>
0097:         * 
0098:         * <p>
0099:         * Optional parameters:
0100:         * 
0101:         * <ul>
0102:         * <li> SRS </li>
0103:         * <li> TRANSPARENT boolean indicatin wether to create a map with transparent
0104:         * background or not (if transparency is supported by the requested output
0105:         * format). </li>
0106:         * <li> EXCEPTIONS MIME type of the exception report. </li>
0107:         * <li> BGCOLOR map background color, in <code>0xRRGGBB</code> format. </li>
0108:         * <li> SLD client supplies a URL for a remote SLD document through this
0109:         * parameter. This parameter takes precedence over STYLES. If present, replaces
0110:         * the LAYERS and STYLES parameters, since they're defined in the remote
0111:         * document itself. The document send by this way will be used in "literal" or
0112:         * "library" mode, see explanation bellow. </li>
0113:         * <li> SLD_BODY client spplies the SLD document itself through this parameter,
0114:         * properly encoded for an HTTP query string. This parameter takes precendence
0115:         * over STYLES and SLD. If present, replaces the LAYERS and STYLES parameters,
0116:         * since they're defined in the inline document itself. The document send by
0117:         * this way will be used in "literal" or "library" mode, see explanation bellow.
0118:         * </li>
0119:         * </ul>
0120:         * </p>
0121:         * 
0122:         * <p>
0123:         * As defined by the Styled Layer Descriptor specification, version 1.0.0, the
0124:         * SLD document supplied by the SLD or SLD_BODY parameter can be used in
0125:         * "literal" or "library" mode, depending on whether the <strong>LAYERS=</strong>
0126:         * parameter is present.
0127:         * </p>
0128:         * 
0129:         * <p>
0130:         * Here is the explanation from the spec, section 6.4, page 10: "the SLD can
0131:         * also be used in one of two different modes depending on whether the LAYERS
0132:         * parameter is present in the request. If it is not present, then all layers
0133:         * identified in the SLD document are rendered with all defined styles, which is
0134:         * equivalent to the XML-POST method of usage. If the LAYERS parameter is
0135:         * present, then only the layers identified by that parameter are rendered and
0136:         * the SLD is used as a style library . "
0137:         * </p>
0138:         * 
0139:         * @author Gabriel Roldan, Axios Engineering
0140:         * @author Simone Giannecchini, GeoSolutions
0141:         * @version $Id: GetMapKvpReader.java 7749 2007-11-13 20:52:54Z jdeolive $
0142:         * 
0143:         * @task TODO: parse and respect SRS parameter (needs reprojection support)
0144:         * @deprecated
0145:         */
0146:        public class GetMapKvpReader extends WmsKvpRequestReader {
0147:            /** DOCUMENT ME! */
0148:            private static final Logger LOGGER = org.geotools.util.logging.Logging
0149:                    .getLogger("org.vfny.geoserver.requests.readers.wms");
0150:
0151:            /** Used to parse SLD documents from SLD and SLD_BODY parameters */
0152:            private static final StyleFactory styleFactory = CommonFactoryFinder
0153:                    .getStyleFactory(null);
0154:
0155:            /**
0156:             * Indicates wether STYLES parameter must be parsed. Defaults to
0157:             * <code>true</code>, but can be set to false, for example, when parsing
0158:             * a GetFeatureInfo request, which shares most of the getmap parameter but
0159:             * not STYLES.
0160:             * 
0161:             * @task TODO: refactor this so it dont stay _so_ ugly
0162:             */
0163:            private boolean stylesRequired = true;
0164:
0165:            /**
0166:             * Creates a new GetMapKvpReader object.
0167:             * 
0168:             * @param kvpPairs
0169:             *            Key Values pairs of the request
0170:             * @param service
0171:             *            The service handling the request
0172:             */
0173:            public GetMapKvpReader(Map kvpPairs, WMService service) {
0174:                super (kvpPairs, service);
0175:            }
0176:
0177:            /**
0178:             * Sets wether the STYLES parameter must be parsed
0179:             * 
0180:             * @param parseStyles
0181:             */
0182:            public void setStylesRequired(boolean parseStyles) {
0183:                this .stylesRequired = parseStyles;
0184:            }
0185:
0186:            /**
0187:             * DOCUMENT ME!
0188:             * 
0189:             * @return DOCUMENT ME!
0190:             */
0191:            public boolean isStylesRquired() {
0192:                return this .stylesRequired;
0193:            }
0194:
0195:            /**
0196:             * Produces a <code>GetMapRequest</code> instance by parsing the GetMap
0197:             * mandatory, optional and custom parameters.
0198:             * 
0199:             * @param httpRequest
0200:             *            the servlet request who's application object holds the server
0201:             *            configuration
0202:             * 
0203:             * @return a <code>GetMapRequest</code> completely setted up upon the
0204:             *         parameters passed to this reader
0205:             * 
0206:             * @throws ServiceException
0207:             *             DOCUMENT ME!
0208:             */
0209:            public Request getRequest(HttpServletRequest httpRequest)
0210:                    throws ServiceException {
0211:                GetMapRequest request = new GetMapRequest((WMService) service);
0212:                request.setHttpServletRequest(httpRequest);
0213:
0214:                String version = getRequestVersion();
0215:                request.setVersion(version);
0216:
0217:                parseMandatoryParameters(request, true);
0218:                parseOptionalParameters(request);
0219:
0220:                return request;
0221:            }
0222:
0223:            /**
0224:             * Parses the optional parameters:
0225:             * 
0226:             * <ul>
0227:             * <li> SRS </li>
0228:             * <li> TRANSPARENT </li>
0229:             * <li> EXCEPTIONS </li>
0230:             * <li> BGCOLOR </li>
0231:             * </ul>
0232:             * 
0233:             * 
0234:             * @param request
0235:             *            DOCUMENT ME!
0236:             * 
0237:             * @throws WmsException
0238:             *             DOCUMENT ME!
0239:             * 
0240:             * @task TODO: implement parsing of transparent, exceptions and bgcolor
0241:             */
0242:            public void parseOptionalParameters(GetMapRequest request)
0243:                    throws WmsException {
0244:                // SRS
0245:                String epsgCode = getValue("SRS");
0246:
0247:                if (epsgCode != null) {
0248:                    try {
0249:                        CoordinateReferenceSystem mapcrs = CRS.decode(epsgCode);
0250:                        request.setCrs(mapcrs);
0251:                        request.setSRS(epsgCode);
0252:                    } catch (Exception e) {
0253:                        // couldnt make it - we send off a service exception with the
0254:                        // correct info
0255:                        throw new WmsException(e.getLocalizedMessage(),
0256:                                "InvalidSRS");
0257:                    }
0258:                }
0259:
0260:                // transparency
0261:                String transparentValue = getValue("TRANSPARENT");
0262:                boolean transparent = (transparentValue == null) ? false
0263:                        : Boolean.valueOf(transparentValue).booleanValue();
0264:                request.setTransparent(transparent);
0265:
0266:                // background
0267:                String bgcolor = getValue("BGCOLOR");
0268:
0269:                if (bgcolor != null) {
0270:                    try {
0271:                        request.setBgColor(Color.decode(bgcolor));
0272:                    } catch (NumberFormatException nfe) {
0273:                        throw new WmsException(
0274:                                "BGCOLOR "
0275:                                        + bgcolor
0276:                                        + " incorrectly specified (0xRRGGBB format expected)");
0277:                    }
0278:                }
0279:
0280:                // filter parsing
0281:                parseFilterParam(request);
0282:
0283:                // buffer
0284:                String bufferValue = getValue("BUFFER");
0285:                int buffer = 0;
0286:
0287:                if (bufferValue != null) {
0288:                    try {
0289:                        buffer = Integer.parseInt(bufferValue);
0290:                    } catch (NumberFormatException nfe) {
0291:                        throw new WmsException(
0292:                                "BUFFER "
0293:                                        + bufferValue
0294:                                        + " incorrectly specified (expected an integer)");
0295:                    }
0296:                }
0297:
0298:                request.setBuffer(buffer);
0299:
0300:                // palette
0301:                String paletteValue = getValue("PALETTE");
0302:
0303:                if (paletteValue != null) {
0304:                    try {
0305:                        final InverseColorMapOp eicm = PaletteManager
0306:                                .getPalette(paletteValue);
0307:                        if (eicm == null) {
0308:                            throw new WmsException(
0309:                                    "Palette "
0310:                                            + paletteValue
0311:                                            + " could not be found "
0312:                                            + "in $GEOSERVER_DATA_DIR/palettes directory");
0313:                        }
0314:
0315:                        request.setPalette(eicm);
0316:                    } catch (Exception e) {
0317:                        throw new WmsException(e, "Palette " + paletteValue
0318:                                + " could not be loaded", null);
0319:                    }
0320:                }
0321:
0322:                // tiling hint
0323:                String tiledValue = getValue("TILED");
0324:                request.setTiled("TRUE".equalsIgnoreCase(tiledValue));
0325:
0326:                // tiling origin
0327:                String origin = getValue("TILESORIGIN");
0328:
0329:                if (origin != null) {
0330:                    request.setTilesOrigin(parseTilesOrigin(origin));
0331:                }
0332:
0333:                // feature version (for versioned requests)
0334:                String featureVersion = getValue("FEATUREVERSION");
0335:                request.setFeatureVersion(featureVersion);
0336:
0337:                /** KML/KMZ score value */
0338:                String KMScore = getValue("KMSCORE");
0339:
0340:                if (KMScore != null) {
0341:                    try {
0342:                        // handle special string cases of "vector" or "raster"
0343:                        if (KMScore.equalsIgnoreCase("vector")) {
0344:                            KMScore = "100"; // vector default
0345:                        } else if (KMScore.equalsIgnoreCase("raster")) {
0346:                            KMScore = "0"; // raster default
0347:                        }
0348:
0349:                        Integer s = new Integer(KMScore);
0350:                        int score = s.intValue();
0351:
0352:                        if ((score < 0) || (score > 100)) {
0353:                            throw new NumberFormatException(
0354:                                    "KMScore not between 0 and 100. "
0355:                                            + "If you wish not to use it, do not specify KMScore as a parameter.");
0356:                        }
0357:
0358:                        request.setKMScore(score);
0359:
0360:                        if (LOGGER.isLoggable(Level.INFO)) {
0361:                            LOGGER.info("Set KMScore: " + score);
0362:                        }
0363:                    } catch (NumberFormatException e) {
0364:                        throw new WmsException(
0365:                                "KMScore parameter ("
0366:                                        + KMScore
0367:                                        + ") incorrectly specified. "
0368:                                        + "Expecting an integer value between between 0 and 100");
0369:                    }
0370:                }
0371:
0372:                /** KMattr: 'full' or 'no' attribution for KML placemark <description> */
0373:                String KMAttr = getValue("KMATTR");
0374:
0375:                if (KMAttr != null) {
0376:                    if (KMAttr.equalsIgnoreCase("no")
0377:                            || KMAttr.equalsIgnoreCase("false")
0378:                            || KMAttr.equalsIgnoreCase("0")) {
0379:                        request.setKMattr(false);
0380:                    } else {
0381:                        request.setKMattr(true); // default to true
0382:                    }
0383:                }
0384:
0385:                /** KML super overlay */
0386:                String super Overlay = getValue("SUPEROVERLAY");
0387:
0388:                if (super Overlay != null) {
0389:                    request.setSuperOverlay("TRUE"
0390:                            .equalsIgnoreCase(super Overlay));
0391:                }
0392:
0393:                /** KML legend */
0394:                String legend = getValue("LEGEND");
0395:
0396:                if (legend != null) {
0397:                    request.setLegend("TRUE".equalsIgnoreCase(legend)
0398:                            || "ON".equalsIgnoreCase(legend));
0399:                }
0400:
0401:                //		/** TIME: a time stamp for multidim coverages <description> */
0402:                //		String time = getValue("TIME");
0403:                //
0404:                //		if (time != null) {
0405:                //			request.setTime(Integer.valueOf(time));
0406:                //
0407:                //			if (LOGGER.isLoggable(Level.INFO)) {
0408:                //				LOGGER.info("Set TIME: " + time);
0409:                //			}
0410:                //		}
0411:
0412:                /**
0413:                 * ELEVATION: elevation (or depth) valu for multidim coverages
0414:                 * <description>
0415:                 */
0416:                String elev = getValue("ELEVATION");
0417:
0418:                if (elev != null) {
0419:                    request.setElevation(Integer.valueOf(elev));
0420:
0421:                    if (LOGGER.isLoggable(Level.INFO)) {
0422:                        LOGGER.info("Set ELEVATION: " + elev);
0423:                    }
0424:                }
0425:            }
0426:
0427:            private Point2D parseTilesOrigin(String origin) {
0428:                Object[] coordValues = readFlat(origin, INNER_DELIMETER)
0429:                        .toArray();
0430:
0431:                if (coordValues.length != 2) {
0432:                    throw new ServiceException(origin
0433:                            + " is not a valid coordinate", getClass()
0434:                            .getName());
0435:                }
0436:
0437:                try {
0438:                    double minx = Double.parseDouble(coordValues[0].toString());
0439:                    double miny = Double.parseDouble(coordValues[1].toString());
0440:
0441:                    return new Point2D.Double(minx, miny);
0442:                } catch (NumberFormatException ex) {
0443:                    throw new ServiceException(ex,
0444:                            "Illegal value for TILESORIGIN parameter: "
0445:                                    + origin, getClass().getName()
0446:                                    + "::parseTilesOrigin()");
0447:                }
0448:            }
0449:
0450:            /**
0451:             * Parses the mandatory GetMap request parameters:
0452:             * 
0453:             * <p>
0454:             * Mandatory parameters:
0455:             * 
0456:             * <ul>
0457:             * <li> LAYERS </li>
0458:             * <li> STYLES ommited if SLD or SLD_BODY parameters are supplied </li>
0459:             * <li> BBOX </li>
0460:             * <li> FORMAT </li>
0461:             * <li> WIDTH </li>
0462:             * <li> HEIGHT </li>
0463:             * </ul>
0464:             * </p>
0465:             * 
0466:             * @param request
0467:             *            DOCUMENT ME!
0468:             * @parseStylesLayers true = normal operation, false = dont parse the styles
0469:             *                    and layers (used by the SLD GET/POST)
0470:             * 
0471:             * @throws WmsException
0472:             *             DOCUMENT ME!
0473:             */
0474:            public void parseMandatoryParameters(GetMapRequest request,
0475:                    boolean parseStylesLayers) throws WmsException {
0476:                try {
0477:                    int width = Integer.parseInt(getValue("WIDTH"));
0478:                    int height = Integer.parseInt(getValue("HEIGHT"));
0479:                    request.setWidth(width);
0480:                    request.setHeight(height);
0481:                } catch (NumberFormatException ex) {
0482:                    throw new WmsException(
0483:                            "WIDTH and HEIGHT incorrectly specified");
0484:                }
0485:
0486:                String format = getValue("FORMAT");
0487:
0488:                if (format == null) {
0489:                    throw new WmsException("parameter FORMAT is required");
0490:                }
0491:
0492:                request.setFormat(format);
0493:
0494:                Envelope bbox = parseBbox(getValue("BBOX"));
0495:                request.setBbox(bbox);
0496:
0497:                // let styles and layers parsing for the end to give more trivial
0498:                // parameters
0499:                // a chance to fail before incurring in retrieving the SLD or SLD_BODY
0500:                if (parseStylesLayers) {
0501:                    parseLayersAndStyles(request);
0502:                }
0503:            }
0504:
0505:            protected Envelope parseBbox(String bboxParam) throws WmsException {
0506:                // overridden to throw the right exception for this context
0507:                try {
0508:                    return super .parseBbox(bboxParam);
0509:                } catch (ServiceException e) {
0510:                    throw new WmsException(e);
0511:                }
0512:            }
0513:
0514:            /**
0515:             * creates a list of requested attributes, wich must be a valid attribute
0516:             * name or one of the following special attributes:
0517:             * 
0518:             * <ul>
0519:             * <li> <b>#FID</b>: a map producer capable of handling attributes (such as
0520:             * SVGMapResponse), will write the feature id of each feature </li>
0521:             * <li> <b>#BOUNDS</b>: a map producer capable of handling attributes (such
0522:             * as SVGMapResponse), will write the bounding box of each feature </li>
0523:             * </ul>
0524:             * 
0525:             * 
0526:             * @param layers
0527:             *            info about the requested map layers
0528:             * 
0529:             * @return an empty list if no attributes was requested, or a
0530:             *         <code>List&lt;List&lt;String&gt;&gt;</code> with an entry for
0531:             *         each requested layer, where each of them consists of a List of
0532:             *         the attribute names requested
0533:             * 
0534:             * @throws WmsException
0535:             *             if:
0536:             *             <ul>
0537:             *             <li>the number of attribute sets requested is not equal to
0538:             *             the number of layers requested.</li>
0539:             *             <li>an illegal attribute name was requested</li>
0540:             *             <li>an IOException occurs while fetching a FeatureType
0541:             *             schema to ask it for propper attribute names</li>
0542:             *             </ul>
0543:             */
0544:            private List parseAttributes(FeatureTypeInfo[] layers)
0545:                    throws WmsException {
0546:                String rawAtts = getValue("ATTRIBUTES");
0547:
0548:                if (LOGGER.isLoggable(Level.FINER)) {
0549:                    LOGGER.finer(new StringBuffer("parsing attributes ")
0550:                            .append(rawAtts).toString());
0551:                }
0552:
0553:                if ((rawAtts == null) || "".equals(rawAtts)) {
0554:                    return Collections.EMPTY_LIST;
0555:                }
0556:
0557:                // raw list of attributes for each feature type requested
0558:                List byFeatureTypes = readFlat(rawAtts, "|");
0559:                int nLayers = layers.length;
0560:
0561:                if (byFeatureTypes.size() != nLayers) {
0562:                    throw new WmsException(byFeatureTypes.size()
0563:                            + " lists of attributes specified, expected "
0564:                            + layers.length, getClass().getName()
0565:                            + "::parseAttributes()");
0566:                }
0567:
0568:                // fill byFeatureTypes with the split of its raw attributes requested
0569:                // separated by commas, and check for the validity of each att name
0570:                FeatureType schema;
0571:                List atts;
0572:                String attName;
0573:
0574:                for (int i = 0; i < nLayers; i++) {
0575:                    rawAtts = (String) byFeatureTypes.get(i);
0576:
0577:                    atts = readFlat(rawAtts, ",");
0578:                    byFeatureTypes.set(i, atts);
0579:
0580:                    // FeatureType schema = layers[i].getSchema();
0581:                    try {
0582:                        schema = layers[i].getFeatureType();
0583:
0584:                        // verify that propper attributes has been requested
0585:                        for (Iterator attIt = atts.iterator(); attIt.hasNext();) {
0586:                            attName = (String) attIt.next();
0587:
0588:                            if (attName.length() > 0) {
0589:                                if (LOGGER.isLoggable(Level.FINER)) {
0590:                                    LOGGER.finer(new StringBuffer(
0591:                                            "checking that ").append(attName)
0592:                                            .append(" is valid").toString());
0593:                                }
0594:
0595:                                if ("#FID".equalsIgnoreCase(attName)
0596:                                        || "#BOUNDS".equalsIgnoreCase(attName)) {
0597:                                    if (LOGGER.isLoggable(Level.FINER)) {
0598:                                        LOGGER
0599:                                                .finer(new StringBuffer(
0600:                                                        "special attribute name requested: ")
0601:                                                        .append(attName)
0602:                                                        .toString());
0603:                                    }
0604:
0605:                                    continue;
0606:                                }
0607:
0608:                                if (schema.getAttributeType(attName) == null) {
0609:                                    throw new WmsException("Attribute '"
0610:                                            + attName
0611:                                            + "' requested for layer "
0612:                                            + schema.getTypeName()
0613:                                            + " does not exists");
0614:                                }
0615:                            } else {
0616:                                if (LOGGER.isLoggable(Level.FINEST)) {
0617:                                    LOGGER
0618:                                            .finest("removing empty attribute name from request");
0619:                                }
0620:
0621:                                attIt.remove();
0622:                            }
0623:                        }
0624:
0625:                        if (LOGGER.isLoggable(Level.FINEST)) {
0626:                            LOGGER.finest(new StringBuffer(
0627:                                    "attributes requested for ").append(
0628:                                    schema.getTypeName()).append(" checked: ")
0629:                                    .append(rawAtts).toString());
0630:                        }
0631:                    } catch (java.io.IOException e) {
0632:                        throw new WmsException(e);
0633:                    }
0634:                }
0635:
0636:                return byFeatureTypes;
0637:            }
0638:
0639:            /**
0640:             * Parses the list of style names requested for each requested layer and
0641:             * looks up the actual Style objects, which are returned in an ordered list.
0642:             * 
0643:             * <p>
0644:             * A client _may_ request teh default Style using a null value (as in
0645:             * "STYLES="). If several layers are requested with a mixture of named and
0646:             * default styles, the STYLES parameter includes null values between commas
0647:             * (as in "STYLES=style1,,style2,,"). If all layers are to be shown using
0648:             * the default style, either the form "STYLES=" or "STYLES=,,," is valid.
0649:             * </p>
0650:             * 
0651:             * @param request
0652:             *            DOCUMENT ME!
0653:             * @param layers
0654:             *            the requested feature types
0655:             * 
0656:             * @return a full <code>List</code> of the style names requested for the
0657:             *         requiered layers with no null style names.
0658:             * 
0659:             * @throws WmsException
0660:             *             if some of the requested styles does not exist or its number
0661:             *             if greater than zero and distinct of the number of requested
0662:             *             layers
0663:             */
0664:            protected List parseStylesParam(GetMapRequest request,
0665:                    MapLayerInfo[] layers) throws WmsException {
0666:                String rawStyles = getValue("STYLES");
0667:                List styles = new ArrayList(layers.length);
0668:
0669:                int numLayers = layers.length;
0670:
0671:                if ("".equals(rawStyles)) {
0672:                    if (LOGGER.isLoggable(Level.FINER)) {
0673:                        LOGGER
0674:                                .finer("Assigning default style to all the requested layers");
0675:                    }
0676:
0677:                    for (int i = 0; i < numLayers; i++)
0678:                        if (layers[i].getType() == MapLayerInfo.TYPE_VECTOR) {
0679:                            styles
0680:                                    .add(layers[i].getFeature()
0681:                                            .getDefaultStyle());
0682:                        } else if (layers[i].getType() == MapLayerInfo.TYPE_RASTER) {
0683:                            styles.add(layers[i].getCoverage()
0684:                                    .getDefaultStyle());
0685:                        }
0686:                } else {
0687:                    List styleNames = readFlat(rawStyles, INNER_DELIMETER);
0688:
0689:                    if (numLayers != styleNames.size()) {
0690:                        String msg = numLayers
0691:                                + " layers requested, but found "
0692:                                + styleNames.size()
0693:                                + " styles specified. "
0694:                                + "Since SLD parameter is not yet implemented, the STYLES parameter "
0695:                                + "is mandatory and MUST have exactly one value per requested layer";
0696:                        throw new WmsException(msg, getClass().getName());
0697:                    }
0698:
0699:                    String currStyleName;
0700:                    Style currStyle;
0701:                    MapLayerInfo currLayer;
0702:
0703:                    for (int i = 0; i < numLayers; i++) {
0704:                        currStyleName = (String) styleNames.get(i);
0705:                        currLayer = layers[i];
0706:
0707:                        if (currLayer.getType() == MapLayerInfo.TYPE_VECTOR) {
0708:                            if ((null == currStyleName)
0709:                                    || "".equals(currStyleName)) {
0710:                                currStyle = currLayer.getFeature()
0711:                                        .getDefaultStyle();
0712:                            } else {
0713:                                currStyle = findStyle(request, currStyleName);
0714:
0715:                                if (currStyle == null) {
0716:                                    String msg = "No default style has been defined for "
0717:                                            + currLayer.getName();
0718:                                    throw new WmsException(msg,
0719:                                            "StyleNotDefined");
0720:                                }
0721:                            }
0722:
0723:                            try {
0724:                                checkStyle(currStyle, layers[i].getFeature()
0725:                                        .getFeatureType());
0726:                            } catch (IOException e) {
0727:                                throw new WmsException(
0728:                                        "Error obtaining FeatureType for layer "
0729:                                                + layers[i].getName());
0730:                            }
0731:
0732:                            if (LOGGER.isLoggable(Level.FINE)) {
0733:                                LOGGER
0734:                                        .fine(new StringBuffer("establishing ")
0735:                                                .append(currStyleName).append(
0736:                                                        " style for ").append(
0737:                                                        layers[i].getName())
0738:                                                .toString());
0739:                            }
0740:
0741:                            styles.add(currStyle);
0742:                        } else if (currLayer.getType() == MapLayerInfo.TYPE_RASTER) {
0743:                            if ((null == currStyleName)
0744:                                    || "".equals(currStyleName)) {
0745:                                currStyle = currLayer.getCoverage()
0746:                                        .getDefaultStyle();
0747:                            } else {
0748:                                currStyle = findStyle(request, currStyleName);
0749:
0750:                                if (currStyle == null) {
0751:                                    String msg = "No default style has been defined for "
0752:                                            + currLayer.getName();
0753:                                    throw new WmsException(msg,
0754:                                            "GetMapKvpReader::parseStyles()");
0755:                                }
0756:                            }
0757:
0758:                            /**
0759:                             * @task TODO: Check for Style Coverage Compatibility ...
0760:                             */
0761:                            styles.add(currStyle);
0762:                        }
0763:                    }
0764:                }
0765:
0766:                return styles;
0767:            }
0768:
0769:            /**
0770:             * DOCUMENT ME!
0771:             * 
0772:             * @param request
0773:             * @param currStyleName
0774:             * 
0775:             * @return the configured style named <code>currStyleName</code> or
0776:             *         <code>null</code> if such a style does not exists on this
0777:             *         server.
0778:             */
0779:            public static Style findStyle(GetMapRequest request,
0780:                    String currStyleName) {
0781:                Style currStyle;
0782:                Map configuredStyles = request.getWMS().getData().getStyles();
0783:
0784:                currStyle = (Style) configuredStyles.get(currStyleName);
0785:
0786:                return currStyle;
0787:            }
0788:
0789:            /**
0790:             * Method to initialize a user layer which contains inline features.
0791:             * 
0792:             * @param request
0793:             *            The request
0794:             * @param mapLayer
0795:             *            The map layer.
0796:             * 
0797:             * @throws Exception
0798:             */
0799:
0800:            // JD: the reason this method is static is to share logic among the xml
0801:            // and kvp reader, ugh...
0802:            public static void initializeInlineFeatureLayer(
0803:                    GetMapRequest getMapRequest, UserLayer ul,
0804:                    MapLayerInfo currLayer) throws Exception {
0805:                // SPECIAL CASE - we make the temporary version
0806:                currLayer.setFeature(new TemporaryFeatureTypeInfo(ul
0807:                        .getInlineFeatureDatastore()));
0808:
0809:                // what if they didn't put an "srsName" on their geometry in their
0810:                // inlinefeature?
0811:                // I guess we should assume they mean their geometry to exist in the
0812:                // output SRS of the
0813:                // request they're making.
0814:                if (ul.getInlineFeatureType().getDefaultGeometry()
0815:                        .getCoordinateSystem() == null) {
0816:                    LOGGER
0817:                            .warning("No CRS set on inline features default geometry.  Assuming the requestor has their inlinefeatures in the boundingbox CRS.");
0818:
0819:                    FeatureType currFt = ul.getInlineFeatureType();
0820:                    Query q = new DefaultQuery(currFt.getTypeName(),
0821:                            Filter.INCLUDE);
0822:                    FeatureReader ilReader = ul.getInlineFeatureDatastore()
0823:                            .getFeatureReader(q, Transaction.AUTO_COMMIT);
0824:                    CoordinateReferenceSystem crs = (getMapRequest.getCrs() == null) ? DefaultGeographicCRS.WGS84
0825:                            : getMapRequest.getCrs();
0826:                    MemoryDataStore reTypedDS = new MemoryDataStore(
0827:                            new ForceCoordinateSystemFeatureReader(ilReader,
0828:                                    crs));
0829:                    currLayer
0830:                            .setFeature(new TemporaryFeatureTypeInfo(reTypedDS));
0831:                }
0832:            }
0833:
0834:            /**
0835:             * Checks to make sure that the style passed in can process the FeatureType.
0836:             * 
0837:             * @param style
0838:             *            The style to check
0839:             * @param fType
0840:             *            The source requested.
0841:             * 
0842:             * @throws WmsException
0843:             *             DOCUMENT ME!
0844:             */
0845:            private void checkStyle(Style style, FeatureType fType)
0846:                    throws WmsException {
0847:                StyleAttributeExtractor sae = new StyleAttributeExtractor();
0848:                sae.visit(style);
0849:
0850:                String[] styleAttributes = sae.getAttributeNames();
0851:                String attName;
0852:                final int length = styleAttributes.length;
0853:
0854:                for (int i = 0; i < length; i++) {
0855:                    attName = styleAttributes[i];
0856:
0857:                    if (fType.getAttributeType(attName) == null) {
0858:                        throw new WmsException(
0859:                                "The requested Style can not be used with "
0860:                                        + "this featureType.  The style specifies an attribute of "
0861:                                        + attName
0862:                                        + " and the featureType definition is: "
0863:                                        + fType);
0864:                    }
0865:                }
0866:            }
0867:
0868:            /**
0869:             * DOCUMENT ME!
0870:             * 
0871:             * @param request
0872:             *            DOCUMENT ME!
0873:             * 
0874:             * @throws WmsException
0875:             *             DOCUMENT ME!
0876:             */
0877:            protected void parseLayersAndStyles(GetMapRequest request)
0878:                    throws WmsException {
0879:                String sldParam = getValue("SLD");
0880:                String sldBodyParam = getValue("SLD_BODY");
0881:
0882:                if (sldBodyParam != null) {
0883:                    if (LOGGER.isLoggable(Level.FINE)) {
0884:                        LOGGER.fine("Getting layers and styles from SLD_BODY");
0885:                    }
0886:
0887:                    parseSldBodyParam(request);
0888:                } else if (sldParam != null) {
0889:                    if (LOGGER.isLoggable(Level.FINE)) {
0890:                        LOGGER
0891:                                .fine("Getting layers and styles from reomte SLD");
0892:                    }
0893:
0894:                    parseSldParam(request);
0895:                } else {
0896:                    MapLayerInfo[] featureTypes = null;
0897:                    List styles = null;
0898:                    featureTypes = parseLayersParam(request);
0899:
0900:                    request.setLayers(featureTypes);
0901:
0902:                    if (isStylesRquired()) {
0903:                        styles = parseStylesParam(request, featureTypes);
0904:
0905:                        if (isStylesRquired()) {
0906:                            request.setStyles(styles);
0907:                        }
0908:                    }
0909:                }
0910:            }
0911:
0912:            /**
0913:             * Takes the SLD_BODY parameter value and parses it to a geotools'
0914:             * <code>StyledLayerDescriptor</code>, then takes the layers and styles
0915:             * to use in the map composition from there.
0916:             * 
0917:             * @param request
0918:             *            DOCUMENT ME!
0919:             * 
0920:             * @throws WmsException
0921:             *             DOCUMENT ME!
0922:             */
0923:            protected void parseSldBodyParam(GetMapRequest request)
0924:                    throws WmsException {
0925:                final String sldBody = getValue("SLD_BODY");
0926:
0927:                if (LOGGER.isLoggable(Level.FINE)) {
0928:                    LOGGER.fine(new StringBuffer("About to parse SLD body: ")
0929:                            .append(sldBody).toString());
0930:                }
0931:
0932:                if (getValue("VALIDATESCHEMA") != null) {
0933:                    // Get a reader from the given string
0934:                    Reader reader = getReaderFromString(sldBody);
0935:
0936:                    // -InputStream in = new StringBufferInputStream(sldBody);
0937:                    // user requested to validate the schema.
0938:                    SLDValidator validator = new SLDValidator();
0939:                    List errors = null;
0940:
0941:                    // Create a sax input source from the reader
0942:                    InputSource in = new InputSource(reader);
0943:                    errors = validator.validateSLD(in, request
0944:                            .getHttpServletRequest().getSession()
0945:                            .getServletContext());
0946:
0947:                    if (errors.size() != 0) {
0948:                        reader = getReaderFromString(sldBody);
0949:                        throw new WmsException(SLDValidator.getErrorMessage(
0950:                                reader, errors));
0951:                    }
0952:
0953:                    // - errors = validator.validateSLD(in,
0954:                    // request.getHttpServletRequest().getSession().getServletContext());
0955:                    // - try{
0956:                    // - in.close();
0957:                    // - }
0958:                    // - catch(Exception e)
0959:                    // - {
0960:                    // - // do nothing
0961:                    // - }
0962:                    // - if (errors.size() != 0)
0963:                    // - {
0964:                    // - in = new StringBufferInputStream(sldBody);
0965:                    // - throw new
0966:                    // WmsException(SLDValidator.getErrorMessage(in,errors));
0967:                    // - }
0968:                }
0969:
0970:                // - InputStream in = new StringBufferInputStream(sldBody);
0971:                // - SLDParser parser = new SLDParser(styleFactory, in);
0972:                Reader reader = getReaderFromString(sldBody);
0973:                SLDParser parser = new SLDParser(styleFactory, reader);
0974:                StyledLayerDescriptor sld = parser.parseSLD();
0975:                parseStyledLayerDescriptor(request, sld);
0976:            }
0977:
0978:            /**
0979:             * Create a reader of the given String. This reader will be used in the
0980:             * InputSource for the sld parser. The advantage with a reader over a input
0981:             * stream is that we don't have to consider encoding. The xml declaration
0982:             * with encoding is ignored using a Reader in parser. The encoding of the
0983:             * string has been appropiate handled by the servlet when streaming in.
0984:             * 
0985:             * @param sldBody
0986:             *            the sldbody to create a reader of.
0987:             * @return The created reader
0988:             * @see Reader
0989:             */
0990:            private Reader getReaderFromString(String sldBody) {
0991:                return new StringReader(sldBody);
0992:            }
0993:
0994:            /**
0995:             * Gets a sequence of url encoded filters and parses them into Filter
0996:             * objects that will be set into the request object
0997:             * 
0998:             * @param request
0999:             * @throws WmsException
1000:             */
1001:            protected void parseFilterParam(GetMapRequest request)
1002:                    throws WmsException {
1003:                String rawFilter = getValue("FILTER");
1004:                String rawCqlFilter = getValue("CQL_FILTER");
1005:                String rawIdFilter = getValue("FEATUREID");
1006:
1007:                // in case of a mixed request, get with sld in post body, layers
1008:                // are not parsed, so we can't parse filters neither...
1009:                if (request.getLayers() == null) {
1010:                    return;
1011:                }
1012:
1013:                int numLayers = request.getLayers().length;
1014:
1015:                if (numLayers == 0) {
1016:                    throw new RuntimeException(
1017:                            "parseFilterParam must be called after the layer list has been built!");
1018:                }
1019:
1020:                List filters = null;
1021:
1022:                // if no filter, no need to proceed
1023:                if ((rawFilter != null) && !rawFilter.equals("")) {
1024:                    try {
1025:                        filters = readOGCFilter(rawFilter);
1026:                    } catch (ServiceException e) {
1027:                        throw new WmsException(e);
1028:                    }
1029:                }
1030:
1031:                if ((rawIdFilter != null) && !rawIdFilter.equals("")) {
1032:                    if (filters != null) {
1033:                        throw new WmsException("GetMap KVP request contained "
1034:                                + "conflicting filters.  Filter: " + rawFilter
1035:                                + ", fid: " + rawFilter);
1036:                    }
1037:
1038:                    filters = readFidFilters(rawIdFilter);
1039:                }
1040:
1041:                if ((rawCqlFilter != null) && !rawCqlFilter.equals("")) {
1042:                    if (filters != null) {
1043:                        throw new WmsException("GetMap KVP request contained "
1044:                                + "conflicting filters.  Filter: " + rawFilter
1045:                                + ", fid: " + rawFilter + ", cql: "
1046:                                + rawCqlFilter);
1047:                    }
1048:
1049:                    try {
1050:                        filters = readCQLFilter(rawCqlFilter);
1051:                    } catch (ServiceException e) {
1052:                        throw new WmsException(e);
1053:                    }
1054:                }
1055:
1056:                if (filters == null) {
1057:                    return;
1058:                }
1059:
1060:                if (numLayers != filters.size()) {
1061:                    // as in wfs getFeatures, perform lenient parsing, if just one
1062:                    // filter, it gets
1063:                    // applied to all layers
1064:                    if (filters.size() == 1) {
1065:                        Filter f = (Filter) filters.get(0);
1066:                        filters = new ArrayList(numLayers);
1067:
1068:                        for (int i = 0; i < numLayers; i++) {
1069:                            filters.add(f);
1070:                        }
1071:                    } else {
1072:                        String msg = numLayers
1073:                                + " layers requested, but found "
1074:                                + filters.size()
1075:                                + " filters specified. "
1076:                                + "When you specify the FILTER parameter, you must provide just one, \n"
1077:                                + " that will be applied to all layers, or exactly one for each requested layer";
1078:                        throw new WmsException(msg, getClass().getName());
1079:                    }
1080:                }
1081:
1082:                request.setFilters(filters);
1083:            }
1084:
1085:            /**
1086:             * DOCUMENT ME!
1087:             * 
1088:             * @param request
1089:             *            DOCUMENT ME!
1090:             * 
1091:             * @throws WmsException
1092:             *             DOCUMENT ME!
1093:             */
1094:            protected void parseSldParam(GetMapRequest request)
1095:                    throws WmsException {
1096:                String urlValue = getValue("SLD");
1097:
1098:                if (LOGGER.isLoggable(Level.FINE)) {
1099:                    LOGGER.fine(new StringBuffer(
1100:                            "about to load remote SLD document: '").append(
1101:                            urlValue).append("'").toString());
1102:                }
1103:
1104:                URL sldUrl;
1105:
1106:                try {
1107:                    sldUrl = new URL(fixURL(urlValue));
1108:                } catch (MalformedURLException e) {
1109:                    String msg = new StringBuffer("Creating remote SLD url: ")
1110:                            .append(e.getMessage()).toString();
1111:
1112:                    if (LOGGER.isLoggable(Level.WARNING)) {
1113:                        LOGGER.log(Level.WARNING, msg, e);
1114:                    }
1115:
1116:                    throw new WmsException(e, msg, "parseSldParam");
1117:                }
1118:
1119:                if (getValue("VALIDATESCHEMA") != null) {
1120:                    // user requested to validate the schema.
1121:                    SLDValidator validator = new SLDValidator();
1122:                    List errors = null;
1123:
1124:                    try {
1125:                        // JD: GEOS-420, Wrap the sldUrl in getINputStream method in
1126:                        // order
1127:                        // to do compression
1128:                        InputStream in = getInputStream(sldUrl);
1129:                        errors = validator.validateSLD(in, request
1130:                                .getHttpServletRequest().getSession()
1131:                                .getServletContext());
1132:                        in.close();
1133:
1134:                        if (errors.size() != 0) {
1135:                            throw new WmsException(SLDValidator
1136:                                    .getErrorMessage(sldUrl.openStream(),
1137:                                            errors));
1138:                        }
1139:                    } catch (IOException e) {
1140:                        String msg = new StringBuffer(
1141:                                "Creating remote SLD url: ").append(
1142:                                e.getMessage()).toString();
1143:
1144:                        if (LOGGER.isLoggable(Level.WARNING)) {
1145:                            LOGGER.log(Level.WARNING, msg, e);
1146:                        }
1147:
1148:                        throw new WmsException(e, msg, "parseSldParam");
1149:                    }
1150:                }
1151:
1152:                SLDParser parser;
1153:
1154:                try {
1155:                    // JD: GEOS-420, Wrap the sldUrl in getINputStream method in order
1156:                    // to do compression
1157:                    parser = new SLDParser(styleFactory, getInputStream(sldUrl));
1158:                } catch (IOException e) {
1159:                    String msg = new StringBuffer("Creating remote SLD url: ")
1160:                            .append(e.getMessage()).toString();
1161:
1162:                    if (LOGGER.isLoggable(Level.WARNING)) {
1163:                        LOGGER.log(Level.WARNING, msg, e);
1164:                    }
1165:
1166:                    throw new WmsException(e, msg, "parseSldParam");
1167:                }
1168:
1169:                StyledLayerDescriptor sld = parser.parseSLD();
1170:                parseStyledLayerDescriptor(request, sld);
1171:            }
1172:
1173:            /**
1174:             * URLEncoder.encode does not respect the RFC 2396, so we rolled our own
1175:             * little encoder. It's not complete, but should work in most cases
1176:             * 
1177:             * @param url
1178:             * @return
1179:             */
1180:            static String fixURL(String url) {
1181:                StringBuffer sb = new StringBuffer();
1182:
1183:                for (int i = 0; i < url.length(); i++) {
1184:                    char c = url.charAt(i);
1185:
1186:                    // From RFC, "Only alphanumerics [0-9a-zA-Z], the special
1187:                    // characters "$-_.+!*'(),", and reserved characters used
1188:                    // for their reserved purposes may be used unencoded within a URL
1189:                    // Here we keep all the good ones, and remove the few uneeded in
1190:                    // their
1191:                    // ascii range. We also keep / and : to make sure basic URL elements
1192:                    // don't get encoded
1193:                    if ((c > ' ') && (c < '{')
1194:                            && ("\"\\<>%^[]`+$,".indexOf(c) == -1)) {
1195:                        sb.append(c);
1196:                    } else {
1197:                        sb.append("%").append(Integer.toHexString(c));
1198:                    }
1199:                }
1200:
1201:                return sb.toString();
1202:            }
1203:
1204:            /**
1205:             * Looks in <code>sld</code> for the layers and styles to use in the map
1206:             * composition and sets them to the <code>request</code>
1207:             * 
1208:             * <p>
1209:             * If <code>sld</code> is used in "library" mode, that is, the LAYERS
1210:             * param is also present, saying what layers must be taken in count, then
1211:             * only the layers from the LAYERS parameter are used and <code>sld</code>
1212:             * is used as a style library, which means that for each layer requested
1213:             * through LAYERS=..., if a style if found in it for that layer it is used,
1214:             * and if not, the layers default is used.
1215:             * </p>
1216:             * 
1217:             * <p>
1218:             * By the other hand, if the LAYERS parameter is not present all the layers
1219:             * found in <code>sld</code> are setted to <code>request</code>.
1220:             * </p>
1221:             * 
1222:             * @param request
1223:             *            the GetMap request to which to set the layers and styles
1224:             * @param sld
1225:             *            a SLD document to take layers and styles from, following the
1226:             *            "literal" or "library" rule.
1227:             * 
1228:             * @throws WmsException
1229:             *             if anything goes wrong
1230:             * @throws RuntimeException
1231:             *             DOCUMENT ME!
1232:             */
1233:            private void parseStyledLayerDescriptor(
1234:                    final GetMapRequest request, final StyledLayerDescriptor sld)
1235:                    throws WmsException {
1236:                MapLayerInfo[] libraryModeLayers = null;
1237:
1238:                if (null != getValue("LAYERS")) {
1239:                    if (LOGGER.isLoggable(Level.INFO)) {
1240:                        LOGGER.info("request comes in \"library\" mode");
1241:                    }
1242:
1243:                    libraryModeLayers = parseLayersParam(request);
1244:                }
1245:
1246:                final StyledLayer[] styledLayers = sld.getStyledLayers();
1247:                final int slCount = styledLayers.length;
1248:
1249:                if (slCount == 0) {
1250:                    throw new WmsException("SLD document contains no layers");
1251:                }
1252:
1253:                final List layers = new ArrayList();
1254:                final List styles = new ArrayList();
1255:
1256:                MapLayerInfo currLayer = null;
1257:                Style currStyle = null;
1258:
1259:                if (null != libraryModeLayers) {
1260:                    int lCount = libraryModeLayers.length;
1261:
1262:                    for (int i = 0; i < lCount; i++) {
1263:                        currLayer = libraryModeLayers[i];
1264:
1265:                        if (currLayer.getType() == MapLayerInfo.TYPE_VECTOR) {
1266:                            currStyle = findStyleOf(request, currLayer
1267:                                    .getFeature(), styledLayers);
1268:                        } else if (currLayer.getType() == MapLayerInfo.TYPE_RASTER) {
1269:                            try {
1270:                                currStyle = findStyleOf(request, currLayer
1271:                                        .getFeature(), styledLayers);
1272:                            } catch (WmsException wm) {
1273:                                currStyle = findStyleOf(request, currLayer
1274:                                        .getFeature(), styledLayers);
1275:                                if (currStyle == null) {
1276:                                    // nope, there's no default raster style. Give up.
1277:                                    throw new WmsException(
1278:                                            wm.getMessage()
1279:                                                    + "  Also tried to use "
1280:                                                    + "the generic raster style 'raster', but it wasn't available.");
1281:                                }
1282:                            }
1283:                        }
1284:
1285:                        layers.add(currLayer);
1286:                        styles.add(currStyle);
1287:                    }
1288:                } else {
1289:                    StyledLayer sl = null;
1290:                    String layerName;
1291:                    UserLayer ul;
1292:
1293:                    for (int i = 0; i < slCount; i++) {
1294:                        sl = styledLayers[i];
1295:                        layerName = sl.getName();
1296:
1297:                        if (null == layerName) {
1298:                            throw new WmsException(
1299:                                    "A UserLayer without layer name was passed");
1300:                        }
1301:
1302:                        currLayer = new MapLayerInfo();
1303:
1304:                        // handle the InLineFeature stuff
1305:                        // TODO: add support for remote WFS here
1306:                        if ((sl instanceof  UserLayer)
1307:                                && ((((UserLayer) sl))
1308:                                        .getInlineFeatureDatastore() != null)) {
1309:                            // SPECIAL CASE - we make the temporary version
1310:                            ul = ((UserLayer) sl);
1311:
1312:                            try {
1313:                                initializeInlineFeatureLayer(request, ul,
1314:                                        currLayer);
1315:                            } catch (Exception e) {
1316:                                throw new WmsException(e);
1317:                            }
1318:                        } else {
1319:                            try {
1320:                                currLayer.setFeature(GetMapKvpReader
1321:                                        .findFeatureLayer(request, layerName));
1322:                            } catch (WmsException e) {
1323:                                currLayer.setCoverage(GetMapKvpReader
1324:                                        .findCoverageLayer(request, layerName));
1325:                            }
1326:                        }
1327:
1328:                        if (currLayer.getType() == MapLayerInfo.TYPE_VECTOR) {
1329:                            // currStyle = findStyleOf(request, currLayer,
1330:                            // styledLayers); // DJB: this looks like a bug, we should
1331:                            // get the style from styledLayers[i]
1332:
1333:                            // the correct thing to do its grab the style from
1334:                            // styledLayers[i]
1335:                            // inside the styledLayers[i] will either be :
1336:                            // a) nothing - in which case grab the layer's default style
1337:                            // b) a set of:
1338:                            // i) NameStyle -- grab it from the pre-loaded styles
1339:                            // ii)UserStyle -- grab it from the sld the user uploaded
1340:                            //
1341:                            // NOTE: we're going to get a set of layer->style pairs for
1342:                            // (b).
1343:                            addStyles(request, currLayer, styledLayers[i],
1344:                                    layers, styles);
1345:                        } else if (currLayer.getType() == MapLayerInfo.TYPE_RASTER) {
1346:                            try {
1347:                                addStyles(request, currLayer, styledLayers[i],
1348:                                        layers, styles);
1349:                            } catch (WmsException wm) {
1350:                                // hmm, well, the style they specified in the wms
1351:                                // request
1352:                                // wasn't found. Let's try the default raster style
1353:                                // named 'raster'
1354:                                currStyle = findStyle(request, "raster");
1355:                                if (currStyle == null) {
1356:                                    // nope, there's no default raster style. Give up.
1357:                                    throw new WmsException(
1358:                                            wm.getMessage()
1359:                                                    + "  Also tried to use "
1360:                                                    + "the generic raster style 'raster', but it wasn't available.");
1361:                                }
1362:                                layers.add(currLayer);
1363:                                styles.add(currStyle);
1364:                            }
1365:                        }
1366:                    }
1367:                }
1368:
1369:                request.setLayers((MapLayerInfo[]) layers
1370:                        .toArray(new MapLayerInfo[layers.size()]));
1371:                request.setStyles(styles);
1372:            }
1373:
1374:            /**
1375:             * the correct thing to do its grab the style from styledLayers[i] inside
1376:             * the styledLayers[i] will either be : a) nothing - in which case grab the
1377:             * layer's default style b) a set of: i) NameStyle -- grab it from the
1378:             * pre-loaded styles ii)UserStyle -- grab it from the sld the user uploaded
1379:             * 
1380:             * NOTE: we're going to get a set of layer->style pairs for (b). these are
1381:             * added to layers,styles
1382:             * 
1383:             * NOTE: we also handle some featuretypeconstraints
1384:             * 
1385:             * @param request
1386:             * @param currLayer
1387:             * @param layer
1388:             * @param layers
1389:             * @param styles
1390:             */
1391:            public static void addStyles(GetMapRequest request,
1392:                    MapLayerInfo currLayer, StyledLayer layer, List layers,
1393:                    List styles) throws WmsException {
1394:                if (currLayer == null) {
1395:                    return; // protection
1396:                }
1397:
1398:                Style[] layerStyles = null;
1399:                FeatureTypeConstraint[] ftcs = null;
1400:
1401:                if (layer instanceof  NamedLayer) {
1402:                    ftcs = ((NamedLayer) layer).getLayerFeatureConstraints();
1403:                    layerStyles = ((NamedLayer) layer).getStyles();
1404:                } else if (layer instanceof  UserLayer) {
1405:                    ftcs = ((UserLayer) layer).getLayerFeatureConstraints();
1406:                    layerStyles = ((UserLayer) layer).getUserStyles();
1407:                }
1408:
1409:                // DJB: TODO: this needs to do the whole thing, not just names
1410:                if (ftcs != null) {
1411:                    FeatureTypeConstraint ftc;
1412:                    final int length = ftcs.length;
1413:
1414:                    for (int t = 0; t < length; t++) {
1415:                        ftc = ftcs[t];
1416:
1417:                        if (ftc.getFeatureTypeName() != null) {
1418:                            String ftc_name = ftc.getFeatureTypeName();
1419:
1420:                            // taken from lite renderer
1421:                            boolean matches;
1422:
1423:                            try {
1424:                                matches = currLayer.getFeature()
1425:                                        .getFeatureType().isDescendedFrom(null,
1426:                                                ftc_name)
1427:                                        || currLayer.getFeature()
1428:                                                .getFeatureType().getTypeName()
1429:                                                .equalsIgnoreCase(ftc_name);
1430:                            } catch (Exception e) {
1431:                                matches = false; // bad news
1432:                            }
1433:
1434:                            if (!matches) {
1435:                                continue; // this layer is fitered out
1436:                            }
1437:                        }
1438:                    }
1439:                }
1440:
1441:                // handle no styles -- use default
1442:                if ((layerStyles == null) || (layerStyles.length == 0)) {
1443:                    layers.add(currLayer);
1444:                    styles.add(currLayer.getDefaultStyle());
1445:
1446:                    return;
1447:                }
1448:
1449:                final int length = layerStyles.length;
1450:                Style s;
1451:
1452:                for (int t = 0; t < length; t++) {
1453:                    if (layerStyles[t] instanceof  NamedStyle) {
1454:                        layers.add(currLayer);
1455:                        s = findStyle(request, ((NamedStyle) layerStyles[t])
1456:                                .getName());
1457:
1458:                        if (s == null) {
1459:                            throw new WmsException("couldnt find style named '"
1460:                                    + ((NamedStyle) layerStyles[t]).getName()
1461:                                    + "'");
1462:                        }
1463:
1464:                        styles.add(s);
1465:                    } else {
1466:                        layers.add(currLayer);
1467:                        styles.add(layerStyles[t]);
1468:                    }
1469:                }
1470:            }
1471:
1472:            /**
1473:             * Finds the style for <code>layer</code> in <code>styledLayers</code>
1474:             * or the layer's default style if <code>styledLayers</code> has no a
1475:             * UserLayer or a NamedLayer with the same name than <code>layer</code>
1476:             * <p>
1477:             * This method is used to parse the style of a layer for SLD and SLD_BODY
1478:             * parameters, both in library and literal mode. Thus, once the declared
1479:             * style for the given layer is found, it is checked for validity of
1480:             * appliance for that layer (i.e., whether the featuretype contains the
1481:             * attributes needed for executing the style filters).
1482:             * </p>
1483:             * 
1484:             * @param request
1485:             *            used to find out an internally configured style when
1486:             *            referenced by name by a NamedLayer
1487:             * 
1488:             * @param layer
1489:             *            one of the internal FeatureType that was requested through the
1490:             *            LAYERS parameter or through and SLD document when the request
1491:             *            is in literal mode.
1492:             * @param styledLayers
1493:             *            a set of StyledLayers from where to find the SLD layer with
1494:             *            the same name as <code>layer</code> and extract the style to
1495:             *            apply.
1496:             * 
1497:             * @return the Style applicable to <code>layer</code> extracted from
1498:             *         <code>styledLayers</code>.
1499:             * 
1500:             * @throws RuntimeException
1501:             *             if one of the StyledLayers is neither a UserLayer nor a
1502:             *             NamedLayer. This shuoldn't happen, since the only allowed
1503:             *             subinterfaces of StyledLayer are NamedLayer and UserLayer.
1504:             * @throws WmsException
1505:             */
1506:            private Style findStyleOf(GetMapRequest request,
1507:                    FeatureTypeInfo layer, StyledLayer[] styledLayers)
1508:                    throws WmsException {
1509:                Style style = null;
1510:                String layerName = layer.getName();
1511:                StyledLayer sl;
1512:
1513:                for (int i = 0; i < styledLayers.length; i++) {
1514:                    sl = styledLayers[i];
1515:
1516:                    if (layerName.equals(sl.getName())) {
1517:                        if (sl instanceof  UserLayer) {
1518:                            Style[] styles = ((UserLayer) sl).getUserStyles();
1519:
1520:                            if ((null != styles) && (0 < styles.length)) {
1521:                                style = styles[0];
1522:                            }
1523:                        } else if (sl instanceof  NamedLayer) {
1524:                            Style[] styles = ((NamedLayer) sl).getStyles();
1525:
1526:                            if ((null != styles) && (0 < styles.length)) {
1527:                                style = styles[0];
1528:                            }
1529:
1530:                            if (style instanceof  NamedStyle) {
1531:                                style = findStyle(request, style.getName());
1532:                            }
1533:                        } else {
1534:                            throw new RuntimeException("Unknown layer type: "
1535:                                    + sl);
1536:                        }
1537:
1538:                        break;
1539:                    }
1540:                }
1541:
1542:                if (null == style) {
1543:                    style = layer.getDefaultStyle();
1544:                }
1545:
1546:                FeatureType type;
1547:
1548:                try {
1549:                    type = layer.getFeatureType();
1550:                } catch (IOException ioe) {
1551:                    throw new RuntimeException(
1552:                            "Error getting FeatureType, this should never happen!");
1553:                }
1554:
1555:                checkStyle(style, type);
1556:
1557:                return style;
1558:            }
1559:
1560:            /**
1561:             * Parses a list of layers in a layer grouping.
1562:             * 
1563:             * @param layerGroup The layer group.
1564:             * 
1565:             * @return List of String.
1566:             */
1567:            public static List parseLayerGroup(String layerGroup) {
1568:                return readFlat(layerGroup, INNER_DELIMETER);
1569:            }
1570:
1571:            /**
1572:             * Parses the requested layers given by the LAYERS request parameter and
1573:             * looks up their corresponding FeatureTypeInfo objects in the server.
1574:             * 
1575:             * @param request
1576:             * 
1577:             * @return
1578:             * 
1579:             * @throws WmsException
1580:             */
1581:            protected MapLayerInfo[] parseLayersParam(GetMapRequest request)
1582:                    throws WmsException {
1583:                MapLayerInfo[] layers;
1584:                String layersParam = getValue("LAYERS");
1585:                List layerNames = readFlat(layersParam, INNER_DELIMETER);
1586:                List realLayerNames = new ArrayList();
1587:
1588:                // expand base layers, if there is any
1589:                WMS wms = request.getWMS();
1590:                if (wms.getBaseMapLayers() != null) {
1591:                    for (int i = 0; i < layerNames.size(); i++) {
1592:                        String layerGroup = (String) wms.getBaseMapLayers()
1593:                                .get(layerNames.get(i));
1594:                        if (layerGroup != null) {
1595:                            List layerGroupExpanded = parseLayerGroup(layerGroup);
1596:                            layerNames.remove(i);
1597:                            layerNames.addAll(i, layerGroupExpanded);
1598:                        }
1599:                    }
1600:                }
1601:
1602:                String layerName = null;
1603:                Data catalog = request.getWMS().getData();
1604:
1605:                String rawStyles = getValue("STYLES");
1606:                List styleNames = readFlat(rawStyles, INNER_DELIMETER);
1607:
1608:                int l_counter = 0;
1609:                int s_counter = styleNames.size();
1610:
1611:                // //
1612:                // Expand the eventually WMS grouped layers into the same WMS Path
1613:                // element
1614:                // //
1615:                for (Iterator it = layerNames.iterator(); it.hasNext();) {
1616:                    layerName = (String) it.next();
1617:
1618:                    Integer layerType = catalog.getLayerType(layerName);
1619:
1620:                    if (layerType == null) {
1621:                        // //
1622:                        // Search for grouped layers (attention: heavy process)
1623:                        // //
1624:                        String catalogLayerName = null;
1625:
1626:                        for (Iterator c_keys = catalog.getLayerNames()
1627:                                .iterator(); c_keys.hasNext();) {
1628:                            catalogLayerName = (String) c_keys.next();
1629:
1630:                            try {
1631:                                FeatureTypeInfo ftype = findFeatureLayer(
1632:                                        request, catalogLayerName);
1633:                                String wmsPath = ftype.getWmsPath();
1634:
1635:                                if ((wmsPath != null)
1636:                                        && wmsPath.matches(".*/" + layerName)) {
1637:                                    realLayerNames.add(catalogLayerName);
1638:                                    l_counter++;
1639:
1640:                                    if (l_counter > s_counter) {
1641:                                        rawStyles = ((rawStyles.length() > 0) ? (rawStyles + ",")
1642:                                                : rawStyles)
1643:                                                + ftype.getDefaultStyle()
1644:                                                        .getName();
1645:                                    }
1646:                                }
1647:                            } catch (WmsException e_1) {
1648:                                try {
1649:                                    CoverageInfo cv = findCoverageLayer(
1650:                                            request, catalogLayerName);
1651:                                    String wmsPath = cv.getWmsPath();
1652:
1653:                                    if ((wmsPath != null)
1654:                                            && wmsPath.matches(".*/"
1655:                                                    + layerName)) {
1656:                                        realLayerNames.add(catalogLayerName);
1657:                                        l_counter++;
1658:
1659:                                        if (l_counter > s_counter) {
1660:                                            rawStyles = ((rawStyles.length() > 0) ? (rawStyles + ",")
1661:                                                    : rawStyles)
1662:                                                    + cv.getDefaultStyle()
1663:                                                            .getName();
1664:                                        }
1665:                                    }
1666:                                } catch (WmsException e_2) {
1667:                                }
1668:                            }
1669:                        }
1670:                    } else {
1671:                        realLayerNames.add(layerName);
1672:                        l_counter++;
1673:                    }
1674:                }
1675:
1676:                // JD: only set if non-null since if the layer is an actual layer
1677:                // (ie. not something matching wms path) with no style specified we
1678:                // dont want to create an empty "STYLES" entry
1679:                if ((rawStyles != null) && !"".equals(rawStyles.trim())) {
1680:                    kvpPairs.put("STYLES", rawStyles);
1681:                }
1682:
1683:                int layerCount = realLayerNames.size();
1684:
1685:                if (layerCount == 0) {
1686:                    throw new WmsException("No LAYERS has been requested",
1687:                            getClass().getName());
1688:                }
1689:
1690:                layers = new MapLayerInfo[layerCount];
1691:
1692:                for (int i = 0; i < layerCount; i++) {
1693:                    layerName = (String) layerNames.get(i);
1694:                    layers[i] = new MapLayerInfo();
1695:
1696:                    try {
1697:                        FeatureTypeInfo ftype = findFeatureLayer(request,
1698:                                layerName);
1699:
1700:                        layers[i].setFeature(ftype);
1701:                    } catch (WmsException e) {
1702:                        CoverageInfo cv = findCoverageLayer(request, layerName);
1703:
1704:                        layers[i].setCoverage(cv);
1705:                    }
1706:                }
1707:
1708:                return layers;
1709:            }
1710:
1711:            /**
1712:             * DOCUMENT ME!
1713:             * 
1714:             * @param request
1715:             * @param layerName
1716:             * 
1717:             * @return
1718:             * 
1719:             * @throws WmsException
1720:             *             DOCUMENT ME!
1721:             */
1722:            public static FeatureTypeInfo findFeatureLayer(
1723:                    GetMapRequest request, String layerName)
1724:                    throws WmsException {
1725:                Data catalog = request.getWMS().getData();
1726:                FeatureTypeInfo ftype = null;
1727:                Integer layerType = catalog.getLayerType(layerName);
1728:
1729:                if (Data.TYPE_VECTOR != layerType) {
1730:                    throw new WmsException(new StringBuffer(layerName).append(
1731:                            ": no such layer on this server").toString(),
1732:                            "LayerNotDefined");
1733:                } else {
1734:                    ftype = catalog.getFeatureTypeInfo(layerName);
1735:                }
1736:
1737:                return ftype;
1738:            }
1739:
1740:            public static CoverageInfo findCoverageLayer(GetMapRequest request,
1741:                    String layerName) throws WmsException {
1742:                Data catalog = request.getWMS().getData();
1743:                CoverageInfo cv = null;
1744:                Integer layerType = catalog.getLayerType(layerName);
1745:
1746:                if (Data.TYPE_RASTER != layerType) {
1747:                    throw new WmsException(new StringBuffer(layerName).append(
1748:                            ": no such layer on this server").toString(),
1749:                            "LayerNotDefined");
1750:                } else {
1751:                    cv = catalog.getCoverageInfo(layerName);
1752:                }
1753:
1754:                return cv;
1755:            }
1756:
1757:            /**
1758:             * This method gets the correct input stream for a URL. If the URL is a
1759:             * http/https connection, the Accept-Encoding: gzip, deflate is added. It
1760:             * the paramter is added, the response is checked to see if the response is
1761:             * encoded in gzip, deflate or plain bytes. The correct input stream wrapper
1762:             * is then selected and returned.
1763:             * 
1764:             * This method was added as part of GEOS-420
1765:             * 
1766:             * @param sldUrl
1767:             *            The url to the sld file
1768:             * @return The InputStream used to validate and parse the SLD xml.
1769:             * @throws IOException
1770:             */
1771:            private InputStream getInputStream(URL sldUrl) throws IOException {
1772:                // Open the connection
1773:                URLConnection conn = sldUrl.openConnection();
1774:
1775:                // If it is the http or https scheme, then ask for gzip if the server
1776:                // supports it.
1777:                if (conn instanceof  HttpURLConnection) {
1778:                    // Send the requested encoding to the remote server.
1779:                    conn.setRequestProperty("Accept-Encoding", "gzip, deflate");
1780:                }
1781:
1782:                // Conect to get the response headers
1783:                conn.connect();
1784:
1785:                // Return the correct inputstream
1786:                // If the connection is a url, connection, check the response encoding.
1787:                if (conn instanceof  HttpURLConnection) {
1788:                    // Get the content encoding of the server response
1789:                    String encoding = conn.getContentEncoding();
1790:
1791:                    // If null, set it to a emtpy string
1792:                    if (encoding == null) {
1793:                        encoding = "";
1794:                    }
1795:
1796:                    if (encoding.equalsIgnoreCase("gzip")) {
1797:                        // For gzip input stream, use a GZIPInputStream
1798:                        return new GZIPInputStream(conn.getInputStream());
1799:                    } else if (encoding.equalsIgnoreCase("deflate")) {
1800:                        // If it is encoded as deflate, then select the inflater
1801:                        // inputstream.
1802:                        return new InflaterInputStream(conn.getInputStream(),
1803:                                new Inflater(true));
1804:                    } else {
1805:                        // Else read the raw bytes
1806:                        return conn.getInputStream();
1807:                    }
1808:                } else {
1809:                    // Else read the raw bytes.
1810:                    return conn.getInputStream();
1811:                }
1812:            }
1813:
1814:            /**
1815:             * Filters the layers and styles if the user specified "layers=basemap".
1816:             * 
1817:             * 
1818:             * @param layers
1819:             * @param styles
1820:             */
1821:            public void filterBaseMap(Map layers, Map styles) {
1822:                List currentLayers = null;
1823:
1824:                try {
1825:                    // read flat can return non modifiable lists
1826:                    currentLayers = new ArrayList(readFlat(getValue("LAYERS"),
1827:                            ","));
1828:                } catch (NullPointerException e) {
1829:                    // No layers defined. This is either wrong or they are listing the
1830:                    // layers
1831:                    // in an SLD document specified with the SLD= parameter
1832:                    LOGGER
1833:                            .fine("No layers defined. This is either wrong or they are listing the layers"
1834:                                    + " in an SLD document specified with the SLD= parameter");
1835:
1836:                    return; // just continue ignoring the basemap option
1837:                }
1838:
1839:                List currentStyles = null;
1840:
1841:                try {
1842:                    currentStyles = new ArrayList(readFlat(getValue("STYLES"),
1843:                            ","));
1844:                } catch (NullPointerException e) {
1845:                    currentStyles = new ArrayList();
1846:                }
1847:
1848:                while (currentStyles.size() < currentLayers.size())
1849:                    currentStyles.add("");
1850:
1851:                String[] baseLayers = (String[]) layers.keySet().toArray(
1852:                        new String[0]);
1853:                boolean replacedOne = false;
1854:
1855:                for (int i = 0; i < baseLayers.length; i++) {
1856:                    String blTitle = baseLayers[i];
1857:                    int index = currentLayers.indexOf(blTitle);
1858:
1859:                    if (index > -1) {
1860:                        replacedOne = true;
1861:                        LOGGER.info("Using BASEMAP layer: " + baseLayers[i]);
1862:
1863:                        // remove the 'basemap layer' from the currentLayers list
1864:                        currentLayers.remove(index);
1865:
1866:                        List blLayers = new ArrayList(readFlat((String) layers
1867:                                .get(blTitle), ","));
1868:                        currentLayers.addAll(index, blLayers);
1869:                        List blStyles = new ArrayList(readFlat((String) styles
1870:                                .get(blTitle), ","));
1871:
1872:                        while (blStyles.size() < blLayers.size())
1873:                            blStyles.add("");
1874:
1875:                        currentStyles.remove(index);
1876:                        currentStyles.addAll(index, blStyles);
1877:                    }
1878:                }
1879:
1880:                if (replacedOne) {
1881:                    kvpPairs.remove("LAYERS");
1882:                    kvpPairs.put("LAYERS", toStringList(currentLayers, ","));
1883:                    kvpPairs.remove("STYLES");
1884:                    kvpPairs.put("STYLES", toStringList(currentStyles, ","));
1885:                }
1886:            }
1887:
1888:            private String toStringList(List currentLayers, String separator) {
1889:                StringBuffer sb = new StringBuffer();
1890:
1891:                for (Iterator it = currentLayers.iterator(); it.hasNext();) {
1892:                    String item = (String) it.next();
1893:                    sb.append(item);
1894:
1895:                    if (it.hasNext()) {
1896:                        sb.append(separator);
1897:                    }
1898:                }
1899:
1900:                return sb.toString();
1901:            }
1902:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.