In order to prevent misuses of non-declared APIs, it would be valuable to give
modules a chance to separate resources (especially icons) that are part of
their API and those that are not.
The simplest way seems to be to allow other modules to access only resources
that are in public packages of other modules.
Then modules could decide to whether their resources are private and keep them
in non-public packages or public and as such move them to public package, or
friend - e.g. also list modules that can access such packages.
This is potentially incompatible change and as such I would suggest to apply
it only to modules that declare requrest for
org.openide.modules.ModuleFormat2 - e.g. newly compiled modules.
As far as I know this is already the case, i.e. if you call
ClassLoader.getResource(...) on a module class loader, it should only offer
resources from public packages.
The problem is that Utilities.loadImage operates on the system class loader,
which not only bypasses public packages, it also ignores module dependencies
(i.e. it does not matter who called it).
How to solve this? I am not sure. Some ideas:
public static Image Utilities.loadImage(String resource, boolean localized,
which would ask only referrer.classLoader.getResource(resource). Pros: explicit.
Cons: does not protect images accessed from existing code; useless for icons
loaded declaratively from layers; cache logic probably would need to change.
2. Making the existing loadImage check for access by stack inspection. Pros:
works for existing calls to this method. Cons: magic change could cause problems
for indirect calls going across module boundaries; could be incompatible for
some legitimate existing code (?); same problems as #1 with layers and cache.
3. Make the system class loader check for public packages. Pros: easy; applies
to layer icons too. Cons: does not work properly with impl or friend deps; does
not even work properly for modules wishing to load images from their own private
So this could get complicated. Perhaps we need a new overload of loadImage
taking Class (and/or ClassLoader), with caching by URL of result; deprecate the
existing loadImage methods and try to correct all usages; and change all
infrastructure code which loads icons from declarative name (SFS.icon, library
decls, annotation decls, ....) to look up declaring module (will need a new API
for this!) and pass the right ClassLoader. Possible but not trivial.
I am not really keen on fixing this.
The situation is somewhat improved by @StaticResource and declarative annotations which result in a call to LayerBuilder.validateResource; you are guided towards declaring icon paths as @SR constants.
These constants may be placed in public or friend packages if needed for use from other modules. In the case of the current Ant harness, it is additionally enforced (0983e2258924) that the icon itself be in a public package, though this is not true for Maven builds and may not be true in the future for Ant builds either .
Bugtraq #7073508, fixed in JDK 7 AFAIK, does prevent you from using @SR on a constant which is also used in a processed annotation (perhaps only within one source root); it is annoying but not so bad since the usages of the constant in typical annotations will have the same benefit as @SR in preventing the icon from being accidentally removed or renamed.
Examples: org.netbeans.spi.java.project.support.ui.templates.JavaTemplates.JAVA_ICON; org.netbeans.modules.maven.spi.nodes.NodeUtils.ICON_DEPENDENCY_JAR; org.netbeans.modules.mobility.end2end.E2EDataObject.ICON_BASE.
All of the above applies only to compile time and so offers no additional runtime protection.