2424import java .io .BufferedInputStream ;
2525import java .io .ByteArrayInputStream ;
2626import java .io .CharArrayWriter ;
27+ import java .io .DataInputStream ;
2728import java .io .DataOutputStream ;
2829import java .io .File ;
2930import java .io .FileNotFoundException ;
3031import java .io .IOException ;
3132import java .io .InputStream ;
32- import java .io .ObjectInputStream ;
33- import java .io .ObjectOutputStream ;
3433import java .io .OutputStream ;
3534import java .io .OutputStreamWriter ;
3635import java .io .PushbackInputStream ;
5150import java .util .jar .JarFile ;
5251import java .util .logging .Level ;
5352import java .util .logging .Logger ;
53+ import java .util .stream .Collectors ;
5454import org .netbeans .DuplicateException ;
5555import org .netbeans .Events ;
5656import org .netbeans .InvalidException ;
@@ -111,7 +111,7 @@ final class ModuleList implements Stamps.Updater {
111111 /** to fire events with */
112112 private final Events ev ;
113113 /** map from code name (base)s to statuses of modules on disk */
114- private final Map <String ,DiskStatus > statuses = new HashMap <String , DiskStatus >(100 );
114+ private final Map <String , DiskStatus > statuses = new HashMap <>(100 );
115115 /** whether the initial round has been triggered or not */
116116 private boolean triggered = false ;
117117 /** listener for changes in modules, etc.; see comment on class Listener */
@@ -197,8 +197,7 @@ private File findJarByName(String jar, String name) throws IOException {
197197 for (File candidate : jars ) {
198198 int candidateMajor = -1 ;
199199 SpecificationVersion candidateSpec = null ;
200- JarFile jf = new JarFile (candidate );
201- try {
200+ try (JarFile jf = new JarFile (candidate )) {
202201 java .util .jar .Attributes attr = jf .getManifest ().getMainAttributes ();
203202 String codename = attr .getValue ("OpenIDE-Module" );
204203 if (codename != null ) {
@@ -211,8 +210,6 @@ private File findJarByName(String jar, String name) throws IOException {
211210 if (sv != null ) {
212211 candidateSpec = new SpecificationVersion (sv );
213212 }
214- } finally {
215- jf .close ();
216213 }
217214 if (newest == null || candidateMajor > major || (spec != null && candidateSpec != null && candidateSpec .compareTo (spec ) > 0 )) {
218215 newest = candidate ;
@@ -434,7 +431,10 @@ private Object processStatusParam(String k, String v) throws NumberFormatExcepti
434431
435432 /** Just checks that all the right stuff is there.
436433 */
437- private void sanityCheckStatus (Map <String ,Object > m ) throws IOException {
434+ private static void sanityCheckStatus (Map <String , Object > m ) throws IOException {
435+ if (m .isEmpty ()) {
436+ throw new IOException ("Must define properties" ); // NOI18N
437+ }
438438 String jar = (String ) m .get ("jar" ); // NOI18N
439439 if (jar == null ) {
440440 throw new IOException ("Must define jar param" ); // NOI18N
@@ -612,45 +612,62 @@ private String readTo(InputStream is, char delim) throws IOException {
612612 }
613613 }
614614
615- final Map <String ,Map <String ,Object >> readCache () {
615+ final Map <String , Map <String , Object >> readCache () {
616616 InputStream is = Stamps .getModulesJARs ().asStream ("all-modules.dat" ); // NOI18N
617617 if (is == null ) {
618618 // schedule write for later
619619 writeCache ();
620620 return null ;
621621 }
622622 LOG .log (Level .FINEST , "Reading cache all-modules.dat" );
623- try {
624- ObjectInputStream ois = new ObjectInputStream (is );
625-
626- Map <String ,Map <String ,Object >> ret = new HashMap <String , Map <String , Object >>(1333 );
627- while (is .available () > 0 ) {
628- Map <String , Object > prop = readStatus (ois , false );
629- if (prop == null ) {
630- LOG .log (Level .CONFIG , "Cache is invalid all-modules.dat" );
631- return null ;
632- }
633- Set <?> deps ;
634- try {
635- deps = (Set <?>) ois .readObject ();
636- } catch (ClassNotFoundException ex ) {
637- throw new IOException (ex );
638- }
639- prop .put ("deps" , deps );
640- String cnb = (String )prop .get ("name" ); // NOI18N
641- ret .put (cnb , prop );
623+ try (DataInputStream dis = new DataInputStream (is )) {
624+ Map <String , Map <String , Object >> cache = new HashMap <>(1333 );
625+ while (dis .available () > 0 ) {
626+ Map <String , Object > props = readProps (dis );
627+ props .put ("deps" , readDeps (dis ));
628+ cache .put ((String ) props .get ("name" ), props );
642629 }
643-
644-
645- is .close ();
646- return ret ;
630+ return cache ;
647631 } catch (IOException ex ) {
648632 LOG .log (Level .INFO , "Cannot read cache" , ex );
649633 writeCache ();
650634 return null ;
651635 }
652636 }
653637
638+ private static Set <Dependency > readDeps (DataInputStream is ) throws IOException {
639+ int depCount = is .readInt ();
640+ if (depCount == 0 ) {
641+ return Set .of ();
642+ }
643+ Set <Dependency > deps = new HashSet <>((int ) Math .ceil (depCount / 0.75 ));
644+ for (int i = 0 ; i < depCount ; i ++) {
645+ deps .add (Dependency .read (is ));
646+ }
647+ return deps ;
648+ }
649+
650+ private static Map <String , Object > readProps (DataInputStream is ) throws IOException {
651+ Map <String , Object > props = new HashMap <>(8 );
652+ for (String str : is .readUTF ().split ("," )) {
653+ String [] entry = str .split ("=" );
654+ // must match computeProperties()
655+ try {
656+ Object val = switch (entry [0 ]) {
657+ case "name" , "jar" -> entry [1 ];
658+ case "enabled" , "autoload" , "eager" , "reloadable" -> Boolean .valueOf (entry [1 ]);
659+ case "startlevel" -> Integer .valueOf (entry [1 ]);
660+ default -> throw new IOException ("unknown key " + entry [0 ]);
661+ };
662+ props .put (entry [0 ], val );
663+ } catch (IllegalArgumentException | ArrayIndexOutOfBoundsException ex ) {
664+ throw new IOException ("unexpected value" , ex );
665+ }
666+ }
667+ sanityCheckStatus (props );
668+ return props ;
669+ }
670+
654671 final void writeCache () {
655672 Stamps .getModulesJARs ().scheduleSave (this , "all-modules.dat" , false );
656673 }
@@ -661,14 +678,23 @@ public void cacheReady() {
661678
662679 @ Override
663680 public void flushCaches (DataOutputStream os ) throws IOException {
664- ObjectOutputStream oss = new ObjectOutputStream (os );
665681 for (Module m : mgr .getModules ()) {
666682 if (m .isFixed ()) {
667683 continue ;
668684 }
669- Map <String , Object > prop = computeProperties (m );
670- writeStatus (prop , oss );
671- oss .writeObject (m .getDependencies ());
685+ // props
686+ String list = computeProperties (m ).entrySet ()
687+ .stream ()
688+ .map (e -> e .getKey () + "=" + e .getValue ())
689+ .collect (Collectors .joining ("," ));
690+ os .writeUTF (list );
691+
692+ // deps
693+ Set <Dependency > deps = m .getDependencies ();
694+ os .writeInt (deps .size ());
695+ for (Dependency dep : deps ) {
696+ dep .write (os );
697+ }
672698 }
673699 }
674700
@@ -694,7 +720,7 @@ private void writeStatus(Map<String, Object> m, OutputStream os) throws IOExcept
694720
695721 // Use TreeMap to sort the keys by name; since the module status files might
696722 // be version-controlled we want to avoid gratuitous format changes.
697- for (Map .Entry <String , Object > entry : new TreeMap <String , Object >(m ).entrySet ()) {
723+ for (Map .Entry <String , Object > entry : new TreeMap <>(m ).entrySet ()) {
698724 String name = entry .getKey ();
699725 if (
700726 name .equals ("name" ) || // NOI18N
@@ -749,11 +775,8 @@ public void run() throws IOException {
749775 LOG .fine ("ModuleList: (re)writing " + nue .file );
750776 FileLock lock = nue .file .lock ();
751777 try {
752- OutputStream os = nue .file .getOutputStream (lock );
753- try {
778+ try (OutputStream os = nue .file .getOutputStream (lock )) {
754779 writeStatus (nue .diskProps , os );
755- } finally {
756- os .close ();
757780 }
758781 } finally {
759782 lock .releaseLock ();
@@ -947,9 +970,9 @@ private void moduleChanged(Module m, DiskStatus status) {
947970 /** Compute what properties we would want to store in XML
948971 * for this module. I.e. 'name', 'reloadable', etc.
949972 */
950- private Map <String ,Object > computeProperties (Module m ) {
973+ private Map <String , Object > computeProperties (Module m ) {
951974 if (m .isFixed () || ! m .isValid ()) throw new IllegalArgumentException ("fixed or invalid: " + m ); // NOI18N
952- Map <String ,Object > p = new HashMap <String , Object >( );
975+ Map <String , Object > p = new HashMap <>( 8 );
953976 p .put ("name" , m .getCodeNameBase ()); // NOI18N
954977 if (!m .isAutoload () && !m .isEager ()) {
955978 p .put ("enabled" , m .isEnabled ()); // NOI18N
@@ -960,8 +983,7 @@ private Map<String,Object> computeProperties(Module m) {
960983 if (m .getStartLevel () > 0 ) {
961984 p .put ("startlevel" , m .getStartLevel ()); // NOI18N
962985 }
963- if (m .getHistory () instanceof ModuleHistory ) {
964- ModuleHistory hist = (ModuleHistory ) m .getHistory ();
986+ if (m .getHistory () instanceof ModuleHistory hist ) {
965987 p .put ("jar" , hist .getJar ()); // NOI18N
966988 }
967989 return p ;
@@ -990,6 +1012,7 @@ private final class Listener implements PropertyChangeListener, ErrorHandler, En
9901012 // Property change coming from ModuleManager or some known Module.
9911013
9921014 private boolean listening = true ;
1015+ @ Override
9931016 public void propertyChange (PropertyChangeEvent evt ) {
9941017 if (! triggered ) throw new IllegalStateException ("Property change before trigger()" ); // NOI18N
9951018 // REMEMBER this is inside *read* mutex, it is forbidden to even attempt
@@ -1036,15 +1059,19 @@ public void propertyChange(PropertyChangeEvent evt) {
10361059
10371060 // SAX stuff.
10381061
1062+ @ Override
10391063 public void warning (SAXParseException e ) throws SAXException {
10401064 LOG .log (Level .WARNING , null , e );
10411065 }
1066+ @ Override
10421067 public void error (SAXParseException e ) throws SAXException {
10431068 throw e ;
10441069 }
1070+ @ Override
10451071 public void fatalError (SAXParseException e ) throws SAXException {
10461072 throw e ;
10471073 }
1074+ @ Override
10481075 public InputSource resolveEntity (String pubid , String sysid ) throws SAXException , IOException {
10491076 if (pubid .equals (PUBLIC_ID )) {
10501077 if (VALIDATE_XML ) {
@@ -1062,6 +1089,7 @@ public InputSource resolveEntity(String pubid, String sysid) throws SAXException
10621089
10631090 // Changes in Modules/ folder.
10641091
1092+ @ Override
10651093 public void fileDeleted (FileEvent ev ) {
10661094 if (isOurs (ev )) {
10671095 if (LOG .isLoggable (Level .FINE )) {
@@ -1073,6 +1101,7 @@ public void fileDeleted(FileEvent ev) {
10731101 fileDeleted0 (fo .getName (), fo .getExt ()/*, ev.getTime()*/ );
10741102 }
10751103
1104+ @ Override
10761105 public void fileDataCreated (FileEvent ev ) {
10771106 if (isOurs (ev )) {
10781107 if (LOG .isLoggable (Level .FINE )) {
@@ -1084,6 +1113,7 @@ public void fileDataCreated(FileEvent ev) {
10841113 fileCreated0 (fo .getName (), fo .getExt ()/*, ev.getTime()*/ );
10851114 }
10861115
1116+ @ Override
10871117 public void fileRenamed (FileRenameEvent ev ) {
10881118 if (isOurs (ev )) {
10891119 throw new IllegalStateException ("I don't rename anything! " + ev ); // NOI18N
@@ -1124,6 +1154,7 @@ private void fileDeleted0(String name, String ext/*, long time*/) {
11241154 } // else ignore
11251155 }
11261156
1157+ @ Override
11271158 public void fileChanged (FileEvent ev ) {
11281159 if (isOurs (ev )) {
11291160 if (LOG .isLoggable (Level .FINE )) {
@@ -1150,9 +1181,11 @@ public void fileChanged(FileEvent ev) {
11501181 } // else ignore
11511182 }
11521183
1184+ @ Override
11531185 public void fileFolderCreated (FileEvent ev ) {
11541186 // ignore
11551187 }
1188+ @ Override
11561189 public void fileAttributeChanged (FileAttributeEvent ev ) {
11571190 // ignore
11581191 }
@@ -1549,7 +1582,7 @@ public void run() {
15491582 Map <String , Map <String , Object >> cache = readCache ();
15501583 String [] names ;
15511584 if (cache != null ) {
1552- names = cache .keySet ().toArray (new String [cache . size ()] );
1585+ names = cache .keySet ().toArray (String []:: new );
15531586 } else {
15541587 FileObject [] children = folder .getChildren ();
15551588 List <String > arr = new ArrayList <String >(children .length );
@@ -1572,7 +1605,7 @@ public void run() {
15721605 LOG .fine ("Strange file encountered in modules folder: " + f );
15731606 }
15741607 }
1575- names = arr .toArray (new String [0 ] );
1608+ names = arr .toArray (String []:: new );
15761609 }
15771610 ev .log (Events .MODULES_FILE_SCANNED , names .length );
15781611 XMLReader reader = null ;
@@ -1635,12 +1668,12 @@ public void run() {
16351668 }
16361669 ModuleHistory history = new ModuleHistory (jar , "loaded from " + f ); // NOI18N
16371670 Boolean reloadableB = (Boolean ) props .get ("reloadable" ); // NOI18N
1638- boolean reloadable = reloadableB != null ? reloadableB . booleanValue () : false ;
1639- boolean enabled = enabledB != null ? enabledB . booleanValue () : false ;
1671+ boolean reloadable = reloadableB != null ? reloadableB : false ;
1672+ boolean enabled = enabledB != null ? enabledB : false ;
16401673 Boolean autoloadB = (Boolean ) props .get ("autoload" ); // NOI18N
1641- boolean autoload = autoloadB != null ? autoloadB . booleanValue () : false ;
1674+ boolean autoload = autoloadB != null ? autoloadB : false ;
16421675 Boolean eagerB = (Boolean ) props .get ("eager" ); // NOI18N
1643- boolean eager = eagerB != null ? eagerB . booleanValue () : false ;
1676+ boolean eager = eagerB != null ? eagerB : false ;
16441677 NbInstaller .register (name , props .get ("deps" )); // NOI18N
16451678 Integer startLevel = (Integer )props .get ("startlevel" ); // NOI18N
16461679 Module m = createModule (jarFile , history , reloadable , autoload , eager , startLevel );
0 commit comments