8013586: audioInputStream.close() does not release the resource

8130305: AudioSystem behavior depends on order that providers are located

Reviewed-by: prr, amenkov
This commit is contained in:
Sergey Bylokhov 2015-07-28 22:31:54 +03:00
parent 7ecc241629
commit 5e745d9ef1
8 changed files with 250 additions and 864 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2015, 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
@ -27,19 +27,14 @@ package com.sun.media.sound;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;
/**
* AIFF file reader and writer.
*
@ -49,177 +44,10 @@ import javax.sound.sampled.UnsupportedAudioFileException;
*/
public final class AiffFileReader extends SunFileReader {
private static final int MAX_READ_LENGTH = 8;
// METHODS TO IMPLEMENT AudioFileReader
/**
* Obtains the audio file format of the input stream provided. The stream must
* point to valid audio file data. In general, audio file providers may
* need to read some data from the stream before determining whether they
* support it. These parsers must
* be able to mark the stream, read enough data to determine whether they
* support the stream, and, if not, reset the stream's read pointer to its original
* position. If the input stream does not support this, this method may fail
* with an IOException.
* @param stream the input stream from which file format information should be
* extracted
* @return an <code>AudioFileFormat</code> object describing the audio file format
* @throws UnsupportedAudioFileException if the stream does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
* @see InputStream#markSupported
* @see InputStream#mark
*/
public AudioFileFormat getAudioFileFormat(InputStream stream) throws UnsupportedAudioFileException, IOException {
// fix for 4489272: AudioSystem.getAudioFileFormat() fails for InputStream, but works for URL
AudioFileFormat aff = getCOMM(stream, true);
// the following is not strictly necessary - but was implemented like that in 1.3.0 - 1.4.1
// so I leave it as it was. May remove this for 1.5.0
stream.reset();
return aff;
}
/**
* Obtains the audio file format of the URL provided. The URL must
* point to valid audio file data.
* @param url the URL from which file format information should be
* extracted
* @return an <code>AudioFileFormat</code> object describing the audio file format
* @throws UnsupportedAudioFileException if the URL does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
*/
public AudioFileFormat getAudioFileFormat(URL url) throws UnsupportedAudioFileException, IOException {
AudioFileFormat fileFormat = null;
InputStream urlStream = url.openStream(); // throws IOException
try {
fileFormat = getCOMM(urlStream, false);
} finally {
urlStream.close();
}
return fileFormat;
}
/**
* Obtains the audio file format of the File provided. The File must
* point to valid audio file data.
* @param file the File from which file format information should be
* extracted
* @return an <code>AudioFileFormat</code> object describing the audio file format
* @throws UnsupportedAudioFileException if the File does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
*/
public AudioFileFormat getAudioFileFormat(File file) throws UnsupportedAudioFileException, IOException {
AudioFileFormat fileFormat = null;
FileInputStream fis = new FileInputStream(file); // throws IOException
// part of fix for 4325421
try {
fileFormat = getCOMM(fis, false);
} finally {
fis.close();
}
return fileFormat;
}
/**
* Obtains an audio stream from the input stream provided. The stream must
* point to valid audio file data. In general, audio file providers may
* need to read some data from the stream before determining whether they
* support it. These parsers must
* be able to mark the stream, read enough data to determine whether they
* support the stream, and, if not, reset the stream's read pointer to its original
* position. If the input stream does not support this, this method may fail
* with an IOException.
* @param stream the input stream from which the <code>AudioInputStream</code> should be
* constructed
* @return an <code>AudioInputStream</code> object based on the audio file data contained
* in the input stream.
* @throws UnsupportedAudioFileException if the stream does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
* @see InputStream#markSupported
* @see InputStream#mark
*/
public AudioInputStream getAudioInputStream(InputStream stream) throws UnsupportedAudioFileException, IOException {
// getCOMM leaves the input stream at the beginning of the audio data
AudioFileFormat fileFormat = getCOMM(stream, true); // throws UnsupportedAudioFileException, IOException
// we've got everything, and the stream is at the
// beginning of the audio data, so return an AudioInputStream.
return new AudioInputStream(stream, fileFormat.getFormat(), fileFormat.getFrameLength());
}
/**
* Obtains an audio stream from the URL provided. The URL must
* point to valid audio file data.
* @param url the URL for which the <code>AudioInputStream</code> should be
* constructed
* @return an <code>AudioInputStream</code> object based on the audio file data pointed
* to by the URL
* @throws UnsupportedAudioFileException if the URL does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
*/
public AudioInputStream getAudioInputStream(URL url) throws UnsupportedAudioFileException, IOException {
InputStream urlStream = url.openStream(); // throws IOException
AudioFileFormat fileFormat = null;
try {
fileFormat = getCOMM(urlStream, false);
} finally {
if (fileFormat == null) {
urlStream.close();
}
}
return new AudioInputStream(urlStream, fileFormat.getFormat(), fileFormat.getFrameLength());
}
/**
* Obtains an audio stream from the File provided. The File must
* point to valid audio file data.
* @param file the File for which the <code>AudioInputStream</code> should be
* constructed
* @return an <code>AudioInputStream</code> object based on the audio file data pointed
* to by the File
* @throws UnsupportedAudioFileException if the File does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
*/
public AudioInputStream getAudioInputStream(File file)
throws UnsupportedAudioFileException, IOException {
FileInputStream fis = new FileInputStream(file); // throws IOException
AudioFileFormat fileFormat = null;
// part of fix for 4325421
try {
fileFormat = getCOMM(fis, false);
} finally {
if (fileFormat == null) {
fis.close();
}
}
return new AudioInputStream(fis, fileFormat.getFormat(), fileFormat.getFrameLength());
}
//--------------------------------------------------------------------
private AudioFileFormat getCOMM(InputStream is, boolean doReset)
throws UnsupportedAudioFileException, IOException {
DataInputStream dis = new DataInputStream(is);
if (doReset) {
dis.mark(MAX_READ_LENGTH);
}
@Override
AudioFileFormat getAudioFileFormatImpl(final InputStream stream)
throws UnsupportedAudioFileException, IOException {
DataInputStream dis = new DataInputStream(stream);
// assumes a stream at the beginning of the file which has already
// passed the magic number test...
@ -234,9 +62,6 @@ public final class AiffFileReader extends SunFileReader {
// $$fb: fix for 4369044: javax.sound.sampled.AudioSystem.getAudioInputStream() works wrong with Cp037
if (magic != AiffFileFormat.AIFF_MAGIC) {
// not AIFF, throw exception
if (doReset) {
dis.reset();
}
throw new UnsupportedAudioFileException("not an AIFF file");
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2015, 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
@ -25,21 +25,15 @@
package com.sun.media.sound;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;
/**
* AU file reader.
*
@ -49,33 +43,10 @@ import javax.sound.sampled.UnsupportedAudioFileException;
*/
public final class AuFileReader extends SunFileReader {
// METHODS TO IMPLEMENT AudioFileReader
/**
* Obtains the audio file format of the input stream provided. The stream must
* point to valid audio file data. In general, audio file providers may
* need to read some data from the stream before determining whether they
* support it. These parsers must
* be able to mark the stream, read enough data to determine whether they
* support the stream, and, if not, reset the stream's read pointer to its original
* position. If the input stream does not support this, this method may fail
* with an IOException.
* @param stream the input stream from which file format information should be
* extracted
* @return an <code>AudioFileFormat</code> object describing the audio file format
* @throws UnsupportedAudioFileException if the stream does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
* @see InputStream#markSupported
* @see InputStream#mark
*/
public AudioFileFormat getAudioFileFormat(InputStream stream) throws UnsupportedAudioFileException, IOException {
AudioFormat format = null;
AuFileFormat fileFormat = null;
int maxReadLength = 28;
@Override
public AudioFileFormat getAudioFileFormatImpl(final InputStream stream)
throws UnsupportedAudioFileException, IOException {
boolean bigendian = false;
int magic = -1;
int headerSize = -1;
int dataSize = -1;
int encoding_local = -1;
@ -90,15 +61,12 @@ public final class AuFileReader extends SunFileReader {
DataInputStream dis = new DataInputStream( stream );
dis.mark(maxReadLength);
magic = dis.readInt();
final int magic = dis.readInt(); nread += 4;
if (! (magic == AuFileFormat.AU_SUN_MAGIC) || (magic == AuFileFormat.AU_DEC_MAGIC) ||
(magic == AuFileFormat.AU_SUN_INV_MAGIC) || (magic == AuFileFormat.AU_DEC_INV_MAGIC) ) {
// not AU, reset the stream, place into exception, throw exception
dis.reset();
// not AU, throw exception
throw new UnsupportedAudioFileException("not an AU file");
}
@ -112,7 +80,6 @@ public final class AuFileReader extends SunFileReader {
sampleRate = (bigendian==true ? dis.readInt() : rllong(dis) ); nread += 4;
channels = (bigendian==true ? dis.readInt() : rllong(dis) ); nread += 4;
if (channels <= 0) {
dis.reset();
throw new UnsupportedAudioFileException("Invalid number of channels");
}
@ -172,7 +139,6 @@ public final class AuFileReader extends SunFileReader {
*/
default:
// unsupported filetype, throw exception
dis.reset();
throw new UnsupportedAudioFileException("not a valid AU file");
}
@ -184,189 +150,13 @@ public final class AuFileReader extends SunFileReader {
//$$fb 2003-10-20: fix for 4940459: AudioInputStream.getFrameLength() returns 0 instead of NOT_SPECIFIED
length = dataSize / frameSize;
}
format = new AudioFormat( encoding, (float)sampleRate, sampleSizeInBits,
channels, frameSize, (float)frameRate, bigendian);
fileFormat = new AuFileFormat( AudioFileFormat.Type.AU, dataSize+headerSize,
format, length);
dis.reset(); // Throws IOException
return fileFormat;
}
/**
* Obtains the audio file format of the URL provided. The URL must
* point to valid audio file data.
* @param url the URL from which file format information should be
* extracted
* @return an <code>AudioFileFormat</code> object describing the audio file format
* @throws UnsupportedAudioFileException if the URL does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
*/
public AudioFileFormat getAudioFileFormat(URL url) throws UnsupportedAudioFileException, IOException {
InputStream urlStream = null;
BufferedInputStream bis = null;
AudioFileFormat fileFormat = null;
AudioFormat format = null;
urlStream = url.openStream(); // throws IOException
try {
bis = new BufferedInputStream( urlStream, bisBufferSize );
fileFormat = getAudioFileFormat( bis ); // throws UnsupportedAudioFileException
} finally {
urlStream.close();
}
return fileFormat;
}
/**
* Obtains the audio file format of the File provided. The File must
* point to valid audio file data.
* @param file the File from which file format information should be
* extracted
* @return an <code>AudioFileFormat</code> object describing the audio file format
* @throws UnsupportedAudioFileException if the File does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
*/
public AudioFileFormat getAudioFileFormat(File file) throws UnsupportedAudioFileException, IOException {
FileInputStream fis = null;
BufferedInputStream bis = null;
AudioFileFormat fileFormat = null;
AudioFormat format = null;
fis = new FileInputStream( file ); // throws IOException
// part of fix for 4325421
try {
bis = new BufferedInputStream( fis, bisBufferSize );
fileFormat = getAudioFileFormat( bis ); // throws UnsupportedAudioFileException
} finally {
fis.close();
}
return fileFormat;
}
/**
* Obtains an audio stream from the input stream provided. The stream must
* point to valid audio file data. In general, audio file providers may
* need to read some data from the stream before determining whether they
* support it. These parsers must
* be able to mark the stream, read enough data to determine whether they
* support the stream, and, if not, reset the stream's read pointer to its original
* position. If the input stream does not support this, this method may fail
* with an IOException.
* @param stream the input stream from which the <code>AudioInputStream</code> should be
* constructed
* @return an <code>AudioInputStream</code> object based on the audio file data contained
* in the input stream.
* @throws UnsupportedAudioFileException if the stream does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
* @see InputStream#markSupported
* @see InputStream#mark
*/
public AudioInputStream getAudioInputStream(InputStream stream) throws UnsupportedAudioFileException, IOException {
DataInputStream dis = null;
int headerSize;
AudioFileFormat fileFormat = null;
AudioFormat format = null;
fileFormat = getAudioFileFormat( stream ); // throws UnsupportedAudioFileException, IOException
// if we passed this call, we have an AU file.
format = fileFormat.getFormat();
dis = new DataInputStream(stream);
// now seek past the header
dis.readInt(); // magic
headerSize = (format.isBigEndian()==true ? dis.readInt() : rllong(dis) );
dis.skipBytes( headerSize - 8 );
// we've got everything, and the stream should be at the
// beginning of the data chunk, so return an AudioInputStream.
return new AudioInputStream(dis, format, fileFormat.getFrameLength());
}
/**
* Obtains an audio stream from the URL provided. The URL must
* point to valid audio file data.
* @param url the URL for which the <code>AudioInputStream</code> should be
* constructed
* @return an <code>AudioInputStream</code> object based on the audio file data pointed
* to by the URL
* @throws UnsupportedAudioFileException if the URL does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
*/
public AudioInputStream getAudioInputStream(URL url) throws UnsupportedAudioFileException, IOException {
InputStream urlStream = null;
BufferedInputStream bis = null;
AudioFileFormat fileFormat = null;
urlStream = url.openStream(); // throws IOException
AudioInputStream result = null;
try {
bis = new BufferedInputStream( urlStream, bisBufferSize );
result = getAudioInputStream( (InputStream)bis );
} finally {
if (result == null) {
urlStream.close();
}
}
return result;
}
/**
* Obtains an audio stream from the File provided. The File must
* point to valid audio file data.
* @param file the File for which the <code>AudioInputStream</code> should be
* constructed
* @return an <code>AudioInputStream</code> object based on the audio file data pointed
* to by the File
* @throws UnsupportedAudioFileException if the File does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
*/
public AudioInputStream getAudioInputStream(File file) throws UnsupportedAudioFileException, IOException {
FileInputStream fis = null;
BufferedInputStream bis = null;
AudioFileFormat fileFormat = null;
fis = new FileInputStream( file ); // throws IOException
AudioInputStream result = null;
// part of fix for 4325421
try {
bis = new BufferedInputStream( fis, bisBufferSize );
result = getAudioInputStream( (InputStream)bis );
} finally {
if (result == null) {
fis.close();
}
}
return result;
dis.skipBytes(headerSize - nread);
AudioFormat format = new AudioFormat(encoding, sampleRate,
sampleSizeInBits, channels,
frameSize, (float) frameRate,
bigendian);
return new AuFileFormat(AudioFileFormat.Type.AU, dataSize + headerSize,
format, length);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2015, 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
@ -25,10 +25,12 @@
package com.sun.media.sound;
import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import javax.sound.sampled.AudioFileFormat;
@ -36,8 +38,6 @@ import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.sound.sampled.spi.AudioFileReader;
/**
* Abstract File Reader class.
*
@ -45,118 +45,109 @@ import javax.sound.sampled.spi.AudioFileReader;
*/
abstract class SunFileReader extends AudioFileReader {
// buffer size for temporary input streams
protected static final int bisBufferSize = 4096;
/**
* Constructs a new SunFileReader object.
*/
SunFileReader() {
@Override
public final AudioFileFormat getAudioFileFormat(final InputStream stream)
throws UnsupportedAudioFileException, IOException {
stream.mark(200); // The biggest value which was historically used
try {
return getAudioFileFormatImpl(stream);
} finally {
// According to specification the following is not strictly
// necessary, if we got correct format. But it was implemented like
// that in 1.3.0 - 1.8. So I leave it as it was, but it seems
// specification should be updated.
stream.reset();
}
}
@Override
public final AudioFileFormat getAudioFileFormat(final URL url)
throws UnsupportedAudioFileException, IOException {
try (InputStream is = url.openStream()) {
return getAudioFileFormatImpl(new BufferedInputStream(is));
}
}
// METHODS TO IMPLEMENT AudioFileReader
@Override
public final AudioFileFormat getAudioFileFormat(final File file)
throws UnsupportedAudioFileException, IOException {
try (InputStream is = new FileInputStream(file)) {
return getAudioFileFormatImpl(new BufferedInputStream(is));
}
}
@Override
public AudioInputStream getAudioInputStream(final InputStream stream)
throws UnsupportedAudioFileException, IOException {
stream.mark(200); // The biggest value which was historically used
try {
final AudioFileFormat fileFormat = getAudioFileFormatImpl(stream);
// we've got everything, the stream is supported and it is at the
// beginning of the audio data, so return an AudioInputStream
return new AudioInputStream(stream, fileFormat.getFormat(),
fileFormat.getFrameLength());
} catch (final UnsupportedAudioFileException e) {
stream.reset();
throw e;
}
}
@Override
public final AudioInputStream getAudioInputStream(final URL url)
throws UnsupportedAudioFileException, IOException {
final InputStream urlStream = url.openStream();
try {
return getAudioInputStream(new BufferedInputStream(urlStream));
} catch (final Throwable e) {
closeSilently(urlStream);
throw e;
}
}
@Override
public final AudioInputStream getAudioInputStream(final File file)
throws UnsupportedAudioFileException, IOException {
final InputStream fileStream = new FileInputStream(file);
try {
return getAudioInputStream(new BufferedInputStream(fileStream));
} catch (final Throwable e) {
closeSilently(fileStream);
throw e;
}
}
/**
* Obtains the audio file format of the input stream provided. The stream must
* point to valid audio file data. In general, audio file providers may
* need to read some data from the stream before determining whether they
* support it. These parsers must
* be able to mark the stream, read enough data to determine whether they
* support the stream, and, if not, reset the stream's read pointer to its original
* position. If the input stream does not support this, this method may fail
* with an IOException.
* @param stream the input stream from which file format information should be
* extracted
* @return an <code>AudioFileFormat</code> object describing the audio file format
* @throws UnsupportedAudioFileException if the stream does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
* @see InputStream#markSupported
* @see InputStream#mark
*/
abstract public AudioFileFormat getAudioFileFormat(InputStream stream) throws UnsupportedAudioFileException, IOException;
/**
* Obtains the audio file format of the URL provided. The URL must
* point to valid audio file data.
* @param url the URL from which file format information should be
* extracted
* @return an <code>AudioFileFormat</code> object describing the audio file format
* @throws UnsupportedAudioFileException if the URL does not point to valid audio
* file data recognized by the system
* Obtains the audio file format of the input stream provided. The stream
* must point to valid audio file data. Note that default implementation of
* {@link #getAudioInputStream(InputStream)} assume that this method leaves
* the input stream at the beginning of the audio data.
*
* @param stream the input stream from which file format information should
* be extracted
* @return an {@code AudioFileFormat} object describing the audio file
* format
* @throws UnsupportedAudioFileException if the stream does not point to
* valid audio file data recognized by the system
* @throws IOException if an I/O exception occurs
*/
abstract public AudioFileFormat getAudioFileFormat(URL url) throws UnsupportedAudioFileException, IOException;
/**
* Obtains the audio file format of the File provided. The File must
* point to valid audio file data.
* @param file the File from which file format information should be
* extracted
* @return an <code>AudioFileFormat</code> object describing the audio file format
* @throws UnsupportedAudioFileException if the File does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
*/
abstract public AudioFileFormat getAudioFileFormat(File file) throws UnsupportedAudioFileException, IOException;
/**
* Obtains an audio stream from the input stream provided. The stream must
* point to valid audio file data. In general, audio file providers may
* need to read some data from the stream before determining whether they
* support it. These parsers must
* be able to mark the stream, read enough data to determine whether they
* support the stream, and, if not, reset the stream's read pointer to its original
* position. If the input stream does not support this, this method may fail
* with an IOException.
* @param stream the input stream from which the <code>AudioInputStream</code> should be
* constructed
* @return an <code>AudioInputStream</code> object based on the audio file data contained
* in the input stream.
* @throws UnsupportedAudioFileException if the stream does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
* @see InputStream#markSupported
* @see InputStream#mark
*/
abstract public AudioInputStream getAudioInputStream(InputStream stream) throws UnsupportedAudioFileException, IOException;
/**
* Obtains an audio stream from the URL provided. The URL must
* point to valid audio file data.
* @param url the URL for which the <code>AudioInputStream</code> should be
* constructed
* @return an <code>AudioInputStream</code> object based on the audio file data pointed
* to by the URL
* @throws UnsupportedAudioFileException if the URL does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
*/
abstract public AudioInputStream getAudioInputStream(URL url) throws UnsupportedAudioFileException, IOException;
/**
* Obtains an audio stream from the File provided. The File must
* point to valid audio file data.
* @param file the File for which the <code>AudioInputStream</code> should be
* constructed
* @return an <code>AudioInputStream</code> object based on the audio file data pointed
* to by the File
* @throws UnsupportedAudioFileException if the File does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
*/
abstract public AudioInputStream getAudioInputStream(File file) throws UnsupportedAudioFileException, IOException;
abstract AudioFileFormat getAudioFileFormatImpl(InputStream stream)
throws UnsupportedAudioFileException, IOException;
// HELPER METHODS
/**
* Closes the InputStream when we have read all necessary data from it, and
* ignores an IOException.
*
* @param is the InputStream which should be closed
*/
private static void closeSilently(final InputStream is) {
try {
is.close();
} catch (final IOException ignored) {
// IOException is ignored
}
}
/**
* rllong

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2015, 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
@ -22,55 +22,40 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.media.sound;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioFormat.Encoding;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.sound.sampled.AudioFormat.Encoding;
import javax.sound.sampled.spi.AudioFileReader;
/**
* WAVE file reader for files using format WAVE_FORMAT_EXTENSIBLE (0xFFFE).
*
* @author Karl Helgason
*/
public final class WaveExtensibleFileReader extends AudioFileReader {
static private class GUID {
long i1;
int s1;
int s2;
int x1;
int x2;
int x3;
int x4;
int x5;
int x6;
int x7;
int x8;
public final class WaveExtensibleFileReader extends SunFileReader {
private static class GUID {
private long i1;
private int s1;
private int s2;
private int x1;
private int x2;
private int x3;
private int x4;
private int x5;
private int x6;
private int x7;
private int x8;
private GUID() {
}
@ -105,10 +90,12 @@ public final class WaveExtensibleFileReader extends AudioFileReader {
return d;
}
@Override
public int hashCode() {
return (int) i1;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof GUID))
return false;
@ -161,7 +148,7 @@ public final class WaveExtensibleFileReader extends AudioFileReader {
private static final GUID SUBTYPE_IEEE_FLOAT = new GUID(0x00000003, 0x0000,
0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
private String decodeChannelMask(long channelmask) {
private static String decodeChannelMask(long channelmask) {
StringBuilder sb = new StringBuilder();
long m = 1;
for (int i = 0; i < allchannelnames.length; i++) {
@ -180,20 +167,8 @@ public final class WaveExtensibleFileReader extends AudioFileReader {
}
public AudioFileFormat getAudioFileFormat(InputStream stream)
throws UnsupportedAudioFileException, IOException {
stream.mark(200);
AudioFileFormat format;
try {
format = internal_getAudioFileFormat(stream);
} finally {
stream.reset();
}
return format;
}
private AudioFileFormat internal_getAudioFileFormat(InputStream stream)
@Override
AudioFileFormat getAudioFileFormatImpl(final InputStream stream)
throws UnsupportedAudioFileException, IOException {
RIFFReader riffiterator = new RIFFReader(stream);
@ -244,12 +219,9 @@ public final class WaveExtensibleFileReader extends AudioFileReader {
break;
}
}
if (!fmt_found)
if (!fmt_found || !data_found) {
throw new UnsupportedAudioFileException();
if (!data_found)
throw new UnsupportedAudioFileException();
}
Map<String, Object> p = new HashMap<String, Object>();
String s_channelmask = decodeChannelMask(channelMask);
if (s_channelmask != null)
@ -273,24 +245,22 @@ public final class WaveExtensibleFileReader extends AudioFileReader {
} else if (subFormat.equals(SUBTYPE_IEEE_FLOAT)) {
audioformat = new AudioFormat(Encoding.PCM_FLOAT,
samplerate, bits, channels, framesize, samplerate, false, p);
} else
} else {
throw new UnsupportedAudioFileException();
AudioFileFormat fileformat = new AudioFileFormat(
AudioFileFormat.Type.WAVE, audioformat,
AudioSystem.NOT_SPECIFIED);
return fileformat;
}
return new AudioFileFormat(AudioFileFormat.Type.WAVE, audioformat,
AudioSystem.NOT_SPECIFIED);
}
public AudioInputStream getAudioInputStream(InputStream stream)
@Override
public AudioInputStream getAudioInputStream(final InputStream stream)
throws UnsupportedAudioFileException, IOException {
AudioFileFormat format = getAudioFileFormat(stream);
// we've got everything, the stream is supported and it is at the
// beginning of the header, so find the data chunk again and return an
// AudioInputStream
RIFFReader riffiterator = new RIFFReader(stream);
if (!riffiterator.getFormat().equals("RIFF"))
throw new UnsupportedAudioFileException();
if (!riffiterator.getType().equals("WAVE"))
throw new UnsupportedAudioFileException();
while (riffiterator.hasNextChunk()) {
RIFFReader chunk = riffiterator.nextChunk();
if (chunk.getFormat().equals("data")) {
@ -300,40 +270,4 @@ public final class WaveExtensibleFileReader extends AudioFileReader {
}
throw new UnsupportedAudioFileException();
}
public AudioFileFormat getAudioFileFormat(URL url)
throws UnsupportedAudioFileException, IOException {
InputStream stream = url.openStream();
AudioFileFormat format;
try {
format = getAudioFileFormat(new BufferedInputStream(stream));
} finally {
stream.close();
}
return format;
}
public AudioFileFormat getAudioFileFormat(File file)
throws UnsupportedAudioFileException, IOException {
InputStream stream = new FileInputStream(file);
AudioFileFormat format;
try {
format = getAudioFileFormat(new BufferedInputStream(stream));
} finally {
stream.close();
}
return format;
}
public AudioInputStream getAudioInputStream(URL url)
throws UnsupportedAudioFileException, IOException {
return getAudioInputStream(new BufferedInputStream(url.openStream()));
}
public AudioInputStream getAudioInputStream(File file)
throws UnsupportedAudioFileException, IOException {
return getAudioInputStream(new BufferedInputStream(new FileInputStream(
file)));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2015, 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
@ -27,20 +27,14 @@ package com.sun.media.sound;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;
/**
* WAVE file reader.
*
@ -50,170 +44,12 @@ import javax.sound.sampled.UnsupportedAudioFileException;
*/
public final class WaveFileReader extends SunFileReader {
private static final int MAX_READ_LENGTH = 12;
/**
* Obtains the audio file format of the input stream provided. The stream must
* point to valid audio file data. In general, audio file providers may
* need to read some data from the stream before determining whether they
* support it. These parsers must
* be able to mark the stream, read enough data to determine whether they
* support the stream, and, if not, reset the stream's read pointer to its original
* position. If the input stream does not support this, this method may fail
* with an IOException.
* @param stream the input stream from which file format information should be
* extracted
* @return an <code>AudioFileFormat</code> object describing the audio file format
* @throws UnsupportedAudioFileException if the stream does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
* @see InputStream#markSupported
* @see InputStream#mark
*/
public AudioFileFormat getAudioFileFormat(InputStream stream) throws UnsupportedAudioFileException, IOException {
// fix for 4489272: AudioSystem.getAudioFileFormat() fails for InputStream, but works for URL
AudioFileFormat aff = getFMT(stream, true);
// the following is not strictly necessary - but was implemented like that in 1.3.0 - 1.4.1
// so I leave it as it was. May remove this for 1.5.0
stream.reset();
return aff;
}
/**
* Obtains the audio file format of the URL provided. The URL must
* point to valid audio file data.
* @param url the URL from which file format information should be
* extracted
* @return an <code>AudioFileFormat</code> object describing the audio file format
* @throws UnsupportedAudioFileException if the URL does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
*/
public AudioFileFormat getAudioFileFormat(URL url) throws UnsupportedAudioFileException, IOException {
InputStream urlStream = url.openStream(); // throws IOException
AudioFileFormat fileFormat = null;
try {
fileFormat = getFMT(urlStream, false);
} finally {
urlStream.close();
}
return fileFormat;
}
/**
* Obtains the audio file format of the File provided. The File must
* point to valid audio file data.
* @param file the File from which file format information should be
* extracted
* @return an <code>AudioFileFormat</code> object describing the audio file format
* @throws UnsupportedAudioFileException if the File does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
*/
public AudioFileFormat getAudioFileFormat(File file) throws UnsupportedAudioFileException, IOException {
AudioFileFormat fileFormat = null;
FileInputStream fis = new FileInputStream(file); // throws IOException
// part of fix for 4325421
try {
fileFormat = getFMT(fis, false);
} finally {
fis.close();
}
return fileFormat;
}
/**
* Obtains an audio stream from the input stream provided. The stream must
* point to valid audio file data. In general, audio file providers may
* need to read some data from the stream before determining whether they
* support it. These parsers must
* be able to mark the stream, read enough data to determine whether they
* support the stream, and, if not, reset the stream's read pointer to its original
* position. If the input stream does not support this, this method may fail
* with an IOException.
* @param stream the input stream from which the <code>AudioInputStream</code> should be
* constructed
* @return an <code>AudioInputStream</code> object based on the audio file data contained
* in the input stream.
* @throws UnsupportedAudioFileException if the stream does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
* @see InputStream#markSupported
* @see InputStream#mark
*/
public AudioInputStream getAudioInputStream(InputStream stream) throws UnsupportedAudioFileException, IOException {
// getFMT leaves the input stream at the beginning of the audio data
AudioFileFormat fileFormat = getFMT(stream, true); // throws UnsupportedAudioFileException, IOException
// we've got everything, and the stream is at the
// beginning of the audio data, so return an AudioInputStream.
return new AudioInputStream(stream, fileFormat.getFormat(), fileFormat.getFrameLength());
}
/**
* Obtains an audio stream from the URL provided. The URL must
* point to valid audio file data.
* @param url the URL for which the <code>AudioInputStream</code> should be
* constructed
* @return an <code>AudioInputStream</code> object based on the audio file data pointed
* to by the URL
* @throws UnsupportedAudioFileException if the URL does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
*/
public AudioInputStream getAudioInputStream(URL url) throws UnsupportedAudioFileException, IOException {
InputStream urlStream = url.openStream(); // throws IOException
AudioFileFormat fileFormat = null;
try {
fileFormat = getFMT(urlStream, false);
} finally {
if (fileFormat == null) {
urlStream.close();
}
}
return new AudioInputStream(urlStream, fileFormat.getFormat(), fileFormat.getFrameLength());
}
/**
* Obtains an audio stream from the File provided. The File must
* point to valid audio file data.
* @param file the File for which the <code>AudioInputStream</code> should be
* constructed
* @return an <code>AudioInputStream</code> object based on the audio file data pointed
* to by the File
* @throws UnsupportedAudioFileException if the File does not point to valid audio
* file data recognized by the system
* @throws IOException if an I/O exception occurs
*/
public AudioInputStream getAudioInputStream(File file) throws UnsupportedAudioFileException, IOException {
FileInputStream fis = new FileInputStream(file); // throws IOException
AudioFileFormat fileFormat = null;
// part of fix for 4325421
try {
fileFormat = getFMT(fis, false);
} finally {
if (fileFormat == null) {
fis.close();
}
}
return new AudioInputStream(fis, fileFormat.getFormat(), fileFormat.getFrameLength());
}
//--------------------------------------------------------------------
private AudioFileFormat getFMT(InputStream stream, boolean doReset) throws UnsupportedAudioFileException, IOException {
@Override
AudioFileFormat getAudioFileFormatImpl(final InputStream stream)
throws UnsupportedAudioFileException, IOException {
// assumes sream is rewound
int bytesRead;
int nread = 0;
int fmt;
int length = 0;
@ -227,10 +63,6 @@ public final class WaveFileReader extends SunFileReader {
DataInputStream dis = new DataInputStream( stream );
if (doReset) {
dis.mark(MAX_READ_LENGTH);
}
int magic = dis.readInt();
int fileLength = rllong(dis);
int waveMagic = dis.readInt();
@ -244,9 +76,6 @@ public final class WaveFileReader extends SunFileReader {
if ((magic != WaveFileFormat.RIFF_MAGIC) || (waveMagic != WaveFileFormat.WAVE_MAGIC)) {
// not WAVE, throw UnsupportedAudioFileException
if (doReset) {
dis.reset();
}
throw new UnsupportedAudioFileException("not a WAVE file");
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2015, 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
@ -22,14 +22,11 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.media.sound;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
@ -37,29 +34,16 @@ import javax.sound.sampled.AudioFormat.Encoding;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.sound.sampled.spi.AudioFileReader;
/**
* Floating-point encoded (format 3) WAVE file loader.
*
* @author Karl Helgason
*/
public final class WaveFloatFileReader extends AudioFileReader {
public final class WaveFloatFileReader extends SunFileReader {
public AudioFileFormat getAudioFileFormat(InputStream stream)
throws UnsupportedAudioFileException, IOException {
stream.mark(200);
AudioFileFormat format;
try {
format = internal_getAudioFileFormat(stream);
} finally {
stream.reset();
}
return format;
}
private AudioFileFormat internal_getAudioFileFormat(InputStream stream)
@Override
AudioFileFormat getAudioFileFormatImpl(final InputStream stream)
throws UnsupportedAudioFileException, IOException {
RIFFReader riffiterator = new RIFFReader(stream);
@ -96,30 +80,25 @@ public final class WaveFloatFileReader extends AudioFileReader {
break;
}
}
if (!fmt_found)
if (!fmt_found || !data_found) {
throw new UnsupportedAudioFileException();
if (!data_found)
throw new UnsupportedAudioFileException();
}
AudioFormat audioformat = new AudioFormat(
Encoding.PCM_FLOAT, samplerate, bits, channels,
framesize, samplerate, false);
AudioFileFormat fileformat = new AudioFileFormat(
AudioFileFormat.Type.WAVE, audioformat,
AudioSystem.NOT_SPECIFIED);
return fileformat;
return new AudioFileFormat(AudioFileFormat.Type.WAVE, audioformat,
AudioSystem.NOT_SPECIFIED);
}
public AudioInputStream getAudioInputStream(InputStream stream)
@Override
public AudioInputStream getAudioInputStream(final InputStream stream)
throws UnsupportedAudioFileException, IOException {
AudioFileFormat format = getAudioFileFormat(stream);
// we've got everything, the stream is supported and it is at the
// beginning of the header, so find the data chunk again and return an
// AudioInputStream
RIFFReader riffiterator = new RIFFReader(stream);
if (!riffiterator.getFormat().equals("RIFF"))
throw new UnsupportedAudioFileException();
if (!riffiterator.getType().equals("WAVE"))
throw new UnsupportedAudioFileException();
while (riffiterator.hasNextChunk()) {
RIFFReader chunk = riffiterator.nextChunk();
if (chunk.getFormat().equals("data")) {
@ -129,39 +108,4 @@ public final class WaveFloatFileReader extends AudioFileReader {
}
throw new UnsupportedAudioFileException();
}
public AudioFileFormat getAudioFileFormat(URL url)
throws UnsupportedAudioFileException, IOException {
InputStream stream = url.openStream();
AudioFileFormat format;
try {
format = getAudioFileFormat(new BufferedInputStream(stream));
} finally {
stream.close();
}
return format;
}
public AudioFileFormat getAudioFileFormat(File file)
throws UnsupportedAudioFileException, IOException {
InputStream stream = new FileInputStream(file);
AudioFileFormat format;
try {
format = getAudioFileFormat(new BufferedInputStream(stream));
} finally {
stream.close();
}
return format;
}
public AudioInputStream getAudioInputStream(URL url)
throws UnsupportedAudioFileException, IOException {
return getAudioInputStream(new BufferedInputStream(url.openStream()));
}
public AudioInputStream getAudioInputStream(File file)
throws UnsupportedAudioFileException, IOException {
return getAudioInputStream(new BufferedInputStream(new FileInputStream(
file)));
}
}

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2015, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;
/**
* @test
* @bug 8013586
* @author Sergey Bylokhov
*/
public final class AudioFileClose {
public static void main(final String[] args) throws Exception {
final File file = Files.createTempFile("JavaSound", "Test").toFile();
try (OutputStream fos = new FileOutputStream(file)) {
fos.write(new byte[200]);
}
try {
final InputStream stream = AudioSystem.getAudioInputStream(file);
stream.close();
} catch (final IOException | UnsupportedAudioFileException ignored) {
}
Files.delete(Paths.get(file.getAbsolutePath()));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2015, 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
@ -21,17 +21,19 @@
* questions.
*/
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.sound.sampled.spi.AudioFileReader;
import static java.util.ServiceLoader.load;
/**
* @test
* @bug 7058662 7058666 7058672
* @bug 7058662 7058666 7058672 8130305
* @author Sergey Bylokhov
*/
public final class ReadersExceptions {
@ -111,16 +113,18 @@ public final class ReadersExceptions {
0, 0, 0, 0, // dataLength
};
static byte[][] data = {wrongAIFFCh, wrongAIFFSSL, wrongAIFFSSH, wrongAUCh,
wrongWAVCh, wrongWAVSSB};
public static void main(final String[] args) throws IOException {
test(wrongAIFFCh);
test(wrongAIFFSSL);
test(wrongAIFFSSH);
test(wrongAUCh);
test(wrongWAVCh);
test(wrongWAVSSB);
for (final byte[] bytes : data) {
testAS(bytes);
testAFR(bytes);
}
}
private static void test(final byte[] buffer) throws IOException {
private static void testAS(final byte[] buffer) throws IOException {
// AudioSystem API
final InputStream is = new ByteArrayInputStream(buffer);
try {
AudioSystem.getAudioFileFormat(is);
@ -130,4 +134,19 @@ public final class ReadersExceptions {
}
throw new RuntimeException("Test Failed");
}
private static void testAFR(final byte[] buffer) throws IOException {
// AudioFileReader API
final InputStream is = new ByteArrayInputStream(buffer);
for (final AudioFileReader afr : load(AudioFileReader.class)) {
for (int i = 0; i < 10; ++i) {
try {
afr.getAudioFileFormat(is);
throw new RuntimeException("UAFE expected");
} catch (final UnsupportedAudioFileException ignored) {
// Expected.
}
}
}
}
}