/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.ode.utils.xml.capture; import org.apache.ode.utils.XMLParserUtils; import java.net.URI; import java.util.*; import org.xml.sax.EntityResolver; import org.xml.sax.XMLReader; /** * XML Dependency Scanner, processes XML and follows "import"s, "include"s, * and the like to discover the transitive closure of the dependencies. * The scanner supports WSDL, XMLSchema, and BPEL import elements, and can * be extended by implementing additional {@link Tracker} classes. */ public class XmlDependencyScanner { /** Errors. */ private Map<URI,Exception> _errors = new HashMap<URI,Exception>(); /** References. */ private Map<URI, Set<URI>> _references = new HashMap<URI, Set<URI>>(); /** Referers. */ private Map<URI, Set<URI>> _referers = new HashMap<URI, Set<URI>>(); private EntityResolver _resolver; private MultiplexTracker _mch; /** Constructor. */ public XmlDependencyScanner() { Set<Tracker> handlers = new HashSet<Tracker>(); handlers.add(new Wsdl11Tracker()); handlers.add(new XmlSchemaTracker()); _mch = new MultiplexTracker(handlers); } /** * Set the {@link EntityResolver} that should be used to obtain the * byte streams for URIs. * @param resolver {@link EntityResolver} or null for the default (URL) resolver */ public void setResolver(EntityResolver resolver) { _resolver = resolver; } public EntityResolver getResolver() { return _resolver; } /** * Process the URI: parse the document and follow any imports (recursively) * to discover all imported resources. * @param uri */ public void process(URI uri) { if (_references.keySet().contains(uri)) return; HashSet<URI> todo = new HashSet<URI>(); todo.add(uri); while (!todo.isEmpty()) { Iterator<URI> i = todo.iterator(); URI x = i.next(); i.remove(); HashSet<URI> refs = new HashSet<URI>(); _mch.init(x, refs); try { XMLReader reader = XMLParserUtils.getXMLReader(); reader.setContentHandler(_mch); reader.setFeature("http://xml.org/sax/features/namespaces", true); reader.setEntityResolver(_resolver); reader.parse(x.toASCIIString()); _references.put(x, new HashSet<URI>(refs)); } catch (Exception e) { _errors.put(x, e); } for (Iterator<URI> i1 = refs.iterator();i1.hasNext();) addReferer(i1.next(), x); refs.removeAll(_references.keySet()); todo.addAll(refs); } } public Set<URI> getURIs() { return _references.keySet(); } /** * Get the references (imports, includes, etc) of a given * resource. * @param uri URI of the resource * @return {@link Set} of references */ public Set<URI> getReferences(URI uri) { Set<URI> r = _references.get(uri); if (r == null) r = Collections.emptySet(); return r; } public boolean isError() { return !_errors.isEmpty(); } /** * Get all the URI's that refer to a URI. * @param uri URI refered to * @return {@link Set} of resources that refer to the resource */ public Set<URI> getReferers(URI uri) { Set<URI> r = _referers.get(uri); if (r == null) r = Collections.emptySet(); return r; } void addReferer(URI reference, URI referer) { Set<URI> x = _referers.get(reference); if (x == null) { x = new HashSet<URI>(); _referers.put(reference,x); } x.add(referer); } public Map<URI, Exception> getErrors() { return _errors; } }