Module change detection...

2008-08-12 Thread Bryan Atsatt
There are a number of class loading optimizations (including HotSpot's 
Class Data Sharing) that are hard to make generic due to the lack of a 
standard way to validate cached class state. We have a unique 
opportunity to fix this in 277...


I propose that we add:

1. An annotation to record a digest over the module's contents, which 
would then be visible from ModuleInfo.

2. A convenience api to return the digest, e.g.:

   public interface ModuleContent {
   ...
   public byte[] getDigest();
   }


The jam tool would compute and add the annotation, and the default 
implementation(s) of ModuleContent would then just return the value from 
the annotation.


Other implementations would be free to compute the value at install time 
(or even runtime); development environments could generate a value 
using a simple counter.


Unlike the version number, this value can be used to ensure that any 
change to the module's contents can be detected. Both HotSpot and other 
JVMs can then introduce optimizations like Class Data Sharing that 
depend on being able to validate the cache file.



It may similarly be useful to have ModuleInfo be able to (lazily) 
compute a digest for itself, and/or have a digest on ModuleDefinition 
that encompasses both the metadata (ModuleInfo) and the contents.


// Bryan







Re: Refactorability proposal...

2008-06-13 Thread Bryan Atsatt
Yes, this could be an issue. If JavaEE:4.0.0 merely imports and 
re-exports the specific packages, the imports can just be copied out. If 
it actually contains them, and they themselves declare their own 
versions, the jam tool could emit imports for those specific versions, 
but it cannot generate ranges.


This brings us back to the contract idea: a named/versioned collection 
of import constraints. The indirection afforded by this could certainly 
solve this problem.


And we do have it, sort of: a module that contains no classes or 
resources itself, only imports and re-exports. In the current model, 
this is a bit of a hack because the module will actually be instantiated 
with its own loader, which is a waste of cycles/resources.


