Hi Sergey, Thanks for pointing it out. It looks like redundant try-catch block. I have removed these blocks in write() methods so that we are handling "cant create cache file" exception in common way in all read() and write() methods. Also I have updated test case description to hold true for only those read() and write() methods where we are using createImageXXXStream() for readability.
Please find updated webrev for review: http://cr.openjdk.java.net/~jdv/8044289/webrev.06/ After CCC is done we will push above change to repo. Thanks, Jay -----Original Message----- From: Sergey Bylokhov Sent: Tuesday, March 29, 2016 6:11 PM To: Philip Race; Jayathirth D V Cc: 2d-dev@openjdk.java.net Subject: Re: [OpenJDK 2D-Dev] Review Request for JDK-8044289 : In ImageIO.read() and write() NPE is not handled properly for stream I am not sure what is the reason of this code? 1546 try { 1547 output.delete(); 1548 stream = createImageOutputStream(output); 1549 } catch (IOException e) { 1550 throw e; 1551 } On 29.03.16 1:12, Philip Race wrote: > This all looks fine to me. Although no new Exception types are thrown > I think we need a CCC anyway, so please prepare and get that approved > before pushing. > > -phil. > > On 3/28/16, 3:30 AM, Jayathirth D V wrote: >> >> Hi Phil, >> >> After discussion with Sergey we have come to conclusion that Sergey >> is okay with throwing exception or returning null/false. >> >> So I have modified the webrev to throw exception. >> >> Also in write() I have modified the catch block to just throw the >> caught exception without adding message since it will create >> confusion between the case where we are not able to create cache and >> when >> createImageOutputStream() returns null. >> >> Regarding catch block of createImageOutputStream() only when we >> usecache is true we use FileCacheImageOutputStream() and it throws >> IOException so I think there is no need to add extra check before >> throwing IOException. >> >> Please find updated webrev for review : >> >> http://cr.openjdk.java.net/~jdv/8044289/webrev.04/ >> <http://cr.openjdk.java.net/%7Ejdv/8044289/webrev.04/> >> >> Thanks, >> >> Jay >> >> *From:*Jayathirth D V >> *Sent:* Thursday, March 24, 2016 3:52 PM >> *To:* Philip Race >> *Cc:* Sergey Bylokhov; 2d-dev@openjdk.java.net >> *Subject:* RE: [OpenJDK 2D-Dev] Review Request for JDK-8044289 : In >> ImageIO.read() and write() NPE is not handled properly for stream >> >> Hi Phil, >> >> We can change the code to something like : >> >> 1522 * @return <code>false</code> if no appropriate writer is >> found or >> 1523 * when needed stream is null. >> >> 1545 try { >> 1546 output.delete(); >> 1547 stream = createImageOutputStream(output); >> 1548 } catch (IOException e) { >> 1549 *throw e;* >> 1550 } >> >> In this case we will be throwing IOException when we are not able to >> create cache file and stream is null. >> >> And return null/false when createImageXXXStream returns null. Also we >> can add check before throwing IIOException from createImageXXXStream >> for usecache. >> >> 350 >> 351 boolean usecache = getUseCache() && hasCachePermission(); >> 352 >> 353 while (iter.hasNext()) { >> 354 ImageInputStreamSpi spi = iter.next(); >> 355 if (spi.getInputClass().isInstance(input)) { >> 356 try { >> 357 return spi.createInputStreamInstance(input, >> 358 usecache, >> 359 >> getCacheDirectory()); >> 360 } catch (IOException e) { >> 361 *if (usecache)* >> 362 throw new IIOException("Can't create cache >> file!", e); >> 363 } >> 364 } >> 365 } >> >> This will be one of the approach. >> >> Or we can throw IOException in all the cases with additional check in >> createImageXXXStream for usecache. This will be like throwing >> IOException when createImageXXXStream returns null/false or it throws >> IIOException when it cant create cache file. This will be another >> approach. Please let us know your inputs. >> >> Thanks, >> >> Jay >> >> *From:*Philip Race >> *Sent:* Thursday, March 24, 2016 5:10 AM >> *To:* Jayathirth D V >> *Cc:* Sergey Bylokhov; 2d-dev@openjdk.java.net >> <mailto:2d-dev@openjdk.java.net> >> *Subject:* Re: [OpenJDK 2D-Dev] Review Request for JDK-8044289 : In >> ImageIO.read() and write() NPE is not handled properly for stream >> >> I don't think this is ready and we need to discuss whether to rework it. >> >> In general I think I prefer IIO rather than null when we have a stream >> problem. >> >> >> For one thing you have this change :- >> >> 1522 * @return <code>false</code> if no appropriate writer is >> found or >> 1523 * not able to create required ImageOutputStream. >> yet the implementation says :- >> 1545 try { >> 1546 output.delete(); >> 1547 stream = createImageOutputStream(output); >> 1548 } catch (IOException e) { >> 1549 throw new IIOException("Can't create output stream!", e); >> 1550 } >> So whilst "null" would mean we cannot find an IOS SPI it isn't the >> only reason we fail to create the IOS A null return seems to get >> passed through to doWrite() which probably throws IIOE And I think >> that the implementation is actually right here where it throws an >> exception. >> The ability to create an image input or output stream could be >> because of some kind of problem opening the file, or with the IIS or >> IOS implementations - like they were de-registered. I think in many >> if not all of these cases IOE - or IIOE is what we want. >> Also since we call createImageInputStream() - which is public - we >> need to look at that, and what it does, which is also something to consider. >> If it returns null, that seems to mean that no suitable SPI is >> registered which can only happen if they are de-registered. For the >> methods where we use createImageInputStream() I think it is fair to >> turn that into IIOE BTW I note that the code there says :- >> 350 >> 351 boolean usecache = getUseCache() && hasCachePermission(); >> 352 >> 353 while (iter.hasNext()) { >> 354 ImageInputStreamSpi spi = iter.next(); >> 355 if (spi.getInputClass().isInstance(input)) { >> 356 try { >> 357 return spi.createInputStreamInstance(input, >> 358 usecache, >> 359 >> getCacheDirectory()); >> 360 } catch (IOException e) { >> 361 throw new IIOException("Can't create cache file!", >> e); >> 362 } >> 363 } >> 364 } >> So far I can see that means it will claim any Exception that is >> generated is because it could not create the cache file without any proof of >> that and even if "useCache" is false. >> It seems to imply to me that the author was not considering things >> like someone passing a closed InputStream .. probably we ought to be >> more vague in this case or look more deeply at what we can tell from whether >> it is IIOE or IOE. >> -phil. >> >> On 3/22/16, 10:49 AM, Jayathirth D V wrote: >> >> Thanks for the review Sergey. >> >> Can I get +1 for this please? >> >> -Jay >> >> -----Original Message----- >> >> From: Sergey Bylokhov >> >> Sent: Tuesday, March 22, 2016 9:52 PM >> >> To: Jayathirth D V; Philip Race >> >> Cc:2d-dev@openjdk.java.net <mailto:2d-dev@openjdk.java.net> >> >> Subject: Re: [OpenJDK 2D-Dev] Review Request for JDK-8044289 : In >> ImageIO.read() and write() NPE is not handled properly for stream >> >> This fix looks fine to me. >> >> At least it made all code work in a similar way. But probably someone >> will have other opinion? >> >> On 22.03.16 12:34, Jayathirth D V wrote: >> >> Hi Sergey, >> >> I have unified changes related to ImageIO.read() and ImageIO.write(). >> >> In case of read() we will be returning null when >> createImageInputStream() returns null. >> >> In case of write() we will be returning false when >> createImageOutputStream() returns null. >> >> Please find updated webrev for review: >> >> http://cr.openjdk.java.net/~jdv/8044289/webrev.03/ >> <http://cr.openjdk.java.net/%7Ejdv/8044289/webrev.03/> >> >> Thanks, >> >> Jay >> >> -----Original Message----- >> >> From: Sergey Bylokhov >> >> Sent: Tuesday, March 22, 2016 7:39 AM >> >> To: Jayathirth D V; Philip Race >> >> Cc:2d-dev@openjdk.java.net <mailto:2d-dev@openjdk.java.net> >> >> Subject: Re: [OpenJDK 2D-Dev] Review Request for JDK-8044289 >> : In >> >> ImageIO.read() and write() NPE is not handled properly for >> stream >> >> Hi, Jay. >> >> Since we decided to update the specification we get an additional >> flexibility in the fix, because we can update the "@exception IOException" >> part of javadoc and describe that it can be thrown if ImageXXXStream cannot >> be created. >> >> I don't see a big differences of both approaches in case of write() >> methods, but in case of read(which has the similar issue but was skipped in >> the fix) there is a difference. >> >> Note that the read(File) unlike other methods throws the >> unspecified >> >> IIOException exception if ImageXXXStream cannot be created. >> We can >> >> think about unification of read/write methods in ImageIO. Hmm >> but even >> >> then >> >> read() in some cases will return null and in some cases throw an >> exception.... >> >> and createImageInputStream/createImageOutputStream() will look alien >> as they always return null not an exception. >> >> Another possible unification is to update javadoc for all >> methods, >> >> that they will return null if related providers are not >> found(in this >> >> case "throw new IIOException("Can't create an ImageInputStream!"))" >> >> should be removed from read(File); >> >> On 21.03.16 10:26, Jayathirth D V wrote: >> >> Hi Sergey, >> >> For the second approach I have created webrev for review. >> >> Please review updated webrev : >> >> http://cr.openjdk.java.net/~jdv/8044289/webrev.02/ >> <http://cr.openjdk.java.net/%7Ejdv/8044289/webrev.02/> >> >> Thanks, >> >> Jay >> >> -----Original Message----- >> >> From: Jayathirth D V >> >> Sent: Friday, March 18, 2016 2:23 PM >> >> To: Sergey Bylokhov >> >> Cc:2d-dev@openjdk.java.net >> <mailto:2d-dev@openjdk.java.net>; Philip Race >> >> Subject: RE: [OpenJDK 2D-Dev] Review Request for >> JDK-8044289 : In >> >> ImageIO.read() and write() NPE is not handled properly >> for stream >> >> Hi Sergey, >> >> Thanks for your inputs. >> >> Indeed all the null values returned by createImageInputStream() >> and createImageInputStream() are valid only. >> >> I went through the code more and found that there is no need for >> fix in ImageIO.read() methods as null stream is handled in >> read(ImageInputStream stream) which is called by all the remaining read() >> API's through IAE. So i can remove the changes made in ImageIO.read() >> functions. Also istream is closed in finally block of read(url). >> >> For ImageIO.write(File) & ImageIO.write(OutputStream) NPE we >> have two approaches for fix: >> >> 1) Keep the present changes of throwing IOException when stream >> is null and change the throw clause of write() spec mentioning: >> >> "IOException - if an error occurs during writing or not >> able to create required ImageOutputStream" >> >> 2) Remove the present changes and handle null in doWrite() >> method by returning false when stream is null & add code in finally block to >> close the stream only when stream is not null. Along with this we can >> also change Returns clause of spec to mention that write() might return >> false when we are not able to create ImageOutputStream. >> >> >> >> private static boolean doWrite(RenderedImage >> im, ImageWriter writer, >> >> >> >> ImageOutputStream output) throws IOException { >> >> if (writer == null) { >> >> return false; >> >> } >> >> + if (output == null) { >> >> + return false; >> >> + } >> >> >> >> try { >> >> return doWrite(im, >> writer, stream); >> >> } finally { >> >> + if (stream != null) >> >> stream.close(); >> >> } >> >> >> >> Returns : >> >> false if no appropriate writer is found or not >> able to create required ImageOutputStream. >> >> Please let me know your inputs. >> >> Thanks, >> >> Jay >> >> -----Original Message----- >> >> From: Sergey Bylokhov >> >> Sent: Friday, March 18, 2016 12:24 AM >> >> To: Jayathirth D V >> >> Cc:2d-dev@openjdk.java.net >> <mailto:2d-dev@openjdk.java.net>; Philip Race >> >> Subject: Re: [OpenJDK 2D-Dev] Review Request for >> JDK-8044289 : In >> >> ImageIO.read() and write() NPE is not handled properly >> for stream >> >> On 17.03.16 21:14, Jayathirth D V wrote: >> >> There are many places in createImageInputStream() and >> createImageOutputStream() where it will return null for stream. >> >> But when why you change the write/read methods? They should take >> null into account and work according to specification. If some bogus null >> returns from createImageInputStream/createImageOutputStream then it should >> be fixed in these methods. >> >> So for NPE described in bug to occur there can be multiple >> paths: >> >> 1) One of the path described in bug is when >> theRegistry.getServiceProviders() throws IAE and we return null. >> >> This is the case when we have no installed spi and should return >> null/false. >> >> 2) When we pass non-existent file path to ImageIO (as >> described >> inhttp://stackoverflow.com/questions/11153200/with-imageio-write-api-call-i-get-nullpointerexception >> ). Here we catch FileNotFoundException but still we return stream as null >> at the end which will cause NPE further. >> >> This is same thing described in the bug(about stream.close()). >> The write method call createImageOutputStream() and got >> FileNotFoundException. >> >> This exception should be propagated to the user, but it is >> replaced in the finally block, because we try to close the stream=null. So >> the fix for this particular case is to check the stream to null in finally, >> No? >> >> 3) When we don't support the provider and >> theRegistry.getServiceProviders() return iterator with size zero. >> >> This means that our providers do not support this case, and we >> should return null/false. >> >> For us to follow first scenario we need access to >> categoryMap of IIORegistry and delete the ImageInputStreamSpi/ >> ImageOutputStreamSpi but I was not able to find a way to tamper it from test >> case. If we follow second case FileNotFoundException will be thrown by >> default eventhough we handle NPE. >> >> But you change the code and we now contradicts the >> specification, in your case the test should expect false/null from >> write()/read(). >> >> In the test case we are trying to following third scenario >> to get stream as null to verify the code changes. >> >> To catch the bogus null we should try to use another approach, >> or change the spec. But it seems all null values above are correct, we >> should be ready for them. >> >> As part of collective fix we are throwing IOException which >> will indicate that we are not able to create required stream. >> >> Thanks, >> >> Jay >> >> -----Original Message----- >> >> From: Sergey Bylokhov >> >> Sent: Thursday, March 17, 2016 7:27 PM >> >> To: Phil Race >> >> Cc: Jayathirth D V;2d-dev@openjdk.java.net >> <mailto:2d-dev@openjdk.java.net> >> >> Subject: Re: [OpenJDK 2D-Dev] Review Request for >> JDK-8044289 : In >> >> ImageIO.read() and write() NPE is not handled >> properly for stream >> >> On 17.03.16 0:36, Phil Race wrote: >> >> I don't think that is the actual reason here >> >> But the test doing exactly this thing -> deregister >> all spi => in >> >> this case according to specification all related >> >> >> methods(read/write/creatImageInputStream/creatImageOutputStream) should >> return null or false. >> >> - it seems likely that there >> >> was some kind of internal error or bad SPI causing this. >> >> So throwing an exception seems more appropriate. >> >> the problem was in some of our methods which do not expect >> null in some places(like stream.close() from the bug description). >> >> And also the bug was originally solely about write(..). >> >> -phil. >> >> On 03/16/2016 01:35 PM, Sergey Bylokhov wrote: >> >> As far as I understand the >> createImageInputStream() returns null >> >> is this stream is unsupported by current >> plugins via spi. Probably >> >> the >> >> read() method should return null too? >> >> /** >> >> * Returns a {@code BufferedImage} as >> the result of decoding >> >> * a supplied {@code InputStream} >> with an {@code ImageReader} >> >> * chosen automatically from among those >> currently registered. >> >> * The {@code InputStream} is wrapped >> in an >> >> * {@code ImageInputStream}. If no >> registered >> >> * {@code ImageReader} claims to be >> able to read the >> >> * resulting stream, {@code null} is >> returned. >> >> * >> >> ....... >> >> * @return a {@code BufferedImage} >> containing the decoded >> >> * contents of the input, or {@code null}. >> >> */ >> >> public static BufferedImage >> read(InputStream input) throws >> >> IOException >> >> On 16.03.16 20:29, Philip Race wrote: >> >> The test writes out into "test.src". >> >> I believe that you should treat that as a >> "read-only" location. >> >> Write to a tempfile (File.createTempFile()) or >> TESTCLASSES. >> >> -phil. >> >> On 3/15/16, 10:50 PM, Jayathirth D V wrote: >> >> Hi Phil,All >> >> _Please review the following fix in >> JDK9:_ >> >> __ >> >> Bug >> :https://bugs.openjdk.java.net/browse/JDK-8044289 >> >> Webrev >> :http://cr.openjdk.java.net/~jdv/8044289/webrev.00/ >> >> <http://cr.openjdk.java.net/%7Ejdv/8044289/webrev.00/> >> >> >> <http://cr.openjdk.java.net/%7Ejdv/8044289/webrev.00/> >> >> <http://cr.openjdk.java.net/%7Ejdv/8044289/webrev.00/> >> >> Issue : When createImageInputStream() >> or createImageOutputStream >> >> returns null in ImageIO.read() or >> ImageIO.write() we are seeing >> >> NPE as it stream is used further without >> null check. >> >> Root cause : "stream" is used without >> checking whether it is >> >> null or not. >> >> Solution : Handle null pointer of stream and >> throw IIOException. >> >> Test case contains all possible >> scenarios where >> >> createImageInputStream() or >> createImageOutputStream can return null. >> >> Thanks, >> >> Jay >> >> -- >> >> Best regards, Sergey. >> >> -- >> >> Best regards, Sergey. >> >> -- >> >> Best regards, Sergey. >> >> -- >> >> Best regards, Sergey. >> -- Best regards, Sergey.