1 /* 2 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package org.openjdk.jigsaw.cli; 27 28 import java.lang.module.*; 29 import java.io.*; 30 import java.util.*; 31 import java.util.regex.*; 32 33 import static java.lang.System.out; 34 import static java.lang.System.err; 35 36 import org.openjdk.jigsaw.*; 37 import org.openjdk.internal.joptsimple.*; 38 39 40 /** 41 * Commands shared by multiple CLIs 42 */ 43 44 class Commands { 45 46 private static JigsawModuleSystem jms 47 = JigsawModuleSystem.instance(); 48 49 private static void formatCommaList(PrintStream out, 50 String prefix, 51 Collection<?> list) 52 { 53 if (list.isEmpty()) 54 return; 55 out.format(" %s", prefix); 56 boolean first = true; 57 for (Object ob : list) { 58 if (first) { 59 out.format(" %s", ob); 60 first = false; 61 } else { 62 out.format(", %s", ob); 63 } 64 } 65 out.format("%n"); 66 } 67 68 private static void formatModuleView(PrintStream out, 69 ModuleView view, 70 String indent) { 71 formatCommaList(out, indent + "provides", 72 view.aliases()); 73 formatCommaList(out, indent + "permits", 74 view.permits()); 75 Map<String,Set<String>> services = view.services(); 76 for (Map.Entry<String,Set<String>> entry: services.entrySet()) { 77 String sn = entry.getKey(); 78 for (String impl: entry.getValue()) { 79 out.format("%s provides service %s with %s%n", indent, sn, impl); 80 } 81 } 82 83 if (!view.exports().isEmpty()) { 84 out.format(" %sexports%n", indent); 85 Set<String> exports = new TreeSet<>(view.exports()); 86 for (String pn : exports) { 87 out.format(" %s %s%n", indent, pn); 88 } 89 } 90 } 91 92 private static void listCommand(Catalog cat, ModuleIdQuery midq, 93 boolean parents, boolean verbose) 94 throws Command.Exception 95 { 96 int n = 0; 97 try { 98 List<ModuleId> mids; 99 if (midq == null) { 100 mids = parents ? cat.listDeclaringModuleIds() : cat.listLocalDeclaringModuleIds(); 101 } else { 102 List<ModuleId> list = parents ? cat.listModuleIds() 103 : cat.listLocalModuleIds(); 104 mids = new ArrayList<>(); 105 for (ModuleId mid : list) { 106 if (midq.matches(mid)) 107 mids.add(mid); 108 } 109 } 110 for (ModuleId mid : mids) { 111 ModuleInfo mi = cat.readModuleInfo(mid); 112 if (verbose) { 113 out.format("%n"); 114 } 115 116 // print module and its views 117 out.format("%s%n", mi.id()); 118 n++; 119 if (verbose) { 120 for (ViewDependence d : mi.requiresModules()) { 121 out.format(" %s%n", d); 122 } 123 for (ServiceDependence sd: mi.requiresServices()) { 124 out.format(" %s%n", sd); 125 } 126 formatModuleView(out, mi.defaultView(), ""); 127 128 for (ModuleView mv : mi.views()) { 129 if (mv == mi.defaultView()) 130 continue; 131 132 out.format(" view %s%n", mv.id().name()); 133 formatModuleView(out, mv, " "); 134 } 135 } 136 } 137 } catch (IOException x) { 138 throw new Command.Exception(x); 139 } 140 if (verbose && n > 0) 141 out.format("%n"); 142 } 143 144 private static Catalog compose(ModuleIdQuery midq, 145 List<? extends Catalog> cats) 146 throws IOException 147 { 148 149 final Set<ModuleId> modules = new HashSet<>(); 150 final Map<ModuleId,ModuleInfo> mods = new HashMap<>(); 151 for (Catalog c : cats) { 152 List<ModuleId> mids = c.listDeclaringModuleIds(); 153 modules.addAll(mids); 154 for (ModuleId mid : mids) { 155 if (mods.containsKey(mid)) 156 continue; 157 158 ModuleInfo mi = c.readModuleInfo(mid); 159 for (ModuleView mv : mi.views()) { 160 mods.put(mid, mi); 161 for (ModuleId alias : mv.aliases()) { 162 mods.put(alias, mi); 163 } 164 } 165 } 166 } 167 168 return new Catalog() { 169 170 public String name() { return "composite"; } 171 172 public Catalog parent() { return null; } 173 174 protected void gatherLocalModuleIds(String moduleName, 175 Set<ModuleId> ids) 176 throws IOException 177 { 178 ids.addAll(mods.keySet()); 179 } 180 181 protected void gatherLocalDeclaringModuleIds(Set<ModuleId> mids) 182 throws IOException 183 { 184 mids.addAll(modules); 185 } 186 187 protected ModuleInfo readLocalModuleInfo(ModuleId mid) 188 throws IOException 189 { 190 return mods.get(mid); 191 } 192 193 }; 194 195 } 196 197 // ## There must be a better way to do this! 198 199 static class ListLibrary extends Command<SimpleLibrary> { 200 protected void go(SimpleLibrary lib) 201 throws Command.Exception 202 { 203 ModuleIdQuery midq; 204 if (hasArg()) 205 midq = jms.parseModuleIdQuery(takeArg()); 206 else 207 midq = null; 208 finishArgs(); 209 boolean parents = opts.has("p"); 210 Catalog cat = lib; 211 try { 212 if (opts.has("R")) 213 cat = compose(midq, lib.repositoryList().repositories()); 214 } catch (IOException x) { 215 throw new Command.Exception(x); 216 } 217 listCommand(cat, midq, parents, verbose); 218 } 219 } 220 221 static class ListRepository extends Command<Repository> { 222 protected void go(Repository repo) 223 throws Command.Exception 224 { 225 ModuleIdQuery midq; 226 if (hasArg()) 227 midq = jms.parseModuleIdQuery(takeArg()); 228 else 229 midq = null; 230 finishArgs(); 231 listCommand(repo, midq, false, verbose); 232 } 233 } 234 235 }