If, OTOH, we special case such contract (indirect?) modules such 
that they are not instantiated (or at least don't have a loader) but act 
only as a bag of import constraints that can be borrowed by an 
importer, that seems like a reasonable solution.


This could be simplified by doing the borrowing at build time, as in my 
proposal, at the cost of some loss of flexibility.


// Bryan


Adrian Brock wrote:

Another issue would be how you handle the generated package
constraints.

e.g. Suppose you a module JavaEE:4.0.0 that
contains packages javax.jms:1.1.0, javax.resource:1.5.0, etc.

I then declare a module constraint
JavaEE:[4.0.0, 5.0.0)
i.e. I work with JavaEE4 but not JavaEE5

What do the package constraints resolve to for jms and jca
if we don't have a JavaEE5 module in the repository? :-)

JavaEE is not a very a good example since package versions
wouldn't change across a major release, but they could
in other cases or more general module version constraints.

On Tue, 2008-06-10 at 18:27 -0700, Bryan Atsatt wrote:
  
(FYI: I've discussed this with Stanley but wanted to ensure it was 
visible to everyone.)


Proposal

1. Eliminate runtime use of import-by-module in the JAM system:

a. Support the (very convenient) import-by-module at the source level.
b. jam tool transforms import-by-module to a list of 
import-by-package statements.


2. Add APIs to fully support import-by-package in the JAM system:

   a. Support Version annotation in package-info.java (or in 
module-info.java). If a
   package does not declare a version, it inherits that of the 
enclosing module.

   b. Add ImportPackage annotation with version constraints.

3. Add APIs to fully support import-by-package in the abstract framework:
 
a. Add methods to Query to produce import-by-package nodes.
b. Replace Query.getIndexableNames() with fully generic variants (I 
proposed

a solution here previously which I will re-post).

Rationale

Module refactoring is inevitable, particularly during the transition 
from the current, effectively flat class space to a fine-grained space 
provided by module systems. We have significant experience with this 
issue at Oracle (with the transition to our own module system), and OSGi 
best-practices for conversion include starting with everything in one 
bundle and then separating out pieces as experience is gained.


A very common pattern, in our experience, is for developers to start 
with many extra jars in their initial module (a mini version of 
class-path hell). As that module is put into wider use, someone 
discovers that package X is also contained in their module, and that 
duplication either leads to runtime conflicts (very bad), or just plain 
footprint bloat. The obvious answer is to put package X in a separate 
module, and have everyone share it via imports.


But... not so fast. If there are consumers of that module who import it 
by module name alone, then pulling X out of it will cause those 
importers to break. And if it is possible for your module to have been 
imported by *anyone* by name alone, then you are stuck: either you break 
them or you live with the incorrect granularity (which just isn't an 
option in the conflict scenarios). Not a happy choice.


Originally, I had proposed to do away with import-by-module altogether, 
both to avoid this problem and to eliminate the conceptual disconnect. 
Your code does not today contain import statements that name *jars*, it 
names packages and/or specific classes in those packages. Why invent a 
new system that takes such a large step backwards?


The answer is simply convenience. Imagine a module that contains 100 
packages and it is obvious that writing a single import statement is far 
easier than discovering and explicitly writing all the package imports. 
Yes, IDEs will likely mostly eliminate this issue, but it still makes 
sense to be able to do this by hand.


This proposal is an attempt to maintain the convenience while adding the 
crucial ability to safely refactor: step 1b is the central idea.


// Bryan



Re: Refactorability proposal...

2008-06-12 Thread Bryan Atsatt
The proposal is to resolve module--packages at *build* time, not 
deploy. This way, the mapping is guaranteed to be valid.


And yes, this does make the sysadmin job a bit more difficult, but that 
should be relatively easy to address with tooling.


The main point is that relying on import-by-module at runtime guarantees 
that refactoring is problematic. My proposal seems like a reasonable way 
to deal with this, but I wanted to start this discussion to explore 
others as well.


Any thoughts on how to solve this problem?

// Bryan

Adrian Brock wrote:

Refactoring:

Aren't there cases where resolving a module import 
into its packages during deployment into the repository

will break with some refactorings?

I'm not talking about the more stable module refactorings
where modules are broken into other modules (which
you seem to be addressing).

This is more development time practices where somebody 
is refactoring module contents. i.e. the importing

module could end up with a stale view of what it
should be importing.

A not very good example would be my module B imports a module A
where A exports com.acme.a.interfaces and 
com.acme.a.implementation

I don't use com.acme.a.implementation explicitly so it
shouldn't really be one of my constraints.

Somebody then refactors module B such that the
implementation is now in com.acme.a.impl
but my module wants to import the now non-existant
(or at least stale) com.acme.a.implementation.

Overrides in the repository:

I know we avoid these discussions on the list since it
is really a tooling issue. 

But it is a lot easier for a sysadmin to change 
a single version constraint for a module import 
than it is to have to figure out

what package versions they need to change on the
package imports and change each one individually.

Basically, the convenience of import-by-module
extends beyond the development/source code phase.

OSGi/291

There's still going to be a kind of module import
somewhere to handle OSGi's bundle import constraint.
i.e. OSGi bundle B issues a request to import bundle A
which is really a 277 module.

On Tue, 2008-06-10 at 18:27 -0700, Bryan Atsatt wrote:
  
(FYI: I've discussed this with Stanley but wanted to ensure it was 
visible to everyone.)


Proposal

1. Eliminate runtime use of import-by-module in the JAM system:

a. Support the (very convenient) import-by-module at the source level.
b. jam tool transforms import-by-module to a list of 
import-by-package statements.


2. Add APIs to fully support import-by-package in the JAM system:

   a. Support Version annotation in package-info.java (or in 
module-info.java). If a
   package does not declare a version, it inherits that of the 
enclosing module.

   b. Add ImportPackage annotation with version constraints.

3. Add APIs to fully support import-by-package in the abstract framework:
 
a. Add methods to Query to produce import-by-package nodes.
b. Replace Query.getIndexableNames() with fully generic variants (I 
proposed

a solution here previously which I will re-post).

Rationale

Module refactoring is inevitable, particularly during the transition 
from the current, effectively flat class space to a fine-grained space 
provided by module systems. We have significant experience with this 
issue at Oracle (with the transition to our own module system), and OSGi 
best-practices for conversion include starting with everything in one 
bundle and then separating out pieces as experience is gained.


A very common pattern, in our experience, is for developers to start 
with many extra jars in their initial module (a mini version of 
class-path hell). As that module is put into wider use, someone 
discovers that package X is also contained in their module, and that 
duplication either leads to runtime conflicts (very bad), or just plain 
footprint bloat. The obvious answer is to put package X in a separate 
module, and have everyone share it via imports.


But... not so fast. If there are consumers of that module who import it 
by module name alone, then pulling X out of it will cause those 
importers to break. And if it is possible for your module to have been 
imported by *anyone* by name alone, then you are stuck: either you break 
them or you live with the incorrect granularity (which just isn't an 
option in the conflict scenarios). Not a happy choice.


Originally, I had proposed to do away with import-by-module altogether, 
both to avoid this problem and to eliminate the conceptual disconnect. 
Your code does not today contain import statements that name *jars*, it 
names packages and/or specific classes in those packages. Why invent a 
new system that takes such a large step backwards?


The answer is simply convenience. Imagine a module that contains 100 
packages and it is obvious that writing a single import statement is far 
easier than discovering and explicitly writing all the package imports. 
Yes, IDEs will likely mostly eliminate this issue

Re: Updates on Interoperability

2008-04-29 Thread Bryan Atsatt

Richard S. Hall wrote:

Bryan Atsatt wrote:

Richard S. Hall wrote:

Sam Pullara wrote:
Did we decide which way it will be compatible?  I'm a little 
concerned that implementing something that can use OSGi modules is 
a far bigger task that implementing something that OSGi can use.  
If we are going for total compatibility it seems like we should 
just use OSGi.  Personally I wanted something in Java that was 
simpler and cleaner that OSGi-users could leverage if they wanted.  
But I'm coming at this from the 
we-need-something-like-maven/gem/ivy camp.


The vast majority of people that are going to use this system will 
have never heard of OSGI nor care about any of their more subtle 
features and just want an easy way to leverage the vast amount of 
libraries available (virtually all of them are not OSGi modules 
today but are jar files in maven repositories).  We shouldn't be 
specing out some sort of uber container but rather a simple way to 
tie code to its dependencies.


If this is all that people wanted, then we could just define 
repositories and associated metadata and forget about all runtime 
modularity support, but I strongly disagree that this is all people 
want or else there wouldn't be such an upsurge in OSGi interest and 
adoption.


I strongly suggest KISS applies to our effort.  I write this 
knowing that the committee seems to be heavily in favor of this 
alternate view that we implement the kitchen sink.


I think our interest is similar, but perhaps our conclusions are 
different. Initially, I think my comments were construed as an 
argument against split packages in general, but I am really arguing 
the same as you (I think) that we don't really need split packages 
to be a concept in our interoperability API, if that is how we are 
to view the 277 API. Of course, I am also willing to have the former 
argument too, but I will leave that for another time. :-)


From my point of view, I do not think it is wholly reasonable to 
assume that we want to try to accomplish interoperability across 
module systems, where that includes arbitrarily sharing split 
packages across module systems.
Nor do I, but I'm trying to understand the implications if we assume 
that OSGi will continue to split packages.


Let me try to accurately conjure the peculiarities of split packages 
in the OSGi module layer...


