Changeset 5546 for FCSSimpleEndpoint/trunk/src/main/java/eu/clarin/sru/server/fcs/utils/SimpleEndpointDescriptionParser.java
- Timestamp:
- 08/09/14 20:45:17 (10 years ago)
- File:
-
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
FCSSimpleEndpoint/trunk/src/main/java/eu/clarin/sru/server/fcs/utils/SimpleEndpointDescriptionParser.java
r5485 r5546 2 2 3 3 import java.io.IOException; 4 import java.net.URI; 5 import java.net.URISyntaxException; 4 6 import java.net.URL; 5 7 import java.util.ArrayList; 6 import java.util.Arrays;7 8 import java.util.HashMap; 8 9 import java.util.HashSet; 9 10 import java.util.Iterator; 10 import java.util.LinkedList;11 11 import java.util.List; 12 12 import java.util.Map; … … 33 33 34 34 import eu.clarin.sru.server.SRUConfigException; 35 import eu.clarin.sru.server.fcs.ResourceInfoInventory; 35 import eu.clarin.sru.server.fcs.DataView; 36 import eu.clarin.sru.server.fcs.DataView.DeliveryPolicy; 37 import eu.clarin.sru.server.fcs.EndpointDescription; 36 38 import eu.clarin.sru.server.fcs.ResourceInfo; 37 39 38 40 39 41 /** 40 * A parser, that parses an XML file and produces a static list of resource info 41 * records. The resulting list can be used to construct a 42 * {@link SimpleResourceInfoInventory} instance. 43 * 44 * @see ResourceInfo 45 * @see SimpleResourceInfoInventory 42 * A parser, that parses an XML file and produces a endpoint description with 43 * static list of resource info records. The XML file has the same format as the 44 * result format defined for endpoint description of the CLARIN-FCS 45 * specification. The {@link #parse(URL)} returns a 46 * {@link SimpleEndpointDescription} instance. 47 * 48 * @see EndpointDescription 49 * @see SimpleEndpointDescription 46 50 */ 47 public class SimpleResourceInfoInventoryParser { 48 private static final String NS = "http://clarin.eu/fcs/endpoint-description"; 51 public class SimpleEndpointDescriptionParser { 52 private static final String NS = 53 "http://clarin.eu/fcs/endpoint-description"; 54 private static final String NS_LEGACY = 55 "http://clarin.eu/fcs/1.0/resource-info"; 56 private static final String CAP_BASIC_SEARCH = 57 "http://clarin.eu/fcs/capability/basic-search"; 49 58 private static final String LANG_EN = "en"; 59 private static final String POLICY_SEND_DEFAULT = "send-by-default"; 60 private static final String POLICY_NEED_REQUEST = "need-to-request"; 50 61 private static final Logger logger = 51 LoggerFactory.getLogger(Simple ResourceInfoInventoryParser.class);62 LoggerFactory.getLogger(SimpleEndpointDescriptionParser.class); 52 63 53 64 54 65 /** 55 66 * Parse an XML file and return a static list of resource info records. 56 * 67 * 57 68 * @param url 58 69 * the URI pointing to the file to be parsed 59 * @return a list of resource info records represented as 60 * {@link ResourceInfo} instances 70 * @return an {@link EndpointDescription} instance 61 71 * @throws SRUConfigException 62 72 * if an error occurred 63 73 */ 64 public static ResourceInfoInventoryparse(URL url) throws SRUConfigException {74 public static EndpointDescription parse(URL url) throws SRUConfigException { 65 75 if (url == null) { 66 76 throw new NullPointerException("url == null"); 67 77 } 68 78 69 logger.debug("parsing resource-info from: {}", url); 70 71 final Set<String> ids = new HashSet<String>(); 79 logger.debug("parsing endpoint description from: {}", url); 80 72 81 try { 73 82 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); … … 77 86 Document doc = db.parse(url.openStream()); 78 87 79 XPathFactory factory = XPathFactory.newInstance(); 80 XPath xpath = factory.newXPath(); 81 xpath.setNamespaceContext(new NamespaceContext() { 82 @Override 83 public Iterator<?> getPrefixes(String namespaceURI) { 84 throw new UnsupportedOperationException(); 85 } 86 87 @Override 88 public String getPrefix(String namespaceURI) { 89 throw new UnsupportedOperationException(); 90 } 91 92 @Override 93 public String getNamespaceURI(String prefix) { 94 if (prefix == null) { 95 throw new NullPointerException("prefix == null"); 88 /* 89 * Detect for deprecated resource-info catalog files and bail, if necessary 90 */ 91 checkLegacyMode(doc, url); 92 93 /* 94 * Parse on and create endpoint description ... 95 */ 96 return parseEndpointDescription(doc); 97 } catch (ParserConfigurationException e) { 98 throw new SRUConfigException("internal error", e); 99 } catch (SAXException e) { 100 throw new SRUConfigException("parsing error", e); 101 } catch (IOException e) { 102 throw new SRUConfigException("error reading file", e); 103 } catch (XPathExpressionException e) { 104 throw new SRUConfigException("internal error", e); 105 } 106 } 107 108 109 private static EndpointDescription parseEndpointDescription(Document doc) 110 throws SRUConfigException, XPathExpressionException { 111 XPathFactory factory = XPathFactory.newInstance(); 112 XPath xpath = factory.newXPath(); 113 114 xpath.setNamespaceContext(new NamespaceContext() { 115 @Override 116 public Iterator<?> getPrefixes(String namespaceURI) { 117 throw new UnsupportedOperationException(); 118 } 119 120 @Override 121 public String getPrefix(String namespaceURI) { 122 throw new UnsupportedOperationException(); 123 } 124 125 @Override 126 public String getNamespaceURI(String prefix) { 127 if (prefix == null) { 128 throw new NullPointerException("prefix == null"); 129 } 130 if (prefix.equals("ed")) { 131 return NS; 132 } else if (prefix.equals(XMLConstants.XML_NS_PREFIX)) { 133 return XMLConstants.XML_NS_URI; 134 } else { 135 return XMLConstants.NULL_NS_URI; 136 } 137 } 138 }); 139 140 // capabilities 141 List<URI> capabilities = new ArrayList<URI>(); 142 XPathExpression exp1 = 143 xpath.compile("//ed:Capabilities/ed:Capability"); 144 NodeList list1 = (NodeList) exp1.evaluate(doc, XPathConstants.NODESET); 145 if ((list1 != null) && (list1.getLength() > 0)) { 146 logger.debug("parsing capabilities"); 147 for (int i = 0; i < list1.getLength(); i++) { 148 String s = list1.item(i).getTextContent().trim(); 149 try { 150 URI uri = new URI(s); 151 if (capabilities.contains(uri)) { 152 logger.warn("ignoring duplicate capability " + 153 "entry for '{}'", uri); 96 154 } 97 if (prefix.equals("ri")) { 98 return NS; 99 } else if (prefix.equals(XMLConstants.XML_NS_PREFIX)) { 100 return XMLConstants.XML_NS_URI; 101 } else { 102 return XMLConstants.NULL_NS_URI; 155 capabilities.add(uri); 156 } catch (URISyntaxException e) { 157 throw new SRUConfigException("capability is not encoded " + 158 "as proper URI: " + s); 159 } 160 } 161 } else { 162 logger.warn("No capabilities where defined in " + 163 "endpoint configuration"); 164 } 165 URI cap = URI.create(CAP_BASIC_SEARCH); 166 if (!capabilities.contains(cap)) { 167 logger.warn("capability '{}' was not defined in endpoint " + 168 "description; added it to meet specification. Please " + 169 "update your endpoint description!", CAP_BASIC_SEARCH); 170 capabilities.add(cap); 171 } 172 logger.debug("CAPS:'{}'", capabilities); 173 174 // supported data views 175 List<DataView> supportedDataViews = new ArrayList<DataView>(); 176 XPathExpression exp2 = 177 xpath.compile("//ed:SupportedDataViews/ed:SupportedDataView"); 178 NodeList list2 = (NodeList) exp2.evaluate(doc, XPathConstants.NODESET); 179 if ((list2 != null) && (list2.getLength() > 0)) { 180 logger.debug("parsing supported data views"); 181 for (int i = 0; i < list2.getLength(); i++) { 182 Element item = (Element) list2.item(i); 183 String id = getAttribute(item, "id"); 184 if (id == null) { 185 throw new SRUConfigException("Element <SupportedDataView> " 186 + "must carry a proper 'id' attribute"); 187 } 188 String p = getAttribute(item, "delivery-policy"); 189 if (p == null) { 190 throw new SRUConfigException("Element <SupportedDataView> " 191 + "must carry a 'delivery-policy' attribute"); 192 } 193 DeliveryPolicy policy = null; 194 if (POLICY_SEND_DEFAULT.equals(p)) { 195 policy = DeliveryPolicy.SEND_BY_DEFAULT; 196 } else if (POLICY_NEED_REQUEST.equals(p)) { 197 policy = DeliveryPolicy.NEED_TO_REQUEST; 198 } else { 199 throw new SRUConfigException("Invalid value '" + p + 200 "' for attribute 'delivery-policy' on element " + 201 "<SupportedDataView>"); 202 } 203 String mimeType = item.getTextContent(); 204 if (mimeType != null) { 205 mimeType = mimeType.trim(); 206 if (mimeType.isEmpty()) { 207 mimeType = null; 103 208 } 104 209 } 105 }); 106 XPathExpression expression = 107 xpath.compile("/ri:Resources/ri:Resource"); 108 NodeList list = 109 (NodeList) expression.evaluate(doc, XPathConstants.NODESET); 110 111 List<ResourceInfo> entries = parseResourceInfo(xpath, list, ids); 112 return new SimpleResourceInfoInventory(entries, false); 113 } catch (ParserConfigurationException e) { 114 e.printStackTrace(); 115 } catch (SAXException e) { 116 e.printStackTrace(); 117 } catch (IOException e) { 118 e.printStackTrace(); 119 } catch (XPathExpressionException e) { 120 e.printStackTrace(); 210 if (mimeType == null) { 211 throw new SRUConfigException("Element <SupportedDataView> " 212 + "must contain a MIME-type as content"); 213 } 214 // check for duplicate entries ... 215 for (DataView dataView : supportedDataViews) { 216 if (id.equals(dataView.getIdentifier())) { 217 throw new SRUConfigException( 218 "A <SupportedDataView> with " + "the id '" + 219 id + "' is already defined!"); 220 } 221 if (mimeType.equals(dataView.getMimeType())) { 222 throw new SRUConfigException( 223 "A <SupportedDataView> with " + 224 "the MIME-type '" + mimeType + 225 "' is already defined!"); 226 } 227 } 228 supportedDataViews.add(new DataView(id, mimeType, policy)); 229 } 230 } else { 231 logger.error("Endpoint configuration contains no valid " + 232 "information about supported data views"); 233 throw new SRUConfigException("Endpoint configuration contains " + 234 "no valid information about supported data views"); 235 } 236 237 logger.debug("DV: {}", supportedDataViews); 238 239 240 // resources 241 XPathExpression x3 = 242 xpath.compile("/ed:EndpointDescription/ed:Resources/ed:Resource"); 243 NodeList l3 = (NodeList) x3.evaluate(doc, XPathConstants.NODESET); 244 final Set<String> ids = new HashSet<String>(); 245 List<ResourceInfo> resources = 246 parseRessources(xpath, l3, ids, supportedDataViews); 247 if ((resources == null) || resources.isEmpty()) { 248 throw new SRUConfigException("No resources where " + 249 "defined in endpoint description"); 250 } 251 252 return new SimpleEndpointDescription(capabilities, 253 supportedDataViews, 254 resources, 255 false); 256 } 257 258 259 private static List<ResourceInfo> parseRessources(XPath xpath, 260 NodeList nodes, Set<String> ids, List<DataView> supportedDataViews) 261 throws SRUConfigException, XPathExpressionException { 262 List<ResourceInfo> ris = null; 263 for (int k = 0; k < nodes.getLength(); k++) { 264 final Element node = (Element) nodes.item(k); 265 String pid = null; 266 Map<String, String> titles = null; 267 Map<String, String> descrs = null; 268 String link = null; 269 List<String> langs = null; 270 List<DataView> availableDataViews = null; 271 List<ResourceInfo> sub = null; 272 273 pid = getAttribute(node, "pid"); 274 if (pid == null) { 275 throw new SRUConfigException("Element <ResourceInfo> " + 276 "must carry a proper 'pid' attribute"); 277 } 278 if (ids.contains(pid)) { 279 throw new SRUConfigException("Another element <Resource> " + 280 "with pid '" + pid + "' already exists"); 281 } 282 ids.add(pid); 283 284 XPathExpression x1 = xpath.compile("ed:Title"); 285 NodeList l1 = (NodeList) x1.evaluate(node, XPathConstants.NODESET); 286 if ((l1 != null) && (l1.getLength() > 0)) { 287 for (int i = 0; i < l1.getLength(); i++) { 288 final Element n = (Element) l1.item(i); 289 290 final String lang = getLangAttribute(n); 291 if (lang == null) { 292 throw new SRUConfigException("Element <Title> must " + 293 "carry a proper 'xml:lang' attribute"); 294 } 295 296 final String title = cleanString(n.getTextContent()); 297 if (title == null) { 298 throw new SRUConfigException("Element <Title> must " + 299 "carry a non-empty 'xml:lang' attribute"); 300 } 301 302 if (titles == null) { 303 titles = new HashMap<String, String>(); 304 } 305 if (titles.containsKey(lang)) { 306 logger.warn("title with language '{}' already exists", 307 lang); 308 } else { 309 logger.debug("title: '{}' '{}'", lang, title); 310 titles.put(lang, title); 311 } 312 } 313 if ((titles != null) && !titles.containsKey(LANG_EN)) { 314 throw new SRUConfigException( 315 "A <Title> with language 'en' is mandatory"); 316 } 317 } 318 319 XPathExpression x2 = xpath.compile("ed:Description"); 320 NodeList l2 = (NodeList) x2.evaluate(node, XPathConstants.NODESET); 321 if ((l2 != null) && (l2.getLength() > 0)) { 322 for (int i = 0; i < l2.getLength(); i++) { 323 Element n = (Element) l2.item(i); 324 325 String lang = getLangAttribute(n); 326 if (lang == null) { 327 throw new SRUConfigException("Element <Description> " + 328 "must carry a proper 'xml:lang' attribute"); 329 330 } 331 String desc = cleanString(n.getTextContent()); 332 333 if (descrs == null) { 334 descrs = new HashMap<String, String>(); 335 } 336 337 if (descrs.containsKey(lang)) { 338 logger.warn("description with language '{}' " 339 + "already exists", lang); 340 } else { 341 logger.debug("description: '{}' '{}'", lang, desc); 342 descrs.put(lang, desc); 343 } 344 } 345 if ((descrs != null) && !descrs.containsKey(LANG_EN)) { 346 throw new SRUConfigException( 347 "A <Description> with language 'en' is mandatory"); 348 } 349 } 350 351 XPathExpression x3 = xpath.compile("ed:LandingPageURI"); 352 NodeList l3 = (NodeList) x3.evaluate(node, XPathConstants.NODESET); 353 if ((l3 != null) && (l3.getLength() > 0)) { 354 for (int i = 0; i < l3.getLength(); i++) { 355 Element n = (Element) l3.item(i); 356 link = cleanString(n.getTextContent()); 357 } 358 } 359 360 XPathExpression x4 = xpath.compile("ed:Languages/ed:Language"); 361 NodeList l4 = (NodeList) x4.evaluate(node, XPathConstants.NODESET); 362 if ((l4 != null) && (l4.getLength() > 0)) { 363 for (int i = 0; i < l4.getLength(); i++) { 364 Element n = (Element) l4.item(i); 365 366 String s = n.getTextContent(); 367 if (s != null) { 368 s = s.trim(); 369 if (s.isEmpty()) { 370 s = null; 371 } 372 } 373 374 /* 375 * enforce three letter codes 376 */ 377 if ((s == null) || (s.length() != 3)) { 378 throw new SRUConfigException("Element <Language> " + 379 "must use ISO-632-3 three letter " + 380 "language codes"); 381 } 382 383 if (langs == null) { 384 langs = new ArrayList<String>(); 385 } 386 langs.add(s); 387 } 388 } 389 390 XPathExpression x5 = xpath.compile("ed:AvailableDataViews"); 391 Node n = (Node) x5.evaluate(node, XPathConstants.NODE); 392 if ((n != null) && (n instanceof Element)) { 393 String ref = getAttribute((Element) n, "ref"); 394 if (ref == null) { 395 throw new SRUConfigException("Element <AvailableDataViews> " + 396 "must carry a 'ref' attribute"); 397 } 398 String[] refs = ref.split("\\s+"); 399 if ((refs == null) || (refs.length < 1)) { 400 throw new SRUConfigException("Attribute 'ref' on element " + 401 "<AvailableDataViews> must contain a whitespace " + 402 "seperated list of data view references"); 403 } 404 405 406 for (int i = 0; i < refs.length; i++) { 407 DataView dataview = null; 408 for (DataView dv : supportedDataViews) { 409 if (refs[i].equals(dv.getIdentifier())) { 410 dataview = dv; 411 break; 412 } 413 } 414 if (dataview != null) { 415 if (availableDataViews == null) { 416 availableDataViews = new ArrayList<DataView>(); 417 } 418 availableDataViews.add(dataview); 419 } else { 420 throw new SRUConfigException("A data view with " + 421 "identifier '" + refs[i] + "' was not defined " + 422 "in <SupportedDataViews>"); 423 } 424 } 425 } else { 426 throw new SRUConfigException( 427 "missing element <ed:AvailableDataViews>"); 428 } 429 if (availableDataViews == null) { 430 throw new SRUConfigException("No available data views where " + 431 "defined for resource with PID '" + pid + "'"); 432 } 433 434 XPathExpression x6 = xpath.compile("ed:Resources/ed:Resource"); 435 NodeList l6 = (NodeList) x6.evaluate(node, XPathConstants.NODESET); 436 if ((l6 != null) && (l6.getLength() > 0)) { 437 sub = parseRessources(xpath, l6, ids, supportedDataViews); 438 } 439 440 if (ris == null) { 441 ris = new ArrayList<ResourceInfo>(); 442 } 443 ris.add(new ResourceInfo(pid, 444 titles, 445 descrs, 446 link, 447 langs, 448 availableDataViews, 449 sub)); 450 } 451 return ris; 452 } 453 454 455 private static String getAttribute(Element el, String localName) { 456 String lang = el.getAttribute(localName); 457 if (lang != null) { 458 lang = lang.trim(); 459 if (!lang.isEmpty()) { 460 return lang; 461 } 121 462 } 122 463 return null; 123 }124 125 126 private static List<ResourceInfo> parseResourceInfo(XPath xpath,127 NodeList nodes, Set<String> ids) throws SRUConfigException,128 XPathExpressionException {129 logger.debug("parsing 'ResourceInfo' ({} nodes) ...",130 nodes.getLength());131 132 List<ResourceInfo> ris = null;133 for (int k = 0; k < nodes.getLength(); k++) {134 final Element node = (Element) nodes.item(k);135 String pid = null;136 int resourceCount = -1;137 Map<String, String> titles = null;138 Map<String, String> descrs = null;139 String link = null;140 List<String> langs = null;141 String[] availableDataViews = null;142 List<ResourceInfo> sub = null;143 144 pid = node.getAttribute("pid");145 if (pid != null) {146 pid = pid.trim();147 if (pid.isEmpty()) {148 pid = null;149 }150 }151 if (pid == null) {152 throw new SRUConfigException("Element <ResourceInfo> " +153 "must carry a proper 'pid' attribute");154 }155 if (ids.contains(pid)) {156 throw new SRUConfigException("Another element <ResourceInfo> " +157 "with pid '" + pid + "' already exists");158 }159 ids.add(pid);160 161 XPathExpression x1 = xpath.compile("ri:Title");162 NodeList l1 = (NodeList) x1.evaluate(node, XPathConstants.NODESET);163 if (l1 != null) {164 for (int i = 0; i < l1.getLength(); i++) {165 final Element n = (Element) l1.item(i);166 167 final String lang = getLangAttribute(n);168 if (lang == null) {169 throw new SRUConfigException("Element <Title> must " +170 "carry a proper 'xml:lang' attribute");171 }172 173 final String title = cleanString(n.getTextContent());174 if (title == null) {175 throw new SRUConfigException("Element <Title> must " +176 "carry a non-empty 'xml:lang' attribute");177 }178 179 if (titles == null) {180 titles = new HashMap<String, String>();181 }182 if (titles.containsKey(lang)) {183 logger.warn("title with language '{}' already exists",184 lang);185 } else {186 logger.debug("title: '{}' '{}'", lang, title);187 titles.put(lang, title);188 }189 }190 if ((titles != null) && !titles.containsKey(LANG_EN)) {191 throw new SRUConfigException(192 "A <Title> with language 'en' is mandatory");193 }194 }195 XPathExpression x2 = xpath.compile("ri:Description");196 NodeList l2 = (NodeList) x2.evaluate(node, XPathConstants.NODESET);197 if (l2 != null) {198 for (int i = 0; i < l2.getLength(); i++) {199 Element n = (Element) l2.item(i);200 201 String lang = getLangAttribute(n);202 if (lang == null) {203 throw new SRUConfigException("Element <Description> " +204 "must carry a proper 'xml:lang' attribute");205 206 }207 String desc = cleanString(n.getTextContent());208 209 if (descrs == null) {210 descrs = new HashMap<String, String>();211 }212 213 if (descrs.containsKey(lang)) {214 logger.warn("description with language '{}' "215 + "already exists", lang);216 } else {217 logger.debug("description: '{}' '{}'", lang, desc);218 descrs.put(lang, desc);219 }220 }221 if ((descrs != null) && !descrs.containsKey(LANG_EN)) {222 throw new SRUConfigException(223 "A <Description> with language 'en' is mandatory");224 }225 }226 227 XPathExpression x3 = xpath.compile("ri:LandingPageURI");228 NodeList l3 = (NodeList) x3.evaluate(node, XPathConstants.NODESET);229 if (l3 != null) {230 for (int i = 0; i < l3.getLength(); i++) {231 Element n = (Element) l3.item(i);232 link = cleanString(n.getTextContent());233 logger.debug("link: \"{}\"", n.getTextContent());234 }235 }236 237 XPathExpression x4 = xpath.compile("ri:Languages/ri:Language");238 NodeList l4 = (NodeList) x4.evaluate(node, XPathConstants.NODESET);239 if (l4 != null) {240 for (int i = 0; i < l4.getLength(); i++) {241 Element n = (Element) l4.item(i);242 243 String s = n.getTextContent();244 if (s != null) {245 s = s.trim();246 if (s.isEmpty()) {247 s = null;248 }249 }250 251 /*252 * enforce three letter codes253 */254 if ((s == null) || (s.length() != 3)) {255 throw new SRUConfigException("Element <Language> " +256 "must use ISO-632-3 three letter " +257 "language codes");258 }259 260 if (langs == null) {261 langs = new ArrayList<String>();262 }263 logger.debug("language: '{}'", n.getTextContent());264 langs.add(s);265 }266 }267 268 XPathExpression x6 = xpath.compile("ri:AvailableDataViews/@ref");269 String ref = (String) x6.evaluate(node, XPathConstants.STRING);270 271 if (ref == null || ref.isEmpty()){272 throw new SRUConfigException("Element <AvailableDataViews> " +273 "must have a non-empty attribute ref.");274 }275 276 availableDataViews = ref.split("\\s+");277 278 279 XPathExpression x5 =280 xpath.compile("ri:Resources/ri:Resource");281 NodeList l5 = (NodeList) x5.evaluate(node, XPathConstants.NODESET);282 if ((l5 != null) && (l5.getLength() > 0)) {283 sub = parseResourceInfo(xpath, l5, ids);284 }285 286 if (ris == null) {287 ris = new LinkedList<ResourceInfo>();288 }289 ris.add(new ResourceInfo(pid, resourceCount, titles, descrs, link,290 langs, Arrays.asList(availableDataViews),sub));291 }292 return ris;293 464 } 294 465 … … 328 499 } 329 500 501 502 private static void checkLegacyMode(Document doc, URL url) 503 throws SRUConfigException { 504 Element root = doc.getDocumentElement(); 505 if (root != null) { 506 String ns = root.getNamespaceURI(); 507 if (ns != null) { 508 if (ns.equals(NS_LEGACY)) { 509 logger.error("Detected out-dated " + 510 "resource info catalog file '" + url + 511 "'. Please update to the " + 512 "current version"); 513 throw new SRUConfigException("unsupport file format: " + ns); 514 } else if (!ns.equals(NS)) { 515 logger.error("Detected unsupported resource info " + 516 "catalog file '" + url + "' with namespace '" + ns + '"'); 517 throw new SRUConfigException("unsupport file format: " + ns); 518 } 519 } else { 520 throw new SRUConfigException("No namespace URI was detected " + 521 "for resource info catalog file '" + url +"'!"); 522 } 523 } else { 524 throw new SRUConfigException("Error retrieving root element"); 525 } 526 } 527 528 529 // private static List<ResourceInfo> parseLegacy(Document doc) 530 // throws SRUConfigException, XPathExpressionException { 531 330 532 } // class SimpleResourceInfoInventoryParser
Note: See TracChangeset
for help on using the changeset viewer.