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 ;
6766import org .openide .filesystems .FileSystem ;
6867import org .openide .filesystems .FileSystem .AtomicAction ;
6968import org .openide .filesystems .FileUtil ;
69+ import org .netbeans .DepUtil ;
7070import org .openide .modules .Dependency ;
7171import org .openide .modules .InstalledFileLocator ;
7272import org .openide .modules .SpecificationVersion ;
@@ -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,72 @@ 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+ throw new IOException ("negative count" );
642+ } else if (depCount == 0 ) {
643+ return Set .of ();
644+ }
645+ Set <Dependency > deps = new HashSet <>((int ) Math .ceil (depCount / 0.75 ));
646+ for (int i = 0 ; i < depCount ; i ++) {
647+ deps .add (DepUtil .read (is ));
648+ }
649+ return deps ;
650+ }
651+
652+ /// @see #computeProperties(org.netbeans.Module)
653+ private static Map <String , Object > readProps (DataInputStream is ) throws IOException {
654+ int propCount = is .readByte ();
655+ if (propCount < 0 ) {
656+ throw new IOException ("negative count" );
657+ }
658+ Map <String , Object > props = new HashMap <>((int ) Math .ceil (propCount / 0.75 ));
659+ for (int i = 0 ; i < propCount ; i ++) {
660+ String entry = is .readUTF ();
661+ int split = entry .indexOf ('=' ); // ok, since keys don't contain '='
662+ String key = entry .substring (0 , split );
663+ String value = entry .substring (split + 1 , entry .length ());
664+ // must match computeProperties()
665+ try {
666+ Object val = switch (key ) {
667+ case "name" , "jar" -> value ;
668+ case "enabled" , "autoload" , "eager" , "reloadable" -> Boolean .valueOf (value );
669+ case "startlevel" -> Integer .valueOf (value );
670+ default -> throw new IOException ("unknown key " + key );
671+ };
672+ props .put (key , val );
673+ } catch (IllegalArgumentException ex ) {
674+ throw new IOException ("unexpected value" , ex );
675+ }
676+ }
677+ sanityCheckStatus (props );
678+ return props ;
679+ }
680+
654681 final void writeCache () {
655682 Stamps .getModulesJARs ().scheduleSave (this , "all-modules.dat" , false );
656683 }
@@ -661,14 +688,23 @@ public void cacheReady() {
661688
662689 @ Override
663690 public void flushCaches (DataOutputStream os ) throws IOException {
664- ObjectOutputStream oss = new ObjectOutputStream (os );
665691 for (Module m : mgr .getModules ()) {
666692 if (m .isFixed ()) {
667693 continue ;
668694 }
669- Map <String , Object > prop = computeProperties (m );
670- writeStatus (prop , oss );
671- oss .writeObject (m .getDependencies ());
695+ // props
696+ Map <String , Object > props = computeProperties (m );
697+ os .writeByte (props .size ());
698+ for (Entry <String , Object > prop : props .entrySet ()) {
699+ os .writeUTF (prop .getKey () + "=" + prop .getValue ());
700+ }
701+
702+ // deps
703+ Set <Dependency > deps = m .getDependencies ();
704+ os .writeInt (deps .size ());
705+ for (Dependency dep : deps ) {
706+ DepUtil .write (dep , os );
707+ }
672708 }
673709 }
674710
@@ -694,7 +730,7 @@ private void writeStatus(Map<String, Object> m, OutputStream os) throws IOExcept
694730
695731 // Use TreeMap to sort the keys by name; since the module status files might
696732 // be version-controlled we want to avoid gratuitous format changes.
697- for (Map .Entry <String , Object > entry : new TreeMap <String , Object >(m ).entrySet ()) {
733+ for (Map .Entry <String , Object > entry : new TreeMap <>(m ).entrySet ()) {
698734 String name = entry .getKey ();
699735 if (
700736 name .equals ("name" ) || // NOI18N
@@ -749,11 +785,8 @@ public void run() throws IOException {
749785 LOG .fine ("ModuleList: (re)writing " + nue .file );
750786 FileLock lock = nue .file .lock ();
751787 try {
752- OutputStream os = nue .file .getOutputStream (lock );
753- try {
788+ try (OutputStream os = nue .file .getOutputStream (lock )) {
754789 writeStatus (nue .diskProps , os );
755- } finally {
756- os .close ();
757790 }
758791 } finally {
759792 lock .releaseLock ();
@@ -944,12 +977,14 @@ private void moduleChanged(Module m, DiskStatus status) {
944977 }
945978 }
946979
947- /** Compute what properties we would want to store in XML
980+ /**
981+ * Compute what properties we would want to store in XML (or the startup cache)
948982 * for this module. I.e. 'name', 'reloadable', etc.
983+ * @see #readProps(java.io.DataInputStream)
949984 */
950- private Map <String ,Object > computeProperties (Module m ) {
985+ private Map <String , Object > computeProperties (Module m ) {
951986 if (m .isFixed () || ! m .isValid ()) throw new IllegalArgumentException ("fixed or invalid: " + m ); // NOI18N
952- Map <String ,Object > p = new HashMap <String , Object >( );
987+ Map <String , Object > p = new HashMap <>( 8 );
953988 p .put ("name" , m .getCodeNameBase ()); // NOI18N
954989 if (!m .isAutoload () && !m .isEager ()) {
955990 p .put ("enabled" , m .isEnabled ()); // NOI18N
@@ -960,8 +995,7 @@ private Map<String,Object> computeProperties(Module m) {
960995 if (m .getStartLevel () > 0 ) {
961996 p .put ("startlevel" , m .getStartLevel ()); // NOI18N
962997 }
963- if (m .getHistory () instanceof ModuleHistory ) {
964- ModuleHistory hist = (ModuleHistory ) m .getHistory ();
998+ if (m .getHistory () instanceof ModuleHistory hist ) {
965999 p .put ("jar" , hist .getJar ()); // NOI18N
9661000 }
9671001 return p ;
@@ -990,6 +1024,7 @@ private final class Listener implements PropertyChangeListener, ErrorHandler, En
9901024 // Property change coming from ModuleManager or some known Module.
9911025
9921026 private boolean listening = true ;
1027+ @ Override
9931028 public void propertyChange (PropertyChangeEvent evt ) {
9941029 if (! triggered ) throw new IllegalStateException ("Property change before trigger()" ); // NOI18N
9951030 // REMEMBER this is inside *read* mutex, it is forbidden to even attempt
@@ -1036,15 +1071,19 @@ public void propertyChange(PropertyChangeEvent evt) {
10361071
10371072 // SAX stuff.
10381073
1074+ @ Override
10391075 public void warning (SAXParseException e ) throws SAXException {
10401076 LOG .log (Level .WARNING , null , e );
10411077 }
1078+ @ Override
10421079 public void error (SAXParseException e ) throws SAXException {
10431080 throw e ;
10441081 }
1082+ @ Override
10451083 public void fatalError (SAXParseException e ) throws SAXException {
10461084 throw e ;
10471085 }
1086+ @ Override
10481087 public InputSource resolveEntity (String pubid , String sysid ) throws SAXException , IOException {
10491088 if (pubid .equals (PUBLIC_ID )) {
10501089 if (VALIDATE_XML ) {
@@ -1062,6 +1101,7 @@ public InputSource resolveEntity(String pubid, String sysid) throws SAXException
10621101
10631102 // Changes in Modules/ folder.
10641103
1104+ @ Override
10651105 public void fileDeleted (FileEvent ev ) {
10661106 if (isOurs (ev )) {
10671107 if (LOG .isLoggable (Level .FINE )) {
@@ -1073,6 +1113,7 @@ public void fileDeleted(FileEvent ev) {
10731113 fileDeleted0 (fo .getName (), fo .getExt ()/*, ev.getTime()*/ );
10741114 }
10751115
1116+ @ Override
10761117 public void fileDataCreated (FileEvent ev ) {
10771118 if (isOurs (ev )) {
10781119 if (LOG .isLoggable (Level .FINE )) {
@@ -1084,6 +1125,7 @@ public void fileDataCreated(FileEvent ev) {
10841125 fileCreated0 (fo .getName (), fo .getExt ()/*, ev.getTime()*/ );
10851126 }
10861127
1128+ @ Override
10871129 public void fileRenamed (FileRenameEvent ev ) {
10881130 if (isOurs (ev )) {
10891131 throw new IllegalStateException ("I don't rename anything! " + ev ); // NOI18N
@@ -1124,6 +1166,7 @@ private void fileDeleted0(String name, String ext/*, long time*/) {
11241166 } // else ignore
11251167 }
11261168
1169+ @ Override
11271170 public void fileChanged (FileEvent ev ) {
11281171 if (isOurs (ev )) {
11291172 if (LOG .isLoggable (Level .FINE )) {
@@ -1150,9 +1193,11 @@ public void fileChanged(FileEvent ev) {
11501193 } // else ignore
11511194 }
11521195
1196+ @ Override
11531197 public void fileFolderCreated (FileEvent ev ) {
11541198 // ignore
11551199 }
1200+ @ Override
11561201 public void fileAttributeChanged (FileAttributeEvent ev ) {
11571202 // ignore
11581203 }
@@ -1549,7 +1594,7 @@ public void run() {
15491594 Map <String , Map <String , Object >> cache = readCache ();
15501595 String [] names ;
15511596 if (cache != null ) {
1552- names = cache .keySet ().toArray (new String [cache . size ()] );
1597+ names = cache .keySet ().toArray (String []:: new );
15531598 } else {
15541599 FileObject [] children = folder .getChildren ();
15551600 List <String > arr = new ArrayList <String >(children .length );
@@ -1572,7 +1617,7 @@ public void run() {
15721617 LOG .fine ("Strange file encountered in modules folder: " + f );
15731618 }
15741619 }
1575- names = arr .toArray (new String [0 ] );
1620+ names = arr .toArray (String []:: new );
15761621 }
15771622 ev .log (Events .MODULES_FILE_SCANNED , names .length );
15781623 XMLReader reader = null ;
@@ -1635,12 +1680,12 @@ public void run() {
16351680 }
16361681 ModuleHistory history = new ModuleHistory (jar , "loaded from " + f ); // NOI18N
16371682 Boolean reloadableB = (Boolean ) props .get ("reloadable" ); // NOI18N
1638- boolean reloadable = reloadableB != null ? reloadableB . booleanValue () : false ;
1639- boolean enabled = enabledB != null ? enabledB . booleanValue () : false ;
1683+ boolean reloadable = reloadableB != null ? reloadableB : false ;
1684+ boolean enabled = enabledB != null ? enabledB : false ;
16401685 Boolean autoloadB = (Boolean ) props .get ("autoload" ); // NOI18N
1641- boolean autoload = autoloadB != null ? autoloadB . booleanValue () : false ;
1686+ boolean autoload = autoloadB != null ? autoloadB : false ;
16421687 Boolean eagerB = (Boolean ) props .get ("eager" ); // NOI18N
1643- boolean eager = eagerB != null ? eagerB . booleanValue () : false ;
1688+ boolean eager = eagerB != null ? eagerB : false ;
16441689 NbInstaller .register (name , props .get ("deps" )); // NOI18N
16451690 Integer startLevel = (Integer )props .get ("startlevel" ); // NOI18N
16461691 Module m = createModule (jarFile , history , reloadable , autoload , eager , startLevel );
0 commit comments