--- /dev/null	Tue Jul  8 18:11:44 2008
+++ new/src/share/classes/sun/module/tools/ImportTraverser.java	Tue Jul  8 18:11:43 2008
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.module.tools;
+
+import java.io.File;
+import java.io.IOException;
+import java.module.Module;
+import java.module.ModuleArchiveInfo;
+import java.module.ModuleDefinition;
+import java.module.ModuleInitializationException;
+import java.module.Modules;
+import java.module.Query;
+import java.module.Repository;
+import java.module.VersionConstraint;
+import java.util.LinkedHashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import sun.module.JamUtils;
+
+/**
+ * Provides a means to visit each of a module's imports.
+ * @since 1.7
+ */
+public class ImportTraverser implements Iterable<Module> {
+    private Set<Module> visited = new LinkedHashSet<Module>();
+
+    /**
+     * Invokes a visitor on each of the imports of the module identified by
+     * the parameters.   The imports are visited in depth-first order with respect to
+     * the graph of interconnected modules.  Note that the module identified
+     * by parameters is the first one visited.
+     *
+     * @param repo repository in which to find a named module
+     * @param name name of the module to find
+     * @param constraint version constraint on the module; may be null
+     * @throws ModuleInitializationException if the identified module cannot be
+     * instantiated
+     */
+    public void visit(Repository repo,
+                      String name,
+                      VersionConstraint constraint)
+            throws ModuleInitializationException{
+
+        visit(repo, name, constraint, null, null);
+    }
+
+    /**
+     * Invokes a visitor on each of the imports of the module identified by
+     * the parameters.   The imports are visited in depth-first order with respect to
+     * the graph of interconnected modules.  Note that the module identified
+     * by parameters is the first one visited.
+     *
+     * @param jamName name of a JAM file for which dependencies are returned
+     * @throws java.io.IOException if a Repository for the named JAM file cannot
+     * be created
+     * @throws ModuleInitializationException if the identified module cannot be
+     * instantiated
+     */
+    public void visit(String jamName)
+            throws IOException, ModuleInitializationException {
+
+        File repoDir = JamUtils.createTempDir();
+        Repository repo = Modules.newLocalRepository("importvisitor", repoDir);
+        ModuleArchiveInfo mai = repo.install(new File(jamName).toURI().toURL());
+        
+        visit(repo, mai.getName(), mai.getVersion().toVersionConstraint(),
+              mai.getPlatform(), mai.getArch());
+    }
+
+    /**
+     * Invokes a visitor on each of the imports of the module identified by
+     * the parameters.   The imports are visited in depth-first order with respect to
+     * the graph of interconnected modules.  Note that the module identified
+     * by parameters is the first one visited.
+     *
+     * @param repo repository in which to find a named module
+     * @param name name of the module to find
+     * @param constraint version constraint on the module; may be null
+     * @param platform platform of the module to find; may be null
+     * @param arch architecture of the module to find; may be null
+     * @throws ModuleInitializationException if the identified module cannot be
+     * instantiated
+     * @throws IllegalArgumentException if one of {@code platform, arch} is
+     * null and the other is not, or if the {@code repository} finds more than
+     * one module matching the given parameters.
+     */
+    public void visit(Repository repo,
+                         String name, VersionConstraint constraint,
+                         String platform, String arch)
+            throws ModuleInitializationException {
+
+        if (repo == null || name == null) {
+            throw new NullPointerException();
+        }
+
+        if (platform == null ^ arch == null) {
+            throw new IllegalArgumentException(
+                "module platform and arch must be either both null or both non-null");
+        }
+        
+        Query q = Query.module(
+            name, constraint == null ? VersionConstraint.DEFAULT : constraint);
+        if (platform != null) {
+            q = Query.and(
+                q, Query.annotation(java.module.annotation.PlatformBinding.class));
+        }
+
+        List<ModuleDefinition> mdList = repo.find(q);
+        if (mdList.size() > 1) {
+            throw new IllegalArgumentException(
+                "more than one matching module found for name=" + name
+                + " version=" + constraint
+                + " platform=" + platform + " arch=" + arch);
+        } else if (mdList.size() == 1) {
+            Module m = mdList.get(0).getModuleInstance();
+            init(m);
+            visit(repo, m);
+        }
+    }
+
+    public void visit(Repository repo,
+                       Module module) {
+                       
+        if (visited.contains(module)) {
+            return;
+        }
+        visited.add(module);
+        if (preVisit(module)) {
+            List<Module> imported = module.getImportedModules();
+            for (Module m : imported) {
+                visit(m);
+                visit(repo, m);
+            }
+        }
+        postVisit(module);
+    }
+
+    /**
+     * @return an unmodifiable list of the {@code Module} instances which have
+     * been visited; note that the list is ordered by the depth-first
+     * traversal of module imports.
+     */
+    public Iterator<Module> iterator() {
+        return visited.iterator();
+    }
+
+    /**
+     * @param m {@code Module} possibly visited by the traverser
+     * @return true if the given {@code Module} has been visited, false
+     * otherwise
+     */
+    protected boolean visited(Module m) {
+        return visited.contains(m);
+    }
+
+    /**
+     * Invoked with the {@code Module} identified by the client-called {@code
+     * visit} method before any other {@code Module} instances are visited.
+     * @param m First {@code Module} visited by the traverser
+     */
+    protected void init(Module m) { }
+
+    /**
+     * Invoked on a {@code Module} instance before its imports are visited.
+     * @param m {@code Module} which imports the module about to be visited by
+     * {@link #visit(Module)}
+     * @return true if the {@code Module} should be visited, false otherwise.
+     */
+    protected boolean preVisit(Module m) {
+        return true;
+    }
+
+    /**
+     * Invoked on a {@code Module} instance as it is visited
+     * @param m {@code Module} being visited
+     */
+    protected void visit(Module m) { }
+
+    /**
+     * Invoked on a {@code Module} instance after its imports are visited.
+     * @param m {@code Module} which imports the module that was just visited by
+     * {@link #visit(Module)}
+     */
+    protected void postVisit(Module m) { }
+}
