1 /* 2 * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 import java.io.ByteArrayInputStream; 25 import java.io.FilterInputStream; 26 import java.io.IOException; 27 import java.io.InputStream; 28 29 import javax.sound.midi.MidiSystem; 30 import javax.sound.midi.Sequence; 31 32 /** 33 * @test 34 * @bug 4910986 35 * @summary MIDI file parser breaks up on http connection 36 */ 37 public class SMFParserBreak { 38 39 public static void main(String[] args) throws Exception { 40 41 InputStream is = new ByteArrayInputStream(midifile); 42 // create a buffered input stream that seems 43 // to be on an unfortunate boundary for the 44 // 1.4.2 SMF parser implementation 45 is = new ChunkInputStream(is, 32); 46 Sequence sequence = MidiSystem.getSequence(is); 47 48 long duration = sequence.getMicrosecondLength() / 10000; 49 System.out.println("Duration: "+duration+" deciseconds "); 50 51 // the test is passed if no exception thrown 52 System.out.println("Test passed"); 53 } 54 55 // A MIDI file 56 static byte[] midifile = { 57 77, 84, 104, 100, 0, 0, 0, 6, 0, 1, 0, 3, -30, 120, 77, 84, 114, 107, 0, 58 0, 0, 123, 0, -112, 30, 100, -113, 49, -128, 50, 100, -114, 69, -112, 31, 59 100, -114, 33, -128, 51, 100, -114, 55, -112, 32, 100, -114, 120, -128, 52, 60 100, -114, 40, -112, 33, 100, -114, 26, -128, 53, 100, -114, 26, -112, 34, 61 100, -114, 76, -128, 54, 100, -114, 12, -112, 35, 100, -114, 91, -128, 55, 62 100, -114, 69, -112, 36, 100, -114, 33, -128, 56, 100, -114, 55, -112, 37, 63 100, -114, 84, -128, 57, 100, -114, 40, -112, 38, 100, -114, 26, -128, 58, 64 100, -114, 26, -112, 39, 100, -113, 24, -128, 59, 100, -113, 60, -112, 40, 65 100, -113, 110, -128, 60, 100, -113, 96, -112, 41, 100, -113, 39, -128, 61, 66 100, 0, -1, 47, 0, 77, 84, 114, 107, 0, 0, 0, 4, 0, -1, 47, 0, 77, 84, 114, 67 107, 0, 0, 0, 4, 0, -1, 47, 0 68 }; 69 } 70 71 /* an input stream that always returns data in chunks */ 72 class ChunkInputStream extends FilterInputStream { 73 int chunkSize; 74 int p = 0; // position 75 76 public ChunkInputStream(InputStream is, int chunkSize) { 77 super(is); 78 this.chunkSize = chunkSize; 79 } 80 81 // override to increase counter 82 public int read() throws IOException { 83 int ret = super.read(); 84 if (ret >= 0) { 85 p++; 86 } 87 return ret; 88 } 89 90 // override to make sure that read(byte[], int, int) is used 91 public int read(byte[] b) throws IOException { 92 return read(b, 0, b.length); 93 } 94 95 // override to split the data in chunks 96 public int read(byte[] b, int off, int len) throws IOException { 97 // if we would pass a chunk boundary, 98 // only return up to the chunk boundary 99 if ( (p / chunkSize) < ( (p+len) / chunkSize)) { 100 // p+len is in the next chunk 101 len -= ((p+len) % chunkSize); 102 } 103 int ret = super.read(b, off, len); 104 if (ret >= 0) { 105 p += ret; 106 } 107 return ret; 108 } 109 }