> I think the following is a reasonable solution.
> 
> If the JarFile is constructed with any of the 5 constructors that do not 
> contain a Release argument, then entries()/stream() returns the set of all 
> entries in the jar file including those under the 
> META-INF/versions/directory.  The base entries are “raw”, they are not 
> aliases for versioned entries.
> 
> If the JarFile is constructed with the 1 constructor that does include a 
> Release argument, then entries()/stream() returns the set of appropriately 
> versioned entries that would result from invoking getEntry()/getJarEntry() 
> with the name of each base entry.  The entries in the tree rooted at the 
> directory META-INF/versions/ are not returned.

I created a new webrev, http://cr.openjdk.java.net/~sdrach/8132734/webrev.05/ 
<http://cr.openjdk.java.net/~sdrach/8132734/webrev.05/>, that implements what I 
outlined above.  In particular I enhanced the JarEntryIterator class and I 
added additional commentary to the entries() and stream() methods.  I also 
added a new test, MultiReleaseJarIterators, to test entries() and stream().

 

> 
>> On Feb 1, 2016, at 12:29 PM, Steve Drach <steve.dr...@oracle.com> wrote:
>> 
>> I’m sorry, I didn’t look at the code close enough before I started talking 
>> ;-)  Right now entries()/stream() returns all entries and if the JarFile is 
>> constructed with a Release object != Release.BASE, the base entries that are 
>> returned are the versioned entries.  I think this behavior is a bit 
>> confusing and we should just return all entries without regard to 
>> versioning.  Then create the two new methods for specific versioned entries.
>> 
>>> On Feb 1, 2016, at 12:18 PM, Steve Drach <steve.dr...@oracle.com> wrote:
>>> 
>>>>>>> Alan’s point is that traversing using entries()/stream() always returns 
>>>>>>> the versioned entries (if any) rather than all entries, thus in a sense 
>>>>>>> filters.
>>>>>>> 
>>>>>>> My assumption was the traversal should by default be consistent with a 
>>>>>>> calls to getEntry, thus:
>>>>>>> 
>>>>>>> jarFile.stream().forEach(e ->  {
>>>>>>>  JarEntry je = jarFile.getJarEntry(e.getName());
>>>>>>>  assert e.equals(je);
>>>>>>> });
>>>>>>> 
>>>>>>> There might need to be another stream method that returns all entries.
>>>>>>> 
>>>>>> Right, I'm mostly just wondering if entries()/streams() should override 
>>>>>> the entries in the stream with versioned entries and filter out the 
>>>>>> META-INF/versions/ tree.
>>>>> I don’t think so.  That kind of behavior might be difficult to 
>>>>> understand.  Returning all the entries provides some flexibility.  One 
>>>>> can write code like this:
>>>>> 
>>>>> jarfile.stream().map(JarEntry::getName).filter(s ->  
>>>>> !s.startsWith(“META-INF”)).map(JarFile::getJarEntry).etc
>>>>> 
>>>>> to get the versioned results for any version you specify when 
>>>>> constructing the JarFile.
>>>> 
>>>> The current specification treats those class files under meta-inf/releases 
>>>> like
>>>> kind of "metadata" of those base entries. Ideally those files should not 
>>>> even
>>>> be individual "files", but part of their corresponding entries. The 
>>>> consumer of
>>>> the MR-Jar should not need to be aware of these version-ed entries at all 
>>>> to use
>>>> this MR-jar file to load classes/resources. From this point of view, these 
>>>> entries
>>>> probably should be "invisible" from entries()/stream(), when the jar file 
>>>> is opened
>>>> with "version-enabled". And all returned entries should have all their 
>>>> "data"
>>>> (size, csize, timestamps, crc ...) pointed to the corresponding version-ed 
>>>> entries,
>>>> withe the only exception is the "name".
>>>> 
>>>> On the other hand it might be desired to keep JarFile.entries()/stream() 
>>>> asis to
>>>> match their "zip file" perspective, to return "all" raw entries. Then it 
>>>> might also
>>>> be desired to have an alternative "versioned streamVersion()" …
>>> 
>>> It seems to that we have two reasonable alternatives: (1) return all 
>>> entries, and (2) return all entries except those under the 
>>> “META-INF/versions/“ directory and for any entries returned, return their 
>>> versioned equivalent if it exists.  If we choose alternative 2, we can 
>>> still get alternative 1 by asking for JarFile.super.entries() and 
>>> JarFile.super.stream().
>>> 
>>> Or we can do it both ways, leaving entries()/stream() as is and adding two 
>>> new methods, versionedEntries() and versionedStream().
>>> 
>>>> 
>>>> something like
>>>> 
>>>> public Stream<JarEntry> stream(Release r); ?
>>> 
>>> We should not parametrize the methods with a Release, because what does it 
>>> mean if we construct the JarFile with one Release but specify a different 
>>> Release for the stream argument.  Parameterizing methods with a Release 
>>> object feels like we’re starting to slide down a slippery slope.
>>> 
>>> I think adding the two new methods is the “right” solution, but I’d like 
>>> some consensus here.
>>> 
>>>> 
>>>> -sherman
>>>> 
>>>> 
>>>> 
>>>> 
>>>>>> If I've gone to trouble of specifying the a Release then it seems the 
>>>>>> right thing to do. On the other hand, it comes at a cost and there will 
>>>>>> be use-cases like "get the names of all entries" that would be more 
>>>>>> efficient to just build on the current entries()/stream(). I'm loath to 
>>>>>> suggest this might need a new method but it might be one of the options 
>>>>>> to consider here. Minimally there is a javadoc to specify on how these 
>>>>>> methods behave when the JAR is multi-release and opened by specifying a 
>>>>>> release.
>>>>> How’s this?
>>>>> 
>>>>> diff -r 68867430065b 
>>>>> src/java.base/share/classes/java/util/jar/JarFile.java
>>>>> --- a/src/java.base/share/classes/java/util/jar/JarFile.java      Fri Jan 
>>>>> 29 12:34:44 2016 -0800
>>>>> +++ b/src/java.base/share/classes/java/util/jar/JarFile.java      Mon Feb 
>>>>> 01 09:48:05 2016 -0800
>>>>> @@ -576,9 +576,11 @@
>>>>>   }
>>>>> 
>>>>>   /**
>>>>> -     * Returns an enumeration of the jar file entries.
>>>>> +     * Returns an enumeration of all the jar file entries.  Constructing 
>>>>> this
>>>>> +     * JarFile with the {@link JarFile#JarFile(File, boolean, int, 
>>>>> Release)}
>>>>> +     * constructor does not modify the behavior of this method.
>>>>>    *
>>>>> -     * @return an enumeration of the jar file entries
>>>>> +     * @return an enumeration of the all jar file entries
>>>>>    * @throws IllegalStateException
>>>>>    *         may be thrown if the jar file has been closed
>>>>>    */
>>>>> @@ -587,11 +589,13 @@
>>>>>   }
>>>>> 
>>>>>   /**
>>>>> -     * Returns an ordered {@code Stream} over the jar file entries.
>>>>> +     * Returns an ordered {@code Stream} over all the jar file entries.
>>>>>    * Entries appear in the {@code Stream} in the order they appear in
>>>>> -     * the central directory of the jar file.
>>>>> +     * the central directory of the jar file.  Constructing this
>>>>> +     * JarFile with the {@link JarFile#JarFile(File, boolean, int, 
>>>>> Release)}
>>>>> +     * constructor does not modify the behavior of this method.
>>>>>    *
>>>>> -     * @return an ordered {@code Stream} of entries in this jar file
>>>>> +     * @return an ordered {@code Stream} of all entries in this jar file
>>>>>    * @throws IllegalStateException if the jar file has been closed
>>>>>    * @since 1.8
>>>>>    */
>> 
> 

Reply via email to