We support split packages in two ways, via required bundles (i.e., 
module dependencies) and via bundle fragments. In general, we 
recommend that if you split your packages that you attach mandatory 
attributes on them so that importers do not get them by mistake. By 
requiring a bundle, you can ignore mandatory attributes and get 
everything a bundle has to offer and combine it with other required 
bundles that might be exporting other parts of the split packages. 
Given this, there is a semi-reasonable chance* that we can tell you 
which bundles are contributing to the complete packages, but we 
have no way of knowing if/when combined split packages are complete. 
Further, we have to assume that split package parts offered by 
different bundles do not overlap, because if we allowed them to 
overlap then we would have shadowing and ordering issues. Again we 
have no easy way to verify that they do not overlap, so we just 
assume they don't.


Fragments on the other hand are a little trickier, since split 
packages from them are loaded from the same class loader to provide 
package private access (which is not afforded for split packages in 
the require bundle approach). The host bundle doesn't really know 
about fragments and it is possible for fragments to shadow or extend 
packages in the host bundle. Since fragments provide their split 
packages in an implicit way (i.e., they largely just become part of 
the host bundle's class path), there is no easy way to determine if 
a fragment is contributing to a given package or not. (* This 
feature of fragments also makes it so it is not really possible to 
know who is contributing classes to a split package in the require 
bundle case.)
Ok, so first I assume it would make sense for an OSGi Repository to 
simply never return a ModuleDefinition for a fragment.


I am not sure I understand your point. Host bundles would be returned 
and during the resolve process, fragments might be attached to that 
host, thus modifying its content in ways that we cannot predict.
I simply meant that a fragment would never be returned by itself, as a 
separate ModuleDefinition.


And the you don't know what you've got till it's resolved problem 
is going to be present in any module system for which package name is 
not a required component of a dependency expression. But as long as 
re-export is not the default behavior (it isn't), doesn't this really 
just boil down to the leakage problem? And this is addressed in 277 
the same as it is in OSGi: you must declare such leaks as 
re-exports (uses). Not perfect, but probably good enough.


So I think we're left

Re: Fw: JSR 291 interoperation status

2007-09-06 Thread Bryan Atsatt

I was just about to send a very similar message :^).

Glyn Normington wrote:


Hi Stanley

Please could you provide an update on your work on interoperation
between JSR 277 and JSR 291?

If the work is still in progress, how's it coming along and roughly
when might there be a strawman proposal to review?

Thanks,

Glyn
- Forwarded by [EMAIL PROTECTED] on 06/09/07 04:12 PM -

[EMAIL PROTECTED] wrote on 21/06/2007 09:59:02 AM:


 Hi Stanley

 Thanks for the status. Please could you indicate roughly when the
 strawman will be ready for initial review by this EG? Hopefully
 early feedback from the Expert Group would be a help...

 Glyn

 Stanley M. Ho [EMAIL PROTECTED] wrote on 20/06/2007 11:43:14 PM:

  Hi Glyn,
 
  That strawman is in progress. As you mentioned, it has significant
  challenges, so it takes more time to produce compared to other
  strawmans. Please stay tuned. ;-)
 
  - Stanley
 
 
  Glyn Normington wrote:
   Please could you give us an update on your work on
interoperation with
   JSR 291 and some idea of when a strawman is likely to be
available for
   initial review by the JSR 277 Expert Group?
  
   Like I said when we spoke at JavaOne, the approach you are
planning on
   taking *might* work, but it has significant challenges, so I'd
like to
   hear how it's coming along.
  
   Thanks,
  
   Glyn





 Unless stated otherwise above:
 IBM United Kingdom Limited - Registered in England and Wales with
 number 741598.
 Registered office: PO Box 41, North Harbour, Portsmouth, Hampshire
PO6 3AU









/
/

/Unless stated otherwise above:
IBM United Kingdom Limited - Registered in England and Wales with
number 741598.
Registered office: PO Box 41, North Harbour, Portsmouth, Hampshire PO6
3AU/








Re: Module system notification mechanism

2007-07-13 Thread Bryan Atsatt

(Sorry, somehow this message got marked read and I only just now saw it.)

Comments inline.


Stanley M. Ho wrote:

Bryan Atsatt wrote:

Stanley, I assume you are proposing a general mechanism in which any
code can register listeners? If so, then I have to agree with Glyn that
this is not sufficient to implement a module activator.


The mechanism I have in mind can be registered only by code that have
the appropriate security permissions, and untrusted code in the sandbox
won't be able to listen to the notification.

I am still a bit puzzled by why the module's state needs to be coupled
directly to the result from the module's activator because this looks to
me more like a solution to a problem than a requirement. For that model
to work, I think there are couple underlying assumptions, but they might
not be valid in our case:

1. If a module's activator is executed before the module is fully
initialized, it can safely register something into some service lookup
mechanism in the system.
2. The service lookup mechanism will make sure the registered thing from
that module is not usable by other modules unless that module becomes
fully initialized.
3. If the module's activator fails to execute when the module is being
initialized, the module system knows how to work with the service lookup
mechanism to undo all the unregisterations automatically and correctly.


So do you expect that java.util.ServiceLoader will do this?


In this case, the module system probably needs to be highly integrated
with the service lookup mechanism, and that mechanism should be the only
one used by all the modules' activators. However, in practice, multiple
service lookup mechanisms exist and can be used in the Java platform,
and I don't think we should expect the module system will know how to
work with these arbitrary mechanisms to provide the suggested module's
state semantic in conjunction with the module's activator. Also, from
our previous discussions, I think our consensus is to avoid pushing the
service mechanism down to the module layer if possible.


I agree that we shouldn't try to push a *service* mechanism into the
module layer.

