private static String toPathString(ModuleIdentifier moduleIdentifier) {
   final StringBuilder builder = new StringBuilder();
   builder.append(moduleIdentifier.getName().replace('.', File.separatorChar));
   builder.append(File.separatorChar).append(moduleIdentifier.getSlot());
   builder.append(File.separatorChar);
   return builder.toString();
 }
 /**
  * Creates a path name from the module identifier. The name always ends with the separator
  * character. A {@code null} identifier will result in no separator being used.
  *
  * @param identifier the module identifier.
  * @param separator the directory separator.
  * @return a path name of the module identifier.
  * @throws IllegalArgumentException if the module identifier is {@code null}.
  */
 public static String baseDirectory(final ModuleIdentifier identifier, final String separator) {
   if (identifier == null) {
     throw new IllegalArgumentException("The module identifier cannot be null.");
   }
   final String namePath = identifier.getName().replace('.', File.separatorChar);
   final StringBuilder baseName = new StringBuilder();
   baseName
       .append(namePath)
       .append((separator == null ? "" : separator))
       .append(identifier.getSlot())
       .append((separator == null ? "" : separator));
   return baseName.toString();
 }
 public ModuleSpec findModule(final ModuleIdentifier identifier, final ModuleLoader delegateLoader)
     throws ModuleLoadException {
   if (identifier.equals(myIdentifier)) {
     // special root JAR module
     Manifest manifest;
     try {
       manifest = jarFile.getManifest();
     } catch (IOException e) {
       throw new ModuleLoadException("Failed to load MANIFEST from JAR", e);
     }
     ModuleSpec.Builder builder = ModuleSpec.build(identifier);
     Attributes mainAttributes = manifest.getMainAttributes();
     String mainClass = mainAttributes.getValue(Attributes.Name.MAIN_CLASS);
     if (mainClass != null) {
       builder.setMainClass(mainClass);
     }
     String classPath = mainAttributes.getValue(Attributes.Name.CLASS_PATH);
     String dependencies = mainAttributes.getValue("Dependencies");
     MultiplePathFilterBuilder pathFilterBuilder = PathFilters.multiplePathFilterBuilder(true);
     pathFilterBuilder.addFilter(PathFilters.is("modules"), false);
     pathFilterBuilder.addFilter(PathFilters.isChildOf("modules"), false);
     builder.addResourceRoot(
         ResourceLoaderSpec.createResourceLoaderSpec(
             new JarFileResourceLoader("", jarFile), pathFilterBuilder.create()));
     String[] classPathEntries =
         classPath == null ? JarModuleLoader.NO_STRINGS : classPath.split("\\s+");
     for (String entry : classPathEntries) {
       if (!entry.isEmpty()) {
         if (entry.startsWith("../")
             || entry.startsWith("./")
             || entry.startsWith("/")
             || entry.contains("/../")) {
           // invalid
           continue;
         }
         if (entry.endsWith("/")) {
           // directory reference
           File root = new File(jarFile.getName(), entry);
           FileResourceLoader resourceLoader = new FileResourceLoader(entry, root);
           builder.addResourceRoot(ResourceLoaderSpec.createResourceLoaderSpec(resourceLoader));
         } else {
           // assume a JAR
           File root = new File(jarFile.getName(), entry);
           JarFile childJarFile;
           try {
             childJarFile = new JarFile(root, true);
           } catch (IOException e) {
             // ignore and continue
             continue;
           }
           builder.addResourceRoot(
               ResourceLoaderSpec.createResourceLoaderSpec(
                   new JarFileResourceLoader(entry, childJarFile)));
         }
       }
     }
     String[] dependencyEntries =
         dependencies == null ? JarModuleLoader.NO_STRINGS : dependencies.split("\\s*,\\s*");
     for (String dependencyEntry : dependencyEntries) {
       boolean optional = false;
       boolean export = false;
       dependencyEntry = dependencyEntry.trim();
       if (!dependencyEntry.isEmpty()) {
         String[] fields = dependencyEntry.split("\\s+");
         if (fields.length < 1) {
           continue;
         }
         String moduleName = fields[0];
         for (int i = 1; i < fields.length; i++) {
           String field = fields[i];
           if (field.equals("optional")) {
             optional = true;
           } else if (field.equals("export")) {
             export = true;
           }
           // else ignored
         }
         builder.addDependency(
             DependencySpec.createModuleDependencySpec(
                 ModuleIdentifier.fromString(moduleName), export, optional));
       }
     }
     builder.addDependency(DependencySpec.createSystemDependencySpec(JDKPaths.JDK));
     builder.addDependency(DependencySpec.createLocalDependencySpec());
     return builder.create();
   } else {
     String namePath = identifier.getName().replace('.', '/');
     String basePath = "modules/" + namePath + "/" + identifier.getSlot();
     JarEntry moduleXmlEntry = jarFile.getJarEntry(basePath + "/module.xml");
     if (moduleXmlEntry == null) {
       return null;
     }
     ModuleSpec moduleSpec;
     try {
       InputStream inputStream = jarFile.getInputStream(moduleXmlEntry);
       try {
         moduleSpec =
             ModuleXmlParser.parseModuleXml(
                 new ModuleXmlParser.ResourceRootFactory() {
                   public ResourceLoader createResourceLoader(
                       final String rootPath, final String loaderPath, final String loaderName)
                       throws IOException {
                     return new JarFileResourceLoader(loaderName, jarFile, loaderPath);
                   }
                 },
                 basePath,
                 inputStream,
                 moduleXmlEntry.getName(),
                 delegateLoader,
                 identifier);
       } finally {
         JarModuleLoader.safeClose(inputStream);
       }
     } catch (IOException e) {
       throw new ModuleLoadException("Failed to read module.xml file", e);
     }
     return moduleSpec;
   }
 }