1 /* 2 * Copyright (c) 2010, 2012 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; 27 28 import java.io.*; 29 import java.lang.module.*; 30 import java.util.*; 31 32 import static org.openjdk.jigsaw.Repository.ModuleFileType; 33 import static org.openjdk.jigsaw.FileConstants.ModuleFile.HashType; 34 35 36 /** 37 * <p> A {@linkplain Repository module repository's} catalog </p> 38 */ 39 40 public abstract class RepositoryCatalog { 41 42 // ## Elements in this class are public only to enable unit tests 43 44 private static final JigsawModuleSystem jms 45 = JigsawModuleSystem.instance(); 46 47 public abstract void gatherDeclaringModuleIds(Set<ModuleId> mids) 48 throws IOException; 49 50 public abstract void gatherModuleIds(String moduleName, Set<ModuleId> mids) 51 throws IOException; 52 53 public abstract void gatherModuleIds(String moduleName, 54 ModuleArchitecture modArch, 55 Set<ModuleId> mids) 56 throws IOException; 57 58 public abstract byte[] readModuleInfoBytes(ModuleId mid) 59 throws IOException; 60 61 static class Entry { 62 63 final ModuleFileType type; 64 final ModuleArchitecture modArch; 65 final byte[] mibs; 66 final long csize; 67 final long usize; 68 final HashType hashType; 69 final byte[] hash; 70 71 Entry(ModuleFileType t, ModuleArchitecture modArch, 72 byte[] m, long cs, long us, HashType ht, byte[] h) { 73 type = t; 74 this.modArch = modArch; 75 mibs = m; 76 csize = cs; 77 usize = us; 78 hashType = ht; 79 hash = h; 80 } 81 82 } 83 84 abstract void add(Entry e); 85 86 public void add(ModuleFileType t, ModuleArchitecture modArch, byte[] mibs, 87 long cs, long us, HashType hashType, byte[] hash) 88 { 89 add(new Entry(t, modArch, mibs, cs, us, hashType, hash)); 90 } 91 92 public abstract boolean remove(ModuleId mid); 93 94 abstract Entry get(ModuleId mid); 95 96 97 /** 98 * <p> A {@linkplain RepositoryCatalog repository catalog} which can be 99 * stored to, and then loaded from, a byte stream </p> 100 */ 101 public static class StreamedRepositoryCatalog 102 extends RepositoryCatalog 103 { 104 105 static final int MAJOR_VERSION = 0; 106 static final int MINOR_VERSION = 0; 107 108 private Map<ModuleId,Entry> modules = new HashMap<>(); 109 private Map<ModuleId,ModuleId> moduleForViewId= new HashMap<>(); 110 111 @Override 112 public void gatherDeclaringModuleIds(Set<ModuleId> mids) { 113 mids.addAll(modules.keySet()); 114 } 115 116 @Override 117 public void gatherModuleIds(String moduleName, Set<ModuleId> mids) { 118 gatherModuleIds(moduleName, ModuleArchitecture.ANY, mids); 119 } 120 121 @Override 122 public void gatherModuleIds(String moduleName, 123 ModuleArchitecture modArch, 124 Set<ModuleId> mids) 125 { 126 for (ModuleId mid : moduleForViewId.keySet()) { 127 if (moduleName == null || mid.name().equals(moduleName)) { 128 Entry entry = get(mid); 129 if (entry.modArch.equals(modArch)) 130 mids.add(mid); 131 } 132 } 133 } 134 135 @Override 136 public byte[] readModuleInfoBytes(ModuleId mid) { 137 Entry e = modules.get(moduleForViewId.get(mid)); 138 return (e != null) ? e.mibs : null; 139 } 140 141 @Override 142 void add(Entry e) { 143 ModuleInfo mi = jms.parseModuleInfo(e.mibs); // ## Need fast path 144 modules.put(mi.id(), e); 145 for (ModuleView mv : mi.views()) { 146 moduleForViewId.put(mv.id(), mi.id()); 147 for (ModuleId alias : mv.aliases()) { 148 moduleForViewId.put(alias, mi.id()); 149 } 150 } 151 } 152 153 @Override 154 public boolean remove(ModuleId mid) { 155 for (Iterator<ModuleId> i = moduleForViewId.values().iterator(); 156 i.hasNext();) 157 { 158 // remove views/aliases defined in the module be removed 159 ModuleId id = i.next(); 160 if (id.equals(mid)) { 161 i.remove(); 162 } 163 } 164 return modules.remove(mid) != null; 165 } 166 167 @Override 168 Entry get(ModuleId mid) { 169 return modules.get(moduleForViewId.get(mid)); 170 } 171 172 /* ## 173 public boolean remove(ModuleIdQuery midq) { 174 int nd = 0; 175 for (Iterator<ModuleId> i = modules.keySet().iterator(); 176 i.hasNext();) 177 { 178 ModuleId mid = i.next(); 179 if (midq.matches(mid)) { 180 i.remove(); 181 nd++; 182 } 183 } 184 return nd != 0; 185 } 186 */ 187 188 private StreamedRepositoryCatalog() { } 189 190 private FileHeader fileHeader() { 191 return (new FileHeader() 192 .type(FileConstants.Type.STREAM_CATALOG) 193 .majorVersion(MAJOR_VERSION) 194 .minorVersion(MINOR_VERSION)); 195 } 196 197 public void store(OutputStream os) throws IOException { 198 OutputStream bos = new BufferedOutputStream(os); 199 try (DataOutputStream out = new DataOutputStream(bos)) { 200 fileHeader().write(out); 201 out.writeInt(modules.size()); 202 for (Map.Entry<ModuleId,Entry> me : modules.entrySet()) { 203 out.writeUTF(me.getKey().toString()); // ## Redundant 204 Entry e = me.getValue(); 205 out.writeUTF(e.type.getFileNameExtension()); 206 out.writeUTF(e.modArch.os()); 207 out.writeUTF(e.modArch.arch()); 208 out.writeLong(e.csize); 209 out.writeLong(e.usize); 210 out.writeShort(e.hashType.value()); 211 out.writeShort(e.hash.length); 212 out.write(e.hash); 213 out.writeShort(e.mibs.length); 214 out.write(e.mibs); 215 } 216 out.writeInt(moduleForViewId.size()); 217 for (Map.Entry<ModuleId,ModuleId> me : moduleForViewId.entrySet()) { 218 out.writeUTF(me.getKey().toString()); 219 out.writeUTF(me.getValue().toString()); 220 } 221 } 222 } 223 224 public StreamedRepositoryCatalog loadStream(InputStream is) 225 throws IOException 226 { 227 BufferedInputStream bis = new BufferedInputStream(is); 228 DataInputStream in = new DataInputStream(bis); 229 FileHeader fh = fileHeader(); 230 fh.read(in); 231 int nms = in.readInt(); 232 for (int i = 0; i < nms; i++) { 233 ModuleId mid = jms.parseModuleId(in.readUTF()); 234 ModuleFileType t = ModuleFileType.fromFileNameExtension(in.readUTF()); 235 ModuleArchitecture modArch = ModuleArchitecture.create(in.readUTF(), 236 in.readUTF()); 237 long cs = in.readLong(); 238 long us = in.readLong(); 239 HashType ht = HashType.valueOf(in.readShort()); 240 int nb = in.readShort(); 241 byte[] hash = new byte[nb]; 242 in.readFully(hash); 243 nb = in.readShort(); 244 byte[] mibs = new byte[nb]; 245 in.readFully(mibs); 246 modules.put(mid, new Entry(t, modArch, mibs, cs, us, ht, hash)); 247 } 248 int nmids = in.readInt(); 249 for (int i = 0; i < nmids; i++) { 250 ModuleId id = jms.parseModuleId(in.readUTF()); 251 ModuleId mid = jms.parseModuleId(in.readUTF()); 252 moduleForViewId.put(id, mid); 253 } 254 return this; 255 } 256 257 } 258 259 public static StreamedRepositoryCatalog load(InputStream in) 260 throws IOException 261 { 262 StreamedRepositoryCatalog src = new StreamedRepositoryCatalog(); 263 if (in != null) { 264 try { 265 src.loadStream(in); 266 } finally { 267 in.close(); 268 } 269 } 270 return src; 271 } 272 273 274 /* 275 276 private static class IndexedRepositoryCatalog { } // ## Later 277 278 static IndexedRepositoryCatalog open(File fn) throws IOException { 279 return new IndexedRepositoryCatalog(...); 280 } 281 282 */ 283 284 } --- EOF ---