But a generic *activator* certainly seems appropriate. Some modules will
need to perform initialization prior to use (e.g. process a config file,
check some environmental constraints, populate a JNDI context, etc,
etc). Successful initialization for such a module is then a
pre-condition for use, and any failure should be treated exactly as
seriously as a resolution failure.

Yes, this *could* be done using the notification mechanism, but that
strikes me as a rather hackish approach. This use case is not limited to
container environments, so, IMO, should be made part of the spec.

And it seems like a rather small addition:

1. A simple interface that the module can implement, e.g.:

   interface ModuleActivator {
   public void start(Module module) throws Exception;
   public void release(Module module) throws Exception;
   }

2. An annotation to declare the activator impl name.

3. Module system instantiates and invokes activator (at end of
prep/validation or a new step). An exception here would put the module
into ERROR state.

Exactly what such an activator does is mostly irrelevant, though it
clearly cannot consume the thread; the usual precautions here should
suffice.

// Bryan


Re: Module isolation

2007-06-18 Thread Bryan Atsatt

Stanley M. Ho wrote:

Hello Bryan,

Bryan Atsatt wrote:

...
But this approach doesn't really work very well. What happens when,
moments after releasing a module, another application is deployed that
needs the same module? It gets a different instance. And that could
easily lead to ClassCastExceptions and/or LinkageErrors.

How is it possible to know when it is safe to free up resources?


The use case I have is that sometimes we might want to make a module
temporary unavailable (e.g. turning off a plugin in the IDE), without
shutting down the repository (possibly with hundreds/thousands of other
modules) or uninstall the module. In this case, the container will
trigger not only the release of the existing module instance (so it will
have a chance to be GCed eventually), but it will also make the module
definition invisible (through visibility policy) from other modules.
Without the second part, it has the potential problem you described.


This use case seems to presume that the IDE can/will ensure that there
is only *one* consumer of the module: itself. What if a different plugin
has a dependency on it, and has already been resolved? Is the intention
that the IDE will be wired into the module system deeply enough to
manage this correctly?

Again, this is why we need either a real, general, isolation model, or
an access control model:

Containers, of any kind, must be able to explicitly control access to
private modules.


An application server, for example, will need to keep one application
from accessing the modules of another. And it must *know* that there is
no sharing, so that the application lifecycles can remain independent.

So we need some notion of a context. A purely private repository
instance is one (probably good) possibility. Another is the wrapper
Repository approach, but this requires definition copies (and management
of sharing content, lifecycle, etc).

I started this thread with another, explicit type (ModuleContext), but
it isn't obvious how to use such beast correctly.

An access control model would also work, where all parties can share
Repository instances, but we somehow discriminate between *callers* to
return different results.

We may even want to support some mixture of private + access control.

Regardless of what approach we take, the releaseModule() idea is too
simplistic. Having originally created the detach() method, thinking
along similar lines as you are with the plugin case, I do understand the
idea; I just no longer think it is sufficient :^).

The only safe time to release a module is when there are *zero*
importers, and, even then, you must hide/release atomically, ensuring
that no new imports spring up during the operation.



Note that I don't think this is a common thing many developers want to
do. In fact, I think we should discourage most developers from calling
releaseModule() because of the potential consequences. On the other
hand, we shouldn't preclude this use case either. If you have better
suggestion to address this use case, I would like to hear it.


Well, I agree in theory. But... I am struggling to understand how we
provide an isolation model. If:

- There is a 1:1 relation for ModuleDefinition-Module instance, and
- Isolation requires separate Module instances, then
- Isolation requires separate ModuleDefinition instances

If this is our isolation model, then how does a ModuleSystem instance
support this? Clearly, it would need to keep a mapping from each
ModuleDefinition to its Module instance. How is this simpler, or better?

In your current model (just as in my detach() model), there is still a
1:1 from *at any given moment*, at least from the perspective of the
definition.

Are you thinking that the ModuleSystem would have to keep track of
released modules?


The ModuleSystem instance would have a ModuleDefinition, Module
mapping, and this should be a very simple thing to support and maintain.
Also, the ModuleSystem needs to maintain this information anyway to
avoid multiple Module instances to be instantiated for a given
ModuleDefinition, or to avoid a Module instance to be instantiated if a
ModuleDefinition has been uninstalled or belongs to a repository which
has been shutdown. And yes, the ModuleSystem would have another map to
keep track of all the ModuleDefinitions that are no longer
usable/instantiated. Having the information centralized in one place has
other benefits too, e.g. if we want to find out what the outstanding
module instances from module definitions in all repositories, the
ModuleSystem can provide the answer easily.


Sure. (And the ModuleSystem could not use strong references to hold
released Module instances, else it would prevent GC.)


My view is that ModuleSystem needs to keep track of various runtime
information related to ModuleDefinition and Module anyway, so I don't
see clear benefit in moving part of that information into other classes.


Other than Module instances, what other runtime information

Re: Exported resources

2007-06-12 Thread Bryan Atsatt

Whoops, .jsp files are not candidates for private resources, since the
*container* must have access to them. But I stand by the gif/html/xml
comment :^).

Another candidate is property files (thanks to Stephen McConnell for
reminding me), when used as default configuration.

Bryan Atsatt wrote:

Stanley M. Ho wrote:

Hi Bryan,

Bryan Atsatt wrote:

Yes, I think we're getting close now :^)

(By privileged reflection, you mean having permission to call
AccessibleObject.setAccessible(true), right? If so, then we're back to
the grant issue!)


Yes. In this case, it's the ResourceBundle API calling it to retrieve
ListResourceBundle, so it'll have the sufficient permissions to do that.
Anyway, I think we should leave this issue aside for now.


I still think we can provide private, (i.e. non-exported) resources
which *are* available to the module classes, but to no class outside
of it.

