# HG changeset patch # User serb # Date 1512893322 28800 # Node ID 4483880d8811d4bd4d51df366110dfcfb57add30 # Parent 1a6c071312a39c867b7ee2a1f6dae09749bf793c 8178401: Various audio files writers do not close file streams properly Reviewed-by: prr diff -r 1a6c071312a3 -r 4483880d8811 src/java.desktop/share/classes/com/sun/media/sound/AiffFileWriter.java --- a/src/java.desktop/share/classes/com/sun/media/sound/AiffFileWriter.java Sat Dec 09 20:40:45 2017 -0800 +++ b/src/java.desktop/share/classes/com/sun/media/sound/AiffFileWriter.java Sun Dec 10 00:08:42 2017 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -113,10 +113,11 @@ AiffFileFormat aiffFileFormat = (AiffFileFormat)getAudioFileFormat(fileType, stream); // first write the file without worrying about length fields - FileOutputStream fos = new FileOutputStream( out ); // throws IOException - BufferedOutputStream bos = new BufferedOutputStream( fos, bisBufferSize ); - int bytesWritten = writeAiffFile(stream, aiffFileFormat, bos ); - bos.close(); + final int bytesWritten; + try (final FileOutputStream fos = new FileOutputStream(out); + final BufferedOutputStream bos = new BufferedOutputStream(fos)) { + bytesWritten = writeAiffFile(stream, aiffFileFormat, bos); + } // now, if length fields were not specified, calculate them, // open as a random access file, write the appropriate fields, @@ -134,20 +135,19 @@ long dataSize=ssndChunkSize-16; //TODO possibly incorrect round int numFrames = (int) (dataSize / ssndBlockSize); - - RandomAccessFile raf=new RandomAccessFile(out, "rw"); - // skip FORM magic - raf.skipBytes(4); - raf.writeInt(aiffLength-8); - // skip aiff2 magic, fver chunk, comm magic, comm size, channel count, - raf.skipBytes(4+aiffFileFormat.getFverChunkSize()+4+4+2); - // write frame count - raf.writeInt(numFrames); - // skip sample size, samplerate, SSND magic - raf.skipBytes(2+10+4); - raf.writeInt(ssndChunkSize-8); - // that's all - raf.close(); + try (final RandomAccessFile raf = new RandomAccessFile(out, "rw")) { + // skip FORM magic + raf.skipBytes(4); + raf.writeInt(aiffLength - 8); + // skip aiff2 magic, fver chunk, comm magic, comm size, channel count, + raf.skipBytes(4 + aiffFileFormat.getFverChunkSize() + 4 + 4 + 2); + // write frame count + raf.writeInt(numFrames); + // skip sample size, samplerate, SSND magic + raf.skipBytes(2 + 10 + 4); + raf.writeInt(ssndChunkSize - 8); + // that's all + } } return bytesWritten; @@ -289,10 +289,6 @@ int compCode = AiffFileFormat.AIFC_PCM; byte header[] = null; - ByteArrayInputStream headerStream = null; - ByteArrayOutputStream baos = null; - DataOutputStream dos = null; - SequenceInputStream aiffStream = null; InputStream codedAudioStream = audioStream; // if we need to do any format conversion, do it here.... @@ -343,52 +339,39 @@ // Now create an AIFF stream header... - baos = new ByteArrayOutputStream(); - dos = new DataOutputStream(baos); - - // Write the outer FORM chunk - dos.writeInt(AiffFileFormat.AIFF_MAGIC); - dos.writeInt( (aiffLength-8) ); - dos.writeInt(AiffFileFormat.AIFF_MAGIC2); - - // Write a FVER chunk - only for AIFC - //dos.writeInt(FVER_MAGIC); - //dos.writeInt( (fverChunkSize-8) ); - //dos.writeInt(FVER_TIMESTAMP); - - // Write a COMM chunk - dos.writeInt(AiffFileFormat.COMM_MAGIC); - dos.writeInt( (commChunkSize-8) ); - dos.writeShort(channels); - dos.writeInt(numFrames); - dos.writeShort(sampleSize); - write_ieee_extended(dos, sampleFramesPerSecond); // 10 bytes - - //Only for AIFC - //dos.writeInt(compCode); - //dos.writeInt(compCode); - //dos.writeShort(0); - - // Write the SSND chunk header - dos.writeInt(AiffFileFormat.SSND_MAGIC); - dos.writeInt( (ssndChunkSize-8) ); - // ssndOffset and ssndBlockSize set to 0 upon - // recommendation in "Sound Manager" chapter in - // "Inside Macintosh Sound", pp 2-87 (from Babu) - dos.writeInt(0); // ssndOffset - dos.writeInt(0); // ssndBlockSize - - // Concat this with the audioStream and return it - - dos.close(); - header = baos.toByteArray(); - headerStream = new ByteArrayInputStream( header ); - - aiffStream = new SequenceInputStream(headerStream, - new NoCloseInputStream(codedAudioStream)); - - return aiffStream; - + try (final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + final DataOutputStream dos = new DataOutputStream(baos)) { + // Write the outer FORM chunk + dos.writeInt(AiffFileFormat.AIFF_MAGIC); + dos.writeInt((aiffLength - 8)); + dos.writeInt(AiffFileFormat.AIFF_MAGIC2); + // Write a FVER chunk - only for AIFC + //dos.writeInt(FVER_MAGIC); + //dos.writeInt( (fverChunkSize-8) ); + //dos.writeInt(FVER_TIMESTAMP); + // Write a COMM chunk + dos.writeInt(AiffFileFormat.COMM_MAGIC); + dos.writeInt((commChunkSize - 8)); + dos.writeShort(channels); + dos.writeInt(numFrames); + dos.writeShort(sampleSize); + write_ieee_extended(dos, sampleFramesPerSecond); // 10 bytes + //Only for AIFC + //dos.writeInt(compCode); + //dos.writeInt(compCode); + //dos.writeShort(0); + // Write the SSND chunk header + dos.writeInt(AiffFileFormat.SSND_MAGIC); + dos.writeInt((ssndChunkSize - 8)); + // ssndOffset and ssndBlockSize set to 0 upon + // recommendation in "Sound Manager" chapter in + // "Inside Macintosh Sound", pp 2-87 (from Babu) + dos.writeInt(0); // ssndOffset + dos.writeInt(0); // ssndBlockSize + header = baos.toByteArray(); + } + return new SequenceInputStream(new ByteArrayInputStream(header), + new NoCloseInputStream(codedAudioStream)); } // HELPER METHODS diff -r 1a6c071312a3 -r 4483880d8811 src/java.desktop/share/classes/com/sun/media/sound/AuFileWriter.java --- a/src/java.desktop/share/classes/com/sun/media/sound/AuFileWriter.java Sat Dec 09 20:40:45 2017 -0800 +++ b/src/java.desktop/share/classes/com/sun/media/sound/AuFileWriter.java Sun Dec 10 00:08:42 2017 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -111,10 +111,11 @@ AuFileFormat auFileFormat = (AuFileFormat)getAudioFileFormat(fileType, stream); // first write the file without worrying about length fields - FileOutputStream fos = new FileOutputStream( out ); // throws IOException - BufferedOutputStream bos = new BufferedOutputStream( fos, bisBufferSize ); - int bytesWritten = writeAuFile(stream, auFileFormat, bos ); - bos.close(); + final int bytesWritten; + try (final FileOutputStream fos = new FileOutputStream(out); + final BufferedOutputStream bos = new BufferedOutputStream(fos)) { + bytesWritten = writeAuFile(stream, auFileFormat, bos); + } // now, if length fields were not specified, calculate them, // open as a random access file, write the appropriate fields, @@ -123,14 +124,14 @@ // $$kk: 10.22.99: jan: please either implement this or throw an exception! // $$fb: 2001-07-13: done. Fixes Bug 4479981 - RandomAccessFile raf=new RandomAccessFile(out, "rw"); - if (raf.length()<=0x7FFFFFFFl) { - // skip AU magic and data offset field - raf.skipBytes(8); - raf.writeInt(bytesWritten-AuFileFormat.AU_HEADERSIZE); - // that's all + try (final RandomAccessFile raf = new RandomAccessFile(out, "rw")) { + if (raf.length() <= 0x7FFFFFFFl) { + // skip AU magic and data offset field + raf.skipBytes(8); + raf.writeInt(bytesWritten - AuFileFormat.AU_HEADERSIZE); + // that's all + } } - raf.close(); } return bytesWritten; @@ -191,39 +192,29 @@ int sampleRate = (int)format.getSampleRate(); int channels = format.getChannels(); - byte header[] = null; - ByteArrayInputStream headerStream = null; - ByteArrayOutputStream baos = null; - DataOutputStream dos = null; - SequenceInputStream auStream = null; - // if we need to do any format conversion, we do it here. //$$ fb 2001-07-13: Bug 4391108 audioStream = AudioSystem.getAudioInputStream(format, audioStream); - baos = new ByteArrayOutputStream(); - dos = new DataOutputStream(baos); - - dos.writeInt(AuFileFormat.AU_SUN_MAGIC); - dos.writeInt(headerSize); - dos.writeInt((int)dataSizeInBytes); - dos.writeInt(auType); - dos.writeInt(sampleRate); - dos.writeInt(channels); - + final byte[] header; + try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos)) { + dos.writeInt(AuFileFormat.AU_SUN_MAGIC); + dos.writeInt(headerSize); + dos.writeInt((int) dataSizeInBytes); + dos.writeInt(auType); + dos.writeInt(sampleRate); + dos.writeInt(channels); + header = baos.toByteArray(); + } // Now create a new InputStream from headerStream and the InputStream // in audioStream - - dos.close(); - header = baos.toByteArray(); - headerStream = new ByteArrayInputStream( header ); - auStream = new SequenceInputStream(headerStream, - new NoCloseInputStream(audioStream)); - - return auStream; + return new SequenceInputStream(new ByteArrayInputStream(header), + new NoCloseInputStream(audioStream)); } - private int writeAuFile(AudioInputStream in, AuFileFormat auFileFormat, OutputStream out) throws IOException { + private int writeAuFile(AudioInputStream in, AuFileFormat auFileFormat, + OutputStream out) throws IOException { int bytesRead = 0; int bytesWritten = 0; diff -r 1a6c071312a3 -r 4483880d8811 src/java.desktop/share/classes/com/sun/media/sound/WaveFileWriter.java --- a/src/java.desktop/share/classes/com/sun/media/sound/WaveFileWriter.java Sat Dec 09 20:40:45 2017 -0800 +++ b/src/java.desktop/share/classes/com/sun/media/sound/WaveFileWriter.java Sun Dec 10 00:08:42 2017 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -113,10 +113,11 @@ WaveFileFormat waveFileFormat = (WaveFileFormat)getAudioFileFormat(fileType, stream); // first write the file without worrying about length fields - FileOutputStream fos = new FileOutputStream( out ); // throws IOException - BufferedOutputStream bos = new BufferedOutputStream( fos, bisBufferSize ); - int bytesWritten = writeWaveFile(stream, waveFileFormat, bos ); - bos.close(); + final int bytesWritten; + try (final FileOutputStream fos = new FileOutputStream(out); + final BufferedOutputStream bos = new BufferedOutputStream(fos)) { + bytesWritten = writeWaveFile(stream, waveFileFormat, bos); + } // now, if length fields were not specified, calculate them, // open as a random access file, write the appropriate fields, @@ -125,16 +126,16 @@ int dataLength=bytesWritten-waveFileFormat.getHeaderSize(); int riffLength=dataLength + waveFileFormat.getHeaderSize() - 8; - - RandomAccessFile raf=new RandomAccessFile(out, "rw"); - // skip RIFF magic - raf.skipBytes(4); - raf.writeInt(big2little( riffLength )); - // skip WAVE magic, fmt_ magic, fmt_ length, fmt_ chunk, data magic - raf.skipBytes(4+4+4+WaveFileFormat.getFmtChunkSize(waveFileFormat.getWaveType())+4); - raf.writeInt(big2little( dataLength )); - // that's all - raf.close(); + try (final RandomAccessFile raf = new RandomAccessFile(out, "rw")) { + // skip RIFF magic + raf.skipBytes(4); + raf.writeInt(big2little(riffLength)); + // skip WAVE magic, fmt_ magic, fmt_ length, fmt_ chunk, data magic + raf.skipBytes(4 + 4 + 4 + WaveFileFormat.getFmtChunkSize( + waveFileFormat.getWaveType()) + 4); + raf.writeInt(big2little(dataLength)); + // that's all + } } return bytesWritten; @@ -262,12 +263,6 @@ int length = waveFileFormat.getByteLength(); int riffLength = dataLength + headerLength - 8; - byte header[] = null; - ByteArrayInputStream headerStream = null; - ByteArrayOutputStream baos = null; - DataOutputStream dos = null; - SequenceInputStream waveStream = null; - AudioFormat audioStreamFormat = null; AudioFormat.Encoding encoding = null; InputStream codedAudioStream = audioStream; @@ -314,37 +309,31 @@ // Now push the header into a stream, concat, and return the new SequenceInputStream - - baos = new ByteArrayOutputStream(); - dos = new DataOutputStream(baos); - - // we write in littleendian... - dos.writeInt(riffMagic); - dos.writeInt(big2little( riffLength )); - dos.writeInt(waveMagic); - dos.writeInt(fmtMagic); - dos.writeInt(big2little(fmtLength)); - dos.writeShort(big2littleShort(wav_type)); - dos.writeShort(big2littleShort(channels)); - dos.writeInt(big2little(sampleRate)); - dos.writeInt(big2little(avgBytesPerSec)); - dos.writeShort(big2littleShort(blockAlign)); - dos.writeShort(big2littleShort(sampleSizeInBits)); - //$$fb 2002-04-16: Fix for 4636355: RIFF audio headers could be _more_ spec compliant - if (wav_type != WaveFileFormat.WAVE_FORMAT_PCM) { - // add length 0 for "codec specific data length" - dos.writeShort(0); + final byte[] header; + try (final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + final DataOutputStream dos = new DataOutputStream(baos)) { + // we write in littleendian... + dos.writeInt(riffMagic); + dos.writeInt(big2little(riffLength)); + dos.writeInt(waveMagic); + dos.writeInt(fmtMagic); + dos.writeInt(big2little(fmtLength)); + dos.writeShort(big2littleShort(wav_type)); + dos.writeShort(big2littleShort(channels)); + dos.writeInt(big2little(sampleRate)); + dos.writeInt(big2little(avgBytesPerSec)); + dos.writeShort(big2littleShort(blockAlign)); + dos.writeShort(big2littleShort(sampleSizeInBits)); + //$$fb 2002-04-16: Fix for 4636355: RIFF audio headers could be _more_ spec compliant + if (wav_type != WaveFileFormat.WAVE_FORMAT_PCM) { + // add length 0 for "codec specific data length" + dos.writeShort(0); + } + dos.writeInt(dataMagic); + dos.writeInt(big2little(dataLength)); + header = baos.toByteArray(); } - - dos.writeInt(dataMagic); - dos.writeInt(big2little(dataLength)); - - dos.close(); - header = baos.toByteArray(); - headerStream = new ByteArrayInputStream( header ); - waveStream = new SequenceInputStream(headerStream, - new NoCloseInputStream(codedAudioStream)); - - return waveStream; + return new SequenceInputStream(new ByteArrayInputStream(header), + new NoCloseInputStream(codedAudioStream)); } } diff -r 1a6c071312a3 -r 4483880d8811 src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileWriter.java --- a/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileWriter.java Sat Dec 09 20:40:45 2017 -0800 +++ b/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileWriter.java Sun Dec 10 00:08:42 2017 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -69,24 +69,23 @@ public void write(AudioInputStream stream, RIFFWriter writer) throws IOException { - - RIFFWriter fmt_chunk = writer.writeChunk("fmt "); - - AudioFormat format = stream.getFormat(); - fmt_chunk.writeUnsignedShort(3); // WAVE_FORMAT_IEEE_FLOAT - fmt_chunk.writeUnsignedShort(format.getChannels()); - fmt_chunk.writeUnsignedInt((int) format.getSampleRate()); - fmt_chunk.writeUnsignedInt(((int) format.getFrameRate()) - * format.getFrameSize()); - fmt_chunk.writeUnsignedShort(format.getFrameSize()); - fmt_chunk.writeUnsignedShort(format.getSampleSizeInBits()); - fmt_chunk.close(); - RIFFWriter data_chunk = writer.writeChunk("data"); - byte[] buff = new byte[1024]; - int len; - while ((len = stream.read(buff, 0, buff.length)) != -1) - data_chunk.write(buff, 0, len); - data_chunk.close(); + try (final RIFFWriter fmt_chunk = writer.writeChunk("fmt ")) { + AudioFormat format = stream.getFormat(); + fmt_chunk.writeUnsignedShort(3); // WAVE_FORMAT_IEEE_FLOAT + fmt_chunk.writeUnsignedShort(format.getChannels()); + fmt_chunk.writeUnsignedInt((int) format.getSampleRate()); + fmt_chunk.writeUnsignedInt(((int) format.getFrameRate()) + * format.getFrameSize()); + fmt_chunk.writeUnsignedShort(format.getFrameSize()); + fmt_chunk.writeUnsignedShort(format.getSampleSizeInBits()); + } + try (RIFFWriter data_chunk = writer.writeChunk("data")) { + byte[] buff = new byte[1024]; + int len; + while ((len = stream.read(buff, 0, buff.length)) != -1) { + data_chunk.write(buff, 0, len); + } + } } private static final class NoCloseOutputStream extends OutputStream { @@ -136,11 +135,11 @@ checkFormat(fileType, stream); if (stream.getFormat().isBigEndian()) stream = toLittleEndian(stream); - RIFFWriter writer = new RIFFWriter(new NoCloseOutputStream(out), "WAVE"); - write(stream, writer); - int fpointer = (int) writer.getFilePointer(); - writer.close(); - return fpointer; + try (final RIFFWriter writer = new RIFFWriter( + new NoCloseOutputStream(out), "WAVE")) { + write(stream, writer); + return (int) writer.getFilePointer(); + } } @Override @@ -153,10 +152,9 @@ checkFormat(fileType, stream); if (stream.getFormat().isBigEndian()) stream = toLittleEndian(stream); - RIFFWriter writer = new RIFFWriter(out, "WAVE"); - write(stream, writer); - int fpointer = (int) writer.getFilePointer(); - writer.close(); - return fpointer; + try (final RIFFWriter writer = new RIFFWriter(out, "WAVE")) { + write(stream, writer); + return (int) writer.getFilePointer(); + } } } diff -r 1a6c071312a3 -r 4483880d8811 test/jdk/ProblemList.txt --- a/test/jdk/ProblemList.txt Sat Dec 09 20:40:45 2017 -0800 +++ b/test/jdk/ProblemList.txt Sun Dec 10 00:08:42 2017 -0800 @@ -273,8 +273,6 @@ ############################################################################ # jdk_sound -javax/sound/sampled/AudioInputStream/FrameLengthAfterConversion.java 8178401 windows-all - javax/sound/sampled/DirectAudio/bug6372428.java 8055097 generic-all javax/sound/sampled/Clip/bug5070081.java 8055097 generic-all javax/sound/sampled/DataLine/LongFramePosition.java 8055097 generic-all diff -r 1a6c071312a3 -r 4483880d8811 test/jdk/javax/sound/sampled/AudioInputStream/FrameLengthAfterConversion.java --- a/test/jdk/javax/sound/sampled/AudioInputStream/FrameLengthAfterConversion.java Sat Dec 09 20:40:45 2017 -0800 +++ b/test/jdk/javax/sound/sampled/AudioInputStream/FrameLengthAfterConversion.java Sun Dec 10 00:08:42 2017 -0800 @@ -49,7 +49,7 @@ /** * @test - * @bug 8038139 + * @bug 8038139 8178401 */ public final class FrameLengthAfterConversion {