diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AbstractMidiDeviceProvider.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AbstractMidiDeviceProvider.java index 3d0d1af514a..8d0003cc987 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AbstractMidiDeviceProvider.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AbstractMidiDeviceProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2014, 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 @@ -117,7 +117,7 @@ public abstract class AbstractMidiDeviceProvider extends MidiDeviceProvider { } } - + @Override public final MidiDevice.Info[] getDeviceInfo() { readDeviceInfos(); Info[] infos = getInfoCache(); @@ -126,7 +126,7 @@ public abstract class AbstractMidiDeviceProvider extends MidiDeviceProvider { return localArray; } - + @Override public final MidiDevice getDevice(MidiDevice.Info info) { if (info instanceof Info) { readDeviceInfos(); @@ -143,9 +143,7 @@ public abstract class AbstractMidiDeviceProvider extends MidiDeviceProvider { } } } - - throw new IllegalArgumentException("MidiDevice " + info.toString() - + " not supported by this provider."); + throw MidiUtils.unsupportedDevice(info); } diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/MidiUtils.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/MidiUtils.java index eecd33fe0b5..40f7cd9f576 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/MidiUtils.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/MidiUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, 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,9 +25,15 @@ package com.sun.media.sound; -import javax.sound.midi.*; import java.util.ArrayList; +import javax.sound.midi.MetaMessage; +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiEvent; +import javax.sound.midi.MidiMessage; +import javax.sound.midi.Sequence; +import javax.sound.midi.Track; + // TODO: // - define and use a global symbolic constant for 60000000 (see convertTempo) @@ -48,6 +54,17 @@ public final class MidiUtils { private MidiUtils() { } + /** + * Returns an exception which should be thrown if MidiDevice is unsupported. + * + * @param info an info object that describes the desired device + * @return an exception instance + */ + static RuntimeException unsupportedDevice(final MidiDevice.Info info) { + return new IllegalArgumentException(String.format( + "MidiDevice %s not supported by this provider", info)); + } + /** return true if the passed message is Meta End Of Track */ public static boolean isMetaEndOfTrack(MidiMessage midiMsg) { // first check if it is a META message at all diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/RealTimeSequencer.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/RealTimeSequencer.java index 7252723e776..ea782e811b0 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/RealTimeSequencer.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/RealTimeSequencer.java @@ -64,7 +64,7 @@ final class RealTimeSequencer extends AbstractMidiDevice /** * All RealTimeSequencers share this info object. */ - static final RealTimeSequencerInfo info = new RealTimeSequencerInfo(); + static final MidiDevice.Info info = new RealTimeSequencerInfo(); private static final Sequencer.SyncMode[] masterSyncModes = { Sequencer.SyncMode.INTERNAL_CLOCK }; @@ -154,7 +154,7 @@ final class RealTimeSequencer extends AbstractMidiDevice /* ****************************** CONSTRUCTOR ****************************** */ - RealTimeSequencer() throws MidiUnavailableException { + RealTimeSequencer(){ super(info); if (Printer.trace) Printer.trace(">> RealTimeSequencer CONSTRUCTOR"); @@ -1088,7 +1088,7 @@ final class RealTimeSequencer extends AbstractMidiDevice private static final String description = "Software sequencer"; private static final String version = "Version 1.0"; - private RealTimeSequencerInfo() { + RealTimeSequencerInfo() { super(name, vendor, description, version); } } // class Info diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/RealTimeSequencerProvider.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/RealTimeSequencerProvider.java index d2724955a0c..fa5bfa1afbf 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/RealTimeSequencerProvider.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/RealTimeSequencerProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, 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 @@ -26,7 +26,6 @@ package com.sun.media.sound; import javax.sound.midi.MidiDevice; -import javax.sound.midi.MidiUnavailableException; import javax.sound.midi.spi.MidiDeviceProvider; /** @@ -36,23 +35,16 @@ import javax.sound.midi.spi.MidiDeviceProvider; */ public final class RealTimeSequencerProvider extends MidiDeviceProvider { - + @Override public MidiDevice.Info[] getDeviceInfo() { - - MidiDevice.Info[] localArray = { RealTimeSequencer.info }; - return localArray; + return new MidiDevice.Info[]{RealTimeSequencer.info}; } - - public MidiDevice getDevice(MidiDevice.Info info) { - if ((info != null) && (!info.equals(RealTimeSequencer.info))) { - return null; - } - - try { + @Override + public MidiDevice getDevice(final MidiDevice.Info info) { + if (RealTimeSequencer.info.equals(info)) { return new RealTimeSequencer(); - } catch (MidiUnavailableException e) { - return null; } + throw MidiUtils.unsupportedDevice(info); } } diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftProvider.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftProvider.java index 9fe8ad07390..89d85362539 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftProvider.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2014, 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,11 +22,10 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + package com.sun.media.sound; -import java.util.Arrays; import javax.sound.midi.MidiDevice; -import javax.sound.midi.MidiDevice.Info; import javax.sound.midi.spi.MidiDeviceProvider; /** @@ -36,17 +35,16 @@ import javax.sound.midi.spi.MidiDeviceProvider; */ public final class SoftProvider extends MidiDeviceProvider { - static final Info softinfo = SoftSynthesizer.info; - private static final Info[] softinfos = {softinfo}; - + @Override public MidiDevice.Info[] getDeviceInfo() { - return Arrays.copyOf(softinfos, softinfos.length); + return new MidiDevice.Info[]{SoftSynthesizer.info}; } - public MidiDevice getDevice(MidiDevice.Info info) { - if (info == softinfo) { + @Override + public MidiDevice getDevice(final MidiDevice.Info info) { + if (SoftSynthesizer.info.equals(info)) { return new SoftSynthesizer(); } - return null; + throw MidiUtils.unsupportedDevice(info); } } diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiSystem.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiSystem.java index 9f790fd0f01..4eee72a9d0a 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiSystem.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiSystem.java @@ -31,6 +31,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.net.URL; import java.util.ArrayList; +import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -162,18 +163,11 @@ public class MidiSystem { * of length 0 is returned. */ public static MidiDevice.Info[] getMidiDeviceInfo() { - List<MidiDevice.Info> allInfos = new ArrayList<>(); - List<MidiDeviceProvider> providers = getMidiDeviceProviders(); - - for(int i = 0; i < providers.size(); i++) { - MidiDeviceProvider provider = providers.get(i); - MidiDevice.Info[] tmpinfo = provider.getDeviceInfo(); - for (int j = 0; j < tmpinfo.length; j++) { - allInfos.add( tmpinfo[j] ); - } + final List<MidiDevice.Info> allInfos = new ArrayList<>(); + for (final MidiDeviceProvider provider : getMidiDeviceProviders()) { + Collections.addAll(allInfos, provider.getDeviceInfo()); } - MidiDevice.Info[] infosArray = allInfos.toArray(new MidiDevice.Info[0]); - return infosArray; + return allInfos.toArray(new MidiDevice.Info[allInfos.size()]); } /** @@ -187,17 +181,15 @@ public class MidiSystem { * MIDI device installed on the system * @see #getMidiDeviceInfo */ - public static MidiDevice getMidiDevice(MidiDevice.Info info) throws MidiUnavailableException { - List<MidiDeviceProvider> providers = getMidiDeviceProviders(); - - for(int i = 0; i < providers.size(); i++) { - MidiDeviceProvider provider = providers.get(i); + public static MidiDevice getMidiDevice(final MidiDevice.Info info) + throws MidiUnavailableException { + for (final MidiDeviceProvider provider : getMidiDeviceProviders()) { if (provider.isDeviceSupported(info)) { - MidiDevice device = provider.getDevice(info); - return device; + return provider.getDevice(info); } } - throw new IllegalArgumentException("Requested device not installed: " + info); + throw new IllegalArgumentException(String.format( + "Requested device not installed: %s", info)); } /** diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/spi/MidiDeviceProvider.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/spi/MidiDeviceProvider.java index b4c95a1ec60..97c9d92b7f0 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/spi/MidiDeviceProvider.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/spi/MidiDeviceProvider.java @@ -25,6 +25,8 @@ package javax.sound.midi.spi; +import java.util.Arrays; + import javax.sound.midi.MidiDevice; /** @@ -45,16 +47,8 @@ public abstract class MidiDeviceProvider { * @return {@code true} if the specified device is supported, otherwise * {@code false} */ - public boolean isDeviceSupported(MidiDevice.Info info) { - - MidiDevice.Info infos[] = getDeviceInfo(); - - for(int i=0; i<infos.length; i++) { - if( info.equals( infos[i] ) ) { - return true; - } - } - return false; + public boolean isDeviceSupported(final MidiDevice.Info info) { + return Arrays.asList(getDeviceInfo()).contains(info); } /** diff --git a/jdk/test/javax/sound/midi/MidiDeviceProvider/NullInfo.java b/jdk/test/javax/sound/midi/MidiDeviceProvider/NullInfo.java new file mode 100644 index 00000000000..9fa00c03172 --- /dev/null +++ b/jdk/test/javax/sound/midi/MidiDeviceProvider/NullInfo.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2014, 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.util.Collection; +import java.util.HashSet; + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.spi.MidiDeviceProvider; + +import static java.util.ServiceLoader.load; + +/** + * @test + * @bug 8058115 + * @summary MidiDeviceProvider shouldn't returns incorrect results or throw NPE + * in case of null MidiDevice.Info + * @author Sergey Bylokhov + */ +public final class NullInfo { + + public static void main(final String[] args) { + // MidiSystem API + try { + MidiSystem.getMidiDevice(null); + throw new RuntimeException("IllegalArgumentException expected"); + } catch (final MidiUnavailableException e) { + throw new RuntimeException("IllegalArgumentException expected", e); + } catch (final IllegalArgumentException ignored) { + // expected + } + // MidiDeviceProvider API + final Collection<String> errors = new HashSet<>(); + for (final MidiDeviceProvider mdp : load(MidiDeviceProvider.class)) { + try { + if (mdp.isDeviceSupported(null)) { + throw new RuntimeException("null is supported"); + } + final MidiDevice device = mdp.getDevice(null); + System.err.println("MidiDevice: " + device); + throw new RuntimeException("IllegalArgumentException expected"); + } catch (final IllegalArgumentException e) { + errors.add(e.getMessage()); + } + } + if (errors.size() != 1) { + throw new RuntimeException("Wrong number of messages:" + errors); + } + } +} diff --git a/jdk/test/javax/sound/midi/MidiDeviceProvider/UnsupportedInfo.java b/jdk/test/javax/sound/midi/MidiDeviceProvider/UnsupportedInfo.java new file mode 100644 index 00000000000..685a5e8af62 --- /dev/null +++ b/jdk/test/javax/sound/midi/MidiDeviceProvider/UnsupportedInfo.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014, 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 javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.spi.MidiDeviceProvider; + +import static java.util.ServiceLoader.load; + +/** + * @test + * @bug 8058115 + * @summary MidiDeviceProvider shouldn't returns incorrect results in case of + * unsupported MidiDevice.Info + * @author Sergey Bylokhov + */ +public final class UnsupportedInfo { + + public static void main(final String[] args) { + final MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo(); + for (final MidiDeviceProvider mdp : load(MidiDeviceProvider.class)) { + for (final MidiDevice.Info info : infos) { + if (mdp.isDeviceSupported(info)) { + if (mdp.getDevice(info) == null) { + throw new RuntimeException("MidiDevice is null"); + } + } else { + try { + mdp.getDevice(info); + throw new RuntimeException( + "IllegalArgumentException expected"); + } catch (final IllegalArgumentException ignored) { + // expected + } + } + } + } + } +}