Without using permissions.

Remember this?

  private static class StackAccessor extends SecurityManager {
  public Class[] getStack() {
  return getClassContext();
  }
  }

  private static final STACK_ACCESSOR = new StackAccessor();

If a resource is found, and is not-exported, a module class loader can
use this (or similar) to get the immediate caller's class (at a fixed
index).

If the caller class' Module does not match that for the loader, we don't
return the resource.


I think we should step back to rethink the use cases a bit.

Typically, a module calls some APIs (e.g. ResourceBundle, AWTToolkit,
etc.) and these APIs might then retrieve resources through the module's
ClassLoader.getResource*(). If we are saying that a module is required
to make these resources exported in order for these use cases to work,
then what are the actual use cases we want to support by hiding
resources from getResource*()?

I think there remains a common use case where hiding resources would be
a good thing if developers want to hide all the resources that are not
used by anyone through ClassLoader.getResource*() (e.g. all the .class
files). On the other hand, I think the use case where the code in the
module calls its own ClassLoader.getResource*() to retrieve private
resources directly is not very common; If this is a rare use case, I
don't think it makes sense to introduce this notion of private
resources. If we are forcing developers to export resources for the
common use cases (like ResourceBundle and ServiceLoader) anyway, then
why not require them to export resources in other cases as well?

It would help if there are some real use cases to support why it is
important to have this notion of private resources.


One very common use case comes from the EE world: web modules containing
html/gif/xml/jsp files, all of which are implementation details.

I would assume that most any app with a UI would have similar resources.



- Stanley





Re: Import specifications (was Re: Import constraints)

2007-06-12 Thread Bryan Atsatt

Bryan Atsatt wrote:

Stanley M. Ho wrote:

Hi Bryan,

Bryan Atsatt wrote:

...
By having Dependency extend Query, instances can be directly passed to
Repository.find(); no conversion required. We could obviously just make
a getter for the Query if we want, but why not make this convenient to
use?


An import dependency describes the relationship between two modules.


Agreed. And I think we would be far better off thinking of and modeling
this relationship as a general *requirement specification*, rather than
using the very narrow definition:

   name + version(s)

Clearly these are important elements of an import specification. But the
design should allow for and even support others.

One concrete example is attributes. What is the point of declaring them
on a module if they cannot be used in an import specification?


Sorry, I meant to change this before sending. I do know that you meant
for attributes to be used by higher level mechanisms (e.g.
ServiceLoader). And that is certainly a valid use case (though it isn't
entirely clear to me how this works other than by polling).

But enabling them as import specifiers seems like an even more natural
use case.


And I think these could be very valuable.

The term constraint makes sense when you think of name as the primary
specification, and everything else as modifiers of it.

But this puts all the emphasis on the wrong syLLable, IMO. What will we
do when a contract model is introduced, where attributes and
version(s) are all that is required to specify the desired contract?

Module name won't be required at all in such a specification.


So far, we have three distinct actors in the resolution process:

1. Developer: creates import specifications, using whatever selection
criteria makes sense.

2. Admin: creates import specification *filter* (ImportOverridePolicy),
mapping developer specification to fit the local environment. (Can also
use a VisibilityPolicy, but it isn't clear to me why that same
functionality can't be achieved in the override policy.)

3. Module System: locates definitions that match specifications.

All of these actors collaborate to produce a single list of candidate
definitions at runtime. If that list contains duplicate packages, the
module system must select the best fit, or fail.

Clearly the Query mechanism provides an extensible solution to the
problem in #3. And annotations give us an extensible solution to the
problem in #1.

But, just as clearly, we have a big gap in the middle: the filter model
is not a general, extensible mechanism. And I think we need to fix this.

It seems to me that the best solution is to use the *same* model to
filter as we use for lookup: Query.

(Please see the Query optimization thread for my proposal to change
Query from an opaque to a transparent type.)

So, rather than pass VersionConstraint instances through the narrow()
method, we can pass Query instances. Yes, this does make it a bit more
work to implement such a filter, but it is then a completely extensible,
symmetric model.

And this is also why I proposed that we change ImportDependency to
simply take a Query as a ctor argument:

  public ImportDependency (Query spec,
   boolean optional,
   boolean reExport) {...}

(I should have sent my optimization proposal before I suggested the
above change, so it would've made more sense. Really this would be so
much easier if you could just read my mind :^)


Further, I don't understand the need to limit the filter to only
narrowing operations. For example, why shouldn't an admin be able to
map a module *name* as well? This could be really handy (and might even
allow for elimination of the refactoring/name problem).

In fact, why not allow the admin to be able to filter *any* part of the
import specification? I would prefer to see a more generic model than
the current ImportOverridePolicy, for example:

public class ImportOverridePolicy {
   public ListImportDependency getImports(ModuleDefinition def) {
   return def.getImportDependencies();
   }

   public static ImportOverridePolicy getPolicy() {...}
   static void setPolicy(ImportOverridePolicy policy) {...}
}

The default implementation does nothing, but subtypes can perform any
transformation they want. The ModuleSystem just calls this method
instead of calling the definition directly.


It is true that we may want to query a module described in the import
dependency, but an import dependency itself is not a query. In fact,
someone may even want to query a module which contains the specific
import dependency, although I think this use case is very rare. Anyway,
it sounded like the main benefit to have import dependency extend query
is to make it easier to pass into Repository.find(). Unfortunately, once
a class is extended from another, all the public/protected
methods/fields from the parent class would automatically become part of
the signature of the child class.


No kidding? :^)


I don't

