-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
WMS.java
2189 lines (1919 loc) · 87.4 KB
/
WMS.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* (c) 2014 - 2016 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2014 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.wms;
import static org.geoserver.catalog.ResourceInfo.ELEVATION;
import static org.geoserver.catalog.ResourceInfo.TIME;
import static org.geoserver.util.HTTPWarningAppender.addWarning;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Point2D;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import org.apache.commons.lang.StringUtils;
import org.geoserver.catalog.AttributeTypeInfo;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.CoverageInfo;
import org.geoserver.catalog.DimensionInfo;
import org.geoserver.catalog.DimensionPresentation;
import org.geoserver.catalog.FeatureTypeInfo;
import org.geoserver.catalog.LayerGroupHelper;
import org.geoserver.catalog.LayerGroupInfo;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.catalog.MetadataMap;
import org.geoserver.catalog.NamespaceInfo;
import org.geoserver.catalog.PublishedInfo;
import org.geoserver.catalog.PublishedType;
import org.geoserver.catalog.ResourceInfo;
import org.geoserver.catalog.StyleInfo;
import org.geoserver.catalog.WMSLayerInfo;
import org.geoserver.catalog.WMTSLayerInfo;
import org.geoserver.catalog.impl.AdvertisedCatalog;
import org.geoserver.catalog.util.ReaderDimensionsAccessor;
import org.geoserver.config.GeoServer;
import org.geoserver.config.GeoServerInfo;
import org.geoserver.config.JAIInfo;
import org.geoserver.data.DimensionFilterBuilder;
import org.geoserver.data.util.CoverageUtils;
import org.geoserver.platform.GeoServerExtensions;
import org.geoserver.platform.ServiceException;
import org.geoserver.util.DimensionWarning;
import org.geoserver.util.NearestMatchFinder;
import org.geoserver.wms.WMSInfo.WMSInterpolation;
import org.geoserver.wms.WatermarkInfo.Position;
import org.geoserver.wms.capabilities.DimensionHelper;
import org.geoserver.wms.dimension.DimensionDefaultValueSelectionStrategy;
import org.geoserver.wms.dimension.DimensionDefaultValueSelectionStrategyFactory;
import org.geoserver.wms.featureinfo.GetFeatureInfoOutputFormat;
import org.geoserver.wms.map.RenderedImageMapOutputFormat;
import org.geoserver.wms.map.RenderedImageMapResponse;
import org.geotools.api.data.FeatureSource;
import org.geotools.api.data.Query;
import org.geotools.api.feature.Feature;
import org.geotools.api.feature.type.FeatureType;
import org.geotools.api.feature.type.Name;
import org.geotools.api.filter.Filter;
import org.geotools.api.filter.FilterFactory;
import org.geotools.api.filter.PropertyIsBetween;
import org.geotools.api.filter.expression.PropertyName;
import org.geotools.api.filter.sort.SortBy;
import org.geotools.api.parameter.GeneralParameterDescriptor;
import org.geotools.api.parameter.GeneralParameterValue;
import org.geotools.api.parameter.ParameterDescriptor;
import org.geotools.api.parameter.ParameterValue;
import org.geotools.api.parameter.ParameterValueGroup;
import org.geotools.api.referencing.FactoryException;
import org.geotools.api.referencing.crs.CoordinateReferenceSystem;
import org.geotools.api.style.Style;
import org.geotools.coverage.grid.io.GridCoverage2DReader;
import org.geotools.data.DataUtilities;
import org.geotools.data.ows.OperationType;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.visitor.CalcResult;
import org.geotools.feature.visitor.MaxVisitor;
import org.geotools.feature.visitor.MinVisitor;
import org.geotools.feature.visitor.UniqueVisitor;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.gml2.SrsSyntax;
import org.geotools.gml2.bindings.GML2EncodingUtils;
import org.geotools.ows.wms.Layer;
import org.geotools.ows.wms.WMSCapabilities;
import org.geotools.referencing.CRS;
import org.geotools.referencing.CRS.AxisOrder;
import org.geotools.util.Converters;
import org.geotools.util.DateRange;
import org.geotools.util.NumberRange;
import org.geotools.util.Range;
import org.geotools.util.SuppressFBWarnings;
import org.geotools.util.Version;
import org.geotools.util.decorate.Wrapper;
import org.geotools.util.factory.GeoTools;
import org.geotools.util.logging.Logging;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/**
* A facade providing access to the WMS configuration details
*
* @author Gabriel Roldan
*/
public class WMS implements ApplicationContextAware {
public static final Version VERSION_1_1_1 = new Version("1.1.1");
public static final Version VERSION_1_3_0 = new Version("1.3.0");
public static final String JPEG_COMPRESSION = "jpegCompression";
public static final int JPEG_COMPRESSION_DEFAULT = 25;
public static final String PNG_COMPRESSION = "pngCompression";
public static final int PNG_COMPRESSION_DEFAULT = 25;
public static final String SCALEHINT_MAPUNITS_PIXEL = "scalehintMapunitsPixel";
public static final Boolean SCALEHINT_MAPUNITS_PIXEL_DEFAULT = Boolean.FALSE;
public static final String DYNAMIC_STYLING_DISABLED = "dynamicStylingDisabled";
public static final String FEATURES_REPROJECTION_DISABLED = "featuresReprojectionDisabled";
static final Logger LOGGER = Logging.getLogger(WMS.class);
public static final String WEB_CONTAINER_KEY = "WMS";
/** SVG renderers. */
public static final String SVG_SIMPLE = "Simple";
public static final String SVG_BATIK = "Batik";
/** Prefix for custom dimensions used in GetMap requests */
public static final String DIM_ = "dim_";
/** KML reflector mode */
public static String KML_REFLECTOR_MODE = "kmlReflectorMode";
/** KML reflector mode values */
public static final String KML_REFLECTOR_MODE_REFRESH = "refresh";
public static final String KML_REFLECTOR_MODE_SUPEROVERLAY = "superoverlay";
public static final String KML_REFLECTOR_MODE_DOWNLOAD = "download";
public static final String KML_REFLECTOR_MODE_DEFAULT = KML_REFLECTOR_MODE_REFRESH;
/** KML superoverlay sub-mode */
public static final String KML_SUPEROVERLAY_MODE = "kmlSuperoverlayMode";
public static final String KML_SUPEROVERLAY_MODE_AUTO = "auto";
public static final String KML_SUPEROVERLAY_MODE_RASTER = "raster";
public static final String KML_SUPEROVERLAY_MODE_OVERVIEW = "overview";
public static final String KML_SUPEROVERLAY_MODE_HYBRID = "hybrid";
public static final String KML_SUPEROVERLAY_MODE_CACHED = "cached";
public static final String KML_SUPEROVERLAY_MODE_DEFAULT = KML_SUPEROVERLAY_MODE_AUTO;
public static final String KML_KMLATTR = "kmlAttr";
public static final boolean KML_KMLATTR_DEFAULT = true;
public static final String KML_KMLPLACEMARK = "kmlPlacemark";
public static final boolean KML_KMLPLACEMARK_DEFAULT = false;
public static final String KML_KMSCORE = "kmlKmscore";
public static final int KML_KMSCORE_DEFAULT = 40;
/** Enable continuous map wrapping (global sys var) */
public static Boolean ENABLE_MAP_WRAPPING = null;
/** Continuous map wrapping key */
public static String MAP_WRAPPING_KEY = "mapWrapping";
/** Enable advanced projection handling */
public static Boolean ENABLE_ADVANCED_PROJECTION = null;
/** Advanced projection key */
public static String ADVANCED_PROJECTION_KEY = "advancedProjectionHandling";
/** Enable advanced projection handling */
public static Boolean ENABLE_ADVANCED_PROJECTION_DENSIFICATION = false;
/** Advanced projection densification key */
public static String ADVANCED_PROJECTION_DENSIFICATION_KEY = "advancedProjectionDensification";
/** Disable DateLine Wrapping Heuristic. */
public static Boolean DISABLE_DATELINE_WRAPPING_HEURISTIC = false;
/** DateLine Wrapping Heuristic key */
public static String DATELINE_WRAPPING_HEURISTIC_KEY = "disableDatelineWrappingHeuristic";
/**
* Capabilities will be produced with a root Layer element, only when needed (there is no single
* top layer element) *
*/
public static Boolean ROOT_LAYER_IN_CAPABILITIES_DEFAULT = true;
/** Root Layer in Capabilities key * */
public static String ROOT_LAYER_IN_CAPABILITIES_KEY = "rootLayerInCapabilities";
/** GIF disposal methods */
public static final String DISPOSAL_METHOD_NONE = "none";
public static final String DISPOSAL_METHOD_NOT_DISPOSE = "doNotDispose";
public static final String DISPOSAL_METHOD_BACKGROUND = "backgroundColor";
public static final String DISPOSAL_METHOD_PREVIOUS = "previous";
public static final String DISPOSAL_METHOD_DEFAULT = DISPOSAL_METHOD_NONE;
public static final String[] DISPOSAL_METHODS = {
DISPOSAL_METHOD_NONE,
DISPOSAL_METHOD_NOT_DISPOSE,
DISPOSAL_METHOD_BACKGROUND,
DISPOSAL_METHOD_PREVIOUS
};
private static final FilterFactory ff = CommonFactoryFinder.getFilterFactory(null);
private final GeoServer geoserver;
private ApplicationContext applicationContext;
private DimensionDefaultValueSelectionStrategyFactory defaultDimensionValueFactory;
public WMS(GeoServer geoserver) {
this.geoserver = geoserver;
}
public Catalog getCatalog() {
return geoserver.getCatalog();
}
public WMSInfo getServiceInfo() {
return geoserver.getService(WMSInfo.class);
}
public Style getStyleByName(String styleName) throws IOException {
StyleInfo styleInfo = getCatalog().getStyleByName(styleName);
return styleInfo == null ? null : styleInfo.getStyle();
}
public LayerInfo getLayerByName(String layerName) {
return getCatalog().getLayerByName(layerName);
}
public LayerGroupInfo getLayerGroupByName(String layerGroupName) {
return getCatalog().getLayerGroupByName(layerGroupName);
}
public boolean isEnabled() {
WMSInfo serviceInfo = getServiceInfo();
return serviceInfo.isEnabled();
}
/**
* Whether to throw an InvalidDimensioValue on invalid dimension values
*
* @return
*/
public boolean exceptionOnInvalidDimension() {
return getServiceInfo().exceptionOnInvalidDimension();
}
/**
* /** Returns a supported version according to the version negotiation rules in section 6.2.4
* of the WMS 1.3.0 spec.
*
* <p>Calls through to {@link #negotiateVersion(Version)}.
*
* @param requestedVersion The version, may be bull.
*/
public static Version negotiateVersion(final String requestedVersion) {
return negotiateVersion(requestedVersion != null ? new Version(requestedVersion) : null);
}
/**
* Returns a supported version according to the version negotiation rules in section 6.2.4 of
* the WMS 1.3.0 spec.
*
* <p>For instance: <u>
* <li>request version not provided? -> higher version supported
* <li>requested version supported? -> that same version
* <li>requested version < lowest supported version? -> lowest supported
* <li>requested version > lowest supported version? -> higher supported version that's lower
* than the requested version </u>
*
* @param requestedVersion the request version, or {@code null} if unspecified
*/
public static Version negotiateVersion(final Version requestedVersion) {
if (null == requestedVersion) {
return VERSION_1_3_0;
}
if (VERSION_1_1_1.equals(requestedVersion)) {
return VERSION_1_1_1;
}
if (VERSION_1_3_0.equals(requestedVersion)) {
return VERSION_1_3_0;
}
if (requestedVersion.compareTo(VERSION_1_3_0) < 0) {
return VERSION_1_1_1;
}
return VERSION_1_3_0;
}
public String getVersion() {
WMSInfo serviceInfo = getServiceInfo();
List<Version> versions = serviceInfo.getVersions();
String version;
if (versions.isEmpty()) {
// shouldn't a version be set?
version = "1.1.1";
} else {
version = versions.get(0).toString();
}
return version;
}
/**
* Checks if request would result in a number of dimensions that exceeds the configured maximum
*
* @param mapLayerInfo the layer info
* @param times the times requested
* @param elevations the elevations requested
* @param isCoverage true if the layer is a coverage
* @throws IOException if an error occurs
*/
public void checkMaxDimensions(
MapLayerInfo mapLayerInfo,
List<Object> times,
List<Object> elevations,
boolean isCoverage)
throws IOException {
if (getServiceInfo() == null
|| getServiceInfo().getMaxRequestedDimensionValues()
== DimensionInfo.DEFAULT_MAX_REQUESTED_DIMENSION_VALUES) {
// max is default, which is unlimited
return;
}
TreeSet<Object> treeSet = new TreeSet<>();
int maxDimensionsToTest = getServiceInfo().getMaxRequestedDimensionValues();
if (times != null && !times.isEmpty() && times.get(0) != null) {
// list is null for default value
ListIterator<Object> timesIterator = times.listIterator();
while (timesIterator.hasNext()) {
Object time = timesIterator.next();
if (time instanceof DateRange) {
DateRange range = (DateRange) times.get(timesIterator.previousIndex());
if (isCoverage) {
treeSet.addAll(
queryCoverageTimes(
mapLayerInfo.getCoverage(),
range,
maxDimensionsToTest + 1));
} else {
treeSet.addAll(
queryFeatureTypeTimes(
mapLayerInfo.getFeature(), range, maxDimensionsToTest + 1));
}
} else {
treeSet.add(time);
}
// check dimensions after each time parameter is added to treeset
checkDimensions(treeSet, maxDimensionsToTest, ResourceInfo.TIME);
}
}
if (elevations != null && !elevations.isEmpty() && elevations.get(0) != null) {
// list is null for default value, so we skip it
ListIterator<Object> elevationsIterator = elevations.listIterator();
while (elevationsIterator.hasNext()) {
Object elevation = elevationsIterator.next();
if (elevation instanceof NumberRange) {
NumberRange range =
(NumberRange) elevations.get(elevationsIterator.previousIndex());
if (isCoverage) {
treeSet.addAll(
queryCoverageElevations(
mapLayerInfo.getCoverage(),
range,
maxDimensionsToTest + 1));
} else {
treeSet.addAll(
queryFeatureTypeElevations(
mapLayerInfo.getFeature(), range, maxDimensionsToTest + 1));
}
} else if (elevation instanceof Double) {
// The queryElevations calls that check ranges are populating the treeset with
// integers,
// so we need to convert the double to an integer for this check
Double elevationSingle = (Double) elevation;
treeSet.add(elevationSingle.intValue());
} else {
treeSet.add(elevation);
}
// check dimensions after each elevation parameter is added to treeset
checkDimensions(treeSet, maxDimensionsToTest, ResourceInfo.ELEVATION);
}
}
}
private static void checkDimensions(
TreeSet<Object> treeSet, int maxDimensionsToTest, String dimensionName) {
if (treeSet.size() > maxDimensionsToTest) {
throw new ServiceException(
"This request would process more "
+ dimensionName
+ " than the maximum allowed: "
+ maxDimensionsToTest
+ ". Please reduce the size of the requested "
+ dimensionName
+ " range.",
"InvalidParameterValue",
dimensionName);
}
}
public GeoServer getGeoServer() {
return this.geoserver;
}
public WMSInterpolation getInterpolation() {
return getServiceInfo().getInterpolation();
}
public boolean isDynamicStylingDisabled() {
return getServiceInfo().isDynamicStylingDisabled();
}
/**
* If TRUE is returned GetFeatureInfo results should NOT be reproject to the map coordinate
* reference system.
*
* @return GetFeatureInfo results reprojection allowance
*/
public boolean isFeaturesReprojectionDisabled() {
return getServiceInfo().isFeaturesReprojectionDisabled();
}
public JAIInfo.PngEncoderType getPNGEncoderType() {
JAIInfo jaiInfo = getJaiInfo();
return jaiInfo.getPngEncoderType();
}
public Boolean getJPEGNativeAcceleration() {
JAIInfo jaiInfo = getJaiInfo();
return Boolean.valueOf(jaiInfo.isJpegAcceleration());
}
private JAIInfo getJaiInfo() {
GeoServer geoServer = getGeoServer();
GeoServerInfo global = geoServer.getGlobal();
return global.getJAI();
}
public Charset getCharSet() {
GeoServer geoServer2 = getGeoServer();
String charset = geoServer2.getSettings().getCharset();
return Charset.forName(charset);
}
public String getProxyBaseUrl() {
GeoServer geoServer = getGeoServer();
return geoServer.getSettings().getProxyBaseUrl();
}
public long getUpdateSequence() {
GeoServerInfo global = getGeoServer().getGlobal();
return global.getUpdateSequence();
}
public int getWatermarkTransparency() {
WatermarkInfo watermark = getServiceInfo().getWatermark();
return watermark.getTransparency();
}
public int getWatermarkPosition() {
WatermarkInfo watermark = getServiceInfo().getWatermark();
Position position = watermark.getPosition();
return position.getCode();
}
public boolean isGlobalWatermarking() {
WatermarkInfo watermark = getServiceInfo().getWatermark();
return watermark.isEnabled();
}
public String getGlobalWatermarkingURL() {
WatermarkInfo watermark = getServiceInfo().getWatermark();
return watermark.getURL();
}
public boolean isRemoteStylesCacheEnabled() {
CacheConfiguration cache = getServiceInfo().getCacheConfiguration();
return cache != null && cache.isEnabled() ? true : false;
}
public CacheConfiguration getRemoteResourcesCacheConfiguration() {
return getServiceInfo().getCacheConfiguration();
}
public void setRemoteResourcesCacheConfiguration(CacheConfiguration cacheCfg) {
getServiceInfo().setCacheConfiguration(cacheCfg);
}
public FeatureTypeInfo getFeatureTypeInfo(final Name name) {
Catalog catalog = getCatalog();
FeatureTypeInfo resource = catalog.getResourceByName(name, FeatureTypeInfo.class);
return resource;
}
public CoverageInfo getCoverageInfo(final Name name) {
Catalog catalog = getCatalog();
CoverageInfo resource = catalog.getResourceByName(name, CoverageInfo.class);
return resource;
}
public WMSLayerInfo getWMSLayerInfo(final Name name) {
Catalog catalog = getCatalog();
WMSLayerInfo resource = catalog.getResourceByName(name, WMSLayerInfo.class);
return resource;
}
public ResourceInfo getResourceInfo(final Name name) {
Catalog catalog = getCatalog();
ResourceInfo resource = catalog.getResourceByName(name, ResourceInfo.class);
return resource;
}
public List<LayerInfo> getLayers() {
Catalog catalog = getCatalog();
return catalog.getLayers();
}
public String getNamespaceByPrefix(final String prefix) {
Catalog catalog = getCatalog();
NamespaceInfo namespaceInfo = catalog.getNamespaceByPrefix(prefix);
return namespaceInfo == null ? null : namespaceInfo.getURI();
}
public List<LayerGroupInfo> getLayerGroups() {
Catalog catalog = getCatalog();
List<LayerGroupInfo> layerGroups = catalog.getLayerGroups();
return layerGroups;
}
/**
* Informs the user that this WMS supports SLD. We don't currently handle sld, still needs to be
* rolled in from geotools, so this now must be false.
*
* <p>//djb: we support it now
*
* @return false
*/
public boolean supportsSLD() {
return true; // djb: we support it now
}
/**
* Informs the user that this WMS supports User Layers
*
* <p>We support this both remote wfs and inlineFeature
*
* @return true
*/
public boolean supportsUserLayer() {
return true;
}
/**
* Informs the user that this WMS supports User Styles
*
* @return true
*/
public boolean supportsUserStyle() {
return true;
}
/**
* Informs the user that this WMS supports Remote WFS.
*
* @return true
*/
public boolean supportsRemoteWFS() {
return true;
}
public void setSvgRenderer(String svgRendererHint) {
WMSInfo serviceInfo = getServiceInfo();
serviceInfo.getMetadata().put("svgRenderer", svgRendererHint);
getGeoServer().save(serviceInfo);
}
public String getSvgRenderer() {
WMSInfo serviceInfo = getServiceInfo();
String svgRendererHint = (String) serviceInfo.getMetadata().get("svgRenderer");
return svgRendererHint;
}
public boolean isSvgAntiAlias() {
WMSInfo serviceInfo = getServiceInfo();
Boolean svgAntiAlias =
Converters.convert(serviceInfo.getMetadata().get("svgAntiAlias"), Boolean.class);
return svgAntiAlias == null ? true : svgAntiAlias.booleanValue();
}
public int getPngCompression() {
WMSInfo serviceInfo = getServiceInfo();
return getMetadataPercentage(
serviceInfo.getMetadata(), PNG_COMPRESSION, PNG_COMPRESSION_DEFAULT);
}
public int getJpegCompression() {
WMSInfo serviceInfo = getServiceInfo();
return getMetadataPercentage(
serviceInfo.getMetadata(), JPEG_COMPRESSION, JPEG_COMPRESSION_DEFAULT);
}
/** Checks if continuous map wrapping is enabled or not */
public boolean isContinuousMapWrappingEnabled() {
// for backwards compatibility we set the config value to the sys variable one if set, but
// once set, the config wins
Boolean enabled = getMetadataValue(MAP_WRAPPING_KEY, ENABLE_MAP_WRAPPING, Boolean.class);
return enabled;
}
/** Checks if advanced projection handling is enabled or not */
public boolean isAdvancedProjectionHandlingEnabled() {
// for backwards compatibility we set the config value to the sys variable one if set, but
// once set, the config wins
Boolean enabled =
getMetadataValue(
ADVANCED_PROJECTION_KEY, ENABLE_ADVANCED_PROJECTION, Boolean.class);
return enabled;
}
public boolean isAdvancedProjectionDensificationEnabled() {
Boolean enabled =
getMetadataValue(
ADVANCED_PROJECTION_DENSIFICATION_KEY,
ENABLE_ADVANCED_PROJECTION_DENSIFICATION,
Boolean.class);
return enabled;
}
public boolean isDateLineWrappingHeuristicDisabled() {
Boolean disabled =
getMetadataValue(
DATELINE_WRAPPING_HEURISTIC_KEY,
DISABLE_DATELINE_WRAPPING_HEURISTIC,
Boolean.class);
return disabled;
}
public boolean isRootLayerInCapabilitesEnabled() {
return getMetadataValue(
ROOT_LAYER_IN_CAPABILITIES_KEY, ROOT_LAYER_IN_CAPABILITIES_DEFAULT, Boolean.class);
}
public Boolean getScalehintUnitPixel() {
return getMetadataValue(
SCALEHINT_MAPUNITS_PIXEL, SCALEHINT_MAPUNITS_PIXEL_DEFAULT, Boolean.class);
}
int getMetadataPercentage(MetadataMap metadata, String key, int defaultValue) {
Integer parsedValue = Converters.convert(metadata.get(key), Integer.class);
if (parsedValue == null) return defaultValue;
int value = parsedValue.intValue();
if (value < 0 || value > 100) {
LOGGER.warning(
"Invalid percertage value for '" + key + "', it should be between 0 and 100");
return defaultValue;
}
return value;
}
<T> T getMetadataValue(String key, T defaultValue, Class<T> clazz) {
if (getServiceInfo() == null) {
return defaultValue;
}
MetadataMap metadata = getServiceInfo().getMetadata();
T parsedValue = Converters.convert(metadata.get(key), clazz);
if (parsedValue == null) return defaultValue;
return parsedValue;
}
public int getNumDecimals() {
return getGeoServer().getSettings().getNumDecimals();
}
public String getNameSpacePrefix(final String nsUri) {
Catalog catalog = getCatalog();
NamespaceInfo ns = catalog.getNamespaceByURI(nsUri);
return ns == null ? null : ns.getPrefix();
}
public int getMaxBuffer() {
return getServiceInfo().getMaxBuffer();
}
public int getMaxRequestMemory() {
return getServiceInfo().getMaxRequestMemory();
}
public int getMaxRenderingTime() {
return getServiceInfo().getMaxRenderingTime();
}
public int getMaxRenderingErrors() {
return getServiceInfo().getMaxRenderingErrors();
}
/**
* Returns the maximum number of requested dimension values, picking from the appropriate
* service configuration
*/
public int getMaxRequestedDimensionValues() {
return getServiceInfo().getMaxRequestedDimensionValues();
}
public String getKmlReflectorMode() {
String value = (String) getServiceInfo().getMetadata().get(KML_REFLECTOR_MODE);
return value != null ? value : KML_REFLECTOR_MODE_DEFAULT;
}
public String getKmlSuperoverlayMode() {
String value = (String) getServiceInfo().getMetadata().get(KML_SUPEROVERLAY_MODE);
return value != null ? value : KML_SUPEROVERLAY_MODE_DEFAULT;
}
public boolean getKmlKmAttr() {
Boolean kmAttr =
Converters.convert(getServiceInfo().getMetadata().get(KML_KMLATTR), Boolean.class);
return kmAttr == null ? KML_KMLATTR_DEFAULT : kmAttr.booleanValue();
}
public boolean getKmlPlacemark() {
Boolean kmAttr =
Converters.convert(
getServiceInfo().getMetadata().get(KML_KMLPLACEMARK), Boolean.class);
return kmAttr == null ? KML_KMLPLACEMARK_DEFAULT : kmAttr.booleanValue();
}
public int getKmScore() {
return getMetadataPercentage(
getServiceInfo().getMetadata(), KML_KMSCORE, KML_KMSCORE_DEFAULT);
}
/** Returns all allowed map output formats. */
public Collection<GetMapOutputFormat> getAllowedMapFormats() {
List<GetMapOutputFormat> result = new ArrayList<>();
for (GetMapOutputFormat producer : WMSExtensions.findMapProducers(applicationContext)) {
if (isAllowedGetMapFormat(producer)) {
result.add(producer);
}
}
return result;
}
/** Returns all map output formats. */
public Collection<GetMapOutputFormat> getAvailableMapFormats() {
return WMSExtensions.findMapProducers(applicationContext);
}
/**
* Grabs the list of allowed MIME-Types for the GetMap operation from the set of {@link
* GetMapOutputFormat}s registered in the application context.
*
* @see GetMapOutputFormat#getContentType()
*/
public Set<String> getAvailableMapFormatNames() {
final Collection<GetMapOutputFormat> producers =
WMSExtensions.findMapProducers(applicationContext);
final Set<String> formats = new HashSet<>();
for (GetMapOutputFormat producer : producers) {
formats.addAll(producer.getOutputFormatNames());
}
return formats;
}
/** @return all allowed GetMap format names */
public Set<String> getAllowedMapFormatNames() {
final Collection<GetMapOutputFormat> producers =
WMSExtensions.findMapProducers(applicationContext);
final Set<String> formats = new HashSet<>();
for (GetMapOutputFormat producer : producers) {
if (isAllowedGetMapFormat(producer) == false) {
continue; // skip this producer, its mime type is not allowed
}
formats.addAll(producer.getOutputFormatNames());
}
return formats;
}
/** Checks is a getMap mime type is allowed */
public boolean isAllowedGetMapFormat(GetMapOutputFormat format) {
if (getServiceInfo().isGetMapMimeTypeCheckingEnabled() == false) return true;
Set<String> mimeTypes = getServiceInfo().getGetMapMimeTypes();
return mimeTypes.contains(format.getMimeType());
}
/** Checks is a getFeatureInfo mime type is allowed */
public boolean isAllowedGetFeatureInfoFormat(GetFeatureInfoOutputFormat format) {
if (getServiceInfo().isGetFeatureInfoMimeTypeCheckingEnabled() == false) return true;
Set<String> mimeTypes = getServiceInfo().getGetFeatureInfoMimeTypes();
return mimeTypes.contains(format.getContentType());
}
/** create a {@link ServiceException} for an unallowed GetFeatureInfo format */
public ServiceException unallowedGetFeatureInfoFormatException(String requestFormat) {
ServiceException e =
new ServiceException(
"Getting feature info using " + requestFormat + " is not allowed",
"ForbiddenFormat");
e.setCode("ForbiddenFormat");
return e;
}
/** create a {@link ServiceException} for an unallowed GetMap format */
public ServiceException unallowedGetMapFormatException(String requestFormat) {
ServiceException e =
new ServiceException(
"Creating maps using " + requestFormat + " is not allowed",
"ForbiddenFormat");
e.setCode("ForbiddenFormat");
return e;
}
public Set<String> getAvailableLegendGraphicsFormats() {
List<GetLegendGraphicOutputFormat> formats =
WMSExtensions.findLegendGraphicFormats(applicationContext);
Set<String> mimeTypes = new HashSet<>();
for (GetLegendGraphicOutputFormat format : formats) {
mimeTypes.add(format.getContentType());
}
return mimeTypes;
}
/** Returns all {@link ExtendedCapabilitiesProvider} extensions. */
public List<ExtendedCapabilitiesProvider> getAvailableExtendedCapabilitiesProviders() {
return WMSExtensions.findExtendedCapabilitiesProviders(applicationContext);
}
@Override
@SuppressFBWarnings("LI_LAZY_INIT_STATIC") // method is not called by multiple threads
public void setApplicationContext(final ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
// get the default dimension value selector factory, picking the one with
// the highest priority (this allows for plugin overrides)
defaultDimensionValueFactory =
GeoServerExtensions.extensions(DimensionDefaultValueSelectionStrategyFactory.class)
.get(0);
// enable/disable map wrapping
if (ENABLE_MAP_WRAPPING == null) {
String wrapping =
GeoServerExtensions.getProperty("ENABLE_MAP_WRAPPING", applicationContext);
// default to true, but allow switching off
if (wrapping == null) ENABLE_MAP_WRAPPING = true;
else ENABLE_MAP_WRAPPING = Boolean.valueOf(wrapping);
}
// enable/disable advanced reprojection handling
if (ENABLE_ADVANCED_PROJECTION == null) {
String projection =
GeoServerExtensions.getProperty(
"ENABLE_ADVANCED_PROJECTION", applicationContext);
// default to true, but allow switching off
if (projection == null) ENABLE_ADVANCED_PROJECTION = true;
else ENABLE_ADVANCED_PROJECTION = Boolean.valueOf(projection);
}
}
/**
* @return a {@link GetFeatureInfoOutputFormat} that can handle the requested mime type or
* {@code null} if none if found
*/
public GetFeatureInfoOutputFormat getFeatureInfoOutputFormat(String requestFormat) {
List<GetFeatureInfoOutputFormat> outputFormats =
WMSExtensions.findFeatureInfoFormats(applicationContext);
for (GetFeatureInfoOutputFormat format : outputFormats) {
if (format.canProduce(requestFormat)) {
return format;
}
}
return null;
}
/** @return a list of all getFeatureInfo content types */
public List<String> getAvailableFeatureInfoFormats() {
List<String> mimeTypes = new ArrayList<>();
for (GetFeatureInfoOutputFormat format :
WMSExtensions.findFeatureInfoFormats(applicationContext)) {
mimeTypes.add(format.getContentType());
}
return mimeTypes;
}
/** @return a list of all allowed getFeature info content types */
public List<String> getAllowedFeatureInfoFormats() {
List<String> mimeTypes = new ArrayList<>();
for (GetFeatureInfoOutputFormat format :
WMSExtensions.findFeatureInfoFormats(applicationContext)) {
if (isAllowedGetFeatureInfoFormat(format) == false) {
continue; // skip this format
}
mimeTypes.add(format.getContentType());
}
return mimeTypes;
}
/** @return a list of allowed remote SLD Urls for AuthorizationHeader forwarding. */
public List<String> getAllowedURLsForAuthForwarding() {
return getServiceInfo().getAllowedURLsForAuthForwarding();
}
/**
* @param mimeType the mime type to look a GetMapOutputFormat for
* @return the GetMapOutputFormat that can handle {@code mimeType}, or {@code null} if none is
* found
*/
public GetMapOutputFormat getMapOutputFormat(final String mimeType) {
GetMapOutputFormat outputFormat =
WMSExtensions.findMapProducer(mimeType, applicationContext);
return outputFormat;
}
/**
* @param outputFormat desired output format mime type
* @return the GetLegendGraphicOutputFormat that can handle {@code mimeType}, or {@code null} if
* none is found
*/
public GetLegendGraphicOutputFormat getLegendGraphicOutputFormat(final String outputFormat) {
GetLegendGraphicOutputFormat format =
WMSExtensions.findLegendGraphicFormat(outputFormat, applicationContext);
return format;
}
/**
* Returns a version object for the specified version string.
* <p>
* Calls through to {@link #version(String, boolean)} with exact set to <code>false</false>.
* </p>
*/
public static Version version(String version) {
return version(version, false);
}
/**
* Returns a version object for the specified version string optionally returning null when the
* version string does not match one of the available WMS versions.
*
* @param version The version string.
* @param exact If set to false, a version object will always be returned. If set to true only a
* version matching on of the available wms versions will be returned.
*/