Lines 71-76
Link Here
|
71 |
import org.openide.filesystems.FileSystem; |
71 |
import org.openide.filesystems.FileSystem; |
72 |
import org.openide.filesystems.FileUtil; |
72 |
import org.openide.filesystems.FileUtil; |
73 |
import org.openide.util.Exceptions; |
73 |
import org.openide.util.Exceptions; |
|
|
74 |
import org.openide.util.Mutex.Action; |
75 |
import org.openide.util.Mutex.ExceptionAction; |
76 |
import org.openide.util.MutexException; |
74 |
|
77 |
|
75 |
/** Controller of the IDE's whole module system. |
78 |
/** Controller of the IDE's whole module system. |
76 |
* Contains higher-level convenience methods to |
79 |
* Contains higher-level convenience methods to |
Lines 153-168
Link Here
|
153 |
* @return list of module-related JARs/ZIPs |
156 |
* @return list of module-related JARs/ZIPs |
154 |
*/ |
157 |
*/ |
155 |
public List<File> getModuleJars () { |
158 |
public List<File> getModuleJars () { |
156 |
mgr.mutexPrivileged().enterReadAccess(); |
159 |
return mgr.mutex().readAccess(new Action<List<File>>() { |
157 |
try { |
160 |
@Override |
158 |
List<File> l = new ArrayList<File>(); |
161 |
public List<File> run() { |
159 |
for (Module m: mgr.getEnabledModules()) { |
162 |
List<File> l = new ArrayList<File>(); |
160 |
l.addAll(m.getAllJars()); |
163 |
for (Module m: mgr.getEnabledModules()) { |
|
|
164 |
l.addAll(m.getAllJars()); |
165 |
} |
166 |
return l; |
161 |
} |
167 |
} |
162 |
return l; |
168 |
}); |
163 |
} finally { |
|
|
164 |
mgr.mutexPrivileged().exitReadAccess(); |
165 |
} |
166 |
} |
169 |
} |
167 |
|
170 |
|
168 |
/** We just make the modules now, restore them later |
171 |
/** We just make the modules now, restore them later |
Lines 178-184
Link Here
|
178 |
// Keep a list of manifest URL bases which we know we do not need to |
181 |
// Keep a list of manifest URL bases which we know we do not need to |
179 |
// parse. Some of these manifests might be signed, and if so, we do not |
182 |
// parse. Some of these manifests might be signed, and if so, we do not |
180 |
// want to touch them, as it slows down startup quite a bit. |
183 |
// want to touch them, as it slows down startup quite a bit. |
181 |
Set<File> ignoredJars = new HashSet<File>(); |
184 |
final Set<File> ignoredJars = new HashSet<File>(); |
182 |
String javaHome = System.getProperty("java.home"); // NOI18N |
185 |
String javaHome = System.getProperty("java.home"); // NOI18N |
183 |
if (javaHome != null) { |
186 |
if (javaHome != null) { |
184 |
File lib = new File(new File(javaHome).getParentFile(), "lib"); // NOI18N |
187 |
File lib = new File(new File(javaHome).getParentFile(), "lib"); // NOI18N |
Lines 189-343
Link Here
|
189 |
ignoredJars.add(new File(entry)); |
192 |
ignoredJars.add(new File(entry)); |
190 |
} |
193 |
} |
191 |
LOG.log(Level.FINE, "Ignored JARs: {0}", ignoredJars); |
194 |
LOG.log(Level.FINE, "Ignored JARs: {0}", ignoredJars); |
192 |
|
195 |
mgr.mutex().writeAccess(new Action<Void>() { |
193 |
mgr.mutexPrivileged().enterWriteAccess(); |
196 |
@Override |
194 |
ev.log(Events.START_LOAD_BOOT_MODULES); |
197 |
public Void run() { |
195 |
try { |
198 |
doLoadBootModules(ignoredJars); |
196 |
bootModules = new HashSet<Module>(10); |
199 |
return null; |
197 |
ClassLoader loader = ModuleSystem.class.getClassLoader(); |
|
|
198 |
Enumeration<URL> e = loader.getResources("META-INF/MANIFEST.MF"); // NOI18N |
199 |
ev.log(Events.PERF_TICK, "got all manifests"); // NOI18N |
200 |
|
201 |
// There will be duplicates: cf. #32576. |
202 |
Set<URL> checkedManifests = new HashSet<URL>(); |
203 |
MANIFESTS: |
204 |
while (e.hasMoreElements()) { |
205 |
URL manifestUrl = e.nextElement(); |
206 |
if (!checkedManifests.add(manifestUrl)) { |
207 |
// Already seen, ignore. |
208 |
continue; |
209 |
} |
210 |
URL jarURL = FileUtil.getArchiveFile(manifestUrl); |
211 |
if (jarURL != null && jarURL.getProtocol().equals("file") && |
212 |
/* #121777 */ jarURL.getPath().startsWith("/")) { |
213 |
LOG.log(Level.FINE, "Considering JAR: {0}", jarURL); |
214 |
try { |
215 |
if (ignoredJars.contains(new File(jarURL.toURI()))) { |
216 |
LOG.log(Level.FINE, "ignoring JDK/JRE manifest: {0}", manifestUrl); |
217 |
continue MANIFESTS; |
218 |
} |
219 |
} catch (URISyntaxException x) { |
220 |
Exceptions.printStackTrace(x); |
221 |
} |
222 |
} |
223 |
LOG.log(Level.FINE, "Checking boot manifest: {0}", manifestUrl); |
224 |
|
225 |
InputStream is; |
226 |
try { |
227 |
is = manifestUrl.openStream(); |
228 |
} catch (IOException ioe) { |
229 |
// Debugging for e.g. #32493 - which JAR was guilty? |
230 |
Exceptions.attachMessage(ioe, "URL: " + manifestUrl); // NOI18N |
231 |
throw ioe; |
232 |
} |
233 |
try { |
234 |
Manifest mani = new Manifest(is); |
235 |
Attributes attr = mani.getMainAttributes(); |
236 |
if (attr.getValue("OpenIDE-Module") == null) { // NOI18N |
237 |
// Not a module. |
238 |
continue; |
239 |
} |
240 |
bootModules.add(mgr.createFixed(mani, manifestUrl, loader)); |
241 |
} finally { |
242 |
is.close(); |
243 |
} |
244 |
} |
200 |
} |
245 |
if (list == null) { |
201 |
}); |
246 |
// Plain calling us, we have to install now. |
|
|
247 |
// Do it the simple way. |
248 |
mgr.enable(bootModules); |
249 |
} |
250 |
ev.log(Events.PERF_TICK, "added all classpath modules"); // NOI18N |
251 |
|
252 |
} catch (IOException ioe) { |
253 |
// Note: includes also InvalidException's for malformed this and that. |
254 |
// Probably if a bootstrap module is corrupt we are in pretty bad shape |
255 |
// anyway, so don't bother trying to be fancy and install just some of |
256 |
// them etc. |
257 |
LOG.log(Level.WARNING, null, ioe); |
258 |
} catch (DuplicateException de) { |
259 |
LOG.log(Level.WARNING, null, de); |
260 |
} finally { |
261 |
// Not 100% accurate in this case: |
262 |
ev.log(Events.FINISH_LOAD_BOOT_MODULES); |
263 |
mgr.mutexPrivileged().exitWriteAccess(); |
264 |
} |
265 |
} |
202 |
} |
266 |
|
|
|
267 |
/** Refreshes the list of modules. Used from autoupdate.services. |
268 |
* @since 1.28 |
269 |
*/ |
270 |
public final void refresh() { |
271 |
list.moduleListChanged(); |
272 |
} |
273 |
|
274 |
/** Read disk settings and determine what the known modules are. |
275 |
*/ |
276 |
public void readList() { |
277 |
ev.log(Events.PERF_START, "ModuleSystem.readList"); // NOI18N |
278 |
mgr.mutexPrivileged().enterWriteAccess(); |
279 |
try { |
280 |
list.readInitial(); |
281 |
} finally { |
282 |
mgr.mutexPrivileged().exitWriteAccess(); |
283 |
} |
284 |
ev.log(Events.PERF_END, "ModuleSystem.readList"); // NOI18N |
285 |
} |
286 |
|
287 |
/** Install read modules. |
288 |
*/ |
289 |
public void restore() { |
290 |
ev.log(Events.PERF_START, "ModuleSystem.restore"); // NOI18N |
291 |
mgr.mutexPrivileged().enterWriteAccess(); |
292 |
try { |
293 |
Set<Module> toTrigger = new HashSet<Module>(bootModules/*Collections.EMPTY_SET*/); |
294 |
list.trigger(toTrigger); |
295 |
mgr.releaseModuleManifests(); |
296 |
} finally { |
297 |
mgr.mutexPrivileged().exitWriteAccess(); |
298 |
} |
299 |
ev.log(Events.PERF_END, "ModuleSystem.restore"); // NOI18N |
300 |
} |
301 |
|
302 |
/** Shut down the system: ask modules to shut down. |
303 |
* Some of them may refuse. |
304 |
*/ |
305 |
public boolean shutDown(final Runnable midHook) { |
306 |
mgr.mutexPrivileged().enterWriteAccess(); |
307 |
boolean res; |
308 |
Runnable both = new Runnable() { |
309 |
@Override |
310 |
public void run() { |
311 |
midHook.run(); |
312 |
Stamps.getModulesJARs().shutdown(); |
313 |
} |
314 |
}; |
315 |
try { |
316 |
res = mgr.shutDown(both); |
317 |
} finally { |
318 |
mgr.mutexPrivileged().exitWriteAccess(); |
319 |
} |
320 |
return res; |
321 |
} |
322 |
|
323 |
/** Load a module in test (reloadable) mode. |
324 |
* If there is an existing module with a different JAR, get |
325 |
* rid of it and load this one instead. |
326 |
* If it is already installed, disable it and reenable it |
327 |
* to reload its contents. |
328 |
* If other modules depend on it, disable them first and |
329 |
* then (try to) enable them again later. |
330 |
*/ |
331 |
final void deployTestModule(File jar) throws IOException { |
332 |
if (! jar.isAbsolute()) throw new IOException("Absolute paths only please"); // NOI18N |
333 |
|
203 |
|
334 |
// Check to see if Javeleon is enabled. If so, |
204 |
private void doDeployTestModule(File jar) throws IOException, IllegalArgumentException { |
335 |
// let Javeleon handle the module reloading. |
|
|
336 |
if (JaveleonModule.isJaveleonPresent && JaveleonModuleReloader.getDefault().reloadJaveleonModule(jar, mgr, installer, ev)) { |
337 |
return; |
338 |
} |
339 |
|
340 |
mgr.mutexPrivileged().enterWriteAccess(); |
341 |
ev.log(Events.START_DEPLOY_TEST_MODULE, jar); |
205 |
ev.log(Events.START_DEPLOY_TEST_MODULE, jar); |
342 |
// For now, just print to stderr directly; could also go thru Events. |
206 |
// For now, just print to stderr directly; could also go thru Events. |
343 |
// No need for I18N, module developers are expected to know English |
207 |
// No need for I18N, module developers are expected to know English |
Lines 412-418
Link Here
|
412 |
System.err.println("Done."); // NOI18N |
276 |
System.err.println("Done."); // NOI18N |
413 |
} finally { |
277 |
} finally { |
414 |
ev.log(Events.FINISH_DEPLOY_TEST_MODULE, jar); |
278 |
ev.log(Events.FINISH_DEPLOY_TEST_MODULE, jar); |
415 |
mgr.mutexPrivileged().exitWriteAccess(); |
279 |
} |
|
|
280 |
} |
281 |
|
282 |
private void doLoadBootModules(Set<File> ignoredJars) throws IllegalArgumentException { |
283 |
ev.log(Events.START_LOAD_BOOT_MODULES); |
284 |
try { |
285 |
bootModules = new HashSet<Module>(10); |
286 |
ClassLoader loader = ModuleSystem.class.getClassLoader(); |
287 |
Enumeration<URL> e = loader.getResources("META-INF/MANIFEST.MF"); // NOI18N |
288 |
ev.log(Events.PERF_TICK, "got all manifests"); // NOI18N |
289 |
|
290 |
// There will be duplicates: cf. #32576. |
291 |
Set<URL> checkedManifests = new HashSet<URL>(); |
292 |
MANIFESTS: |
293 |
while (e.hasMoreElements()) { |
294 |
URL manifestUrl = e.nextElement(); |
295 |
if (!checkedManifests.add(manifestUrl)) { |
296 |
// Already seen, ignore. |
297 |
continue; |
298 |
} |
299 |
URL jarURL = FileUtil.getArchiveFile(manifestUrl); |
300 |
if (jarURL != null && jarURL.getProtocol().equals("file") && |
301 |
/* #121777 */ jarURL.getPath().startsWith("/")) { |
302 |
LOG.log(Level.FINE, "Considering JAR: {0}", jarURL); |
303 |
try { |
304 |
if (ignoredJars.contains(new File(jarURL.toURI()))) { |
305 |
LOG.log(Level.FINE, "ignoring JDK/JRE manifest: {0}", manifestUrl); |
306 |
continue MANIFESTS; |
307 |
} |
308 |
} catch (URISyntaxException x) { |
309 |
Exceptions.printStackTrace(x); |
310 |
} |
311 |
} |
312 |
LOG.log(Level.FINE, "Checking boot manifest: {0}", manifestUrl); |
313 |
|
314 |
InputStream is; |
315 |
try { |
316 |
is = manifestUrl.openStream(); |
317 |
} catch (IOException ioe) { |
318 |
// Debugging for e.g. #32493 - which JAR was guilty? |
319 |
Exceptions.attachMessage(ioe, "URL: " + manifestUrl); // NOI18N |
320 |
throw ioe; |
321 |
} |
322 |
try { |
323 |
Manifest mani = new Manifest(is); |
324 |
Attributes attr = mani.getMainAttributes(); |
325 |
if (attr.getValue("OpenIDE-Module") == null) { // NOI18N |
326 |
// Not a module. |
327 |
continue; |
328 |
} |
329 |
bootModules.add(mgr.createFixed(mani, manifestUrl, loader)); |
330 |
} finally { |
331 |
is.close(); |
332 |
} |
333 |
} |
334 |
if (list == null) { |
335 |
// Plain calling us, we have to install now. |
336 |
// Do it the simple way. |
337 |
mgr.enable(bootModules); |
338 |
} |
339 |
ev.log(Events.PERF_TICK, "added all classpath modules"); // NOI18N |
340 |
|
341 |
} catch (IOException ioe) { |
342 |
// Note: includes also InvalidException's for malformed this and that. |
343 |
// Probably if a bootstrap module is corrupt we are in pretty bad shape |
344 |
// anyway, so don't bother trying to be fancy and install just some of |
345 |
// them etc. |
346 |
LOG.log(Level.WARNING, null, ioe); |
347 |
} catch (DuplicateException de) { |
348 |
LOG.log(Level.WARNING, null, de); |
349 |
} finally { |
350 |
// Not 100% accurate in this case: |
351 |
ev.log(Events.FINISH_LOAD_BOOT_MODULES); |
352 |
} |
353 |
} |
354 |
|
355 |
/** Refreshes the list of modules. Used from autoupdate.services. |
356 |
* @since 1.28 |
357 |
*/ |
358 |
public final void refresh() { |
359 |
list.moduleListChanged(); |
360 |
} |
361 |
|
362 |
/** Read disk settings and determine what the known modules are. |
363 |
*/ |
364 |
public void readList() { |
365 |
ev.log(Events.PERF_START, "ModuleSystem.readList"); // NOI18N |
366 |
mgr.mutex().writeAccess(new Runnable() { |
367 |
@Override |
368 |
public void run() { |
369 |
list.readInitial(); |
370 |
} |
371 |
}); |
372 |
ev.log(Events.PERF_END, "ModuleSystem.readList"); // NOI18N |
373 |
} |
374 |
|
375 |
/** Install read modules. |
376 |
*/ |
377 |
public void restore() { |
378 |
ev.log(Events.PERF_START, "ModuleSystem.restore"); // NOI18N |
379 |
mgr.mutex().writeAccess(new Runnable() { |
380 |
@Override |
381 |
public void run() { |
382 |
Set<Module> toTrigger = new HashSet<Module>(bootModules/*Collections.EMPTY_SET*/); |
383 |
list.trigger(toTrigger); |
384 |
mgr.releaseModuleManifests(); |
385 |
} |
386 |
}); |
387 |
ev.log(Events.PERF_END, "ModuleSystem.restore"); // NOI18N |
388 |
} |
389 |
|
390 |
/** Shut down the system: ask modules to shut down. |
391 |
* Some of them may refuse. |
392 |
*/ |
393 |
public boolean shutDown(final Runnable midHook) { |
394 |
class ActionImpl implements Runnable { |
395 |
boolean second; |
396 |
boolean res; |
397 |
|
398 |
public ActionImpl() { |
399 |
} |
400 |
|
401 |
@Override |
402 |
public void run() { |
403 |
if (second) { |
404 |
midHook.run(); |
405 |
Stamps.getModulesJARs().shutdown(); |
406 |
} else { |
407 |
second = true; |
408 |
res = mgr.shutDown(this); |
409 |
} |
410 |
} |
411 |
} |
412 |
ActionImpl impl = new ActionImpl(); |
413 |
return impl.res; |
414 |
} |
415 |
|
416 |
/** Load a module in test (reloadable) mode. |
417 |
* If there is an existing module with a different JAR, get |
418 |
* rid of it and load this one instead. |
419 |
* If it is already installed, disable it and reenable it |
420 |
* to reload its contents. |
421 |
* If other modules depend on it, disable them first and |
422 |
* then (try to) enable them again later. |
423 |
*/ |
424 |
final void deployTestModule(final File jar) throws IOException { |
425 |
try { |
426 |
if (! jar.isAbsolute()) throw new IOException("Absolute paths only please"); // NOI18N |
427 |
|
428 |
// Check to see if Javeleon is enabled. If so, |
429 |
// let Javeleon handle the module reloading. |
430 |
if (JaveleonModule.isJaveleonPresent && JaveleonModuleReloader.getDefault().reloadJaveleonModule(jar, mgr, installer, ev)) { |
431 |
return; |
432 |
} |
433 |
|
434 |
mgr.mutex().writeAccess(new ExceptionAction<Void>() { |
435 |
@Override |
436 |
public Void run() throws IOException { |
437 |
doDeployTestModule(jar); |
438 |
return null; |
439 |
} |
440 |
}); |
441 |
} catch (MutexException ex) { |
442 |
throw (IOException)ex.getException(); |
416 |
} |
443 |
} |
417 |
} |
444 |
} |
418 |
/** Make sure some module is disabled. |
445 |
/** Make sure some module is disabled. |