Re: Relationship to JSR 291 [was: Re: Bryan's comments]

2007-06-07 Thread Bryan Atsatt

[snip]
Richard S.Hall wrote:


My question below still stands. In general, it seems to me that
resolution consists of:

1. Selection of candidate module/bundles based on import declarations.

2. Class space consistency validation (which may narrow the list if
multiple choices, or result in a failure).

I don't understand what possible difference it could make whether we
use
a module name or a package name to select candidates in step 1. Or even
if some custom code makes that selection (though I'm not a fan of this
either.)


In general, I can say your two steps above are correct...Felix actually
has what amounts to a two-pass resolve that does (1) from above in the
first step and (2) from above in the second step. However, it turns out
that (2) is actually quite difficult and difficult to do in an
efficient way.

Perhaps it is more difficult for the OSGi framework due to some of the
sophistication of its model, e.g., package substitutability, fragments,
split packages, package-level uses constraints, etc.

All I know is that we are still finding cases that need to be clarified
in the OSGi framework for this process...

I won't say that I am disagreeing with you...if we can strip away some
of the complexity of the OSGi model, then I am sure you could implement
a reasonably straightforward resolver.


Right, that is what I'm trying to get at here. I believe *very* strongly
that import-by-name is a bad idea. Period. It is just plain wrong to do
the equivalent of import foo.jar. We can do this already, with
manifest Class-Path. Simply layering version support on it does *not*
eliminate jar-hell!

It is far too brittle, raising all kinds of maintenance issues. Under
import-by-name, refactoring *requires* introducing a facade module to
avoid breaking importers. And this facade module now becomes *another*
product artifact to be managed: documented, maintained, distributed,
deprecated, and ultimately perhaps removed.

I truly believe that the Java world will be far better served by having
277 support ONLY import-by-package!

But there has been this background fear that import-by-package is
somehow terribly complex. I can certainly believe that the union of all
the OSGi features *does* result in a lot of complexity.

I just think that is almost entirely orthogonal to *this* domain, since
we are not trying to expose all those other features.


That won't necessarily help us in achieving interoperability, though.


Absolutely; regardless of the outcome of the import-by-package issue, we
still need to deal with exactly how the loaders can share classes and
resources...

// Bryan


Re: JSR 277 EG observer mailing list

2007-06-04 Thread Bryan Atsatt

How are people supposed to find this? Shouldn't there be an easily
spotted link somewhere on the public 277 page?

// Bryan

Stanley M. Ho wrote:

Hi JSR 277 experts,

Just an update. This EG mailing list has been hooked up with the
observer list over the weekend, and you will find the public mailing
list archive here:

http://mail.openjdk.java.net/pipermail/jsr277-eg-observer/

- Stanley



Re: Exported resources

2007-05-31 Thread Bryan Atsatt

I don't think I'm missing anything, just looking at it from perhaps a
different perspective :^)

First, 294 will determine accessibility for non-exported classes. The
assumption at the moment is that they will not be accessible to *any*
class outside of the module.

I do understand the value of a friend semantic; it would certainly be
nice to grant certain frameworks special access. But, so far, that is
not on the table for classes.

And if we don't have it for classes, I can't see why we should have it
for resources.

// Bryan

Glyn Normington wrote:


Some feedback from an observer which may help:

  Bryan misses the need for extender model to load internal impl
classes ala
  Bundle.loadClass in OSGi.
 
  You do not want to have to export the service impl class from a module.
  You want to hide the class from others' casual loading. However an
  extender bundle (e.g. ServiceLoader) will need to be able to load that
  class to make it instances of it available to others under the service
  interface class.

Glyn

*Bryan Atsatt [EMAIL PROTECTED]* wrote on 30/05/2007 21:21:36:

  I've been assuming that Module private resources should not be visible
  to *any* class outside of the module. Including ResourceBundle, or any
  other existing framework classes that do resource lookups (e.g.
  ServiceLoader, JSF, etc). If resources need to be visible to these
  existing classes, they must be exported. The very simple check I
  proposed (immediate caller) is sufficient to make this assertion.
 
  I believe your point is that if we used the permission model instead, it
  would become possible for a module to invoke an external class (e.g.
  ResourceBundle.getBundle()) and enable *it* to successfully load a
  private resource from the module.
 
  Aside from the permission *grant* mechanism this model would rely on, it
  is an entirely different model than that used for classes! (Though we
  haven't explicitly defined this in 294, it seems extremely unlikely that
  we will rely on permissions--none of the other access modes do so.) Such
  asymmetry is very disconcerting to me, and, I believe, just plain
wrong...
 
  Consider that you could grant the ServiceLoader, for example, access to
  a resource that names a class that it could not instantiate. That class
  would have to be exported. I believe the resource should be as well.
 
  // Bryan
 
 
 
 
  Stanley M. Ho wrote:
   Hi Bryan,
  
   Those resource-related methods in ClassLoader can be called by anyone,
   including code that is part of the module, code that is from other
   modules, or code that is part of the platform libraries (e.g.
   ResourceBundle). The approach you described would require walking the
   stack to get the caller's Module, but the real issue is that it is
   difficult to determine who the actual caller is from the stack.
  
   Treating the immediate caller on the stack as the actual caller
