156 157 @Override 158 protected void gatherLocalDeclaringModuleIds(Set<ModuleId> mids) 159 throws IOException 160 { 161 RepositoryCatalog cat = loadCatalog(); 162 cat.gatherDeclaringModuleIds(mids); 163 } 164 165 @Override 166 protected ModuleInfo readLocalModuleInfo(ModuleId mid) 167 throws IOException 168 { 169 RepositoryCatalog cat = loadCatalog(); 170 Entry e = cat.get(mid); 171 if (e == null) 172 throw new IllegalArgumentException(mid + ": No such module"); 173 return jms.parseModuleInfo(e.mibs); 174 } 175 176 private ModuleType getModuleType(Path modp) { 177 for (ModuleType type: ModuleType.values()) { 178 if (modp.getFileName().toString().endsWith(type.getFileNameSuffix())) { 179 return type; 180 } 181 } 182 183 // ## check magic numbers? 184 throw new IllegalArgumentException(modp + ": Unrecognized module file"); 185 } 186 187 private Path getModulePath(ModuleId mid, String ext) throws IOException { 188 return path.resolve(mid.toString() + ext); 189 } 190 191 private Path getModulePath(ModuleId mid, ModuleType type) throws IOException { 192 return getModulePath(mid, type.getFileNameSuffix()); 193 } 194 195 private Path getModulePath(ModuleId mid) throws IOException { 196 for (ModuleType type: ModuleType.values()) { 197 Path file = getModulePath(mid, type); 198 if (Files.exists(file)) { 199 return file; 200 } 201 } 202 throw new IllegalArgumentException(mid + ": No such module file"); 203 } 204 205 private Entry readModuleInfo(Path modp) throws IOException { 206 return readModuleInfo(modp, getModuleType(modp)); 207 } 208 209 private Entry getModuleInfo(ModuleId mid) throws IOException { 210 return readModuleInfo(getModulePath(mid)); 211 } 212 213 private Entry readModuleInfo(Path modp, ModuleType type) throws IOException { 214 switch(getModuleType(modp)) { 215 case JAR: 216 return readModuleInfoFromModularJarFile(modp); 217 case JMOD: 218 return readModuleInfoFromJmodFile(modp); 219 default: 220 // Cannot occur; 221 throw new AssertionError(); 222 } 223 } 224 225 private Entry readModuleInfoFromJmodFile(Path modp) throws IOException { 226 try (InputStream mfis = Files.newInputStream(modp)) { 227 ValidatingModuleFileParser parser = 228 ModuleFile.newValidatingParser(mfis); 229 230 ModuleFileHeader mfh = parser.fileHeader(); 231 232 // Move to the module info section 233 parser.next(); 234 235 return new Entry(ModuleType.JMOD, 236 toByteArray(parser.getContentStream()), 237 mfh.getCSize(), 238 mfh.getUSize(), 239 mfh.getHashType(), 240 mfh.getHash()); 241 } 242 } 243 244 private Entry readModuleInfoFromModularJarFile(Path modp) throws IOException { 245 File jf = modp.toFile(); 246 try (JarFile j = new JarFile(jf)) { 247 JarEntry moduleInfo = j.getJarEntry(JarFile.MODULEINFO_NAME); 248 if (moduleInfo == null) { 249 throw new IllegalArgumentException(modp + ": not a modular JAR file"); 250 } 251 252 long usize = 0; 253 for (JarEntry je: Collections.list(j.entries())) { 254 if (je.isDirectory()) { 255 continue; 256 } 257 258 usize += je.getSize(); 259 } 260 261 return new Entry(ModuleType.JAR, 262 toByteArray(j, moduleInfo), 263 jf.length(), 264 usize, 265 HashType.SHA256, 266 digest(jf)); 267 } 268 } 269 270 private byte[] digest(File f) throws IOException { 271 MessageDigest md; 272 try { 273 md = MessageDigest.getInstance("SHA-256"); 274 } catch (NoSuchAlgorithmException ex) { 275 // Cannot occur 276 throw new AssertionError(); 277 } 278 279 try (DigestInputStream in = new DigestInputStream(new FileInputStream(f), md)) { 280 byte[] buf = new byte[4096]; 281 while (in.read(buf) != -1) { 319 throw x; 320 } 321 322 // Then update the catalog 323 StreamedRepositoryCatalog cat = loadCatalog(); 324 cat.add(e); 325 storeCatalogWhileLocked(cat); 326 } 327 } 328 329 @Override 330 public InputStream fetch(ModuleId mid) throws IOException { 331 RepositoryCatalog cat = loadCatalog(); 332 Entry e = cat.get(mid); 333 if (e == null) 334 throw new IllegalArgumentException(mid + ": No such module"); 335 return Files.newInputStream(getModulePath(mid, e.type)); 336 } 337 338 @Override 339 public ModuleMetaData fetchMetaData(ModuleId mid) throws IOException { 340 RepositoryCatalog cat = loadCatalog(); 341 Entry e = cat.get(mid); 342 if (e == null) 343 throw new IllegalArgumentException(mid + ": No such module"); 344 return new ModuleMetaData(e.type, e.csize, e.usize); 345 } 346 347 public boolean remove(ModuleId mid) throws IOException { 348 try (FileChannel lc = FileChannel.open(lockp, READ, WRITE)) { 349 lc.lock(); 350 351 // Update catalog first 352 StreamedRepositoryCatalog cat = loadCatalog(); 353 Entry e = cat.get(mid); 354 if (!cat.remove(mid)) 355 return false; 356 storeCatalogWhileLocked(cat); 357 358 // Then remove the file 359 Files.delete(getModulePath(mid, e.type)); 360 } 361 362 return true; 363 } 364 365 private <T> Set<T> del(Set<T> all, Set<T> todel) { 366 Set<T> s = new HashSet<>(all); 367 s.removeAll(todel); 368 return s; 369 } 370 371 private void gatherModuleIdsFromDirectoryWhileLocked(Set<ModuleId> mids) 372 throws IOException 373 { 374 // ## Change to use String joiner when lamda is merged into JDK8 375 StringBuilder sb = new StringBuilder(); 376 sb.append("*.{"); 377 int l = sb.length(); 378 for (ModuleType type: ModuleType.values()) { 379 if (sb.length() > l) { 380 sb.append(","); 381 } 382 sb.append(type.getFileNameExtension()); 383 } 384 sb.append("}"); 385 try (DirectoryStream<Path> ds = Files.newDirectoryStream(path, sb.toString())) { 386 for (Path modp : ds) { 387 ModuleType type = getModuleType(modp); 388 String fn = modp.getFileName().toString(); 389 ModuleId mid 390 = jms.parseModuleId(fn.substring(0, fn.length() - type.getFileNameSuffix().length())); 391 mids.add(mid); 392 } 393 } 394 } 395 396 private static void msg(List<String> msgs, String fmt, Object ... args) { 397 String msg = String.format(fmt, args); 398 if (msgs != null) 399 msgs.add(msg); 400 else 401 out.println(msg); 402 } 403 404 public boolean validate(List<String> msgs) throws IOException { 405 int errors = 0; 406 try (FileChannel lc = FileChannel.open(lockp, READ, WRITE)) { 407 lc.lock(); | 156 157 @Override 158 protected void gatherLocalDeclaringModuleIds(Set<ModuleId> mids) 159 throws IOException 160 { 161 RepositoryCatalog cat = loadCatalog(); 162 cat.gatherDeclaringModuleIds(mids); 163 } 164 165 @Override 166 protected ModuleInfo readLocalModuleInfo(ModuleId mid) 167 throws IOException 168 { 169 RepositoryCatalog cat = loadCatalog(); 170 Entry e = cat.get(mid); 171 if (e == null) 172 throw new IllegalArgumentException(mid + ": No such module"); 173 return jms.parseModuleInfo(e.mibs); 174 } 175 176 private ModuleFileType getModuleFileType(Path modp) { 177 for (ModuleFileType type: ModuleFileType.values()) { 178 if (modp.getFileName().toString().endsWith(type.getFileNameSuffix())) { 179 return type; 180 } 181 } 182 183 // ## check magic numbers? 184 throw new IllegalArgumentException(modp + ": Unrecognized module file"); 185 } 186 187 private Path getModulePath(ModuleId mid, String ext) throws IOException { 188 return path.resolve(mid.toString() + ext); 189 } 190 191 private Path getModulePath(ModuleId mid, ModuleFileType type) throws IOException { 192 return getModulePath(mid, type.getFileNameSuffix()); 193 } 194 195 private Path getModulePath(ModuleId mid) throws IOException { 196 for (ModuleFileType type: ModuleFileType.values()) { 197 Path file = getModulePath(mid, type); 198 if (Files.exists(file)) { 199 return file; 200 } 201 } 202 throw new IllegalArgumentException(mid + ": No such module file"); 203 } 204 205 private Entry readModuleInfo(Path modp) throws IOException { 206 return readModuleInfo(modp, getModuleFileType(modp)); 207 } 208 209 private Entry getModuleInfo(ModuleId mid) throws IOException { 210 return readModuleInfo(getModulePath(mid)); 211 } 212 213 private Entry readModuleInfo(Path modp, ModuleFileType type) throws IOException { 214 switch(getModuleFileType(modp)) { 215 case JAR: 216 return readModuleInfoFromModularJarFile(modp); 217 case JMOD: 218 return readModuleInfoFromJmodFile(modp); 219 default: 220 // Cannot occur; 221 throw new AssertionError(); 222 } 223 } 224 225 private Entry readModuleInfoFromJmodFile(Path modp) throws IOException { 226 try (InputStream mfis = Files.newInputStream(modp)) { 227 ValidatingModuleFileParser parser = 228 ModuleFile.newValidatingParser(mfis); 229 230 ModuleFileHeader mfh = parser.fileHeader(); 231 232 // Move to the module info section 233 parser.next(); 234 235 return new Entry(ModuleFileType.JMOD, 236 mfh.getArchitecture(), 237 toByteArray(parser.getContentStream()), 238 mfh.getCSize(), 239 mfh.getUSize(), 240 mfh.getHashType(), 241 mfh.getHash()); 242 } 243 } 244 245 private Entry readModuleInfoFromModularJarFile(Path modp) throws IOException { 246 File jf = modp.toFile(); 247 try (JarFile j = new JarFile(jf)) { 248 JarEntry moduleInfo = j.getJarEntry(JarFile.MODULEINFO_NAME); 249 if (moduleInfo == null) { 250 throw new IllegalArgumentException(modp + ": not a modular JAR file"); 251 } 252 253 long usize = 0; 254 for (JarEntry je: Collections.list(j.entries())) { 255 if (je.isDirectory()) { 256 continue; 257 } 258 259 usize += je.getSize(); 260 } 261 262 return new Entry(ModuleFileType.JAR, 263 ModuleArchitecture.ANY, 264 toByteArray(j, moduleInfo), 265 jf.length(), 266 usize, 267 HashType.SHA256, 268 digest(jf)); 269 } 270 } 271 272 private byte[] digest(File f) throws IOException { 273 MessageDigest md; 274 try { 275 md = MessageDigest.getInstance("SHA-256"); 276 } catch (NoSuchAlgorithmException ex) { 277 // Cannot occur 278 throw new AssertionError(); 279 } 280 281 try (DigestInputStream in = new DigestInputStream(new FileInputStream(f), md)) { 282 byte[] buf = new byte[4096]; 283 while (in.read(buf) != -1) { 321 throw x; 322 } 323 324 // Then update the catalog 325 StreamedRepositoryCatalog cat = loadCatalog(); 326 cat.add(e); 327 storeCatalogWhileLocked(cat); 328 } 329 } 330 331 @Override 332 public InputStream fetch(ModuleId mid) throws IOException { 333 RepositoryCatalog cat = loadCatalog(); 334 Entry e = cat.get(mid); 335 if (e == null) 336 throw new IllegalArgumentException(mid + ": No such module"); 337 return Files.newInputStream(getModulePath(mid, e.type)); 338 } 339 340 @Override 341 public ModuleFileMetaData fetchMetaData(ModuleId mid) throws IOException { 342 RepositoryCatalog cat = loadCatalog(); 343 Entry e = cat.get(mid); 344 if (e == null) 345 throw new IllegalArgumentException(mid + ": No such module"); 346 return new ModuleFileMetaData(e.type, e.modArch, e.csize, e.usize); 347 } 348 349 public boolean remove(ModuleId mid) throws IOException { 350 try (FileChannel lc = FileChannel.open(lockp, READ, WRITE)) { 351 lc.lock(); 352 353 // Update catalog first 354 StreamedRepositoryCatalog cat = loadCatalog(); 355 Entry e = cat.get(mid); 356 if (!cat.remove(mid)) 357 return false; 358 storeCatalogWhileLocked(cat); 359 360 // Then remove the file 361 Files.delete(getModulePath(mid, e.type)); 362 } 363 364 return true; 365 } 366 367 private <T> Set<T> del(Set<T> all, Set<T> todel) { 368 Set<T> s = new HashSet<>(all); 369 s.removeAll(todel); 370 return s; 371 } 372 373 private void gatherModuleIdsFromDirectoryWhileLocked(Set<ModuleId> mids) 374 throws IOException 375 { 376 // ## Change to use String joiner when lamda is merged into JDK8 377 StringBuilder sb = new StringBuilder(); 378 sb.append("*.{"); 379 int l = sb.length(); 380 for (ModuleFileType type: ModuleFileType.values()) { 381 if (sb.length() > l) { 382 sb.append(","); 383 } 384 sb.append(type.getFileNameExtension()); 385 } 386 sb.append("}"); 387 try (DirectoryStream<Path> ds = Files.newDirectoryStream(path, sb.toString())) { 388 for (Path modp : ds) { 389 ModuleFileType type = getModuleFileType(modp); 390 String fn = modp.getFileName().toString(); 391 ModuleId mid 392 = jms.parseModuleId(fn.substring(0, fn.length() - type.getFileNameSuffix().length())); 393 mids.add(mid); 394 } 395 } 396 } 397 398 private static void msg(List<String> msgs, String fmt, Object ... args) { 399 String msg = String.format(fmt, args); 400 if (msgs != null) 401 msgs.add(msg); 402 else 403 out.println(msg); 404 } 405 406 public boolean validate(List<String> msgs) throws IOException { 407 int errors = 0; 408 try (FileChannel lc = FileChannel.open(lockp, READ, WRITE)) { 409 lc.lock(); |