1616import java .nio .file .StandardCopyOption ;
1717import java .nio .file .attribute .FileTime ;
1818import java .time .Instant ;
19+ import java .util .Arrays ;
20+ import java .util .Collections ;
1921import java .util .Enumeration ;
22+ import java .util .HashSet ;
23+ import java .util .List ;
24+ import java .util .Set ;
2025import java .util .jar .Attributes ;
2126import java .util .jar .JarEntry ;
2227import java .util .jar .JarFile ;
@@ -39,6 +44,7 @@ public class AddModuleInfo {
3944 private static final int DEFAULT_BUFFER_SIZE = 8192 ;
4045 private static final String NO_JVM_VERSION = "base" ;
4146 private static final String MANIFEST_ENTRY_NAME = "META-INF/MANIFEST.MF" ;
47+ private static final String META_INF_VERSIONS_DIR = "META-INF/versions/" ;
4248 private static final String MODULE_INFO_CLASS = "module-info.class" ;
4349
4450 private final String moduleInfoSource ;
@@ -107,18 +113,31 @@ public void run() {
107113 }
108114
109115 boolean versionedModuleInfo = jvmVersion != null ;
110- String versionedModuleInfoClass = "META-INF/versions/" + jvmVersion + "/" + MODULE_INFO_CLASS ;
116+ String moduleInfoDir = versionedModuleInfo ? META_INF_VERSIONS_DIR + jvmVersion + "/" : "" ;
117+ String moduleInfoEntryName = moduleInfoDir + MODULE_INFO_CLASS ;
111118 long lastModifiedTime = toFileTime (timestamp ).toMillis ();
112119
120+ // For compatibility with Eclipse IDE create directory entries for the multi-version dir
121+ // See https://github.com/moditect/moditect/issues/254
122+ List <String > dirEntriesToCreate = Collections .emptyList ();
123+ if (versionedModuleInfo ) {
124+ dirEntriesToCreate = Arrays .asList (META_INF_VERSIONS_DIR , moduleInfoDir );
125+ }
126+
127+ Set <String > overwrittenEntries = new HashSet <>();
128+ overwrittenEntries .add (moduleInfoEntryName );
129+ overwrittenEntries .addAll (dirEntriesToCreate );
130+
113131 // brute force copy all entries
114132 try (JarFile jarFile = new JarFile (inputJar .toAbsolutePath ().toFile ());
115133 JarOutputStream jarout = new JarOutputStream (Files .newOutputStream (tmpOutputJar .toAbsolutePath (), TRUNCATE_EXISTING ))) {
116134 Enumeration <JarEntry > entries = jarFile .entries ();
117135 while (entries .hasMoreElements ()) {
118136 JarEntry inputEntry = entries .nextElement ();
137+ String entryName = inputEntry .getName ();
119138
120139 // manifest requires extra care due to MRJARs
121- if (MANIFEST_ENTRY_NAME .equals (inputEntry . getName ()) && versionedModuleInfo ) {
140+ if (versionedModuleInfo && MANIFEST_ENTRY_NAME .equals (entryName ) ) {
122141 Manifest manifest = jarFile .getManifest ();
123142 if (null == manifest ) {
124143 manifest = new Manifest ();
@@ -128,28 +147,34 @@ public void run() {
128147 ByteArrayOutputStream baos = new ByteArrayOutputStream ();
129148 manifest .write (baos );
130149
131- JarEntry outputEntry = new JarEntry (inputEntry . getName () );
150+ JarEntry outputEntry = new JarEntry (entryName );
132151 outputEntry .setTime (lastModifiedTime );
133152 jarout .putNextEntry (outputEntry );
134153 jarout .write (baos .toByteArray (), 0 , baos .size ());
135154 jarout .closeEntry ();
136155 }
137- else if ((MODULE_INFO_CLASS .equals (inputEntry .getName ()) && !versionedModuleInfo ) ||
138- (versionedModuleInfoClass .equals (inputEntry .getName ()) && versionedModuleInfo )) {
156+ else if (overwrittenEntries .contains (entryName )) {
139157 // skip this entry as we'll overwrite it
140158 }
141159 else {
142160 // copy entry as is, set timestamp
143- JarEntry outputEntry = new JarEntry (inputEntry . getName () );
161+ JarEntry outputEntry = new JarEntry (entryName );
144162 outputEntry .setTime (lastModifiedTime );
145163 jarout .putNextEntry (outputEntry );
146164 copy (jarFile .getInputStream (inputEntry ), jarout );
147165 jarout .closeEntry ();
148166 }
149167 }
150168
169+ for (String dirEntryName : dirEntriesToCreate ) {
170+ JarEntry dirEntry = new JarEntry (dirEntryName );
171+ dirEntry .setTime (lastModifiedTime );
172+ jarout .putNextEntry (dirEntry );
173+ jarout .closeEntry ();
174+ }
175+
151176 // copy module descriptor
152- JarEntry outputEntry = versionedModuleInfo ? new JarEntry (versionedModuleInfoClass ) : new JarEntry ( MODULE_INFO_CLASS );
177+ JarEntry outputEntry = new JarEntry (moduleInfoEntryName );
153178 outputEntry .setTime (lastModifiedTime );
154179 jarout .putNextEntry (outputEntry );
155180 jarout .write (clazz , 0 , clazz .length );
0 commit comments