wouldn't
   be sufficient because the immediate caller could be called by someone
   else who is the one actually making the call. On the other hand,
   treating the originated caller on the stack as the actual caller would
   be the right semantic, but this is basically the same as the security
   permission approach.
  
   - Stanley
  
  
   Bryan Atsatt wrote:
   Both solutions require stack walking (unless there is some new
   implementation of the java security model I've not yet seen!).
  
   The permission check does much more work than is necessary here.
Take a
   look at AccessController.checkPermission() to see what I mean.
  
   And actually there is a very simple API to get the stack, which I've
   used for years:
  
 private static class StackAccessor extends SecurityManager {
 public Class[] getStack() {
 return getClassContext();
 }
 }
  
 private static final STACK_ACCESSOR = new StackAccessor();
  
   Now the enclosing class can simply call STACK_ACCESSOR.getStack().
  
   // Bryan
  
  
  
   Stanley M. Ho wrote:
   Hi Bryan,
  
   Bryan Atsatt wrote:
   1. Definitely agree that resource search order should be
identical to
   class search order.
  
   Glad to hear!
  
   2. Using permissions to limit access to private resources seems like
   overkill to me. The prototype implemented this in a very simple
   fashion:
  
   a. If resource is exported, return it, else
   a. Get the caller's Module (get class from stack, get module
from it)
   b. If callerModule == this, return resource, else return null.
  
   The issue is that this approach still requires stack walking and
there
   is no public API in the SE platform that let you implement this.
  
   If stack walking is required for the check anyway, I think the
security
   permission approach is better that it is implementable with the
existing
   API in the SE platform.
  
   - Stanley
  
  





/
/

/Unless stated otherwise above:
IBM United Kingdom Limited - Registered

