Lines 34-39
Link Here
|
34 |
import org.openide.util.Utilities; |
34 |
import org.openide.util.Utilities; |
35 |
import org.openide.util.lookup.InstanceContent; |
35 |
import org.openide.util.lookup.InstanceContent; |
36 |
import java.beans.BeanInfo; |
36 |
import java.beans.BeanInfo; |
|
|
37 |
import java.util.jar.Manifest; |
37 |
import org.openide.ErrorManager; |
38 |
import org.openide.ErrorManager; |
38 |
import org.openide.execution.NbClassPath; |
39 |
import org.openide.execution.NbClassPath; |
39 |
|
40 |
|
Lines 257-262
Link Here
|
257 |
ev.log(Events.PERF_END, "NbInstaller.load - ModuleInstalls"); // NOI18N |
258 |
ev.log(Events.PERF_END, "NbInstaller.load - ModuleInstalls"); // NOI18N |
258 |
|
259 |
|
259 |
ev.log(Events.FINISH_LOAD, modules); |
260 |
ev.log(Events.FINISH_LOAD, modules); |
|
|
261 |
|
262 |
maybeSaveManifestCache(); |
260 |
} |
263 |
} |
261 |
|
264 |
|
262 |
public void unload(List modules) { |
265 |
public void unload(List modules) { |
Lines 1016-1021
Link Here
|
1016 |
Iterator it = jars.iterator(); |
1019 |
Iterator it = jars.iterator(); |
1017 |
while (it.hasNext()) { |
1020 |
while (it.hasNext()) { |
1018 |
cp.add(((File)it.next()).getAbsolutePath() + qualification); |
1021 |
cp.add(((File)it.next()).getAbsolutePath() + qualification); |
|
|
1022 |
} |
1023 |
} |
1024 |
|
1025 |
// Manifest caching: #26786. |
1026 |
|
1027 |
/** The actual file where the manifest cache is stored, |
1028 |
* or null if it will not be used. |
1029 |
* Binary format: |
1030 |
* Sequence of records, one per cached manifest; no particular order. |
1031 |
* Record: |
1032 |
* 1. Absolute JAR path, UTF-8. |
1033 |
* 2. Null byte. |
1034 |
* 3. Last modification time of JAR, System.currentTimeMillis format, big-endian (8-byte long). |
1035 |
* 4. The manifest body. |
1036 |
* 5. Null byte. |
1037 |
*/ |
1038 |
private File manifestCacheFile; |
1039 |
|
1040 |
/** While true, try to use the manifest cache. |
1041 |
* So (non-reloadable) JARs scanned during startup will have their manifests cached. |
1042 |
* After the primary set of modules has been scanned, this will be set to false. |
1043 |
* Initially true, unless -J-Dnetbeans.cache.manifests=false is specified, |
1044 |
* or there is no available cache directory. |
1045 |
*/ |
1046 |
private boolean usingManifestCache; |
1047 |
|
1048 |
{ |
1049 |
usingManifestCache = Boolean.valueOf(System.getProperty("netbeans.cache.manifests", "true")).booleanValue(); |
1050 |
if (usingManifestCache) { |
1051 |
String userdir = System.getProperty("netbeans.user"); |
1052 |
if (userdir != null) { |
1053 |
manifestCacheFile = new File(new File(new File(userdir), "cache"), "all-manifests.dat"); // NOI18N |
1054 |
Util.err.log("Using manifest cache in " + manifestCacheFile); |
1055 |
} else { |
1056 |
// Some special startup mode, e.g. with Plain. |
1057 |
usingManifestCache = false; |
1058 |
Util.err.log("Not using any manifest cache; no user directory"); |
1059 |
} |
1060 |
} else { |
1061 |
Util.err.log("Manifest cache disabled"); |
1062 |
} |
1063 |
} |
1064 |
|
1065 |
/** Cache of known JAR manifests. |
1066 |
* Initially null. If the cache is read, it may be used to quickly serve JAR manifests. |
1067 |
* Each JAR file is mapped to a two-element array consisting of |
1068 |
* its modification date when last read; and the manifest itself. |
1069 |
*/ |
1070 |
private Map manifestCache = null; // Map<File,[Date,Manifest]> |
1071 |
|
1072 |
/** If true, at least one manifest has had to be read explicitly. |
1073 |
* This might be because the cache did not initially exist; |
1074 |
* or the JAR was not present in the cache; |
1075 |
* or the JAR was present but did not match the cache timestamp. |
1076 |
*/ |
1077 |
private boolean manifestCacheDirty = false; |
1078 |
|
1079 |
// XXX consider logging using Events |
1080 |
|
1081 |
/** Overrides superclass method to keep a cache of module manifests, |
1082 |
* so that their JARs do not have to be opened twice during startup. |
1083 |
*/ |
1084 |
public Manifest loadManifest(File jar) throws IOException { |
1085 |
if (!usingManifestCache) { |
1086 |
return super.loadManifest(jar); |
1087 |
} |
1088 |
if (manifestCache == null) { |
1089 |
manifestCache = loadManifestCache(manifestCacheFile); |
1090 |
} |
1091 |
Object[] entry = (Object[])manifestCache.get(jar); |
1092 |
if (entry != null) { |
1093 |
if (((Date)entry[0]).getTime() == jar.lastModified()) { |
1094 |
// Cache hit. |
1095 |
Util.err.log("Found manifest for " + jar + " in cache"); |
1096 |
return (Manifest)entry[1]; |
1097 |
} else { |
1098 |
Util.err.log("Wrong timestamp for " + jar + " in manifest cache"); |
1099 |
} |
1100 |
} else { |
1101 |
Util.err.log("No entry for " + jar + " in manifest cache"); |
1102 |
} |
1103 |
// Cache miss. |
1104 |
Manifest m = super.loadManifest(jar); |
1105 |
// (If that threw IOException, we leave it out of the cache.) |
1106 |
manifestCache.put(jar, new Object[] {new Date(jar.lastModified()), m}); |
1107 |
manifestCacheDirty = true; |
1108 |
return m; |
1109 |
} |
1110 |
|
1111 |
/** If the manifest cache had been in use, and is now dirty, write it to disk. |
1112 |
*/ |
1113 |
private void maybeSaveManifestCache() { |
1114 |
if (usingManifestCache && manifestCacheDirty) { |
1115 |
try { |
1116 |
saveManifestCache(manifestCache, manifestCacheFile); |
1117 |
} catch (IOException ioe) { |
1118 |
Util.err.notify(ErrorManager.WARNING, ioe); |
1119 |
} |
1120 |
usingManifestCache = false; |
1121 |
manifestCacheDirty = false; |
1122 |
manifestCache = null; |
1123 |
manifestCacheFile = null; |
1124 |
} |
1125 |
} |
1126 |
|
1127 |
/** Really save the cache. |
1128 |
* @see #manifestCacheFile |
1129 |
*/ |
1130 |
private void saveManifestCache(Map manifestCache, File manifestCacheFile) throws IOException { |
1131 |
Util.err.log("Saving manifest cache"); |
1132 |
manifestCacheFile.getParentFile().mkdirs(); |
1133 |
OutputStream os = new FileOutputStream(manifestCacheFile); |
1134 |
try { |
1135 |
try { |
1136 |
os = new BufferedOutputStream(os); |
1137 |
Iterator it = manifestCache.entrySet().iterator(); |
1138 |
while (it.hasNext()) { |
1139 |
Map.Entry e = (Map.Entry)it.next(); |
1140 |
File jar = (File)e.getKey(); |
1141 |
Object[] v = (Object[])e.getValue(); |
1142 |
long time = ((Date)v[0]).getTime(); |
1143 |
Manifest m = (Manifest)v[1]; |
1144 |
os.write(jar.getAbsolutePath().getBytes("UTF-8")); // NOI18N |
1145 |
os.write(0); |
1146 |
for (int i = 7; i >= 0; i--) { |
1147 |
os.write((int)((time >> (i * 8)) & 0xFF)); |
1148 |
} |
1149 |
m.write(os); |
1150 |
os.write(0); |
1151 |
} |
1152 |
} finally { |
1153 |
os.close(); |
1154 |
} |
1155 |
} catch (IOException ioe) { |
1156 |
// Do not leave behind a bogus half-written file. |
1157 |
manifestCacheFile.delete(); |
1158 |
throw ioe; |
1159 |
} |
1160 |
} |
1161 |
|
1162 |
/** Load the cache if present. |
1163 |
* If not present, or there are problems with it, |
1164 |
* just create an empty cache. |
1165 |
* @see #manifestCacheFile |
1166 |
*/ |
1167 |
private Map loadManifestCache(File manifestCacheFile) { |
1168 |
if (!manifestCacheFile.canRead()) { |
1169 |
Util.err.log("No manifest cache found at " + manifestCacheFile); |
1170 |
return new HashMap(200); |
1171 |
} |
1172 |
ev.log(Events.PERF_START, "NbInstaller - loadManifestCache"); // NOI18N |
1173 |
try { |
1174 |
InputStream is = new FileInputStream(manifestCacheFile); |
1175 |
try { |
1176 |
BufferedInputStream bis = new BufferedInputStream(is); |
1177 |
Map m = new HashMap(200); |
1178 |
while (true) { |
1179 |
bis.mark(1); |
1180 |
if (bis.read() == -1) { |
1181 |
break; |
1182 |
} |
1183 |
bis.reset(); |
1184 |
readManifestCacheEntry(bis, m); |
1185 |
} |
1186 |
tmpbuf = null; |
1187 |
return m; |
1188 |
} finally { |
1189 |
is.close(); |
1190 |
ev.log(Events.PERF_END, "NbInstaller - loadManifestCache"); // NOI18N |
1191 |
} |
1192 |
} catch (IOException ioe) { |
1193 |
Util.err.annotate(ioe, ErrorManager.UNKNOWN, "While reading: " + manifestCacheFile, null, null, null); // NOI18N |
1194 |
Util.err.notify(ErrorManager.WARNING, ioe); |
1195 |
return new HashMap(200); |
1196 |
} |
1197 |
} |
1198 |
|
1199 |
/** buf to be filled, starting at beginning of array */ |
1200 |
private byte[] tmpbuf; |
1201 |
/** bytes successfully read into buf */ |
1202 |
private int pos; |
1203 |
private void readUpTillNullByte(InputStream is) throws IOException { |
1204 |
if (tmpbuf == null) { |
1205 |
tmpbuf = new byte[4096]; |
1206 |
} |
1207 |
final int size = tmpbuf.length; |
1208 |
pos = 0; |
1209 |
while (true) { |
1210 |
final int toread = size - pos; |
1211 |
is.mark(toread); |
1212 |
int read = is.read(tmpbuf, pos, toread); |
1213 |
if (read == -1) throw new IOException("EOF"); // NOI18N |
1214 |
int end = pos + read; |
1215 |
for (int i = pos; i < end; i++) { |
1216 |
if (tmpbuf[i] == 0) { |
1217 |
// It fit into the 4k buffer (as it usually will, I hope). |
1218 |
pos = i; |
1219 |
is.reset(); |
1220 |
while (true) { |
1221 |
int toskip = i + 1; |
1222 |
long s = is.skip(toskip); |
1223 |
if (s == 0 || s > toskip) throw new IOException("Cannot skip"); // NOI18N |
1224 |
toskip -= s; |
1225 |
if (toskip == 0) break; |
1226 |
} |
1227 |
return; |
1228 |
} |
1229 |
} |
1230 |
// Did not read the null byte. |
1231 |
if (read < toread) { |
1232 |
// Neither filled the buffer nor got to the null byte. |
1233 |
pos = end; |
1234 |
} else { |
1235 |
// Did not fit, try again. |
1236 |
byte[] tmpbuf2 = new byte[size * 2]; |
1237 |
System.arraycopy(tmpbuf, 0, tmpbuf2, 0, size); |
1238 |
pos = size; |
1239 |
tmpbuf = tmpbuf2; |
1240 |
} |
1241 |
// continue reading |
1242 |
} |
1243 |
} |
1244 |
|
1245 |
private void readManifestCacheEntry(InputStream is, Map m) throws IOException { |
1246 |
readUpTillNullByte(is); |
1247 |
File jar = new File(new String(tmpbuf, 0, pos, "UTF-8")); // NOI18N |
1248 |
long time = 0L; |
1249 |
for (int i = 7; i >= 0; i--) { |
1250 |
time |= (((long)is.read()) << (i * 8)); |
1251 |
} |
1252 |
readUpTillNullByte(is); |
1253 |
Manifest mani = new Manifest(new ByteArrayInputStream(tmpbuf, 0, pos)); |
1254 |
m.put(jar, new Object[] {new Date(time), mani}); |
1255 |
if (Util.err.isLoggable(ErrorManager.INFORMATIONAL)) { |
1256 |
Util.err.log("Manifest cache entry: jar=" + jar + " date=" + new Date(time) + " codename=" + mani.getMainAttributes().getValue("OpenIDE-Module")); |
1019 |
} |
1257 |
} |
1020 |
} |
1258 |
} |
1021 |
|
1259 |
|