I'm not sure I understand the exact limitations you have for implementing a solution, but it seems that the cleanest way to do this would be to store the audio data in a buffer the first time you play through the file. Then, if there are more iterations (full or partial) wanted by the user, just rewrite the data you have cached back out to the SourceDataLine the desired number of times.
Here is a link to a sample sound file player (PCM) that has code that should be very easy to modify (or just learn from). I also hacked up some (note: untested) code that just shows the logic I described above: (You probably also want to modify what I have below to conform to the rules concerning only writing chunks of data that have a size that is a multiple of the frame size.)
public void playSoundFile(SourceDataLine line, InputStream inputStream, AudioFormat format, long length, float times)
{
int index = 0;
int size = length * format.getFrameSize();
int currentSize = 0;
byte[] buffer = new byte[size];
AudioInputStream audioInputStream = new AudioInputStream(inputStream, format, length);
while (index < size)
{
currentSize = audioInputStream.read(buffer, index, size - index);
line.write(buffer, index, currentSize);
index += currentSize;
}
float currentTimes = 1.0;
while (currentTimes < times)
{
float timesLeft = times - currentTimes;
int writeBlockSize = line.available();
index = 0;
if (timesLeft >= 1.0)
{
while (index < size)
{
currentSize = ((size - index) < writeBlockSize) ? size - index : writeBlockSize;
line.write(buffer, index, currentSize);
index += currentSize;
}
currentTimes += 1.0;
}
else
{
int partialSize = (int)(timesLeft * ((float) size) + 0.5f);
while (index < partialSize)
{
currentSize = ((partialSize - index) < writeBlockSize) ? partialSize - index : writeBlockSize;
line.write(buffer, index, currentSize);
index += currentSize;
}
currentTimes += timesLeft;
}
}
}
Hope that helps!