Re: Relationship to JSR 291 [was: Re: Bryan's comments]

2007-05-30 Thread Bryan Atsatt

Responses inline, and a few clarifications here (I was a bit tired when
I finished this last night :^)...

The main point I was trying to make is that resolution must occur within
a specific context, but I don't think my example APIs showed that well.
I was assuming that ImportResolver had a ModuleContext as a field, but
we can make this much cleaner and easier to understand by passing it as
an argument:

public abstract class ImportResolver {
public abstract Module resolve(ModuleDefinition def,
   ModuleContext ctx);
}

And we can really tie this together by adding a convenience method to
ModuleContext:

public abstract class ModuleContext {
...
public Module resolve(ModuleDefinition def) {
return getImportResolver().resolve(def, this);
}
}

Now resolution becomes simply:

context.resolve(definition);


(I also left out any use of the ImportPolicy, as it isn't yet clear to
me that it should remain a separate type in this model.)

// Bryan

Glyn Normington wrote:


*Bryan Atsatt [EMAIL PROTECTED]* wrote on 30/05/2007 07:57:59:

  Andy Piper wrote:
At 23:19 25/05/2007, Stanley M. Ho wrote:
Anyway, it seems the EG consensus so far is to not add import package
support. If any EG member disagrees, please speak up.
   
Well, it depends on what the solution for enabling interoperation
with JSR 291 is.
Our requirement is that there must be a solution, if that requires
import package, so be it. If not then not.
 
  Exactly.
 
  I think we can all agree that, at minimum, interoperation means that
  classes and resources are sharable *across* ModuleSystems at runtime.
 
  Which implies that *import dependencies must be resolvable across
  multiple ModuleSystem instances*. (BTW, I think we should change the
  state name PREPARING to RESOLVING in 7.2.1.)

Agreed. We must avoid the trap of thinking that module system interop.
can be achieved by exposing class loaders (as loadClass will happily
load unexported classes).

 
  So the open issue is the richness of the import language: must we
  support only lowest-common-denominator, or can we do better without
  over-complicating the design?
 
  I for one would like to be able to have a single module express
  dependencies on modules from both the same and different ModuleSystems,
  *using the standard semantics of each*. This may be reaching too far,
  but we should at least explore it seriously while we figure out what
  interop means here...

At this point, I feel that is likely to be reaching too far, but I'm
happy to play along and see what we can learn along the way.

 
 
  BASICS
 
  So far, we only know of two different import semantics: module-name, and
  package-name. For discussion, let's call these:
 
  a. import-module
  b. import-package
 
  So, to start, we could:
 
  1. Support declaration of both import types. If 294 supports imports at
  all, it should be relatively easy to support both, since a superpackage
name is a module name, and it contains member package names. (Compiler
  support is clearly the critical issue here, but it will obviously
  require use of the 277 runtime, so the import *type* should be
  transparent to it.) At worst, we'd need two new annotation types.

A superpackage name is a deployment module name in the JSR 277 model of
one superpackage per deployment module, but I don't see any reason why a
JSR 291 deployment module should not contain more than one superpackage.
So if 294 were to support import, then its import-module would really be
a superpackage import rather than a development module import.


If we end up with nested superpackages, might it make sense to model
multiple superpackages by enclosing them in a single top-level one?



 
  2. Provide API for both import types (e.g. ImportDependency has
  getModuleName() and getPackageName() methods, one of which will return
  null on a given instance).
 
  However, we know these are necessary but not sufficient. Leaving aside
  the resolution issue for a moment, support for import-package also
  suggests that we:
 
  3. Enable a single module to declare different versions for each of its
  member packages.
 
  4. Enable efficient Repository lookup by package name.
 
  I think these are relatively easy (but *could* be considered optional).
 
  We also need:
 
  5. Standard Query types for lookup by module and package name.
 
 
  EXISTING DEPENDENCY RESOLUTION MODEL
 
  The more interesting issue is dependency resolution. But this hasn't
  been discussed in any real detail, so lets do so before talking further
  about import-package. To simplify this discussion, I'm ignoring
  bundled/custom import policies for now...
 
  Resolution in the current spec is delegated to the associated
  ModuleSystem instance (7.2.2 #8). While the details are not spelled out,
  the expectation appears to be that
  ModuleSystem.getModule(ModuleDefinition) must:
 
  - Select an initial repository. Call

Re: Exported resources

2007-05-30 Thread Bryan Atsatt

I've been assuming that Module private resources should not be visible
to *any* class outside of the module. Including ResourceBundle, or any
other existing framework classes that do resource lookups (e.g.
ServiceLoader, JSF, etc). If resources need to be visible to these
existing classes, they must be exported. The very simple check I
proposed (immediate caller) is sufficient to make this assertion.

I believe your point is that if we used the permission model instead, it
would become possible for a module to invoke an external class (e.g.
ResourceBundle.getBundle()) and enable *it* to successfully load a
private resource from the module.

Aside from the permission *grant* mechanism this model would rely on, it
is an entirely different model than that used for classes! (Though we
haven't explicitly defined this in 294, it seems extremely unlikely that
we will rely on permissions--none of the other access modes do so.) Such
asymmetry is very disconcerting to me, and, I believe, just plain wrong...

Consider that you could grant the ServiceLoader, for example, access to
a resource that names a class that it could not instantiate. That class
would have to be exported. I believe the resource should be as well.

// Bryan




Stanley M. Ho wrote:

Hi Bryan,

Those resource-related methods in ClassLoader can be called by anyone,
including code that is part of the module, code that is from other
modules, or code that is part of the platform libraries (e.g.
ResourceBundle). The approach you described would require walking the
stack to get the caller's Module, but the real issue is that it is
difficult to determine who the actual caller is from the stack.

Treating the immediate caller on the stack as the actual caller wouldn't
be sufficient because the immediate caller could be called by someone
else who is the one actually making the call. On the other hand,
treating the originated caller on the stack as the actual caller would
be the right semantic, but this is basically the same as the security
permission approach.

- Stanley


Bryan Atsatt wrote:

Both solutions require stack walking (unless there is some new
implementation of the java security model I've not yet seen!).

The permission check does much more work than is necessary here. Take a
look at AccessController.checkPermission() to see what I mean.

And actually there is a very simple API to get the stack, which I've
used for years:

  private static class StackAccessor extends SecurityManager {
  public Class[] getStack() {
  return getClassContext();
  }
  }

  private static final STACK_ACCESSOR = new StackAccessor();

Now the enclosing class can simply call STACK_ACCESSOR.getStack().

// Bryan



Stanley M. Ho wrote:

Hi Bryan,

Bryan Atsatt wrote:

1. Definitely agree that resource search order should be identical to
class search order.


Glad to hear!


2. Using permissions to limit access to private resources seems like
overkill to me. The prototype implemented this in a very simple
fashion:

a. If resource is exported, return it, else
a. Get the caller's Module (get class from stack, get module from it)
b. If callerModule == this, return resource, else return null.


The issue is that this approach still requires stack walking and there
is no public API in the SE platform that let you implement this.

If stack walking is required for the check anyway, I think the security
permission approach is better that it is implementable with the existing
API in the SE platform.

- Stanley





Re: Exported resources

2007-05-30 Thread Bryan Atsatt

Hey Stanley,

Sorry to be generating so much traffic while you're traveling! I'm not
in any rush here, so feel free to take your time responding...

Stanley M. Ho wrote:

Hi Bryan,

A module can use the ResourceBundle API to retrieve resources from other
resource modules, but it can also use the ResourceBundle API to retrieve
resources from the (target) module itself. In the latter case, the
resources are currently not required to be exported from the target module.

I don't think we want to force a module to export its own private
resources simply because it wants to use the ResourceBundle API in this
case, would you agree?


No, I don't agree. That's what I said before :^). I *really* don't like
the idea that I'm going to have to explicitly grant permission to some
module to access my resource. This *significantly* complicates
deployment. How will the grant occur, especially given that each
environment can use an entirely different permission storage mechanism?

Or are you thinking that the loaders in the module system will construct
ProtectionDomains pre-wired with permissions? If so, exactly which
entities will be blessed? Just the JRE code? What about all the existing
non-JRE frameworks in use?


Regarding there are differences in the access models between classes and
resources, I also prefer symmetry if possible. However, the access model
for classes and resources have always been different, and there are
built-in JVM support for classes while there is none for resources, so
it is unclear if we can completely eliminate this asymmetry after all.


Sure, resources have never had JVM access control applied to them. But I
don't think we should go to the other extreme (permissions) just so that
I can give friend access to private resources. I'd much prefer that
such resources simply be exported.

And I don't see this as a particular problem, either. We've gotten along
just fine without private resources so far (or maybe there is some big
demand for this that I'm missing?).

And what about the mismatch issue I brought up? Lots of existing
frameworks use the services pattern, in which:

1. A well known resource name is used in a getResource() call.
2. The resource contains a string naming a provider class.
3. The provider class is loaded using Class.forName().

This is a simple but very powerful pattern, but it requires that *both*
the resource and the named class be accessible to the framework. If we
require a permission grant for the resource, but not for the class, it
will be very easy to get access to one and not the other. Is it really
worth opening up this potential headache to enable a friend model for
resources?

// Bryan



- Stanley


Bryan Atsatt wrote:

I've been assuming that Module private resources should not be visible
to *any* class outside of the module. Including ResourceBundle, or any
other existing framework classes that do resource lookups (e.g.
ServiceLoader, JSF, etc). If resources need to be visible to these
existing classes, they must be exported. The very simple check I
proposed (immediate caller) is sufficient to make this assertion.

I believe your point is that if we used the permission model instead, it
would become possible for a module to invoke an external class (e.g.
ResourceBundle.getBundle()) and enable *it* to successfully load a
private resource from the module.

Aside from the permission *grant* mechanism this model would rely on, it
is an entirely different model than that used for classes! (Though we
haven't explicitly defined this in 294, it seems extremely unlikely that
we will rely on permissions--none of the other access modes do so.) Such
asymmetry is very disconcerting to me, and, I believe, just plain
wrong...

Consider that you could grant the ServiceLoader, for example, access to
a resource that names a class that it could not instantiate. That class
would have to be exported. I believe the resource should be as well.

// Bryan