[2512] | 1 | // License: GPL. For details, see LICENSE file.
|
---|
| 2 | package org.openstreetmap.josm.io;
|
---|
| 3 |
|
---|
[2599] | 4 | import static org.openstreetmap.josm.tools.I18n.tr;
|
---|
| 5 |
|
---|
[7473] | 6 | import java.io.IOException;
|
---|
[3934] | 7 | import java.util.ArrayList;
|
---|
| 8 | import java.util.Collections;
|
---|
[2512] | 9 | import java.util.HashMap;
|
---|
[3934] | 10 | import java.util.List;
|
---|
[6317] | 11 | import java.util.Map;
|
---|
[2512] | 12 |
|
---|
[7473] | 13 | import javax.xml.parsers.ParserConfigurationException;
|
---|
| 14 |
|
---|
[6248] | 15 | import org.openstreetmap.josm.Main;
|
---|
[8287] | 16 | import org.openstreetmap.josm.tools.Utils;
|
---|
[7473] | 17 | import org.xml.sax.Attributes;
|
---|
| 18 | import org.xml.sax.InputSource;
|
---|
| 19 | import org.xml.sax.SAXException;
|
---|
| 20 | import org.xml.sax.helpers.DefaultHandler;
|
---|
[6248] | 21 |
|
---|
[2512] | 22 | /**
|
---|
[7473] | 23 | * Represents the OSM API server capabilities.
|
---|
[2512] | 24 | *
|
---|
[3934] | 25 | * Example capabilites document:
|
---|
[6830] | 26 | * <pre>
|
---|
| 27 | * <osm version="0.6" generator="OpenStreetMap server">
|
---|
| 28 | * <api>
|
---|
| 29 | * <version minimum="0.6" maximum="0.6"/>
|
---|
| 30 | * <area maximum="0.25"/>
|
---|
| 31 | * <tracepoints per_page="5000"/>
|
---|
| 32 | * <waynodes maximum="2000"/>
|
---|
[11523] | 33 | * <changesets maximum_elements="10000"/>
|
---|
[6830] | 34 | * <timeout seconds="300"/>
|
---|
[11523] | 35 | * <status database="online" api="online" gpx="online"/>
|
---|
[6830] | 36 | * </api>
|
---|
| 37 | * <policy>
|
---|
| 38 | * <imagery>
|
---|
| 39 | * <blacklist regex=".*\.google\.com/.*"/>
|
---|
| 40 | * <blacklist regex=".*209\.85\.2\d\d.*"/>
|
---|
| 41 | * <blacklist regex=".*209\.85\.1[3-9]\d.*"/>
|
---|
| 42 | * <blacklist regex=".*209\.85\.12[89].*"/>
|
---|
| 43 | * </imagery>
|
---|
| 44 | * </policy>
|
---|
| 45 | * </osm>
|
---|
| 46 | * </pre>
|
---|
[3934] | 47 | * This class is used in conjunction with a very primitive parser
|
---|
| 48 | * and simply stuffs the each tag and its attributes into a hash
|
---|
| 49 | * of hashes, with the exception of the "blacklist" tag which gets
|
---|
| 50 | * a list of its own. The DOM hierarchy is disregarded.
|
---|
[2512] | 51 | */
|
---|
| 52 | public class Capabilities {
|
---|
| 53 |
|
---|
[8510] | 54 | private final Map<String, Map<String, String>> capabilities;
|
---|
[7473] | 55 | private final List<String> imageryBlacklist;
|
---|
[3934] | 56 |
|
---|
[6316] | 57 | /**
|
---|
| 58 | * Constructs new {@code Capabilities}.
|
---|
| 59 | */
|
---|
[2512] | 60 | public Capabilities() {
|
---|
[7473] | 61 | capabilities = new HashMap<>();
|
---|
| 62 | imageryBlacklist = new ArrayList<>();
|
---|
[2512] | 63 | }
|
---|
| 64 |
|
---|
[7473] | 65 | /**
|
---|
| 66 | * Determines if given element and attribute are defined.
|
---|
| 67 | *
|
---|
| 68 | * @param element the name of the element
|
---|
| 69 | * @param attribute the name of the attribute
|
---|
| 70 | * @return {@code true} if defined, {@code false} otherwise
|
---|
| 71 | */
|
---|
[2512] | 72 | public boolean isDefined(String element, String attribute) {
|
---|
[8443] | 73 | if (!capabilities.containsKey(element)) return false;
|
---|
[8338] | 74 | Map<String, String> e = capabilities.get(element);
|
---|
[2512] | 75 | if (e == null) return false;
|
---|
[8345] | 76 | return e.get(attribute) != null;
|
---|
[2512] | 77 | }
|
---|
| 78 |
|
---|
[7473] | 79 | /**
|
---|
| 80 | * Returns the value of configuration item in the capabilities as string value.
|
---|
| 81 | *
|
---|
| 82 | * @param element the name of the element
|
---|
| 83 | * @param attribute the name of the attribute
|
---|
| 84 | * @return the value; {@code null}, if the respective configuration item does not exist
|
---|
| 85 | */
|
---|
| 86 | public String get(String element, String attribute) {
|
---|
[8443] | 87 | if (!capabilities.containsKey(element)) return null;
|
---|
[8338] | 88 | Map<String, String> e = capabilities.get(element);
|
---|
[2512] | 89 | if (e == null) return null;
|
---|
| 90 | return e.get(attribute);
|
---|
| 91 | }
|
---|
| 92 |
|
---|
| 93 | /**
|
---|
[7473] | 94 | * Returns the value of configuration item in the capabilities as double value.
|
---|
[2512] | 95 | *
|
---|
[7473] | 96 | * @param element the name of the element
|
---|
[2512] | 97 | * @param attribute the name of the attribute
|
---|
[7473] | 98 | * @return the value; {@code null}, if the respective configuration item does not exist
|
---|
| 99 | * @throws NumberFormatException if the value is not a valid double
|
---|
[2512] | 100 | */
|
---|
[10632] | 101 | public Double getDouble(String element, String attribute) {
|
---|
[2512] | 102 | String s = get(element, attribute);
|
---|
| 103 | if (s == null) return null;
|
---|
[8390] | 104 | return Double.valueOf(s);
|
---|
[2512] | 105 | }
|
---|
| 106 |
|
---|
[7473] | 107 | /**
|
---|
| 108 | * Returns the value of configuration item in the capabilities as long value.
|
---|
| 109 | *
|
---|
| 110 | * @param element the name of the element
|
---|
| 111 | * @param attribute the name of the attribute
|
---|
| 112 | * @return the value; {@code null}, if the respective configuration item does not exist
|
---|
| 113 | * @throws NumberFormatException if the value is not a valid long
|
---|
| 114 | */
|
---|
[2512] | 115 | public Long getLong(String element, String attribute) {
|
---|
| 116 | String s = get(element, attribute);
|
---|
| 117 | if (s == null) return null;
|
---|
[8390] | 118 | return Long.valueOf(s);
|
---|
[2512] | 119 | }
|
---|
| 120 |
|
---|
[7473] | 121 | /**
|
---|
| 122 | * Adds a new configuration item.
|
---|
| 123 | *
|
---|
| 124 | * @param element the name of the element
|
---|
| 125 | * @param attribute the name of the attribute
|
---|
| 126 | * @param value the value as string
|
---|
| 127 | */
|
---|
[2512] | 128 | public void put(String element, String attribute, String value) {
|
---|
[7012] | 129 | if ("blacklist".equals(element)) {
|
---|
| 130 | if ("regex".equals(attribute)) {
|
---|
[3934] | 131 | imageryBlacklist.add(value);
|
---|
| 132 | }
|
---|
| 133 | } else {
|
---|
[10378] | 134 | if (!capabilities.containsKey(element)) {
|
---|
[11523] | 135 | capabilities.put(element, new HashMap<>());
|
---|
[3934] | 136 | }
|
---|
[11523] | 137 | capabilities.get(element).put(attribute, value);
|
---|
[2512] | 138 | }
|
---|
| 139 | }
|
---|
| 140 |
|
---|
[7473] | 141 | /**
|
---|
| 142 | * Clears the API capabilities.
|
---|
| 143 | */
|
---|
[6890] | 144 | public final void clear() {
|
---|
[7473] | 145 | capabilities.clear();
|
---|
| 146 | imageryBlacklist.clear();
|
---|
[2512] | 147 | }
|
---|
| 148 |
|
---|
[7473] | 149 | /**
|
---|
| 150 | * Determines if a given API version is supported.
|
---|
| 151 | * @param version The API version to check
|
---|
| 152 | * @return {@code true} is version is between the minimum supported version and the maximum one, {@code false} otherwise
|
---|
| 153 | */
|
---|
[2512] | 154 | public boolean supportsVersion(String version) {
|
---|
| 155 | return get("version", "minimum").compareTo(version) <= 0
|
---|
[11523] | 156 | && get("version", "maximum").compareTo(version) >= 0;
|
---|
[2512] | 157 | }
|
---|
| 158 |
|
---|
[7529] | 159 | private static void warnIllegalValue(String attr, String elem, Object val) {
|
---|
| 160 | Main.warn(tr("Illegal value of attribute ''{0}'' of element ''{1}'' in server capabilities. Got ''{2}''", attr, elem, val));
|
---|
| 161 | }
|
---|
| 162 |
|
---|
[2599] | 163 | /**
|
---|
[3934] | 164 | * Returns the max number of objects in a changeset. -1 if either the capabilities
|
---|
[2599] | 165 | * don't include this parameter or if the parameter value is illegal (not a number,
|
---|
| 166 | * a negative number)
|
---|
[2711] | 167 | *
|
---|
[2599] | 168 | * @return the max number of objects in a changeset
|
---|
| 169 | */
|
---|
[2915] | 170 | public int getMaxChangesetSize() {
|
---|
[2599] | 171 | String v = get("changesets", "maximum_elements");
|
---|
[7529] | 172 | if (v != null) {
|
---|
| 173 | try {
|
---|
| 174 | int n = Integer.parseInt(v);
|
---|
| 175 | if (n <= 0) {
|
---|
| 176 | warnIllegalValue("changesets", "maximum_elements", n);
|
---|
| 177 | } else {
|
---|
| 178 | return n;
|
---|
| 179 | }
|
---|
| 180 | } catch (NumberFormatException e) {
|
---|
| 181 | warnIllegalValue("changesets", "maximum_elements", v);
|
---|
[2599] | 182 | }
|
---|
| 183 | }
|
---|
[7529] | 184 | return -1;
|
---|
[2599] | 185 | }
|
---|
[3934] | 186 |
|
---|
| 187 | /**
|
---|
[7529] | 188 | * Returns the max number of nodes in a way. -1 if either the capabilities
|
---|
| 189 | * don't include this parameter or if the parameter value is illegal (not a number,
|
---|
| 190 | * a negative number)
|
---|
| 191 | *
|
---|
| 192 | * @return the max number of nodes in a way
|
---|
| 193 | */
|
---|
| 194 | public long getMaxWayNodes() {
|
---|
| 195 | String v = get("waynodes", "maximum");
|
---|
| 196 | if (v != null) {
|
---|
| 197 | try {
|
---|
[8390] | 198 | long n = Long.parseLong(v);
|
---|
[7529] | 199 | if (n <= 0) {
|
---|
| 200 | warnIllegalValue("waynodes", "maximum", n);
|
---|
| 201 | } else {
|
---|
| 202 | return n;
|
---|
| 203 | }
|
---|
| 204 | } catch (NumberFormatException e) {
|
---|
| 205 | warnIllegalValue("waynodes", "maximum", v);
|
---|
| 206 | }
|
---|
| 207 | }
|
---|
| 208 | return -1;
|
---|
| 209 | }
|
---|
| 210 |
|
---|
| 211 | /**
|
---|
[7473] | 212 | * Checks if the given URL is blacklisted by one of the of the regular expressions.
|
---|
| 213 | * @param url Imagery URL to check
|
---|
| 214 | * @return {@code true} if URL is blacklisted, {@code false} otherwise
|
---|
[3934] | 215 | */
|
---|
[7473] | 216 | public boolean isOnImageryBlacklist(String url) {
|
---|
[4063] | 217 | if (url != null && imageryBlacklist != null) {
|
---|
[3986] | 218 | for (String blacklistRegex : imageryBlacklist) {
|
---|
| 219 | if (url.matches(blacklistRegex))
|
---|
| 220 | return true;
|
---|
[3934] | 221 | }
|
---|
| 222 | }
|
---|
| 223 | return false;
|
---|
| 224 | }
|
---|
| 225 |
|
---|
[3986] | 226 | /**
|
---|
[7473] | 227 | * Returns the full list of imagery blacklist regular expressions.
|
---|
| 228 | * @return full list of imagery blacklist regular expressions
|
---|
[3934] | 229 | */
|
---|
[7473] | 230 | public List<String> getImageryBlacklist() {
|
---|
[3934] | 231 | return Collections.unmodifiableList(imageryBlacklist);
|
---|
| 232 | }
|
---|
[7473] | 233 |
|
---|
| 234 | /**
|
---|
| 235 | * A parser for the "capabilities" response XML.
|
---|
| 236 | * @since 7473
|
---|
| 237 | */
|
---|
| 238 | public static final class CapabilitiesParser extends DefaultHandler {
|
---|
| 239 |
|
---|
| 240 | private Capabilities capabilities;
|
---|
| 241 |
|
---|
| 242 | @Override
|
---|
[11453] | 243 | public void startDocument() {
|
---|
[7473] | 244 | capabilities = new Capabilities();
|
---|
| 245 | }
|
---|
| 246 |
|
---|
| 247 | @Override
|
---|
[11453] | 248 | public void startElement(String namespaceURI, String localName, String qName, Attributes atts) {
|
---|
[8510] | 249 | for (int i = 0; i < atts.getLength(); i++) {
|
---|
[7473] | 250 | capabilities.put(qName, atts.getQName(i), atts.getValue(i));
|
---|
| 251 | }
|
---|
| 252 | }
|
---|
| 253 |
|
---|
| 254 | /**
|
---|
| 255 | * Returns the read capabilities.
|
---|
| 256 | * @return the read capabilities
|
---|
| 257 | */
|
---|
| 258 | public Capabilities getCapabilities() {
|
---|
| 259 | return capabilities;
|
---|
| 260 | }
|
---|
| 261 |
|
---|
| 262 | /**
|
---|
| 263 | * Parses and returns capabilities from the given input source.
|
---|
| 264 | *
|
---|
| 265 | * @param inputSource The input source to read capabilities from
|
---|
| 266 | * @return the capabilities
|
---|
| 267 | * @throws SAXException if any SAX errors occur during processing
|
---|
| 268 | * @throws IOException if any I/O errors occur
|
---|
| 269 | * @throws ParserConfigurationException if a parser cannot be created
|
---|
| 270 | */
|
---|
| 271 | public static Capabilities parse(InputSource inputSource) throws SAXException, IOException, ParserConfigurationException {
|
---|
| 272 | CapabilitiesParser parser = new CapabilitiesParser();
|
---|
[8347] | 273 | Utils.parseSafeSAX(inputSource, parser);
|
---|
[7473] | 274 | return parser.getCapabilities();
|
---|
| 275 | }
|
---|
| 276 | }
|
---|
[2512] | 277 | }
|
---|