| /* |
| * Copyright (c) 2009, Oracle and/or its affiliates. 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. |
| * |
| * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| package com.sun.classanalyzer; |
| |
| import java.io.*; |
| import java.util.*; |
| |
| /** |
| * A simple tool to check module dependencies against a known list of |
| * dependencies. The tool fails (by throwing a RuntimeException) is an |
| * unexpected dependency is detected. |
| */ |
| |
| public class CheckDeps { |
| |
| /** |
| * Represents a dependency from one module to another module. The dependency |
| * may be optional. |
| */ |
| static class Dependency { |
| private final String module; |
| private final String other; |
| private final boolean optional; |
| |
| private Dependency(String module, String other, boolean optional) { |
| this.module = module; |
| this.other = other; |
| this.optional = optional; |
| } |
| |
| String module() { return module; } |
| String other() { return other; } |
| boolean isOptional() { return optional; } |
| |
| /** |
| * Parses a dependency in one of the following forms: |
| * a -> b |
| * [optional] a -> b |
| */ |
| static Dependency fromString(String s) { |
| String[] components = s.split(" "); |
| int count = components.length; |
| if (count != 3 && count != 4) |
| throw new IllegalArgumentException(s); |
| boolean optional = (count == 4); |
| if (optional && !components[0].equals("[optional]")) |
| throw new IllegalArgumentException(s); |
| String arrow = optional ? components[2] : components[1]; |
| if (!arrow.equals("->")) |
| throw new IllegalArgumentException(s); |
| String module = optional ? components[1] : components[0]; |
| String other = optional ? components[3] : components[2]; |
| return new Dependency(module, other, optional); |
| } |
| |
| @Override public String toString() { |
| StringBuilder sb = new StringBuilder(); |
| if (optional) |
| sb.append("[optional] "); |
| sb.append(module); |
| sb.append(" -> "); |
| sb.append(other); |
| return sb.toString(); |
| } |
| } |
| |
| /** |
| * Represents the "tail" |
| */ |
| static class DependencyTail { |
| private final String module; |
| private final boolean optional; |
| |
| DependencyTail(String module, boolean optional) { |
| this.module = module; |
| this.optional = optional; |
| } |
| String module() { return module; } |
| boolean isOptional() { return optional; } |
| } |
| |
| static void usage() { |
| System.out.println("java CheckDeps file1 file2"); |
| System.out.println(" where file1 is the expected dependencies and file2 is"); |
| System.out.println(" the actual dependencies. Both files are assumed to be"); |
| System.out.println(" in modules.summary format (see ClassAnalyzer tool)."); |
| System.out.println(); |
| System.out.println("Example usages:"); |
| System.out.println(" java CheckDeps make/modules/modules.summary " + |
| "$(OUTPUTDIR)/modules.summary"); |
| System.exit(-1); |
| } |
| |
| public static void main(String[] args) throws IOException { |
| if (args.length != 2) |
| usage(); |
| |
| // maps a module to the list of modules that it depends on |
| Map<String,List<DependencyTail>> expected = |
| new HashMap<String,List<DependencyTail>>(); |
| |
| // parse the expected dependencies file |
| Scanner s; |
| s = new Scanner(new FileInputStream(args[0])); |
| try { |
| while (s.hasNextLine()) { |
| Dependency ref = Dependency.fromString(s.nextLine()); |
| if (ref != null) { |
| String module = ref.module(); |
| List<DependencyTail> list = expected.get(module); |
| if (list == null) { |
| list = new ArrayList<DependencyTail>(); |
| expected.put(module, list); |
| } |
| list.add(new DependencyTail(ref.other(), ref.isOptional())); |
| } |
| } |
| } finally { |
| s.close(); |
| } |
| |
| // parse the actual dependencies file, checking each dependency |
| // against the expected list. |
| boolean fail = false; |
| s = new Scanner(new FileInputStream(args[1])); |
| try { |
| while (s.hasNextLine()) { |
| Dependency dep = Dependency.fromString(s.nextLine()); |
| |
| // check if this dependency is expected |
| List<DependencyTail> list = expected.get(dep.module()); |
| DependencyTail tail = null; |
| if (list != null) { |
| for (DependencyTail t: list) { |
| if (t.module().equals(dep.other())) { |
| tail = t; |
| break; |
| } |
| } |
| } |
| if (tail == null) { |
| System.err.println("Unexpected dependency: " + dep); |
| fail = true; |
| } else { |
| // hard dependency when optional dependency is expected |
| if (tail.isOptional() != dep.isOptional()) { |
| if (tail.isOptional()) { |
| System.err.println("Unexpected dependency: " + dep); |
| fail = true; |
| } |
| } |
| } |
| } |
| } finally { |
| s.close(); |
| } |
| |
| if (fail) |
| throw new RuntimeException("Unexpected dependencies found"); |
| } |
| } |